Skip to content

feat: snapshot unit config on invoice lines - OM-398#4642

Open
rolosp wants to merge 1 commit into
mainfrom
feat/om-398-unit-config-snapshot-on-invoice-lines
Open

feat: snapshot unit config on invoice lines - OM-398#4642
rolosp wants to merge 1 commit into
mainfrom
feat/om-398-unit-config-snapshot-on-invoice-lines

Conversation

@rolosp

@rolosp rolosp commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Overview

Snapshots applied_unit_config on usage-based invoice lines so re-rating converts from raw metered quantity using the config applied at billing time, even after the rate card changes. Adds one nullable jsonb column; converted value is recomputed on read.

Written on both billing paths (charges line-mapper + legacy line-engine via AsNewStandardLine), so unitConfig works even when lines route to the legacy engine. StandardLine.GetUnitConfig() now returns the snapshot.

Summary by CodeRabbit

  • New Features
    • Billing now persists a billing-time unit_config snapshot (including legacy gathering lines) and exposes it on usage-based invoice lines for inspection.
  • Bug Fixes
    • Missing optional unit-config input no longer clears an existing snapshot on inserts/upserts.
    • Invalid unit_config inputs are now rejected during rating-time mutation (fails gracefully instead of converting).
    • Standard line GetUnitConfig() now returns the stored snapshot when available.
  • Tests
    • Added coverage for snapshot persistence, propagation, deep-copy behavior, and legacy rating semantics.

@rolosp rolosp requested a review from a team as a code owner July 3, 2026 12:42
@rolosp rolosp added the release-note/misc Miscellaneous changes label Jul 3, 2026
@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds an AppliedUnitConfig snapshot for usage-based billing lines, persists it in storage, carries it through gathering/standard line flows, validates unit configs before rating mutation, and expands coverage with tests.

Changes

Applied unit config snapshot feature

Layer / File(s) Summary
Schema and line fields
tools/migrate/migrations/20260703084504_applied-unit-config-snapshot.{up,down}.sql, openmeter/ent/schema/billing.go, openmeter/billing/gatheringinvoice.go, openmeter/billing/stdinvoiceline.go, openmeter/billing/derived.gen.go
Adds the persisted applied_unit_config column, adds UnitConfig/AppliedUnitConfig fields, and extends equality checks to include them.
Gathering and standard line snapshot propagation
openmeter/billing/gatheringinvoice.go, openmeter/billing/stdinvoiceline.go, openmeter/billing/adapter/*, openmeter/billing/worker/subscriptionsync/service/targetstate/targetstateitem.go
Deep-copies gathering-line unit config, carries it into new standard lines, persists and maps the snapshot through adapters, and reads it back through GetUnitConfig().
Rating-time capture and validation
openmeter/billing/charges/usagebased/service/linemapper.go, openmeter/billing/rating/service/mutator/unitconfig.go, .agents/skills/ent/SKILL.md
Captures the effective unit config on billed lines, validates unit config before mutation, and documents the nil-guarded create/upsert pattern.
Snapshot coverage tests
openmeter/billing/*_test.go, test/billing/*
Adds tests for snapshot propagation, persistence round trips, deep-copy behavior, rating assertions, and invalid config handling.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • openmeterio/openmeter#4616: This PR builds on the unit-config rating flow and GetUnitConfig() exposure that this change extends with persisted snapshots.

Suggested labels: release-note/feature, area/billing, kind/feature

Suggested reviewers: turip

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: snapshotting unit config on invoice lines.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/om-398-unit-config-snapshot-on-invoice-lines

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR snapshots the rate card's unit_config onto usage-based invoice lines (both standard and gathering) so re-rating always converts raw metered quantity using the configuration that was active at billing time, even if the rate card is later edited.

  • Adds a nullable applied_unit_config jsonb column to billing_invoice_usage_based_line_configs via a non-destructive migration, with a matching Ent schema field and generated DB code using the existing UnitConfigValueScanner.
  • Wires the snapshot through both billing paths: the charges reconciler (populateStandardLineFromRun) sets it directly on the standard line, while the legacy line-engine path stores it on the gathering line (GatheringLineBase.UnitConfig) and carries it through AsNewStandardLineUsageBasedLine.AppliedUnitConfig.
  • StandardLine.GetUnitConfig() now returns the snapshot instead of nil, eliminating the seam introduced in OM-395 and making the UnitConfig mutator work correctly on the legacy path; a defensive Validate() call before Apply guards against corrupt imported configs reaching the billing worker.

Confidence Score: 5/5

Safe to merge. The migration is additive (nullable column, no default), both billing paths correctly snapshot the config, the write-once DB contract is sound, and the defensive Validate() guard in the UnitConfig mutator closes the zero-factor panic window.

The change is well-scoped: one nullable column, two write paths with consistent nil-guards, a correct GetUnitConfig() return, and solid end-to-end test coverage for both the charges and legacy line-engine paths. The only inconsistency found (shallow vs. deep copy between the charges and gathering-line paths) is latent and not observable under the current write-once contract.

openmeter/billing/charges/usagebased/service/linemapper.go — direct pointer assignment is inconsistent with the deep-copy pattern used in gatheringinvoice.go.

Important Files Changed

Filename Overview
openmeter/billing/charges/usagebased/service/linemapper.go Charges path: directly assigns input.UnitConfig pointer to AppliedUnitConfig without deep-copying, unlike the gathering-line path which calls Clone().
openmeter/billing/gatheringinvoice.go Adds UnitConfig field to GatheringLineBase, correctly deep-copies in Clone() and AsNewStandardLine, and carries the snapshot through to UsageBasedLine.AppliedUnitConfig.
openmeter/billing/stdinvoiceline.go Adds AppliedUnitConfig to UsageBasedLine, wires GetUnitConfig() to return it, and updates equality. UsageBasedLine.Clone() remains a shallow copy (pre-existing pattern).
openmeter/billing/adapter/stdinvoicelines.go Correctly implements the write-once behavioral contract: sets AppliedUnitConfig only when non-nil on CREATE, so ON CONFLICT DO UPDATE skips the field and preserves an existing snapshot.
openmeter/billing/adapter/gatheringlines.go Persists and reads back UnitConfig on gathering-line UBP config; write-once on CREATE is correctly implemented with the same nil-guard pattern as stdinvoicelines.go.
openmeter/billing/rating/service/mutator/unitconfig.go Adds defensive Validate() call before Apply to prevent a corrupt zero conversion factor from panicking the billing worker. Well-targeted guard.
openmeter/ent/schema/billing.go Adds nullable applied_unit_config jsonb field to the Ent schema using the existing UnitConfigValueScanner, consistent with the price field pattern.
openmeter/billing/worker/subscriptionsync/service/targetstate/targetstateitem.go Correctly snapshots the rate card's UnitConfig onto the gathering line with a deep copy via Clone() at subscription-sync time.
openmeter/ent/db/setorclear.go Adds SetOrClearAppliedUnitConfig helpers; the double-pointer signature is a footgun for future callers but no current caller invokes it.
test/billing/unitconfig_legacy_test.go New end-to-end integration test covering the full legacy path: CreatePendingInvoiceLines → InvoicePendingLines, verifying conversion (7400 → 8 units) and snapshot round-trip. Uses s.T().Context() correctly.
tools/migrate/migrations/20260703084504_applied-unit-config-snapshot.up.sql Safe additive migration — ADD COLUMN applied_unit_config jsonb NULL with no default, no locks on existing rows.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant RC as Rate Card
    participant TSI as TargetStateItem
    participant GL as GatheringLine
    participant Adapter as Adapter (DB)
    participant ANSL as AsNewStandardLine
    participant SL as StandardLine
    participant LM as linemapper (charges)
    participant UnitMut as UnitConfig Mutator

    Note over RC,UnitMut: Legacy path (gathering line engine)
    RC->>TSI: AsMeta().UnitConfig
    TSI->>GL: "GatheringLineBase.UnitConfig = Clone()"
    GL->>Adapter: UpsertGatheringLines (SetAppliedUnitConfig if non-nil)
    Adapter-->>GL: Read back (UnitConfig from DB)
    GL->>ANSL: AsNewStandardLine(invoice-id)
    ANSL->>SL: "UsageBased.AppliedUnitConfig = Clone()"
    SL->>UnitMut: GetUnitConfig() → AppliedUnitConfig

    Note over RC,UnitMut: Charges path (reconciler)
    RC->>LM: input.UnitConfig (from charge intent)
    LM->>SL: "stdLine.UsageBased.AppliedUnitConfig = input.UnitConfig"
    SL->>Adapter: UpsertInvoiceLines (SetAppliedUnitConfig if non-nil)
    Adapter-->>SL: Read back (AppliedUnitConfig from DB)
    SL->>UnitMut: GetUnitConfig() → AppliedUnitConfig

    Note over UnitMut: Both paths
    UnitMut->>UnitMut: Validate() guard (prevents corrupt factor divide)
    UnitMut->>SL: Apply(rawMeteredQty) → invoiced Quantity
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant RC as Rate Card
    participant TSI as TargetStateItem
    participant GL as GatheringLine
    participant Adapter as Adapter (DB)
    participant ANSL as AsNewStandardLine
    participant SL as StandardLine
    participant LM as linemapper (charges)
    participant UnitMut as UnitConfig Mutator

    Note over RC,UnitMut: Legacy path (gathering line engine)
    RC->>TSI: AsMeta().UnitConfig
    TSI->>GL: "GatheringLineBase.UnitConfig = Clone()"
    GL->>Adapter: UpsertGatheringLines (SetAppliedUnitConfig if non-nil)
    Adapter-->>GL: Read back (UnitConfig from DB)
    GL->>ANSL: AsNewStandardLine(invoice-id)
    ANSL->>SL: "UsageBased.AppliedUnitConfig = Clone()"
    SL->>UnitMut: GetUnitConfig() → AppliedUnitConfig

    Note over RC,UnitMut: Charges path (reconciler)
    RC->>LM: input.UnitConfig (from charge intent)
    LM->>SL: "stdLine.UsageBased.AppliedUnitConfig = input.UnitConfig"
    SL->>Adapter: UpsertInvoiceLines (SetAppliedUnitConfig if non-nil)
    Adapter-->>SL: Read back (AppliedUnitConfig from DB)
    SL->>UnitMut: GetUnitConfig() → AppliedUnitConfig

    Note over UnitMut: Both paths
    UnitMut->>UnitMut: Validate() guard (prevents corrupt factor divide)
    UnitMut->>SL: Apply(rawMeteredQty) → invoiced Quantity
Loading

Reviews (3): Last reviewed commit: "feat: snapshot unit config on invoice li..." | Re-trigger Greptile

Comment thread test/billing/collection_test.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/billing/adapter_test.go (1)

443-469: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

"Re-upsert keeps the snapshot" test can't actually catch an overwrite regression.

The re-upserted updated line still carries the exact same unitConfig value/pointer as the original, so this assertion would pass identically whether the upsert path truly preserves the existing DB snapshot on conflict, or naively overwrites it with whatever AppliedUnitConfig happens to be on the incoming struct. Since the write-once contract is described as behavioral (the caller never sends a different config), a regression where a caller mistakenly sends a different/nil config on a later upsert wouldn't be caught here.

Consider adding a case where the second upsert carries a different (or nil) AppliedUnitConfig value and asserting the persisted snapshot doesn't change — that would actually exercise the "write-once" guarantee this test's comment describes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/billing/adapter_test.go` around lines 443 - 469, The “re-upserting the
line keeps the snapshot” test is not exercising the overwrite path because the
second upsert reuses the same AppliedUnitConfig as the original line. Update the
test around UpsertInvoiceLines and ListInvoiceLines so the re-upserted
StandardLine carries a different or nil AppliedUnitConfig, then assert the
persisted UsageBased.AppliedUnitConfig still matches the original snapshot. Use
the existing unitConfig and updated line setup to verify the write-once behavior
actually survives a conflicting incoming config.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/billing/collection_test.go`:
- Around line 185-186: The round-trip test uses non-fatal s.NoError(err) before
dereferencing pointer results like created and stdLine, which can lead to nil
panics and hide the real failure. Update the checks in the test around the
created/standard line assertions to use s.Require().NoError(err) in the same
style already used later in the test, so execution stops immediately on error
before accessing created.Lines or stdLine.UsageBased...

---

Nitpick comments:
In `@test/billing/adapter_test.go`:
- Around line 443-469: The “re-upserting the line keeps the snapshot” test is
not exercising the overwrite path because the second upsert reuses the same
AppliedUnitConfig as the original line. Update the test around
UpsertInvoiceLines and ListInvoiceLines so the re-upserted StandardLine carries
a different or nil AppliedUnitConfig, then assert the persisted
UsageBased.AppliedUnitConfig still matches the original snapshot. Use the
existing unitConfig and updated line setup to verify the write-once behavior
actually survives a conflicting incoming config.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: dac6024e-b47d-474b-b639-a3d2b3e3bdbe

📥 Commits

Reviewing files that changed from the base of the PR and between f7f3d35 and db6a1b3.

⛔ Files ignored due to path filters (10)
  • openmeter/ent/db/billinginvoiceusagebasedlineconfig.go is excluded by !**/ent/db/**
  • openmeter/ent/db/billinginvoiceusagebasedlineconfig/billinginvoiceusagebasedlineconfig.go is excluded by !**/ent/db/**
  • openmeter/ent/db/billinginvoiceusagebasedlineconfig/where.go is excluded by !**/ent/db/**
  • openmeter/ent/db/billinginvoiceusagebasedlineconfig_create.go is excluded by !**/ent/db/**
  • openmeter/ent/db/billinginvoiceusagebasedlineconfig_update.go is excluded by !**/ent/db/**
  • openmeter/ent/db/migrate/schema.go is excluded by !**/ent/db/**
  • openmeter/ent/db/mutation.go is excluded by !**/ent/db/**
  • openmeter/ent/db/runtime.go is excluded by !**/ent/db/**
  • openmeter/ent/db/setorclear.go is excluded by !**/ent/db/**
  • tools/migrate/migrations/atlas.sum is excluded by !**/*.sum, !**/*.sum
📒 Files selected for processing (18)
  • .agents/skills/ent/SKILL.md
  • openmeter/billing/adapter/gatheringlines.go
  • openmeter/billing/adapter/stdinvoicelinemapper.go
  • openmeter/billing/adapter/stdinvoicelines.go
  • openmeter/billing/charges/service/unitconfig_rating_test.go
  • openmeter/billing/charges/usagebased/service/linemapper.go
  • openmeter/billing/derived.gen.go
  • openmeter/billing/gatheringinvoice.go
  • openmeter/billing/gatheringinvoice_test.go
  • openmeter/billing/rating/service/mutator/unitconfig.go
  • openmeter/billing/rating/service/mutator/unitconfig_test.go
  • openmeter/billing/stdinvoiceline.go
  • openmeter/billing/worker/subscriptionsync/service/targetstate/targetstateitem.go
  • openmeter/ent/schema/billing.go
  • test/billing/adapter_test.go
  • test/billing/collection_test.go
  • tools/migrate/migrations/20260703084504_applied-unit-config-snapshot.down.sql
  • tools/migrate/migrations/20260703084504_applied-unit-config-snapshot.up.sql

Comment thread test/billing/collection_test.go Outdated
@rolosp rolosp force-pushed the feat/om-398-unit-config-snapshot-on-invoice-lines branch from db6a1b3 to e4592de Compare July 3, 2026 13:34
@rolosp rolosp force-pushed the feat/om-398-unit-config-snapshot-on-invoice-lines branch from e4592de to 61749a1 Compare July 3, 2026 15:30

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
test/billing/unitconfig_legacy_test.go (1)

65-99: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Second clock.FreezeTime call isn't paired with its own UnFreeze.

The coding guidelines call for pairing every clock.FreezeTime(...) with an immediate defer clock.UnFreeze(). Line 65 does this correctly, but the re-freeze at Line 99 has no matching unfreeze call nearby — it just relies on the single deferred unfreeze from earlier. Since UnFreeze is presumably idempotent (just clears the frozen state), this isn't causing a bug here, but it deviates from the stated pattern and could be confusing if someone copies this test as a template.

🕒 Suggested fix
 	// Collect after the line's invoice-at so the completed-period line is billable.
 	clock.FreezeTime(invoiceAt.Add(time.Hour))
+	defer clock.UnFreeze()

As per coding guidelines: "When using clock.FreezeTime(...) in tests, immediately pair it with defer clock.UnFreeze() in the same scope."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/billing/unitconfig_legacy_test.go` around lines 65 - 99, The test has a
second clock.FreezeTime call that is not immediately paired with its own defer
clock.UnFreeze(), which breaks the test pattern. In this test around the
repeated FreezeTime usage in unitconfig_legacy_test.go, add a matching UnFreeze
right after the second freeze so each frozen time scope is self-contained and
consistent with the existing pattern used earlier in the test.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@test/billing/unitconfig_legacy_test.go`:
- Around line 65-99: The test has a second clock.FreezeTime call that is not
immediately paired with its own defer clock.UnFreeze(), which breaks the test
pattern. In this test around the repeated FreezeTime usage in
unitconfig_legacy_test.go, add a matching UnFreeze right after the second freeze
so each frozen time scope is self-contained and consistent with the existing
pattern used earlier in the test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b5ebe7c1-1e3f-473a-856b-67aef41d0354

📥 Commits

Reviewing files that changed from the base of the PR and between e4592de and 61749a1.

⛔ Files ignored due to path filters (10)
  • openmeter/ent/db/billinginvoiceusagebasedlineconfig.go is excluded by !**/ent/db/**
  • openmeter/ent/db/billinginvoiceusagebasedlineconfig/billinginvoiceusagebasedlineconfig.go is excluded by !**/ent/db/**
  • openmeter/ent/db/billinginvoiceusagebasedlineconfig/where.go is excluded by !**/ent/db/**
  • openmeter/ent/db/billinginvoiceusagebasedlineconfig_create.go is excluded by !**/ent/db/**
  • openmeter/ent/db/billinginvoiceusagebasedlineconfig_update.go is excluded by !**/ent/db/**
  • openmeter/ent/db/migrate/schema.go is excluded by !**/ent/db/**
  • openmeter/ent/db/mutation.go is excluded by !**/ent/db/**
  • openmeter/ent/db/runtime.go is excluded by !**/ent/db/**
  • openmeter/ent/db/setorclear.go is excluded by !**/ent/db/**
  • tools/migrate/migrations/atlas.sum is excluded by !**/*.sum, !**/*.sum
📒 Files selected for processing (19)
  • .agents/skills/ent/SKILL.md
  • openmeter/billing/adapter/gatheringlines.go
  • openmeter/billing/adapter/stdinvoicelinemapper.go
  • openmeter/billing/adapter/stdinvoicelines.go
  • openmeter/billing/charges/service/unitconfig_rating_test.go
  • openmeter/billing/charges/usagebased/service/linemapper.go
  • openmeter/billing/derived.gen.go
  • openmeter/billing/gatheringinvoice.go
  • openmeter/billing/gatheringinvoice_test.go
  • openmeter/billing/rating/service/mutator/unitconfig.go
  • openmeter/billing/rating/service/mutator/unitconfig_test.go
  • openmeter/billing/stdinvoiceline.go
  • openmeter/billing/worker/subscriptionsync/service/targetstate/targetstateitem.go
  • openmeter/ent/schema/billing.go
  • test/billing/adapter_test.go
  • test/billing/collection_test.go
  • test/billing/unitconfig_legacy_test.go
  • tools/migrate/migrations/20260703084504_applied-unit-config-snapshot.down.sql
  • tools/migrate/migrations/20260703084504_applied-unit-config-snapshot.up.sql
✅ Files skipped from review due to trivial changes (1)
  • .agents/skills/ent/SKILL.md
🚧 Files skipped from review as they are similar to previous changes (17)
  • openmeter/billing/adapter/stdinvoicelinemapper.go
  • tools/migrate/migrations/20260703084504_applied-unit-config-snapshot.up.sql
  • openmeter/billing/gatheringinvoice_test.go
  • openmeter/billing/charges/usagebased/service/linemapper.go
  • openmeter/billing/charges/service/unitconfig_rating_test.go
  • openmeter/billing/rating/service/mutator/unitconfig.go
  • openmeter/billing/derived.gen.go
  • openmeter/billing/gatheringinvoice.go
  • openmeter/ent/schema/billing.go
  • openmeter/billing/rating/service/mutator/unitconfig_test.go
  • openmeter/billing/stdinvoiceline.go
  • tools/migrate/migrations/20260703084504_applied-unit-config-snapshot.down.sql
  • openmeter/billing/adapter/stdinvoicelines.go
  • openmeter/billing/adapter/gatheringlines.go
  • openmeter/billing/worker/subscriptionsync/service/targetstate/targetstateitem.go
  • test/billing/adapter_test.go
  • test/billing/collection_test.go

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note/misc Miscellaneous changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant