feat(catalog): wire metered billing through ProcessService - #6396
tiagolupepic wants to merge 10 commits into
Conversation
Extend Fees::ChargeService so a metered product's BillingSegment can be priced into product-backed fees, without going through a legacy Charge. - MeteredItem gains a from_billing_segment source and drives buckets through source.pricing_buckets, so filter expansion, true-up target and filter association are resolved polymorphically by the source rather than assuming charge-shaped data. - Segment-backed fees persist fee_type: :product with the product as invoiceable and set product_filter_id (never charge_filter_id). Legacy charge filters are not expanded, adjusted-fee lookup is skipped, and no charge-shaped CachedAggregation is written. - Segment items use a nil cache path instead of building a charge cache middleware from fake boundaries. - Fees::CreateTrueUpService supports segment-backed true-ups, reading the prorated minimum, proration ratio and pricing-unit conversion from the segment snapshot while leaving charge-backed true-ups unchanged. - Add fees.product_filter_id (nullable, indexed, FK validated in a paired migration) and the discarded-aware Fee#product_filter association. Billing-state idempotency is owned by BillingSegment persistence, so fee-level already_billed? is bypassed for segments. Store/enrichment and cache identity by product_id remain out of scope and are tracked by TODOs. Covered by charge_service_billing_segment_spec and create_true_up_service_spec.
- Remove fixed-only filter from billing_segments scope to include metered - Partition segments by product_type using PRODUCT_TYPES constants - Add attach_fixed_fees and attach_metered_fees methods - Call ChargeService for metered segments with pre-loaded filter targets - Add specs for count/sum aggregations, graduated pricing, minimum amounts - Add mixed fixed+metered segments spec
…o feat/process-metered-items-billing-segments
|
Automated pre-review (advisory, not a required check) — verdict: HOLD · CI green HOLD: Consolidated metered segments from different contracts can be billed with zero usage.
|
…ices Previously, build_invoice grouped segments across contracts but resolved event filters using only the first contract's external_id. This caused ChargeService to bypass aggregation for another contract's segment. Changes: - Remove contract parameter from BillingPeriodFilterService.for_billing_segments! - Remove contract dependency from BillingSegmentsResolver - Memoize event_store by contract.id in BillingSegmentsResolver - Aggregate event combinations across all contracts in filter_targets - Add regression spec with two consolidated metered contracts The BillingSegmentsResolver now: 1. Extracts unique contracts from the billing segments 2. Creates a separate event store for each contract (memoized by id) 3. Queries distinct_codes_and_property_combinations for each contract 4. Merges the results before matching against product filters
## Context Consolidated billing segments can belong to different contracts with different metric codes, event boundaries, and filter keys. Recurring metrics also need their historical event pass to retain ingestion timestamps. ## Description Scope billing-segment event resolution by contract and preserve recurring history handling. Add regression coverage for consolidated contracts with different billing periods and product filters.
Billing segments from different contracts can reference the same product while using different event boundaries and filter sets. Product-only target keys merge their filter results. Qualify billing-segment target keys with the contract and product identities, use the key when attaching filtered aggregations, and add regression coverage for the shared-product scenario.
Refactored the event filters to use the contract scope.
|
|
Automated pre-review (advisory, not a required check) — verdict: HOLD · CI green HOLD — metered segment processing now accepts configurations that the contract-backed charge path cannot execute.
|
Both options are going to be addressed soon in another ticket. It's part of |
|
Automated pre-review (advisory, not a required check) — verdict: HOLD · CI green HOLD — the broadened pending scope processes valid metered configurations that this contract-backed fee path cannot safely finalize.
|
Consolidated invoices can contain the same product under multiple contracts. Event combinations and their ingestion timestamps are contract-specific. Match each contract's event combinations only against its own billing segment targets and add regression coverage for filter buckets and last-seen timestamps.
|
Automated pre-review (advisory, not a required check) — verdict: HOLD · CI green HOLD: Metered segment processing now incorrectly finalizes supported advance-billed cards at the segment start.
|
## Context Advance metered segments are billed per event and are not ready for periodic invoice finalization. Processing them through the metered period-finalization path can create invoices before usage exists. ## Description Exclude advance metered segments from pending billing-segment processing while retaining arrears metered and fixed segments. Add regression coverage to ensure advance segments remain pending without an invoice.
|
Automated pre-review (advisory, not a required check) — verdict: HOLD · CI green HOLD — periodic processing now admits every arrears metered segment, but segment-backed recurring state is not implemented.
|
This commit introduces the metered items compute Fee in ProcessService