feat(billing): Billing engine v2 date services - #6267
Merged
Merged
Conversation
tiagolupepic
reviewed
Sep 1, 2026
tiagolupepic
reviewed
Sep 1, 2026
tiagolupepic
reviewed
Sep 1, 2026
tiagolupepic
reviewed
Sep 1, 2026
tiagolupepic
reviewed
Sep 1, 2026
tiagolupepic
reviewed
Sep 1, 2026
tiagolupepic
reviewed
Sep 1, 2026
tiagolupepic
reviewed
Sep 1, 2026
annvelents
reviewed
Sep 1, 2026
tiagolupepic
reviewed
Sep 1, 2026
tiagolupepic
reviewed
Sep 1, 2026
tiagolupepic
reviewed
Sep 1, 2026
annvelents
reviewed
Sep 1, 2026
annvelents
reviewed
Sep 1, 2026
annvelents
reviewed
Sep 1, 2026
annvelents
reviewed
Sep 1, 2026
annvelents
reviewed
Sep 1, 2026
annvelents
reviewed
Sep 1, 2026
annvelents
reviewed
Sep 1, 2026
annvelents
reviewed
Sep 1, 2026
annvelents
reviewed
Sep 1, 2026
annvelents
reviewed
Sep 1, 2026
annvelents
reviewed
Sep 1, 2026
brunomiguelpinto
commented
Sep 1, 2026
brunomiguelpinto
left a comment
Contributor
Author
There was a problem hiding this comment.
Read it end to end. The pure layer is the strongest part — Interval, Calendar and Segments have no dependencies, and having the QA scenarios pinned as value tables means an expectation can be checked against the plan rather than argued about. Three things I'd want addressed before this lands, one of them structural.
tiagolupepic
reviewed
Sep 2, 2026
tiagolupepic
reviewed
Sep 2, 2026
annvelents
reviewed
Sep 3, 2026
annvelents
reviewed
Sep 3, 2026
annvelents
reviewed
Sep 3, 2026
annvelents
reviewed
Sep 7, 2026
annvelents
reviewed
Sep 7, 2026
annvelents
reviewed
Sep 7, 2026
annvelents
reviewed
Sep 7, 2026
annvelents
reviewed
Sep 7, 2026
annvelents
reviewed
Sep 7, 2026
annvelents
reviewed
Sep 7, 2026
annvelents
reviewed
Sep 7, 2026
annvelents
reviewed
Sep 8, 2026
annvelents
reviewed
Sep 8, 2026
annvelents
reviewed
Sep 8, 2026
annvelents
reviewed
Sep 8, 2026
annvelents
reviewed
Sep 8, 2026
annvelents
reviewed
Sep 8, 2026
annvelents
reviewed
Sep 8, 2026
annvelents
approved these changes
Sep 8, 2026
annvelents
left a comment
Contributor
There was a problem hiding this comment.
LGTM! 👏 ⭐ 🦸 🪨 🐐 🤘 🎊 🥇
brunomiguelpinto
changed the base branch from
products-and-plans-subscription-runtime
to
main
September 8, 2026 16:36
brunomiguelpinto
changed the base branch from
main
to
products-and-plans-subscription-runtime
September 8, 2026 16:55
brunomiguelpinto
force-pushed
the
engine-dates
branch
from
September 8, 2026 16:58
19f6e64 to
271bfce
Compare
brunomiguelpinto
changed the base branch from
products-and-plans-subscription-runtime
to
main
September 8, 2026 17:01
## Context Contract billing needs consistent dates across rate changes, phase interval overrides and long billing histories. ## Description Add schedules for due segments, future billing dates and consumption ratios. Separate cycle traversal from segment construction, with resume support and reusable calendars. Build schedules from contract rate cards and resume from their latest persisted cycle. Interpret card dates in the customer timezone and respect both card and contract termination boundaries. Seed the initial contract billing clock from the schedule. Add helpers for converting exclusive schedule ends to inclusive stored ends. Cover full and resumed walks, rate and phase transitions, proration, termination, persisted history and contract materialization.
## Context Billing segments already exist on main. Their pricing-unit and base-rate indexes are not used by the current billing queries. ## Description Remove the two indexes with a new concurrent migration and restore them on rollback. Update the schema and model annotations to match.
brunomiguelpinto
force-pushed
the
engine-dates
branch
from
September 8, 2026 17:16
271bfce to
cdab799
Compare
brunomiguelpinto
marked this pull request as ready for review
September 8, 2026 17:24
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Contract billing needs consistent dates across rate changes, phase overrides and long billing histories. This adds a rate-card schedule that produces billable segments and can resume near a requested date without walking every historical cycle.
Behaviour
CycleWalkerowns traversal and resume. It stops at rate and phase transitions, recalculates the calendar when the interval changes, and reuses calendars between calls. Walking the complete history remains supported.Schedulesplits cycles at rate changes and assigns each priced segment its own billing date: start for advance, end for arrears. Unpriced windows still consume cycle indices.BillingSegment.inclusive_endand.exclusive_endconvert stored boundaries.BuildScheduleServicereadsContractRateCard, resolves ordered rates and card or plan phases, and resumes from that attachment's latest persisted cycle. The last cycle is intentionally returned again, so the writer must deduplicate persisted segments. Separate attachments do not share billing history.Public schedule API
segments_due_by(timestamp)next_billing_at(after:)billing_at_covering(timestamp)consumed_ratio(segment:, at:)Integration with main
This PR is based directly on
mainand contains only the date engine and its contract integration. It uses the existing contract models and billing-segment table. Existing migrations, Ruby 4.0.6 and dependencies are unchanged.A separate migration removes the unused
pricing_unit_idandrate_card_rate_idindexes frombilling_segments, with concurrent operations and a reversible rollback.The invoice writer and processor are outside this PR.
Validation