npm test -- --watchAll=false --testPathPattern='(BillingSection|finance\\.test)'
Signed-in user with paid invoices: plan + history render; Manage subscription redirects to portal URL
User with no invoices: empty copy + Complete payment starts Checkout
Portal/list API errors show alert text (no silent fail)
Return from Stripe portal lands on /account/
No card fields collected in-app
## Summary
- Closes [#33](https://git.aimloperations.com/ai_ml_operations/chat_web_app/issues/33)
- Add Billing glass cards on `/account/` (`Account2`): current plan summary + billing history from `GET /finance/invoices/` (and payments fallback)
- **Manage subscription** CTA → `POST /finance/portal/` → redirect to Stripe hosted Customer Portal (return URL `/account/`)
- Empty / unpaid users get **Complete payment** → Checkout instead of a dead portal button
- Visible errors for list/portal failures; fire `BILLING_PORTAL_OPENED`
- Depends on backend portal endpoint: [chat_backend#35](https://git.aimloperations.com/ai_ml_operations/chat_backend/pulls/35)
## Test plan
- [ ] `npm test -- --watchAll=false --testPathPattern='(BillingSection|finance\\.test)'`
- [ ] Signed-in user with paid invoices: plan + history render; Manage subscription redirects to portal URL
- [ ] User with no invoices: empty copy + Complete payment starts Checkout
- [ ] Portal/list API errors show alert text (no silent fail)
- [ ] Return from Stripe portal lands on `/account/`
- [ ] No card fields collected in-app
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
/account/(Account2): current plan summary + billing history fromGET /finance/invoices/(and payments fallback)POST /finance/portal/→ redirect to Stripe hosted Customer Portal (return URL/account/)BILLING_PORTAL_OPENEDTest plan
npm test -- --watchAll=false --testPathPattern='(BillingSection|finance\\.test)'/account/