gsinghpal
d770c0c3a9
fix(billing): resolve code-review findings (authz, cross-billing, validation, webhook integrity)
...
- C1/H4: rating cron only rates subs on the charge's own plan_id
- C1: _fc_rate_usage skips creating a line when amount is 0 (still updates existing)
- C2/C4: /usage authorizes each event (exists + is_subscription + linked customer)
- C3: API handlers validate input and return 4xx-shaped errors instead of raising;
controller maps status=='error' to HTTP 400
- H1: cron uses real billing window [last_invoice_date or start_date, next_invoice_date)
- H2: _aggregate uses half-open window anchored on period_start
- H3: idempotency scoped to (subscription_id, metric_id, idempotency_key)
- H5: webhook stores canonical body, signs+POSTs it verbatim, adds X-Fusion-Event-Id,
caps backoff at 2**min(attempts,10)
- H6: SSRF guard rejects non-https / localhost / private / link-local webhook_url
- M7: charge_model reduced to standard/package (dropped unimplemented graduated/volume)
- L1: currency_id required on charge + reconciliation
- L2: charge price non-negative + unit_batch positive DB constraints
Adds 17 regression tests (suite 22 -> 39, all green via fcb_test_on_trial.sh).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-27 08:42:08 -04:00
gsinghpal
a5db0fe71e
feat(billing): usage-rating + webhook-dispatch crons
...
- SaleOrder._fc_rate_usage: aggregates usage, computes overage via
charge._compute_billable, upserts sale.order.line for the overage product
- FusionBillingUsage._cron_rate_open_periods: hourly cron iterates active
charges × in-progress subscriptions, calls _fc_rate_usage
- data/ir_cron.xml: two crons — rate usage (hourly), dispatch webhooks (2 min)
- __manifest__.py: registers data/ir_cron.xml in data list
- test_usage.py: test_rate_open_period_creates_overage_line (TDD, FCB_EXIT=0)
Reference: _create_recurring_invoice / _get_invoiceable_lines confirmed in
Enterprise sale_subscription/models/sale_order.py — overage line goes onto
sale.order so native invoicing picks it up via _get_invoiceable_lines.
2026-05-27 08:42:08 -04:00
gsinghpal
6c395709cf
feat(billing): outbound webhook engine (HMAC + retry/backoff)
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-27 08:42:08 -04:00
gsinghpal
0754d0b101
feat(billing): subscription creation handler (sale.order is_subscription)
...
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-27 08:42:08 -04:00
gsinghpal
2435096f32
feat(billing): inbound API handlers (customer/usage/catalog)
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-27 08:42:08 -04:00
gsinghpal
25952cf226
feat(billing): period usage aggregation by metric function
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-27 08:42:08 -04:00
gsinghpal
eb1ee85d24
feat(billing): idempotent usage ingestion
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-27 08:42:08 -04:00
gsinghpal
1e34a67384
feat(billing): metered charge math (quota + overage)
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-27 08:42:08 -04:00
gsinghpal
a1cfab6fe9
feat(billing): identity resolution external account -> partner
2026-05-27 08:42:08 -04:00
gsinghpal
a46e31e710
feat(billing): service API-key generation + matching
...
Add _match_api_key() class method to fusion.billing.service, with a
TDD test suite (TestServiceApiKey) covering key generation, hash storage,
positive match, and rejection of bad/inactive keys. Also fix
fcb_test_on_trial.sh to use --http-port 8070, as Odoo 19 forces
http_spawn() even under --no-http when --test-enable is set.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-27 08:42:08 -04:00