Skip to content

Miguel engine v2 - #5836

Draft
brunomiguelpinto wants to merge 57 commits into
products-and-plans-subscription-runtimefrom
miguel-engine-v2
Draft

Miguel engine v2#5836
brunomiguelpinto wants to merge 57 commits into
products-and-plans-subscription-runtimefrom
miguel-engine-v2

Conversation

@brunomiguelpinto

Copy link
Copy Markdown
Contributor

Roadmap Task

👉 https://getlago.canny.io/feature-requests/p/{{FEATURE_SLUG}}

Context

Include relevant motivation and context.

Description

Describe your changes in detail.

List any dependencies that are required.

@brunomiguelpinto
brunomiguelpinto changed the base branch from main to api-v2-foundation July 1, 2026 18:47
@brunomiguelpinto
brunomiguelpinto changed the base branch from api-v2-foundation to products-and-plans-subscription-runtime July 8, 2026 15:58
tiagolupepic and others added 30 commits August 26, 2026 23:45
## Context

Billing cycle specs should use FactoryBot setup instead of constructing records directly.

## Description

Add a billing cycle factory with the required associations and default period values. Update the process service spec to create its pending cycle through the factory while preserving explicit pricing references for the override scenario.
Rate phase overrides can be edited after subscriptions exist, including pricing properties. Billing cycles must keep the effective pricing data selected at scheduling time so later override edits do not change already scheduled fees.

Add stored rate properties to billing cycles and populate them from the effective rate or override when cycles are scheduled. Use the stored properties during processing and final cycle creation, and update specs to cover snapshot behavior.
## Context

The cycles preview endpoint reported a calendar next billing date even when no billable cycle existed in the requested range because rates were not yet available.

## Description

Return only the cycles payload when no cycle can be generated, and cover future-dated rate windows so clients do not receive a misleading next billing date.
## Context

Backdated advance activations could schedule billing cycles with billing_at set to the historical period boundary. That timestamp then flowed into invoice creation and produced a backdated invoice issuing date.

## Description

Clamp billing cycle billing_at to the current time when the billing boundary is in the past, while preserving future billing boundaries. Add scheduler specs for past and future advance periods.
## Context

Subscription rate card termination needs to create the final arrears billing cycle directly so the clock processor can pick up pending cycles later. Regular scheduling should only generate cycles for rate cards whose billing clock is due.

## Description

Add a due_for_range scope based on next_billing_at and use it from the billing cycle scheduler. Move final arrears cycle creation into SubscriptionRateCards::TerminateService using the existing billing period date service, while advance termination only sets ended_at. Update the related scheduler, model, and termination specs.
## Context

Advance subscription rate cards are credited on termination based on the paid period that contains the termination date. The credit path should use the same period and rate resolution as billing cycle scheduling instead of a standalone rate resolver or direct boundary calculation.

## Description

Use BillingPeriods::DatesService to resolve advance periods for unused credit calculation and expose the consumed ratio on each period. Remove the unused ResolveRateService and add coverage for split-rate periods so credits use the period-specific ratio.
## Context

Arrears termination uses the current item clock as the date range end so the existing date service can emit the open cycle before it is clamped to the termination instant.

## Description

Add an inline comment documenting why SubscriptionRateCards::TerminateService passes next_billing_at as the range end when resolving termination periods.
## Context

Billing period ratios need the same anchor date that generated each cycle. Realigned billing anchors can differ from the subscription rate card anchor after interval changes.

## Description

Store the generated cycle anchor date on DatesService cycles and pass it to ratio calculation so backdated advance stub periods use the correct generated boundaries.
## Context

Billing period cycles exposed billing interval and anchor values that were only needed while building periods and computing ratios.

## Description

Remove the internal billing interval and anchor fields from cycle and period value objects. Keep boundary lookup state private to the dates service and update the related spec expectations.
## Context

Manual product-catalog billing can optionally terminate subscriptions before billing them inline.

## Description

Terminate subscriptions at the current time when manual billing runs with termination enabled. Update the service spec to freeze time and assert the deterministic termination timestamp.
## Context

Manual product-catalog billing and termination are separate API actions. The bill path no longer needs to accept or execute a termination option.

## Description

Remove termination handling from the manual bill endpoint and service. Add request coverage for the terminate action, including applied rate cards, credit notes, current-time fallback, permissions, and not-found behavior.
## Context

V2 product-catalog subscription termination needs request coverage for the real service behavior, including arrears final billing cycles and advance credit notes.

## Description

Parse the termination timestamp before calling the termination service and add request specs that exercise monthly arrears, phased arrears, and billed advance termination scenarios.
Charge model services used to receive different chargeable records and a separate properties hash.
This made the pricing boundary depend on ActiveRecord models and duplicated how charge model inputs were passed around.

Introduce ChargeModels::ChargeableData as the normalized input for charge model calculations.
Build it with ChargeModels::ChargeableData.from_charge(charge) for usage charges and ChargeModels::ChargeableData.from_fixed_charge(fixed_charge) for fixed charges.

Pass ChargeableData to ChargeModels::Factory and charge model services instead of passing raw charge objects and separate properties.
When charge filter properties must override the charge properties, use .with(properties:) on the data object before invoking the factory or service.

Update charge model callers, pay-in-advance pricing, projections, and specs to use the normalized chargeable data boundary.
## Context

Fixed-product billing cycles could only price standard rate properties directly, so graduated and volume rate models resolved their ranges but produced zero-amount fees.

## Description

Price billing cycles through the charge model factory using PricingStructure data from the resolved cycle. Preserve charge model amount details on the fee and add regression coverage for tiered fixed-product rates.
Billing cycle fee processing needs to preserve the pricing unit selected during scheduling so retries and processing do not resolve pricing configuration again.

Add an optional pricing unit association to billing cycles and persist it from the scheduler. Move billing cycle fee computation under BillingCycles::Fees, split amount conversion into a dedicated service, and use the stored pricing unit when building fee pricing unit usage.
## Context

Billing cycle product fees must honor rate minimum amounts so fixed product subscriptions are not finalized below their configured floor.

## Description

Add billing cycle minimum amount resolution and return base and true-up amount payloads from the billing cycle fee amount service. Decorate an optional linked true-up fee in the compute service and persist both fees during cycle processing, including pricing unit and prorated minimum scenarios.
Billing cycle fee computation should not rebuild billing calendar boundaries when the scheduler already resolves each cycle period.

Persist the proration ratio on billing cycles, compute the value in the billing period date services, and make fee amount calculation read it from the billing cycle. Keep advance unused-credit calculations on a separate consumed ratio so termination refunds continue to use elapsed-period semantics.
Termination billing needs periods that overlap the termination window instead of extending the regular arrears lookup to the next billing date.

Route termination date generation through a dedicated billing period service selected by DatesService options. Generate overlapping periods from the provided termination range, clamp the final period in the date layer, and let rate card termination persist all generated billing cycles without local period math.
## Context

Billing cycle invoice generation needs to separate invoices by all grouping dimensions that affect invoice content and payment handling.

## Description

Use billing cycle data when grouping and creating invoices, including cycle currency, cycle-level consolidation, purchase order numbers, billing entity, payment method, and local billing date. Persist zero-amount finalization transitions and avoid setting legacy charge date ranges on new billing cycle invoice subscriptions. Add focused specs for invoice grouping, purchase order numbers, payment method combinations, consolidation, and zero-amount finalization behavior.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants