-
Notifications
You must be signed in to change notification settings - Fork 152
refactor: allow single discount per type #2639
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
📝 WalkthroughWalkthroughThe pull request overhauls discount handling across the API schemas, internal data models, and database structures. Old discount types (e.g., BillingDiscount, InvoiceLineDiscount) have been removed or renamed, and new unified types (e.g., BillingDiscounts, Discounts, BillingInvoiceLineUsageDiscount) have been introduced. In addition, conversion functions, OpenAPI definitions, and specification files have been updated accordingly. Database migration scripts now split and restructure invoice-line discount tables, while test code is modified to access discounts via new fields. A new model type (ManagedModelWithID) has also been added to improve identifier handling. Changes
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 golangci-lint (1.64.8)Error: you are using a configuration file for golangci-lint v2 with golangci-lint v1: please use golangci-lint v2 🔧 SQLFluff (3.3.0)tools/migrate/migrations/20250411062903_billing-split-line-discounts.up.sqlUser Error: No dialect was specified. You must configure a dialect or specify one on the command line using --dialect after the command. Available dialects: tools/migrate/migrations/20250411062903_billing-split-line-discounts.down.sqlUser Error: No dialect was specified. You must configure a dialect or specify one on the command line using --dialect after the command. Available dialects: Tip ⚡💬 Agentic Chat (Pro Plan, General Availability)
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
58cfc86 to
fdcdf3e
Compare
ec60da3 to
737fe8b
Compare
c35b3da to
608047a
Compare
3318f3a to
2b03f78
Compare
68f6faa to
85bb524
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🔭 Outside diff range comments (1)
openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (1)
1-192: 💡 Verification agent❓ Verification inconclusive
Missing entity-specific unit tests.
No test code is shown for the newly introducedbillinginvoicelineusagediscountentity. Consider adding unit tests (or integration tests) verifying record creation, validations (ReasonValidator), and relationships (EdgeBillingInvoiceLine).Below is a script to check if tests exist for
billinginvoicelineusagediscountin the codebase:
🏁 Script executed:
#!/bin/bash # Description: Search for tests related to billinginvoicelineusagediscount. fd billinginvoicelineusagediscount_test | xargs catLength of output: 53
Action Required: Add Unit and Integration Tests for the billinginvoicelineusagediscount Entity
The codebase scan did not reveal any tests (e.g., *_test.go files referencingbillinginvoicelineusagediscountor related identifiers). To ensure robust coverage, please add tests that verify:
- Record Creation: Validate default values (e.g.,
DefaultCreatedAt,DefaultUpdatedAt, etc.) and proper data insertion for the entity.- Validations: Confirm that
ReasonValidatorproperly accepts the allowed enum values ("maximum_spend","ratecard_percentage","ratecard_usage") and rejects invalid ones.- Relationships: Test the handling of the relationship edge (
EdgeBillingInvoiceLine) to ensure the entity correctly links with the billing invoice line and related entities.
🧹 Nitpick comments (40)
openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (1)
87-91: ValidColumn function now handles special fields differently.The function has been updated to check additional fields that aren't included in the main Columns slice. While functional, this creates an inconsistency in how column validation is handled.
Consider whether these fields should be included directly in the Columns slice for consistency, though I understand this may be constrained by the code generation patterns.
openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (2)
15-72: Check table naming and single discount per type enforcement.
The table name isbilling_invoice_line_usage_discounts, implying that multiple records can exist for each line. Since the PR aims to enforce only one discount entry per type, ensure that database constraints or application logic prevent multiple usage-discount records of the same type from being inserted.Would you like guidance on adding uniqueness constraints in Ent to guarantee only a single usage discount per type and line?
84-95: Add validation for ReasonDetails if applicable.
TheValueScannerincludesReasonDetailsbut there's currently no validation function for it. If you need to enforce constraints (e.g., max length, allowed characters), consider adding a validator similar toNamespaceValidator.openmeter/billing/httpdriver/invoiceline.go (1)
428-490: Consider revising the error message for usage discounts.
Inside the usage discount mapping block (lines 462-487), the error at line 483 logs "failed to map amount discounts" instead of "failed to map usage discounts."- return nil, fmt.Errorf("failed to map amount discounts: %w", err) + return nil, fmt.Errorf("failed to map usage discounts: %w", err)api/openapi.yaml (9)
10585-10606: Improve Correlation ID Description Clarity
The description for the correlation ID field (lines 10588–10600) is quite verbose and contains a grammatical issue (“setups the discount amounts” should be rephrased). Consider simplifying and clarifying this text; for example:“If not provided, the invoicing engine will auto‐generate one. When editing an invoice line, ensure that the correlation ID remains unchanged to prevent discount amount inaccuracies.”
10624-10644: Standardize Correlation ID Guidance for Usage Discounts
The correlation ID guidance (lines 10627–10629) is very similar to that used elsewhere. To promote consistency and reduce duplication, consider standardizing this wording across discount types.
12179-12203: Enhance Clarity for Ratecard Percentage Discount Details
For the DiscountReasonRatecardPercentage schema, the addedcorrelationIdand its detailed description are helpful. However, the text could be simplified and the grammatical error (“setups” should be “setup”) corrected. A revised version might read:“Correlation ID for the discount. If not provided, the invoicing engine will auto‐generate one. When editing an invoice line, maintain the same correlation ID to ensure accurate discount amounts.”
12209-12234: Review DiscountReasonRatecardUsage Schema Consistency
The DiscountReasonRatecardUsage schema (lines 12209–12234) mirrors the structure of its percentage counterpart. The inclusion ofquantityandcorrelationIdis consistent. As with the previous schema, consider refining the long description for clarity and consistency.
14430-14437: Correct Typo in Discounts Description
The description in line 14436 contains a typo ("detailes"). Please correct it to "details" to maintain professionalism.
14810-14852: Review InvoiceLineDiscounts Structure and Terminology
The InvoiceLineDiscounts schema (lines 14810–14852) now features arrays for both amount- and usage-based discounts. The structure is clear; however, review the use of “deduced” in the descriptions to ensure it accurately reflects the business logic—if the intention is to imply “deducted,” that change might be necessary.
14934-15008: Grammar Correction in InvoiceLineUsageDiscount Description
In the InvoiceLineUsageDiscount schema (lines 14934–15008), the description states “represents an usage-based discount.” This should be corrected to “represents a usage-based discount.”
15552-15559: Fix Typo in Repeated Discounts Description
The typo “detailes” appears again in the description (line 15558). Please fix it to “details.”
15837-15844: Minor Rephrase for Usage-Based Rate Card Description
In the InvoiceUsageBasedRateCard schema (lines 15837–15844), change “an usage-based line” to “a usage-based line” to correct the article usage.openmeter/ent/db/migrate/schema.go (2)
777-783: Rename 'type' field for clarity & ensure references are updated
The newly introduced"type"field here might be ambiguous in the broader context. Consider renaming it to something like"discount_type"to avoid collisions with other"type"fields and to improve clarity. Also ensure that all references in application code and migrations are updated accordingly.- {Name: "type", Type: field.TypeString, Nullable: true}, + {Name: "discount_type", Type: field.TypeString, Nullable: true},
826-879: New usage-based discounts table
This new table cleanly separates usage-based discounts from amount-based discounts, aligning with the single discount per type objective. The schema fields appear consistent.
As an optional improvement, consider matching naming conventions (e.g., adding adiscount_typefield or grouping some fields under one JSON structure) for uniformity with the existing discount table.api/openapi.cloud.yaml (11)
10759-10778: Clarify Correlation ID Text and BillingDiscountReason Structure.
The updated description for auto-generating a correlation ID is helpful, but the phrase “setups the discount amounts might be incorrect” is unclear. Consider rephrasing it (e.g., “otherwise, the discount amounts might be incorrect”) for better clarity. Additionally, the newBillingDiscountReasonschema using aoneOfconstruct and discriminator is well structured.
10797-10816: Consolidate Discount Types Using BillingDiscounts.
The addition of theBillingDiscountsschema—which encapsulates both percentage and usage discounts—is a clear step toward the single discount per type objective. To improve consistency, consider revising the repeated correlation ID text (especially the unclear “setups” wording) across similar descriptions.
12275-12298: Verify DiscountPercentage and DiscountReasonMaximumSpend Schemas.
The newDiscountPercentageschema effectively constrains the percentage value, andDiscountReasonMaximumSpendis clearly set up with an enum. Ensure that any additional documentation or examples elsewhere in the API clarify their intended usage.
12304-12328: Ensure Clarity in DiscountReasonRatecardPercentage.
The schema for a ratecard percentage discount is well defined with properties for type, percentage, and a correlationId. However, the correlationId’s description repeats the unclear phrasing regarding auto-generation. A clearer wording and a verification of the regex pattern’s correctness are recommended.
12334-12363: Review DiscountReasonRatecardUsage and DiscountUsage Schemas.
TheDiscountReasonRatecardUsageschema mirrors the ratecard percentage structure, including a correlationId with similar descriptive text. The subsequent minimalDiscountUsageschema is acceptable; however, double-check that the “quantity” requirement (noting it must be positive) is captured consistently in both documentation and schema constraints.
14362-14369: Fix Typographical Error in Discount Description.
The description reads “Discounts detailes applied to this line.” Please correct “detailes” to “details” for clarity.
14866-14940: Review InvoiceLineUsageDiscount Schema for Completeness.
TheInvoiceLineUsageDiscountschema is detailed and includes all necessary fields such as timestamps, IDs, and references to external IDs. Note the grammatical error “an usage-based discount” (should be “a usage-based discount”) and consider revising it. Also, verify that the explanation forpreLinePeriodQuantityis unambiguous.
15484-15491: Correct Typo in Discount Details Description.
Similar to an earlier comment, the description “Discounts detailes applied to this line.” contains a typographical error. Please change “detailes” to “details.”
15769-15776: Review InvoiceUsageBasedRateCard Discount Integration.
TheInvoiceUsageBasedRateCardschema now includes adiscountsproperty referencingBillingDiscounts. Correct the grammatical error (“an usage-based line” should be “a usage-based line”) and ensure that the discount information is applied consistently with the overall model changes.
17785-17792: Verify Discount Schema Usage in Example Configuration.
In this example configuration, thediscountsfield now references theDiscountsschema (instead ofBillingDiscounts). Confirm that this is intentional for flat fee rate cards—especially given the comment that only percentage discounts are supported when the price is set—and that the provided example values (e.g., amount: '100') appropriately reflect real-world usage.
19214-19221: Validate Nested Discount Field within Price Object.
Thediscountsproperty within the Price object uses theDiscountsschema and is properly titled. To further aid API consumers, consider providing a concrete example (beyond an empty object) if applicable.openmeter/billing/service/lineservice/discountpercentage.go (1)
54-66: Add brief documentation on CorrelationID usage.
The logic to return an error ifCorrelationIDis missing is valid. Consider adding a short doc comment explaining "CorrelationID" to maintainers.openmeter/billing/adapter/invoicelinediff.go (3)
64-72: Typo in type aliases.
Consider renaming "Manged" to "Managed" for clarity and consistency.-usageLineDiscountMangedWithLine +usageLineDiscountManagedWithLine -amountLineDiscountMangedWithLine +amountLineDiscountManagedWithLine
80-81: Separate diffs for usage and amount discounts.
Storing them individually improves clarity in the single-discount-per-type flow. Just be mindful of the “Managed” spelling in the type aliases.
388-421: Versatile discount handling logic.
Splitting logic by operation (create, delete, update) is straightforward. Consider adefaultcase if new operations arise.openmeter/ent/schema/billing.go (1)
543-555: Refactoring for the future rename.
There's a TODO about renaming this struct. If a rename is still planned, consider coordinating it with related table/entity names to avoid confusion.Do you want me to open an issue to track this rename for a subsequent release?
openmeter/ent/db/billinginvoicelinediscount_update.go (5)
128-132: Setter for InvoicingAppExternalID is properly aligned with the typical ent pattern.
Consider whether an additional validation (e.g., length or format) is needed.
194-198: Setter for the 'type' field.
Marked as deprecated; if usage is minimal, consider removing it in a future refactor.
200-206: Nillable setter for deprecated 'type'.
Continues the existing pattern but reevaluate usage of this deprecated field.
391-396: Handles the (deprecated) type field in the SQL update.
Implementation is fine, but consider removing this logic once the field is fully phased out.
845-847: Retrieves 'type' from mutation and sets it in the UpdateOne flow.
Again, watch for usage in future cleanups.openmeter/ent/db/billinginvoicelineusagediscount_create.go (3)
193-200: Use caution with SaveX in production
SaveXpanics on error, which can be disruptive in production if not carefully handled. Consider usingSaveand returning the error for a more graceful approach.
251-257: Consider enforcing single discount per reason typeThe check enforces that
reasonmust be set, but there's no unique constraint on(line_id, reason). To guarantee only one discount per reason type per line, consider adding a unique database constraint in the Ent schema.
817-844: Caution with ID retrieval on MySQL upsertMySQL doesn't support returning string IDs in upsert scenarios. If you rely on retrieving the ID to continue processing, consider an alternative database or logic path to handle ID lookups after conflict resolution.
openmeter/ent/db/billinginvoicelinediscount_create.go (1)
117-121: Consider adding validation forInvoicingAppExternalID.
If this field has a prescribed format or length limits, a validator would improve data integrity.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
tools/migrate/migrations/atlas.sumis excluded by!**/*.sum
📒 Files selected for processing (96)
api/client/javascript/src/client/schemas.ts(20 hunks)api/convert.gen.go(0 hunks)api/openapi.cloud.yaml(19 hunks)api/openapi.yaml(20 hunks)api/spec/src/billing/invoices/discounts.tsp(4 hunks)api/spec/src/billing/invoices/invoice.tsp(3 hunks)api/spec/src/productcatalog/discounts.tsp(1 hunks)api/spec/src/productcatalog/ratecards.tsp(2 hunks)api/spec/src/productcatalog/subscription.tsp(2 hunks)e2e/productcatalog_test.go(4 hunks)openmeter/app/stripe/entity/app/invoice.go(2 hunks)openmeter/billing/adapter/invoicelinediff.go(2 hunks)openmeter/billing/adapter/invoicelinediff_test.go(16 hunks)openmeter/billing/adapter/invoicelinemapper.go(2 hunks)openmeter/billing/adapter/invoicelineprogressive.go(2 hunks)openmeter/billing/adapter/invoicelines.go(5 hunks)openmeter/billing/app.go(1 hunks)openmeter/billing/discount.go(4 hunks)openmeter/billing/httpdriver/deprecations.go(2 hunks)openmeter/billing/httpdriver/discounts.go(1 hunks)openmeter/billing/httpdriver/invoiceline.go(1 hunks)openmeter/billing/invoiceline.go(1 hunks)openmeter/billing/invoicelinediscount.go(9 hunks)openmeter/billing/service/discounts.go(1 hunks)openmeter/billing/service/lineservice/discountpercentage.go(3 hunks)openmeter/billing/service/lineservice/feeline.go(3 hunks)openmeter/billing/service/lineservice/feeline_test.go(2 hunks)openmeter/billing/service/lineservice/pricedynamic_test.go(1 hunks)openmeter/billing/service/lineservice/pricegraduatedtiered_test.go(1 hunks)openmeter/billing/service/lineservice/pricepackage_test.go(1 hunks)openmeter/billing/service/lineservice/priceunit_test.go(3 hunks)openmeter/billing/service/lineservice/pricevolumetiered_test.go(1 hunks)openmeter/billing/service/lineservice/usagebasedline.go(2 hunks)openmeter/billing/service/lineservice/usagebasedline_test.go(5 hunks)openmeter/ent/db/addonratecard_create.go(1 hunks)openmeter/ent/db/addonratecard_update.go(2 hunks)openmeter/ent/db/billinginvoicediscount.go(0 hunks)openmeter/ent/db/billinginvoicediscount/billinginvoicediscount.go(0 hunks)openmeter/ent/db/billinginvoicediscount/where.go(0 hunks)openmeter/ent/db/billinginvoicediscount_create.go(0 hunks)openmeter/ent/db/billinginvoicediscount_delete.go(0 hunks)openmeter/ent/db/billinginvoicediscount_query.go(0 hunks)openmeter/ent/db/billinginvoicediscount_update.go(0 hunks)openmeter/ent/db/billinginvoiceline.go(6 hunks)openmeter/ent/db/billinginvoiceline/billinginvoiceline.go(4 hunks)openmeter/ent/db/billinginvoiceline/where.go(1 hunks)openmeter/ent/db/billinginvoiceline_create.go(3 hunks)openmeter/ent/db/billinginvoiceline_query.go(10 hunks)openmeter/ent/db/billinginvoiceline_update.go(9 hunks)openmeter/ent/db/billinginvoicelinediscount.go(5 hunks)openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go(6 hunks)openmeter/ent/db/billinginvoicelinediscount/where.go(4 hunks)openmeter/ent/db/billinginvoicelinediscount_create.go(12 hunks)openmeter/ent/db/billinginvoicelinediscount_update.go(8 hunks)openmeter/ent/db/billinginvoicelineusagediscount.go(1 hunks)openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go(1 hunks)openmeter/ent/db/billinginvoicelineusagediscount/where.go(1 hunks)openmeter/ent/db/billinginvoicelineusagediscount_create.go(1 hunks)openmeter/ent/db/billinginvoicelineusagediscount_delete.go(1 hunks)openmeter/ent/db/billinginvoicelineusagediscount_query.go(1 hunks)openmeter/ent/db/billinginvoicelineusagediscount_update.go(1 hunks)openmeter/ent/db/client.go(11 hunks)openmeter/ent/db/ent.go(2 hunks)openmeter/ent/db/expose.go(1 hunks)openmeter/ent/db/hook/hook.go(1 hunks)openmeter/ent/db/migrate/schema.go(5 hunks)openmeter/ent/db/paginate.go(5 hunks)openmeter/ent/db/planratecard_create.go(1 hunks)openmeter/ent/db/planratecard_update.go(2 hunks)openmeter/ent/db/predicate/predicate.go(1 hunks)openmeter/ent/db/runtime.go(2 hunks)openmeter/ent/db/setorclear.go(3 hunks)openmeter/ent/db/subscriptionitem_create.go(1 hunks)openmeter/ent/db/subscriptionitem_update.go(2 hunks)openmeter/ent/db/tx.go(2 hunks)openmeter/ent/schema/billing.go(6 hunks)openmeter/ent/schema/productcatalog.go(0 hunks)openmeter/productcatalog/addon/ratecard_test.go(1 hunks)openmeter/productcatalog/discount.go(3 hunks)openmeter/productcatalog/discount_test.go(3 hunks)openmeter/productcatalog/http/mapping.go(5 hunks)openmeter/productcatalog/plan/ratecard_test.go(1 hunks)openmeter/productcatalog/ratecard.go(4 hunks)openmeter/productcatalog/ratecard_test.go(9 hunks)openmeter/productcatalog/subscription/http/mapping.go(1 hunks)openmeter/productcatalog/subscription/service/plan_test.go(1 hunks)openmeter/subscription/repo/mapping.go(1 hunks)openmeter/subscription/repo/subscriptionitemrepo.go(1 hunks)openmeter/subscription/testutils/ratecard.go(1 hunks)pkg/models/model.go(1 hunks)test/app/stripe/invoice_test.go(1 hunks)test/billing/adapter_test.go(3 hunks)test/billing/discount_test.go(4 hunks)test/billing/invoice_test.go(8 hunks)tools/migrate/migrations/20250411062903_billing-split-line-discounts.down.sql(1 hunks)tools/migrate/migrations/20250411062903_billing-split-line-discounts.up.sql(1 hunks)
💤 Files with no reviewable changes (9)
- openmeter/ent/schema/productcatalog.go
- api/convert.gen.go
- openmeter/ent/db/billinginvoicediscount/where.go
- openmeter/ent/db/billinginvoicediscount_update.go
- openmeter/ent/db/billinginvoicediscount_delete.go
- openmeter/ent/db/billinginvoicediscount_query.go
- openmeter/ent/db/billinginvoicediscount_create.go
- openmeter/ent/db/billinginvoicediscount.go
- openmeter/ent/db/billinginvoicediscount/billinginvoicediscount.go
🧰 Additional context used
🧬 Code Graph Analysis (55)
openmeter/subscription/repo/mapping.go (5)
openmeter/billing/discount.go (1)
Discounts(78-81)api/client/javascript/src/client/schemas.ts (1)
Discounts(9386-9386)api/api.gen.go (1)
Discounts(2020-2026)openmeter/productcatalog/discount.go (1)
Discounts(113-116)api/client/go/client.gen.go (1)
Discounts(1891-1897)
openmeter/ent/db/predicate/predicate.go (2)
openmeter/ent/db/billinginvoicelineusagediscount.go (2)
BillingInvoiceLineUsageDiscount(19-51)BillingInvoiceLineUsageDiscount(74-93)openmeter/ent/schema/billing.go (5)
BillingInvoiceLineUsageDiscount(627-629)BillingInvoiceLineUsageDiscount(631-638)BillingInvoiceLineUsageDiscount(640-664)BillingInvoiceLineUsageDiscount(666-675)BillingInvoiceLineUsageDiscount(677-685)
test/app/stripe/invoice_test.go (7)
openmeter/billing/discount.go (1)
Discounts(78-81)api/api.gen.go (1)
Discounts(2020-2026)openmeter/productcatalog/discount.go (1)
Discounts(113-116)api/client/go/client.gen.go (1)
Discounts(1891-1897)openmeter/ent/db/billinginvoiceline/where.go (2)
Amount(102-104)Description(97-99)openmeter/ent/db/billinginvoicelinediscount/where.go (2)
Amount(111-113)Description(101-103)openmeter/ent/db/billinginvoicelineusagediscount/where.go (1)
Description(101-103)
openmeter/ent/db/expose.go (4)
openmeter/ent/db/billinginvoicelineusagediscount.go (2)
BillingInvoiceLineUsageDiscount(19-51)BillingInvoiceLineUsageDiscount(74-93)openmeter/ent/db/predicate/predicate.go (1)
BillingInvoiceLineUsageDiscount(93-93)openmeter/ent/schema/billing.go (5)
BillingInvoiceLineUsageDiscount(627-629)BillingInvoiceLineUsageDiscount(631-638)BillingInvoiceLineUsageDiscount(640-664)BillingInvoiceLineUsageDiscount(666-675)BillingInvoiceLineUsageDiscount(677-685)openmeter/ent/db/client.go (1)
NewBillingInvoiceLineUsageDiscountClient(2921-2923)
openmeter/billing/adapter/invoicelineprogressive.go (5)
openmeter/ent/db/billinginvoicelinediscount_query.go (1)
BillingInvoiceLineDiscountQuery(21-32)openmeter/ent/db/billinginvoiceline/where.go (1)
DeletedAtIsNil(398-400)openmeter/ent/db/billinginvoicelinediscount/where.go (1)
DeletedAtIsNil(321-323)openmeter/ent/db/billinginvoicelineusagediscount/where.go (1)
DeletedAtIsNil(306-308)openmeter/ent/db/billinginvoicelineusagediscount_query.go (1)
BillingInvoiceLineUsageDiscountQuery(21-32)
openmeter/productcatalog/subscription/http/mapping.go (6)
api/api.gen.go (3)
Discounts(2020-2026)SubscriptionItem(5695-5755)RateCard(4980-4982)openmeter/productcatalog/discount.go (1)
Discounts(113-116)openmeter/productcatalog/http/mapping.go (1)
FromDiscounts(320-339)openmeter/subscription/item.go (1)
SubscriptionItem(9-39)openmeter/ent/db/subscriptionitem.go (2)
SubscriptionItem(21-71)SubscriptionItem(129-154)openmeter/productcatalog/ratecard.go (1)
RateCard(27-38)
test/billing/discount_test.go (3)
openmeter/billing/discount.go (3)
PercentageDiscount(24-28)Discounts(78-81)UsageDiscount(49-53)openmeter/productcatalog/discount.go (3)
PercentageDiscount(21-24)Discounts(113-116)UsageDiscount(60-62)openmeter/billing/invoiceline.go (1)
Line(279-293)
openmeter/billing/service/lineservice/usagebasedline_test.go (2)
openmeter/billing/discount.go (3)
Discounts(78-81)NewDiscountReasonFrom(154-191)MaximumSpendDiscount(145-145)openmeter/billing/invoicelinediscount.go (4)
LineDiscounts(312-315)AmountLineDiscountManaged(104-107)AmountLineDiscount(56-64)LineDiscountBase(22-27)
openmeter/billing/httpdriver/discounts.go (3)
openmeter/productcatalog/http/mapping.go (3)
AsDiscounts(523-545)AsPercentageDiscount(558-562)AsUsageDiscount(547-556)api/api.gen.go (3)
BillingDiscounts(1089-1095)Discounts(2020-2026)Percentage(4688-4688)openmeter/productcatalog/discount.go (3)
Discounts(113-116)PercentageDiscount(21-24)UsageDiscount(60-62)
openmeter/ent/db/tx.go (4)
openmeter/ent/db/billinginvoicelineusagediscount.go (2)
BillingInvoiceLineUsageDiscount(19-51)BillingInvoiceLineUsageDiscount(74-93)openmeter/ent/db/predicate/predicate.go (1)
BillingInvoiceLineUsageDiscount(93-93)openmeter/ent/schema/billing.go (5)
BillingInvoiceLineUsageDiscount(627-629)BillingInvoiceLineUsageDiscount(631-638)BillingInvoiceLineUsageDiscount(640-664)BillingInvoiceLineUsageDiscount(666-675)BillingInvoiceLineUsageDiscount(677-685)openmeter/ent/db/client.go (2)
BillingInvoiceLineUsageDiscountClient(2916-2918)NewBillingInvoiceLineUsageDiscountClient(2921-2923)
openmeter/ent/db/runtime.go (1)
openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (1)
ValueScanner(96-98)
openmeter/ent/db/hook/hook.go (2)
openmeter/ent/db/mutation.go (1)
BillingInvoiceLineUsageDiscountMutation(18699-18721)openmeter/ent/db/ent.go (2)
Value(64-64)Mutation(75-75)
openmeter/productcatalog/ratecard.go (4)
openmeter/billing/discount.go (1)
Discounts(78-81)api/api.gen.go (1)
Discounts(2020-2026)openmeter/productcatalog/discount.go (1)
Discounts(113-116)api/client/go/client.gen.go (1)
Discounts(1891-1897)
openmeter/billing/service/lineservice/feeline_test.go (3)
openmeter/billing/discount.go (2)
PercentageDiscount(24-28)Discounts(78-81)openmeter/productcatalog/discount.go (2)
PercentageDiscount(21-24)Discounts(113-116)openmeter/billing/invoicelinediscount.go (3)
LineDiscounts(312-315)AmountLineDiscount(56-64)LineDiscountBase(22-27)
openmeter/ent/db/subscriptionitem_update.go (3)
openmeter/billing/discount.go (1)
Discounts(78-81)api/api.gen.go (1)
Discounts(2020-2026)pkg/models/validator.go (1)
Validate(16-26)
openmeter/productcatalog/http/mapping.go (5)
openmeter/billing/discount.go (1)
Discounts(78-81)api/api.gen.go (4)
Discounts(2020-2026)DiscountUsage(2012-2017)Percentage(4688-4688)DiscountPercentage(1954-1957)openmeter/productcatalog/discount.go (1)
Discounts(113-116)api/client/go/client.gen.go (4)
Discounts(1891-1897)DiscountUsage(1883-1888)Percentage(4384-4384)DiscountPercentage(1825-1828)openmeter/billing/httpdriver/discounts.go (3)
AsDiscounts(34-64)AsUsageDiscount(20-32)AsPercentageDiscount(13-18)
openmeter/billing/adapter/invoicelinemapper.go (4)
openmeter/billing/discount.go (3)
Discounts(78-81)MaximumSpendDiscountReason(131-131)MaximumSpendDiscount(145-145)openmeter/ent/db/billinginvoicelineusagediscount.go (2)
BillingInvoiceLineUsageDiscount(19-51)BillingInvoiceLineUsageDiscount(74-93)openmeter/billing/invoicelinediscount.go (3)
UsageLineDiscountManaged(254-257)LineDiscountBase(22-27)UsageLineDiscount(205-210)openmeter/billing/invoiceline.go (1)
LineExternalIDs(235-237)
test/billing/adapter_test.go (2)
openmeter/billing/discount.go (4)
Discounts(78-81)NewDiscountReasonFrom(154-191)MaximumSpendDiscount(145-145)PercentageDiscount(24-28)openmeter/billing/invoicelinediscount.go (4)
LineDiscounts(312-315)AmountLineDiscountManaged(104-107)AmountLineDiscount(56-64)LineDiscountBase(22-27)
openmeter/billing/service/discounts.go (3)
api/api.gen.go (2)
Percentage(4688-4688)Discounts(2020-2026)openmeter/billing/discount.go (1)
Discounts(78-81)openmeter/productcatalog/discount.go (1)
Discounts(113-116)
openmeter/productcatalog/ratecard_test.go (2)
pkg/models/percentage.go (2)
Percentage(9-11)NewPercentage(15-28)openmeter/productcatalog/discount.go (2)
PercentageDiscount(21-24)UsageDiscount(60-62)
openmeter/billing/service/lineservice/priceunit_test.go (2)
openmeter/billing/discount.go (4)
Discounts(78-81)NewDiscountReasonFrom(154-191)MaximumSpendDiscount(145-145)PercentageDiscount(24-28)openmeter/billing/invoicelinediscount.go (4)
LineDiscounts(312-315)AmountLineDiscountManaged(104-107)AmountLineDiscount(56-64)LineDiscountBase(22-27)
openmeter/ent/db/billinginvoicelinediscount.go (4)
openmeter/billing/discount.go (3)
DiscountReasonType(128-128)DiscountReasonType(136-142)DiscountReason(147-152)openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (9)
FieldRoundingAmount(41-41)FieldQuantity(47-47)FieldPreLinePeriodQuantity(49-49)FieldAmount(39-39)FieldReason(35-35)FieldInvoicingAppExternalID(37-37)FieldType(45-45)FieldSourceDiscount(43-43)ValueScanner(107-109)openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (5)
FieldQuantity(67-67)FieldAmount(35-35)FieldInvoicingAppExternalID(73-73)FieldType(61-61)ValueScanner(249-251)openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (5)
FieldQuantity(39-39)FieldPreLinePeriodQuantity(41-41)FieldReason(35-35)FieldInvoicingAppExternalID(37-37)ValueScanner(96-98)
openmeter/ent/db/billinginvoicelineusagediscount_query.go (4)
openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (3)
OrderOption(112-112)FieldID(19-19)FieldLineID(29-29)openmeter/ent/db/billinginvoiceline_query.go (1)
BillingInvoiceLineQuery(29-50)openmeter/ent/db/billinginvoiceline/where.go (3)
Name(92-94)IDIn(32-34)ID(17-19)openmeter/ent/db/billinginvoicelineusagediscount/where.go (3)
LineID(91-93)IDIn(31-33)ID(16-18)
openmeter/billing/httpdriver/invoiceline.go (3)
openmeter/billing/invoicelinediscount.go (3)
LineDiscounts(312-315)AmountLineDiscountManaged(104-107)UsageLineDiscountManaged(254-257)api/api.gen.go (6)
InvoiceLineDiscounts(3380-3390)InvoiceLineAmountDiscount(3344-3368)InvoiceLineAppExternalIds(3371-3377)InvoiceLineUsageDiscount(3441-3470)BillingDiscountReason(1067-1069)Percentage(4688-4688)openmeter/billing/discount.go (4)
DiscountReason(147-152)MaximumSpendDiscountReason(131-131)RatecardPercentageDiscountReason(132-132)RatecardUsageDiscountReason(133-133)
openmeter/billing/service/lineservice/pricegraduatedtiered_test.go (2)
openmeter/billing/discount.go (3)
Discounts(78-81)NewDiscountReasonFrom(154-191)MaximumSpendDiscount(145-145)openmeter/billing/invoicelinediscount.go (5)
LineDiscounts(312-315)AmountLineDiscountManaged(104-107)AmountLineDiscount(56-64)LineDiscountBase(22-27)LineMaximumSpendReferenceID(19-19)
openmeter/ent/db/billinginvoiceline_query.go (5)
openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (1)
OrderOption(285-285)openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (1)
OrderOption(123-123)openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (1)
OrderOption(112-112)openmeter/ent/db/billinginvoicelineusagediscount_query.go (1)
BillingInvoiceLineUsageDiscountQuery(21-32)openmeter/ent/db/billinginvoicelinediscount_query.go (1)
BillingInvoiceLineDiscountQuery(21-32)
openmeter/billing/discount.go (1)
openmeter/productcatalog/discount.go (3)
Discounts(113-116)PercentageDiscount(21-24)UsageDiscount(60-62)
openmeter/ent/db/ent.go (5)
openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (2)
Table(53-53)ValidColumn(81-93)openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (2)
Table(47-47)ValidColumn(75-82)openmeter/ent/db/billinginvoiceusagebasedlineconfig/billinginvoiceusagebasedlineconfig.go (2)
Table(31-31)ValidColumn(46-53)openmeter/ent/db/billinginvoice/billinginvoice.go (2)
Table(142-142)ValidColumn(260-267)openmeter/ent/db/billinginvoiceflatfeelineconfig/billinginvoiceflatfeelineconfig.go (2)
Table(27-27)ValidColumn(40-47)
openmeter/productcatalog/discount_test.go (3)
api/api.gen.go (2)
Discounts(2020-2026)Percentage(4688-4688)openmeter/productcatalog/discount.go (3)
Discounts(113-116)PercentageDiscount(21-24)UsageDiscount(60-62)api/client/go/client.gen.go (2)
Discounts(1891-1897)Percentage(4384-4384)
openmeter/billing/adapter/invoicelines.go (2)
openmeter/ent/db/billinginvoicelineusagediscount_create.go (1)
BillingInvoiceLineUsageDiscountCreate(22-27)openmeter/ent/db/billinginvoicelinediscount_create.go (1)
BillingInvoiceLineDiscountCreate(22-27)
openmeter/ent/db/billinginvoiceline/where.go (3)
openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (5)
Table(105-105)LineUsageDiscountsTable(136-136)LineUsageDiscountsColumn(141-141)LineAmountDiscountsTable(143-143)LineAmountDiscountsColumn(148-148)openmeter/ent/db/billinginvoicelineusagediscount.go (2)
BillingInvoiceLineUsageDiscount(19-51)BillingInvoiceLineUsageDiscount(74-93)openmeter/ent/db/billinginvoicelinediscount.go (2)
BillingInvoiceLineDiscount(19-63)BillingInvoiceLineDiscount(86-105)
openmeter/billing/service/lineservice/discountpercentage.go (4)
openmeter/billing/discount.go (2)
Discounts(78-81)PercentageDiscount(24-28)api/api.gen.go (2)
Discounts(2020-2026)Percentage(4688-4688)openmeter/productcatalog/discount.go (2)
Discounts(113-116)PercentageDiscount(21-24)openmeter/billing/invoicelinediscount.go (2)
AmountLineDiscountManaged(104-107)AmountLineDiscount(56-64)
openmeter/ent/db/billinginvoiceline_create.go (3)
openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (6)
Table(105-105)LineUsageDiscountsTable(136-136)LineUsageDiscountsColumn(141-141)FieldID(19-19)LineAmountDiscountsTable(143-143)LineAmountDiscountsColumn(148-148)openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (2)
Table(53-53)FieldID(19-19)openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (2)
Table(47-47)FieldID(19-19)
openmeter/billing/adapter/invoicelinediff_test.go (4)
openmeter/billing/discount.go (1)
Discounts(78-81)openmeter/productcatalog/discount.go (1)
Discounts(113-116)openmeter/billing/invoicelinediscount.go (3)
AmountLineDiscountManaged(104-107)LineDiscounts(312-315)AmountLineDiscount(56-64)pkg/models/model.go (1)
ManagedModelWithID(155-158)
openmeter/ent/schema/billing.go (2)
openmeter/ent/db/billinginvoicelineusagediscount.go (2)
BillingInvoiceLineUsageDiscount(19-51)BillingInvoiceLineUsageDiscount(74-93)openmeter/ent/db/billinginvoicelinediscount.go (2)
BillingInvoiceLineDiscount(19-63)BillingInvoiceLineDiscount(86-105)
openmeter/ent/db/migrate/schema.go (3)
openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (1)
Columns(173-206)openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (1)
Columns(64-78)openmeter/ent/db/billinginvoice/billinginvoice.go (1)
Columns(202-257)
openmeter/ent/db/billinginvoicelineusagediscount_delete.go (4)
openmeter/ent/db/ent.go (3)
IsConstraintError(361-367)ConstraintError(345-348)NotFoundError(278-280)openmeter/ent/db/mutation.go (1)
BillingInvoiceLineUsageDiscountMutation(18699-18721)openmeter/ent/db/predicate/predicate.go (1)
BillingInvoiceLineUsageDiscount(93-93)openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (3)
Table(47-47)FieldID(19-19)Label(17-17)
openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (3)
openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (5)
FieldReason(35-35)FieldInvoicingAppExternalID(37-37)ReasonValidator(102-109)OrderOption(112-112)ByInvoicingAppExternalID(160-162)openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (4)
FieldInvoicingAppExternalID(73-73)FieldType(61-61)OrderOption(285-285)ByInvoicingAppExternalID(413-415)openmeter/billing/discount.go (3)
DiscountReason(147-152)DiscountReasonType(128-128)DiscountReasonType(136-142)
openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (3)
openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (10)
FieldID(19-19)FieldNamespace(21-21)FieldCreatedAt(25-25)FieldUpdatedAt(27-27)FieldDeletedAt(29-29)FieldChildUniqueReferenceID(75-75)FieldDescription(33-33)FieldInvoicingAppExternalID(73-73)FieldQuantity(67-67)Columns(173-206)openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (14)
FieldID(19-19)FieldNamespace(21-21)FieldCreatedAt(23-23)FieldUpdatedAt(25-25)FieldDeletedAt(27-27)FieldLineID(29-29)FieldChildUniqueReferenceID(31-31)FieldDescription(33-33)FieldReason(35-35)FieldInvoicingAppExternalID(37-37)FieldQuantity(47-47)FieldPreLinePeriodQuantity(49-49)Columns(64-78)ReasonValidator(113-120)openmeter/billing/discount.go (3)
DiscountReason(147-152)DiscountReasonType(128-128)DiscountReasonType(136-142)
e2e/productcatalog_test.go (4)
api/api.gen.go (3)
DiscountPercentage(1954-1957)Percentage(4688-4688)Discounts(2020-2026)pkg/models/percentage.go (2)
Percentage(9-11)NewPercentage(15-28)openmeter/billing/discount.go (1)
Discounts(78-81)openmeter/productcatalog/discount.go (1)
Discounts(113-116)
openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (1)
openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (3)
OrderOption(112-112)Table(47-47)FieldID(19-19)
openmeter/productcatalog/discount.go (6)
openmeter/billing/discount.go (1)
PercentageDiscount(24-28)pkg/models/percentage.go (1)
Percentage(9-11)pkg/models/error.go (1)
NewNillableGenericValidationError(129-135)openmeter/productcatalog/price.go (1)
Price(84-91)pkg/models/equaler.go (1)
Equaler(3-6)pkg/models/clonable.go (1)
Clonable(3-5)
openmeter/ent/db/billinginvoicelineusagediscount.go (1)
openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (15)
Label(17-17)FieldPreLinePeriodQuantity(41-41)FieldQuantity(39-39)FieldID(19-19)FieldNamespace(21-21)FieldLineID(29-29)FieldChildUniqueReferenceID(31-31)FieldDescription(33-33)FieldReason(35-35)FieldInvoicingAppExternalID(37-37)FieldCreatedAt(23-23)FieldUpdatedAt(25-25)FieldDeletedAt(27-27)FieldReasonDetails(43-43)ValueScanner(96-98)
openmeter/ent/db/billinginvoiceline.go (4)
openmeter/ent/db/billinginvoicelineusagediscount.go (2)
BillingInvoiceLineUsageDiscount(19-51)BillingInvoiceLineUsageDiscount(74-93)openmeter/ent/db/billinginvoicelinediscount.go (2)
BillingInvoiceLineDiscount(19-63)BillingInvoiceLineDiscount(86-105)openmeter/ent/db/billinginvoicelineusagediscount_query.go (1)
BillingInvoiceLineUsageDiscountQuery(21-32)openmeter/ent/db/billinginvoicelinediscount_query.go (1)
BillingInvoiceLineDiscountQuery(21-32)
openmeter/ent/db/billinginvoicelinediscount_update.go (2)
openmeter/billing/discount.go (3)
DiscountReasonType(128-128)DiscountReasonType(136-142)DiscountReason(147-152)openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (5)
FieldReason(35-35)FieldInvoicingAppExternalID(37-37)FieldType(45-45)FieldQuantity(47-47)FieldPreLinePeriodQuantity(49-49)
openmeter/ent/db/billinginvoicelinediscount_create.go (6)
openmeter/billing/discount.go (3)
DiscountReasonType(128-128)DiscountReasonType(136-142)DiscountReason(147-152)openmeter/billing/invoiceline.go (1)
LineID(20-20)openmeter/ent/db/billinginvoicelinediscount/where.go (4)
LineID(91-93)Amount(111-113)InvoicingAppExternalID(106-108)Type(121-123)openmeter/ent/db/billinginvoiceline/where.go (3)
Name(92-94)Amount(102-104)InvoicingAppExternalID(173-175)openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (4)
FieldInvoicingAppExternalID(37-37)FieldAmount(39-39)FieldType(45-45)FieldSourceDiscount(43-43)openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (3)
FieldInvoicingAppExternalID(73-73)FieldAmount(35-35)FieldType(61-61)
openmeter/ent/db/setorclear.go (3)
openmeter/ent/db/billinginvoicelinediscount_update.go (2)
BillingInvoiceLineDiscountUpdate(22-26)BillingInvoiceLineDiscountUpdateOne(451-456)openmeter/billing/discount.go (1)
DiscountReason(147-152)openmeter/ent/db/billinginvoicelineusagediscount_update.go (2)
BillingInvoiceLineUsageDiscountUpdate(22-26)BillingInvoiceLineUsageDiscountUpdateOne(373-378)
openmeter/ent/db/client.go (4)
openmeter/ent/db/billinginvoicelineusagediscount_query.go (1)
BillingInvoiceLineUsageDiscountQuery(21-32)openmeter/ent/db/billinginvoicelineusagediscount_create.go (1)
BillingInvoiceLineUsageDiscountCreate(22-27)openmeter/ent/db/billinginvoicelineusagediscount_update.go (1)
BillingInvoiceLineUsageDiscountUpdate(22-26)openmeter/ent/db/billinginvoicelineusagediscount_delete.go (1)
BillingInvoiceLineUsageDiscountDelete(16-20)
openmeter/ent/db/billinginvoiceline_update.go (2)
openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (1)
FieldID(19-19)openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (1)
FieldID(19-19)
openmeter/billing/invoicelinediscount.go (6)
openmeter/billing/invoiceline.go (1)
LineExternalIDs(235-237)openmeter/billing/discount.go (1)
DiscountReason(147-152)pkg/models/validator.go (1)
Validate(16-26)pkg/models/model.go (2)
ManagedModelWithID(155-158)ManagedModel(107-113)pkg/models/clonable.go (1)
Clonable(3-5)pkg/models/error.go (1)
NewNillableGenericValidationError(129-135)
openmeter/ent/db/billinginvoicelineusagediscount_create.go (4)
openmeter/ent/db/mutation.go (1)
BillingInvoiceLineUsageDiscountMutation(18699-18721)openmeter/billing/discount.go (3)
DiscountReasonType(128-128)DiscountReasonType(136-142)DiscountReason(147-152)openmeter/ent/db/billinginvoicelineusagediscount.go (2)
BillingInvoiceLineUsageDiscount(19-51)BillingInvoiceLineUsageDiscount(74-93)openmeter/billing/invoiceline.go (1)
LineID(20-20)
openmeter/ent/db/billinginvoicelinediscount/where.go (4)
openmeter/ent/db/predicate/predicate.go (1)
BillingInvoiceLineDiscount(79-79)openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (2)
FieldInvoicingAppExternalID(73-73)FieldType(61-61)openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (4)
FieldInvoicingAppExternalID(37-37)FieldType(45-45)FieldReason(35-35)FieldSourceDiscount(43-43)openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (2)
FieldInvoicingAppExternalID(37-37)FieldReason(35-35)
openmeter/ent/db/billinginvoicelineusagediscount_update.go (4)
openmeter/ent/db/mutation.go (1)
BillingInvoiceLineUsageDiscountMutation(18699-18721)openmeter/ent/db/predicate/predicate.go (2)
BillingInvoiceLineUsageDiscount(93-93)BillingInvoiceLine(65-65)openmeter/ent/db/billinginvoicelineusagediscount/where.go (8)
ID(16-18)UpdatedAt(81-83)DeletedAt(86-88)ChildUniqueReferenceID(96-98)Description(101-103)InvoicingAppExternalID(106-108)Quantity(111-113)PreLinePeriodQuantity(116-118)openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (10)
UpdateDefaultUpdatedAt(92-92)ReasonValidator(102-109)FieldID(19-19)FieldUpdatedAt(25-25)FieldDeletedAt(27-27)FieldChildUniqueReferenceID(31-31)FieldDescription(33-33)FieldInvoicingAppExternalID(37-37)FieldQuantity(39-39)FieldPreLinePeriodQuantity(41-41)
openmeter/ent/db/billinginvoicelineusagediscount/where.go (7)
openmeter/ent/db/billinginvoicelineusagediscount.go (2)
BillingInvoiceLineUsageDiscount(19-51)BillingInvoiceLineUsageDiscount(74-93)openmeter/ent/db/predicate/predicate.go (2)
BillingInvoiceLineUsageDiscount(93-93)BillingInvoiceLine(65-65)openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (9)
FieldID(19-19)FieldNamespace(21-21)FieldCreatedAt(25-25)FieldUpdatedAt(27-27)FieldDeletedAt(29-29)FieldChildUniqueReferenceID(75-75)FieldDescription(33-33)FieldInvoicingAppExternalID(73-73)FieldQuantity(67-67)openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (12)
FieldID(19-19)FieldNamespace(21-21)FieldCreatedAt(23-23)FieldUpdatedAt(25-25)FieldDeletedAt(27-27)FieldLineID(29-29)FieldChildUniqueReferenceID(31-31)FieldDescription(33-33)FieldInvoicingAppExternalID(37-37)FieldQuantity(47-47)FieldPreLinePeriodQuantity(49-49)FieldReason(35-35)openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (13)
FieldID(19-19)FieldNamespace(21-21)FieldCreatedAt(23-23)FieldUpdatedAt(25-25)FieldDeletedAt(27-27)FieldLineID(29-29)FieldChildUniqueReferenceID(31-31)FieldDescription(33-33)FieldInvoicingAppExternalID(37-37)FieldQuantity(39-39)FieldPreLinePeriodQuantity(41-41)FieldReason(35-35)FieldReasonDetails(43-43)openmeter/billing/invoiceline.go (1)
LineID(20-20)openmeter/billing/discount.go (2)
DiscountReasonType(128-128)DiscountReasonType(136-142)
api/client/javascript/src/client/schemas.ts (4)
api/api.gen.go (12)
BillingDiscountReason(1067-1069)BillingDiscountUsage(1072-1086)BillingDiscounts(1089-1095)DiscountReasonMaximumSpend(1960-1962)DiscountReasonRatecardPercentage(1968-1981)DiscountReasonRatecardUsage(1987-2002)DiscountUsage(2012-2017)Discounts(2020-2026)InvoiceLineAmountDiscount(3344-3368)InvoiceLineAppExternalIds(3371-3377)InvoiceLineDiscounts(3380-3390)InvoiceLineUsageDiscount(3441-3470)api/client/go/client.gen.go (12)
BillingDiscountReason(965-967)BillingDiscountUsage(970-984)BillingDiscounts(987-993)DiscountReasonMaximumSpend(1831-1833)DiscountReasonRatecardPercentage(1839-1852)DiscountReasonRatecardUsage(1858-1873)DiscountUsage(1883-1888)Discounts(1891-1897)InvoiceLineAmountDiscount(3093-3117)InvoiceLineAppExternalIds(3120-3126)InvoiceLineDiscounts(3129-3139)InvoiceLineUsageDiscount(3190-3219)openmeter/billing/discount.go (1)
Discounts(78-81)openmeter/productcatalog/discount.go (1)
Discounts(113-116)
⏰ Context from checks skipped due to timeout of 90000ms (4)
- GitHub Check: E2E
- GitHub Check: CI
- GitHub Check: Developer environment
- GitHub Check: Analyze (go)
🔇 Additional comments (571)
openmeter/ent/db/ent.go (1)
29-29: Nice job updating the import and database table validation.The addition of the new
billinginvoicelineusagediscountimport and its corresponding entry in the column validation map aligns well with the PR objectives. This change supports the separation of unit and amount discounts into different tables, allowing for more precise management of discount types in the database.Also applies to: 131-131
openmeter/ent/db/tx.go (2)
43-44: The addition of BillingInvoiceLineUsageDiscount client is consistent with the PR objectives.This new client for handling usage-based discounts aligns with the PR goal of restructuring discounts to allow single discount per type and separating unit and amount discounts into different tables.
241-241: Proper initialization of the new client.The initialization of the BillingInvoiceLineUsageDiscount client is correctly implemented in the init method, maintaining consistency with the initialization pattern used for other clients.
openmeter/ent/db/billinginvoiceline/where.go (4)
1896-1905: Function renamed to reflect specific discount type.The function
HasLineDiscountshas been properly renamed toHasLineUsageDiscountsto specifically target usage-based discounts, aligning with the PR's objective to separate discount types. This function now correctly references theLineUsageDiscountsTableandLineUsageDiscountsColumnconstants.
1907-1917: Updated function signature to match new discount model structure.The function
HasLineUsageDiscountsWith(previouslyHasLineDiscountsWith) now appropriately accepts predicates of typeBillingInvoiceLineUsageDiscountand uses the newnewLineUsageDiscountsStep()helper. This change properly supports the database schema restructuring that separates unit and amount discounts.
1919-1928: New function added for amount-based discount filtering.This new function
HasLineAmountDiscountsimplements the necessary predicate for querying invoice lines with amount-based discounts. It correctly implements the edge relationship using the appropriate table and column constants, supporting the PR's goal of separate discount type management.
1930-1940: New conditional filtering function for amount-based discounts.The
HasLineAmountDiscountsWithfunction completes the restructuring by providing conditional filtering for amount discounts, mirroring the pattern used for usage discounts. This ensures consistent query capabilities across both discount types.openmeter/ent/db/runtime.go (3)
22-22: Added import for new billing invoice line usage discount package.This import is correctly added to support the new BillingInvoiceLineUsageDiscount schema implementation, which is part of the database schema changes for separating different discount types.
498-499: Updated ValueScanner type for source discount.The ValueScanner type for SourceDiscount is now updated to use billing.DiscountReason type, which aligns with the PR objective to modify the discount structure with both percentage and usage values.
504-533: Added BillingInvoiceLineUsageDiscount schema setup.The implementation correctly adds the new schema for BillingInvoiceLineUsageDiscount, including all required validators and field descriptors. This change fulfills the PR objective of splitting unit and amount discounts into different tables for more precise management of null and non-null flags.
The schema setup follows the same pattern as other entities in the codebase, with proper namespace validators, timestamp handling, and ID generation. The ReasonDetails field using the DiscountReason type is particularly important for the new discount structure.
openmeter/ent/db/setorclear.go (6)
1136-1148: This code correctly handles null values for InvoicingAppExternalID.The implementation follows the established pattern for handling nullable fields in database updates.
1164-1190: Good implementation of new discount handling patterns.These methods allow for properly setting or clearing the source discount and type fields based on their nullability, aligning with the PR objective to modify the discount structure to permit only a single discount per type.
1220-1232: Proper implementation of time deletion handling for usage discounts.The DeletedAt field is correctly implemented with the same null-checking pattern used throughout the codebase.
1234-1260: Good implementation of string field handlers for usage discounts.The ChildUniqueReferenceID and Description fields follow the consistent pattern for handling nullable string values in the database.
1262-1274: InvoicingAppExternalID handler properly implemented for usage discounts.The implementation correctly follows the same pattern used for the discount line handler version.
1276-1302: New quantity and reason handlers properly support the discount restructuring.These methods provide the necessary support for the separation of unit and amount discounts into different tables as described in the PR objectives. The PreLinePeriodQuantity and ReasonDetails fields can now be properly set or cleared.
openmeter/ent/db/paginate.go (4)
494-538: Implementation correctly supports billing model restructuring.This pagination method has been updated to work with
BillingInvoiceFlatFeeLineConfiginstead of what was likely previouslyBillingInvoiceDiscount, aligning with the PR's objective of restructuring the discount handling in the system. The implementation maintains the same pagination pattern used throughout the file.
542-586: Changes maintain consistency with pagination pattern.The method properly follows the established pagination pattern while updating the type to work with
BillingInvoiceLine. The implementation correctly handles limit, offset, cloning for count, and result aggregation.
590-634: Pagination properly implemented for updated discount model.This method correctly implements pagination for the
BillingInvoiceLineDiscounttype, maintaining the established code pattern. The rename aligns with the PR goal of restructuring discounts to allow only a single discount per type.
638-682: Added support for usage-specific discounts.The introduction of
BillingInvoiceLineUsageDiscountQuery.Paginateproperly supports the PR objective of separating unit and amount discounts into different tables. The implementation correctly follows the established pagination pattern and maintains consistency with other methods.openmeter/ent/db/expose.go (1)
118-118:Details
✅ Verification successful
Addition of BillingInvoiceLineUsageDiscount client aligns with the new discount structure.
This change adds the new
BillingInvoiceLineUsageDiscountclient as part of the broader restructuring to allow only a single discount per type. The new client will facilitate operations on the separated usage discount table, which is now distinct from amount discounts per the PR objectives.
🏁 Script executed:
#!/bin/bash # Let's verify this is part of a complete transition by checking if BillingInvoiceDiscount # was removed and if there are corresponding references in the codebase # Check for removed BillingInvoiceDiscount git diff -- openmeter/ent/db/expose.go | grep -A 3 -B 3 "BillingInvoiceDiscount" # Check for other instances of BillingInvoiceLineUsageDiscount across the codebase rg "BillingInvoiceLineUsageDiscount" --type goLength of output: 73150
BillingInvoiceLineUsageDiscount client addition validated and integrated consistently.
- The new client is correctly instantiated in
openmeter/ent/db/expose.go(line 118) usingNewBillingInvoiceLineUsageDiscountClient(config).- Our diff check shows no lingering references to the removed
BillingInvoiceDiscountwithin this file, indicating that this part of the migration is isolated.- A repository-wide search confirms that the
BillingInvoiceLineUsageDiscountclient is used extensively, which aligns with the PR’s objective of separating usage discounts from amount discounts.Overall, the changes fulfill the intended restructuring, and no further modifications are necessary.
openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (7)
34-37: Adding back field constants for billing invoice line discounts.The reintroduction of
FieldReasonandFieldInvoicingAppExternalIDconstants aligns with the PR objective to restructure the discount system by separating unit and amount discounts into different tables.
42-45: Reinstating source discount and type field constants.These constants are correctly reintroduced to support the refactored discount structure, allowing for proper database field mapping.
73-74: Updating Columns slice with newly reinstated fields.The addition of
FieldReasonandFieldInvoicingAppExternalIDto the Columns slice ensures these fields are properly recognized as valid columns for database operations.
108-108: Updated ValueScanner type for source discount.Changing from
*billing.Discountto*billing.DiscountReasonproperly aligns with the PR objective of restructuring discounts, focusing on storing only the reason rather than the full discount.
113-115: Updated ReasonValidator function signature and valid cases.The function now:
- Takes
billing.DiscountReasonTypeinstead ofbilling.LineDiscountReason- Supports the expanded set of valid cases including "ratecard_percentage" and "ratecard_usage"
This properly supports the new discount structure mentioned in the PR objectives.
165-173: Added ordering functions for reason and invoicing app external ID.These functions follow the established pattern for defining ordering options and are necessary for enabling sorting by these fields in database queries.
185-193: Added ordering functions for source discount and type.These ordering functions properly enable sorting by the reinstated fields, maintaining consistency with the rest of the codebase.
openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (4)
1-2: Auto-generated code acknowledgment.
These lines indicate that this file is generated by Ent. Typically, direct manual edits are discouraged, as changes may be overwritten by future code generations.
74-82: Validity check approach.
TheValidColumnfunction correctly verifies columns against the defined list. This helps guard against malformed queries or column references.
101-109: Enum validation alignment.
TheReasonValidatorcorrectly restricts thereasonfield to the known discount reasons (maximum_spend,ratecard_percentage,ratecard_usage). This preserves consistent usage of enum values and aligns with the new discount structure.
179-191: Ordering by BillingInvoiceLine.
The logic inByBillingInvoiceLineFieldandnewBillingInvoiceLineStep()ensures the query can order by a distinct field of the relatedbilling_invoice_line. This is standard Ent practice and appears solid.openmeter/subscription/repo/subscriptionitemrepo.go (1)
123-123: More robust discount validationChanged from checking if
input.RateCard.AsMeta().Discountsis nil to checking if it's empty usingIsEmpty(). This ensures that discounts are only set when explicitly defined with content, not just when a pointer is non-nil but potentially contains an empty structure.openmeter/subscription/repo/mapping.go (1)
122-122: Improved null safety for Discounts fieldChanged default value from
nilto an emptyproductcatalog.Discounts{}structure. This prevents potential nil pointer dereferences when working with the Discounts field and ensures a consistent representation of empty discounts throughout the codebase.openmeter/billing/adapter/invoicelineprogressive.go (2)
12-13: Added imports for new discount typesAdded necessary imports for the refactored discount structure, enabling separate handling of amount and usage discounts.
92-97: Split discount retrieval into amount and usage typesThe original
WithLineDiscounts()call has been replaced with separate calls for retrieving amount and usage discounts. This change aligns with the PR objective of allowing a single discount per type by splitting the discount storage into separate tables.Each query now properly filters out deleted records with
DeletedAtIsNil(), ensuring that only active discounts are considered in the invoice line processing.openmeter/billing/invoiceline.go (1)
493-493: Simplified access to RateCardDiscounts fieldDirect access to
i.RateCardDiscountsinstead ofi.LineBase.RateCardDiscounts. SinceLineembedsLineBase, this field is directly accessible from theLinestruct and this change simplifies the code without altering functionality.openmeter/billing/service/lineservice/pricevolumetiered_test.go (1)
397-410: Refactored discount structure for better type safety and clarityThe discount structure has been updated to use the new
LineDiscountstype, which clearly separates amount-based discounts in a dedicated array field. This aligns with the PR objective of allowing a single discount per type while still maintaining the ability to record multiple amount discounts.openmeter/subscription/testutils/ratecard.go (1)
96-98: Direct assignment of percentage discount improves clarityThe discount creation has been simplified by directly assigning a pointer to a
PercentageDiscountstructure rather than using the factory method. This change aligns with the PR objective of modifying the discount field in the ratecard to a new format that includes both percentage and usage values.test/app/stripe/invoice_test.go (1)
561-565: Updated discount access to match new structureThe code now correctly accesses discounts through the
Amountarray field of theDiscountsstruct, rather than iterating directly overline.Discounts. This change is consistent with the PR objective of updating the discount structure on invoice lines.openmeter/productcatalog/subscription/service/plan_test.go (1)
91-93: Simplified discount access and validationThe test now directly accesses the percentage discount via the
Percentagefield rather than using slice indexing and type conversion. This is more concise and less error-prone, aligning with the PR objective of modifying the discount structure within the subscription system.openmeter/ent/db/addonratecard_create.go (1)
341-345: Added validation for the discounts field aligns with new discount structure.This new validation check ensures that when discounts are specified, they're properly validated before an AddonRateCard is created. This supports the PR objective of allowing only a single discount per type by enforcing data integrity at the creation level.
pkg/models/model.go (1)
155-178: Well-structured model type for ID handling.The new
ManagedModelWithIDtype provides a clean abstraction for entities that need ID management. It includes proper validation and comparison functionality through theValidate()andEqual()methods. This supports the PR's restructuring of discount handling by providing a reusable base type for entities that need IDs.openmeter/productcatalog/addon/ratecard_test.go (1)
120-126: Updated test code to use direct field assignments for the new discount structure.The test code now directly assigns discount values to the appropriate fields in the
Discountsstruct instead of using factory methods. This aligns with the PR's objective of supporting a single discount per type by properly testing the new structure where a discount can have both percentage and usage components.openmeter/ent/db/subscriptionitem_create.go (1)
407-411: Added validation for discounts in subscription items.Similar to the changes in the AddonRateCard, this validation ensures that the discounts in subscription items are properly validated before creation. This is an important part of maintaining data integrity with the new discount structure that allows a single discount per type.
openmeter/productcatalog/plan/ratecard_test.go (1)
120-125: Discount structure updated to support single discount per type.The code now directly creates the percentage and usage discounts as individual fields within the
Discountsstruct instead of using factory methods. This change aligns with the PR objective to modify the discount structure to permit only a single discount per type.openmeter/ent/db/addonratecard_update.go (2)
360-364: Added validation for new discount structure.Proper validation has been added for the discounts field in the AddonRateCard update operations. This ensures that any discount structure assigned to rate cards will be validated before persisting to the database, maintaining data integrity.
924-928: Added consistent validation in the single-item update method.The same discounts validation logic has been applied to the
AddonRateCardUpdateOnemethod, ensuring consistency between batch and single-item update operations.openmeter/billing/service/lineservice/pricepackage_test.go (1)
243-256: Updated test case to use new line discount structure.The test case now uses the new
LineDiscountsstructure that separates discounts by type. This change correctly implements the array-based approach for representing calculated discounts on invoice lines, which allows recording multiple amount discounts (for cases where both percentage and maximum spend discounts apply).The updated structure provides better type safety by using strongly-typed discount categories (Amount) with appropriate arrays for each type, rather than a generic collection.
openmeter/productcatalog/subscription/http/mapping.go (1)
250-250: Simplified discount mapping with direct conversion.The code now directly converts discounts from the rate card without intermediate variables or explicit error handling. This is possible because
productcataloghttp.FromDiscounts()handles empty discounts gracefully by returning nil.This simplification makes the code more readable while maintaining correct behavior for converting the new discount structure to API responses.
openmeter/billing/service/lineservice/pricedynamic_test.go (1)
188-201: Updated discount structure implementation looks goodThe refactoring changes the way discounts are constructed in the test, aligning with the new discount structure where each discount type has its own field. The new implementation with
billing.LineDiscountsstructure containing an array ofbilling.AmountLineDiscountManagedmatches the PR's goal of having a single discount per type.openmeter/app/stripe/entity/app/invoice.go (2)
187-189: Correctly updated discount access patternChanged from using method call to direct field access, matching the refactored discount structure design. This simplifies the code and makes it clearer what type of discount is being processed.
296-297: Good adjustment to the new discount structureUpdated from
line.Discounts.GetAmountDiscountsByID()toline.Discounts.Amount.GetByID(), properly aligning with the new discount structure. The change maintains the same functionality while making the discount type more explicit.openmeter/billing/app.go (1)
219-229: Improved discount processing with the new structureThe refactoring simplifies the discount handling by:
- Directly accessing the
AmountandUsagefields instead of iterating over generic discounts- Setting external IDs directly on the discount objects without complex mutation logic
- Eliminating unnecessary error handling
This approach is more maintainable and makes the code more type-safe by being explicit about the discount types.
openmeter/ent/db/predicate/predicate.go (1)
92-104: Added database predicate for the new discount entityThe addition of
BillingInvoiceLineUsageDiscountpredicate type and its error handler follows the established pattern in the codebase and properly supports the database schema changes for separating discount types into different tables.openmeter/billing/httpdriver/discounts.go (2)
34-47: Updated AsDiscounts function to handle the new BillingDiscounts structureThe function has been refactored to accept a pointer to the new
api.BillingDiscountstype instead of a slice. This change correctly implements the new discount model where there can only be one discount per type (percentage or usage).Good additions:
- Proper nil check for the input pointer
- Clear initialization of the output structure
- Explicit handling for each discount type separately
49-61: Well-structured usage discount handlingThe usage discount handling properly extracts and converts the discount information while maintaining good error handling. The code clearly handles the scenario where a usage discount exists in the input structure.
openmeter/billing/httpdriver/deprecations.go (2)
169-177: Updated discount processing in flat fee rate card handlerThe code has been updated to use the new
AsDiscountsfunction that accepts a pointer toapi.BillingDiscountsinstead of a slice. This change correctly aligns with the new discount model implementation where there can only be one discount per type.The error handling is well implemented with a clear validation error message that includes the underlying error.
301-309: Updated discount processing in usage-based rate card handlerThis change mirrors the update in the flat fee handler, ensuring consistent discount handling across different rate card types. The consistent approach to validation errors makes debugging easier.
openmeter/ent/db/subscriptionitem_update.go (2)
456-460: Added validation for discounts fieldThe validation logic for the
Discountsfield has been added to thecheckmethod of theSubscriptionItemUpdatestruct. This ensures that any discounts added to a subscription item conform to the validation rules. The implementation follows the same pattern as other field validations, maintaining consistency in the codebase.
1154-1158: Added validation for discounts field in SubscriptionItemUpdateOneThe validation logic for the
Discountsfield has been consistently added to theSubscriptionItemUpdateOnestruct as well, ensuring validation across both update methods. This consistency prevents potential validation gaps when updating subscription items.openmeter/billing/service/lineservice/feeline.go (3)
44-51: Updated discount retrieval to support single discount per typeThe code has been modified to retrieve a single discount instead of multiple discounts, aligning with the new discount model. The conditional check has been updated appropriately to check if the discount is nil rather than checking the length of a slice.
65-70: Updated line discount calculation for single discountThe discount calculation has been updated to work with a single discount instead of iterating through multiple discounts. The result is now correctly appended to the
l.line.Discounts.Amountfield, maintaining the expected behavior while using the new structure.
84-85: Updated discount total calculationThe calculation of
DiscountsTotalhas been updated to sum theAmountfield ofl.line.Discountsdirectly, rather than summing all discounts. This change correctly reflects the new discount structure and ensures accurate total calculations.test/billing/discount_test.go (7)
111-115: Refactoring discount initialization to use the new structureThe test is now using direct assignment to the
Percentagefield in theRateCardDiscountsstructure, which aligns with the PR objective of allowing a single discount per type.
133-135: Direct access to percentage discount is now more idiomaticAccessing the discount directly through
RateCardDiscounts.Percentagesimplifies the code and removes the need for helper methods to extract the discount.
156-156: Test correctly verifies correlation ID persistenceThe test now directly accesses the correlation ID from the percentage discount, ensuring it's properly retained during the invoice creation process.
161-161: Correlation ID verification for child lines is appropriately handledThe test correctly verifies that the correlation ID is propagated to all child lines in the progressive billing hierarchy.
168-175: Amount discount validation is comprehensiveThe test now properly checks that the amount discount maintains the same correlation ID as its source percentage discount, validating the correct conversion between discount types.
186-190: Usage discount initialization follows the new patternThe test correctly adds a usage discount to the existing discounts structure, maintaining consistency with the new discount model.
198-201: Correlation ID differentiation between discount typesThe test verifies that different discount types have different correlation IDs, which is a critical aspect of the discount tracking system.
openmeter/productcatalog/ratecard.go (4)
126-126: Simplified discount cloningThe code now directly calls the
Clonemethod on theDiscountsstruct, removing unnecessary conditional logic. This is cleaner and more maintainable.
199-201: Improved discount validationThe conditional check for discount length before validation has been removed, allowing validation to occur unconditionally. This ensures all discounts are always validated properly.
294-300: Enhanced discount validation for flat fee rate cardsThe validation now explicitly checks that usage discounts are not allowed for flat fee rate cards, which is an important business rule that prevents incorrect discount configurations.
410-412: Streamlined usage discount validation for usage-based rate cardsThe simplified validation logic directly checks if a usage discount exists for a flat price type, which is a clearer and more direct approach than the previous implementation.
openmeter/billing/service/discounts.go (2)
12-28: Simplified discount correlation ID generationThe function has been refactored to handle percentage and usage discounts separately, which aligns with the new discount structure of permitting only a single discount per type. This implementation is clearer and more maintainable.
31-42: Helper function for correlation ID generationA new helper function
generateCorrelationIDencapsulates the logic for generating or validating correlation IDs, promoting code reuse and maintainability. The function properly handles empty correlation IDs by generating new ones and validates existing IDs.openmeter/billing/service/lineservice/pricegraduatedtiered_test.go (2)
258-271: Updated discount structure in test expectationsThe test now uses the new
LineDiscountsstructure with anAmountfield containing a slice ofAmountLineDiscountManaged, which aligns with the PR objective of restructuring discounts by type. This ensures that the tests validate the correct behavior of the new discount model.
279-292: Consistent usage of the new discount structureThe test maintains consistency by using the same discount structure pattern throughout all test cases. This ensures that all discount scenarios are properly tested with the new model.
openmeter/ent/db/hook/hook.go (1)
168-178: New adapter function matches the revised discount model architecture.This new
BillingInvoiceLineUsageDiscountFunctype replaces the removedBillingInvoiceDiscountFunc, aligning with the system-wide discount restructuring that separates usage discounts from amount discounts. The implementation follows the consistent pattern used for all adapter functions in this file.test/billing/invoice_test.go (2)
2220-2226: Updated discount iteration to match the new discount model.The code now properly iterates over the separate discount collections (Amount and Usage) rather than a single combined collection, aligning with the PR objective to separate discount types. This ensures all discounts are correctly processed when upserting an invoice.
2254-2260: Consistent implementation of the discount model in the finalization process.This change correctly applies the same discount type separation pattern during invoice finalization, ensuring external IDs are properly associated with each type of discount. This maintains consistency with the changes made in the upsert operation.
openmeter/billing/service/lineservice/usagebasedline_test.go (5)
33-33: Updated discount structure in test case to match new model.The
ubpCalculationTestCasestruct has been updated to use the newbilling.Discountstype instead of an array of discounts, aligning with the system-wide discount model changes.
180-193: Restructured discount expectation to use the new discount model.The test expectations have been updated to use the structured
LineDiscountstype with separated amount and usage discount arrays. This properly reflects the new discount model architecture.
208-221: Consistent usage of the new discount model structure.Similar to the previous test case, this expectation has been updated to match the new discount structure. The test now properly validates that maximum spend discounts are correctly added to the amount discount array.
236-249: Maintained test validation with updated discount structure.This test case for 100% discount has been updated to follow the new discount model, validating that full discounts are properly represented within the amount discount array.
264-277: Consistent implementation in extreme overage test case.The final test case also correctly implements the new discount structure when testing scenarios with significant overage, ensuring consistent behavior across all test scenarios.
openmeter/billing/service/lineservice/feeline_test.go (4)
22-27: Updated discount input to match new single discount per type model.The test now uses a single
PercentageDiscountobject rather than an array, aligning with the PR objective to "allow single discount per type." The inclusion of aCorrelationIDenables proper tracking and referencing of this discount.
32-49: Restructured expectations to validate the new discount model.The test expectations have been updated to use the
LineDiscountsstructure with itsAmountarray, properly reflecting how percentage discounts are now converted to amount discounts for invoice lines.
56-56: Updated test input struct to reflect single discount model.The
generateFeeLineInputstructure now accepts a singleRateCardDiscountrather than an array, aligning with the PR's goal of allowing only a single discount per type.
69-71: Updated discount initialization to use the new structure.The discount is now correctly assigned to the
Percentagefield of theDiscountsstruct using theClonemethod, properly implementing the new discount model in the test fixture.openmeter/billing/httpdriver/invoiceline.go (1)
492-532: Looks good.
The switch-case covers all known discount reason types comprehensively, returning clear errors for unknown types.openmeter/ent/db/billinginvoicelineusagediscount_query.go (13)
1-32: No immediate correctness issues.
This file sets up the query builder, imports, and type definitions. Everything appears standard for an Ent-generated file.
34-86: Parameter chaining architecture is clear.
The methods (Where, Limit, Offset, Unique, Order, QueryBillingInvoiceLine) appear well-structured, providing straightforward query customizations.
87-130: Query convenience methods for the first entity.
These look standard and provide concise ways to get the first matching record or ID.
132-185: Only, OnlyX, OnlyID, and OnlyIDX methods
All follow the Ent pattern. Proper error handling for not singular and not found.
187-225: All, AllX, IDs, IDsX methods
No issues. The code is consistent with typical Ent usage for retrieving all records or just the IDs.
227-295: Count, CountX, Exist, ExistX, Clone, WithBillingInvoiceLine
Logic for counting, existence checks, and cloning the query builder is standard. The usage of interceptors suggests an extensible approach.
297-343: Aggregation and field selection
GroupBy, Select, and Aggregate methods are consistent with Ent's approach to grouping and partial selection of columns.
345-407: Query preparation and row fetching
The prepareQuery and sqlAll methods handle interceptors, enforce field validation, and retrieve results. Implementation looks correct.
409-437: Foreign-key loading
The loadBillingInvoiceLine function properly retrieves related billing invoice lines and attaches them to the edges.
439-527: sqlCount, querySpec, and sqlQuery
These methods define the specifics of the query structure, ordering, and field selection. They comply with Ent’s recommended pattern.
529-553: Locking mechanisms
The ForUpdate and ForShare methods implement row-level locking for Postgres. Implementation looks appropriate.
555-602: BillingInvoiceLineUsageDiscountGroupBy
GroupBy builder includes aggregation logic, column selection, and the standard scanning approach.
604-644: BillingInvoiceLineUsageDiscountSelect
Select builder is consistent with the rest of the Ent code, providing aggregated selection. No issues found.openmeter/productcatalog/ratecard_test.go (7)
102-106: Valid percentage discount test
The code correctly checks a 10% discount scenario. Good coverage.
124-126: Invalid usage discount test
Assertions ensure that usage discounts are disallowed in this context. Good negative test.
268-275: Mixed discount test
Checks that a rate card can include both percentage and usage discounts without error. Good scenario coverage.
295-299: Invalid usage discount for flat price
Matrix testing approach ensures that usage discounts don’t apply incorrectly to a flat price. Nicely validated.
403-410: Percentage and usage discount definitions
Shows a scenario with combined discount types. Proper initialization and reusability.
456-457: Usage discount block
Defines usage discount quantity at 100. Straightforward test coverage.
563-567: Discount ordering irrelevance
Confirms that usage and percentage discount ordering doesn’t matter. Comprehensive test approach.tools/migrate/migrations/20250411062903_billing-split-line-discounts.down.sql (3)
1-20: Database schema changes properly support new discount model.The migration script correctly recreates the
billing_invoice_discountstable with all necessary fields and indexes as part of the down migration. This aligns with the PR objective of separating unit and amount discounts into different tables for better management of null and non-null flags.
21-30: Proper cleanup of usage discount table and indexes.The migration properly removes the indexes and the
billing_invoice_line_usage_discountstable that were created in the forward migration. This ensures a clean rollback of the schema changes if needed.
31-33: Constraint and column property modifications correctly implemented.The script properly reverts the changes to the
billing_invoice_line_discountstable by modifying the constraints and column properties. The SQL syntax is correct and properly handles:
- Dropping the new foreign key constraint
- Setting column nullability requirements
- Adding back the original foreign key constraint
This ensures the table structure is properly restored to its original state.
test/billing/adapter_test.go (7)
647-681: Updated discount structure implementation looks good.The code now uses the new
LineDiscountsstructure with separateAmountarrays ofAmountLineDiscountManagedobjects, aligning with the PR objective to permit only a single discount per type. The test correctly sets up three different amount discounts for testing.
694-696: Assertion update correctly validates the new discount structure.The test now properly validates both the Amount and Usage discount collections separately, confirming the structural change from a single discount array to separate typed collections.
698-714: Discount mutation function looks good.The code correctly uses the new mutate pattern to modify
AmountLineDiscountManagedobjects, removing theManagedModelWithIDfields before comparison. This allows for proper content comparison without being affected by database-generated fields.
719-728: Discount ID retrieval correctly implemented.The new approach to find a discount by description is properly implemented. This ensures the test can maintain referential integrity when updating existing discounts.
729-768: Discount update test case handles all scenarios correctly.The updated test properly covers three scenarios:
- Updating an existing discount with the same reference ID
- Updating an existing discount with an explicit ID reference
- Adding a completely new discount
This comprehensive testing validates the new discount structure handling.
792-822: Verification logic correctly uses the new discount accessor methods.The test verification now uses the appropriate methods to locate and validate discounts, including:
- Using
GetDiscountByChildUniqueReferenceIDfor reference-based lookups- Using
findAmountDiscountByDescriptionfor description-based lookups- Proper verification of both changed and unchanged fields
This ensures the discount update functionality works as expected.
843-854: Helper method updated to match new discount type structure.The helper method has been correctly renamed from
findDiscountByDescriptiontofindAmountDiscountByDescriptionand updated to work with the newAmountLineDiscountManagedtype rather than the previousLineDiscounttype.api/openapi.yaml (11)
12147-12176: Validate New Discount Reason Schemas
The introduction of the new DiscountPercentage and DiscountReasonMaximumSpend schemas appears to align with the new discount structure. The requirements for a percentage field (with appropriate min/max values) and the enum for discount reasons seem accurate. Ensure that these validations meet the business logic expectations.
12250-12265: Verify Consolidated Discounts Schema Implementation
The new Discounts schema (lines 12250–12265) consolidates both percentage and usage discounts under one object. This aligns well with the PR objective of allowing a single discount per type. In future iterations, adding illustrative examples could further enhance clarity.
14721-14728: Verify Discount Schema Consistency in InvoiceFlatFeeRateCard
The InvoiceFlatFeeRateCard schema now includes adiscountsproperty that references BillingDiscounts (lines 14723–14727). Please verify that using BillingDiscounts here (as opposed to Discounts used in other contexts) is intentional and aligns with the overall discount strategy.
14760-14769: Approve Addition of InvoiceLineAmountDiscount Schema
The newly added InvoiceLineAmountDiscount schema (lines 14760–14769) includes the required fields and appears well structured. Ensure that all downstream systems interpret the new schema correctly.
14798-14804: Confirm Updated Reason Field Reference
Thereasonproperty now references BillingDiscountReason (lines 14798–14804), which reflects the consolidation of discount reasons. This change is consistent with the new design.
17960-17967: Validate Discount Schema Reference for Flat Fee Rate Cards
The discounts property (lines 17960–17967) now references Discounts instead of BillingDiscounts. Please confirm that this naming difference is intentional and that it reflects the design choice whereby flat fee rate cards support only percentage discounts.
18115-18122: Confirm Consistent Use of Discounts Schema in Rate Cards
Similar to hunk 15, the discounts property here (lines 18115–18122) references Discounts. Verify that the distinction from BillingDiscounts is deliberate and documented.
19368-19375: Approve Discount Integration in Price Schema
The integration of the discounts property (lines 19368–19375) with a reference to Discounts within the price schema appears correct and consistent with the new unified discount structure.
19487-19494: Review Plan-Level Discount Field
The plan schema’sdiscountsfield (lines 19487–19494) referencing Discounts is defined consistently with similar objects. The pattern and description are clear.
19527-19534: Confirm Discount Representation in Plan Duration
Thediscountsfield (lines 19527–19534) within the plan duration section appears to be handled consistently with the rest of the document. No changes needed.
19609-19616: Ensure Downstream Compatibility for Plan Discounts
Thediscountsattribute in the final plan schema (lines 19609–19616) correctly references Discounts. Please verify that any downstream processing or validation logic is updated to accept the revised discount structure.openmeter/ent/db/migrate/schema.go (3)
794-794: Foreign key symbol naming looks acceptable
The foreign key symbol is quite long but still under PostgreSQL’s 63‐character limit, so there should be no issues in practice.
819-823: Validate partial index criteria
This addition enforces uniqueness only whenchild_unique_reference_idis not null. If multiple null records for the same line are permissible, this is correct. Otherwise, you may need a different approach. Please confirm this is intended behavior.
2365-2365: Link usage discounts to invoice lines
Referencing the usage discounts table back to the invoice lines table with cascade deletion ensures orphan records are avoided. This is consistent with existing schema design.api/openapi.cloud.yaml (8)
14653-14659: Ensure Correct Integration of BillingDiscounts in InvoiceFlatFeeRateCard.
IntegratingBillingDiscountsas the value for thediscountsproperty is consistent with the overall refactor. Verify that the default values (noted earlier in the snippet) and the descriptive text align with the updated discount handling logic.
14692-14705: Review InvoiceLineAmountDiscount Schema Integration.
The newInvoiceLineAmountDiscountschema—requiring fields likecreatedAt,updatedAt,id,reason, andamount—is well introduced. Confirm that its design aligns with the overall invoicing discount model and that all properties are handled as intended downstream.
14730-14736: Verify Use of BillingDiscountReason in Amount Discount.
Thereasonfield in this section now correctly referencesBillingDiscountReasonand is marked readOnly. Ensure that this integration is consistent with other parts of the schema and that consumers understand its purpose clearly.
14742-14786: Review InvoiceLineDiscounts and Related Schemas.
The grouping ofInvoiceLineAmountDiscount,InvoiceLineAppExternalIds, andInvoiceLineDiscountsinto separate, clear objects is well executed. Confirm that the descriptions (e.g., “deduced from the total price of the line” for amount discounts and the analogous note for usage discounts) are accurate and fully reflect the discount calculation order.
17934-17941: Review Discount Integration in Rate Card Configuration.
The rate card configuration correctly incorporates thediscountsfield via a reference to theDiscountsschema. Ensure that the description “The discounts of the rate card” adequately communicates the behavior and that any default or null scenarios are handled per the new discount structure.
19295-19302: Review Discount Schema within Plan Configuration.
The plan object’sdiscountsfield references theDiscountsschema and is adequately documented. No additional changes are required, but please double-check that this integration aligns with consumer expectations.
19377-19384: Ensure Consistent Discount Field Definition in Plan Schema.
Thediscountsproperty is consistently defined here, and the accompanying regular expression for the resource identifier appears proper. Verify that the overall description fits the intended use cases and that similar definitions across the API remain uniform.
12375-12389:Details
❓ Verification inconclusive
Review the Aggregated Discounts Schema.
The new top-levelDiscountsschema aggregates both percentage and usage discount details, which aligns with the PR objectives. Verify that its description (“Discount by type on a price”) and the accompanying explanations fully capture the intended billing behavior, particularly how usage discounts translate to “free” items until exhausted.
Verify Aggregated Discounts Schema Implementation
The aggregated Discounts schema inapi/openapi.cloud.yamlnow correctly combines the percentage and usage discount details. The description “Discount by type on a price” and the notes about the usage discount—clarifying that the first N items are effectively free until exhausted—accomplish the intended explanation of the billing behavior. Please verify that the referenced schemas (DiscountPercentageandDiscountUsage) align with the underlying discount logic and that any edge-case scenarios (e.g., discount exhaustion) are handled appropriately in the billing system.openmeter/billing/adapter/invoicelinemapper.go (5)
163-163: Defaulting RateCardDiscounts to an empty struct is a good practice.
This change ensures that theRateCardDiscountsfield is always initialized, preventing potential nil pointer issues. Looks good!
213-220: Good usage discount mapping block.
The logic properly iterates usage discounts, maps them usingmapInvoiceLineUsageDiscountFromDB, and returns an actionable error on failure. This approach cleanly assigns the result toinvoiceLine.Discounts.Usage.
222-228: Consistent handling of amount discounts.
The code similarly maps amount-based discounts, ensuring a parallel structure to usage discount handling. Error handling is consistent, enhancing maintainability.
233-269: mapInvoiceLineUsageDiscountFromDB function logic is sound.
The function correctly differentiates between maximum spend discounts with no reason details and other discount reasons with non-nil reason details. Explicit error handling for missingReasonDetailsis appreciated.
271-307: mapInvoiceLineAmountDiscountFromDB function logic is cohesive.
The approach mirrors usage discount handling, ensuring consistent error checks for theSourceDiscountfield. Assigning default zero forRoundingAmountis a smart fallback.openmeter/ent/db/billinginvoicelinediscount.go (8)
37-50: Introducing new fields for discount reasoning and referencing is consistent with single-discount-per-type logic.
The added fields forReason,InvoicingAppExternalID,SourceDiscount, andTypeappear aligned with the new discount structure, while the deprecation comments clarify usage of fields slated for removal. This is coherent with the PR's objectives.
52-58: Deprecating quantity fields for amount/usage table split.
Marking these fields as deprecated helps convey the new design, preventing confusion among developers regarding how discount quantity should be referenced moving forward.
90-94: Updated scanning logic for rounding amounts and quantities.
Refactoring the handling of numeric discount fields clarifies how these values are read, consistent with the single discount structure. No issues noted.
166-178: New case blocks for reason and invoicing fields.
These additions properly cast string values into the correct discount reason and external ID fields, with robust type checking and error reporting. This is vital for data consistency.
180-183: Improved handling of the amount field.
The logic ensures the scanned decimal is valid before assignment. This check helps avoid silent data corruption for the discount amount.
192-198: Mapping the SourceDiscount from scanned values.
The code properly delegates scanning toValueScanner.SourceDiscount, returning an error if parsing fails, then assigns the resulting structure tobild.SourceDiscount. Good approach to keep the scanning logic separated.
199-204: Assigning the optional Type field.
This case block ensures type information is captured if present, reflecting the new discount approach. The fallback scenario is also handled gracefully when it's invalid.
287-321: Extending the String() builder to include discount fields.
By includingreason,invoicing_app_external_id,amount,source_discount,type,quantity, andpre_line_period_quantityin the output, debugging becomes easier, providing a thorough textual record of the discount. This is a valuable addition.openmeter/productcatalog/http/mapping.go (5)
75-75: Mapping new discount structure in RateCardFlatFee.
CallingFromDiscountsensures the correct attachment of discount data, aligning with the new design. Solid approach.
107-107: Mapping new discount structure in RateCardUsageBased.
Similarly referencingFromDiscountsfor usage-based rate cards promotes consistent discount handling across card types.
459-465: AsDiscounts call for flat.Discounts.
IntroducingAsDiscounts(flat.Discounts)clarifies discount parsing, returning an error on invalid data to ensure robust data integrity.
513-519: Handling usage-based rate cards' discount field.
Extracting usage-based discounts viaAsDiscounts(usage.Discounts)preserves a uniform code path for discount conversion.
523-545: New AsDiscounts function: streamlined discount processing.
The function gracefully handlesnildiscounts, usage discounts, and percentage discounts, returning a structuredproductcatalog.Discountsobject. This significantly simplifies discount conversions without sacrificing error handling.openmeter/billing/adapter/invoicelines.go (9)
18-18: No concerns with the new usage discount import.
Looks good as it enables the usage-discount functionality referenced below.
118-118: Conditional check onRateCardDiscountsis clear.
Only applies the discount field if non-empty. This looks correct.
224-226: Error handling for usage discount upsert is straightforward.
The wrapping of the error context is well done.
228-263: Check for consistent conflict handling in amount discounts.
Here we correctly usebillinginvoicelinediscount.CreateBulk(...), referencingbillinginvoicelinediscount.FieldID. The only questionable detail is ignoringbillinginvoiceline.FieldCreatedAtinstead ofbillinginvoicelinediscount.FieldCreatedAt, which may be a minor oversight if you intended to preserve the discount's original creation timestamp. Otherwise, logic looks solid.
264-268: Soft-delete approach for amount discounts is consistent.
Marking the discount'sDeletedAttimestamp is aligned with typical soft-delete patterns.
271-271: Clear error message on amount discount upsert failure.
Good practice to wrap the underlying error.
279-279: Updatingupdated_atensures correct last-modified tracking.
This is a good practice to maintain accurate timestamps.
291-291: Refetching lines post-upsert is prudent.
Helps return the most up-to-date state after database changes.
429-434: Appending usage discounts withWhere(...DeletedAtIsNil()).
This ensures only active usage discount entries are included for expanded line items.openmeter/billing/discount.go (12)
76-76: Interface assertion forDiscountsis fine.
Verifies thatDiscountscorrectly implementsmodels.Clonable.
78-82:Discountsstruct definition looks clean.
Organizes percentage and usage discounts under a single type.
83-95:Clone()method forDiscountsis well-structured.
Correctly creates a deep copy of nested pointers.
101-111: Validation logic is straightforward.
Gracefully returns upon finding a non-nil discount field.
113-113: Comment forDiscountReasonis minimal and fine.
114-114:discountReasoninterface name is clear.
Provides unambiguous contract for discount subtypes.
120-134: Interface methods fordiscountReasonare logically distinct.
Makes it easy to access typed discount data (percentage, usage, etc.).
136-141:Values()function enumerates discount reason types.
Good to have a helper for all possible enumerations.
144-145:MaximumSpendDiscountplaceholder type is acceptable.
Keeps the structure consistent with other discount subtypes.
147-300:DiscountReasonstruct and JSON methods are well-designed.
They ensure typed marshalling/unmarshalling for each discount category.
302-313:Validate()function covers all discount reason cases.
Handles recognized types properly and flags invalid ones.
97-99:Details
✅ Verification successful
Verify
IsEmpty()usage.
lo.IsEmpty(d)may behave unexpectedly for struct values. Confirm it truly checks if bothPercentageandUsagearenil.
🏁 Script executed:
#!/bin/bash # Searching for references to IsEmpty in the codebase rg -A 3 'IsEmpty\('Length of output: 11295
Discounts.IsEmpty: Confirmed Correct Behavior
I’ve verified that using
lo.IsEmpty(d)for theDiscountsstruct is consistent with its intended use. The function properly returns true when both thePercentageandUsagefields are nil (i.e. the struct is at its zero state). Similar patterns throughout the codebase further support that this behavior is expected.No changes are required.
openmeter/productcatalog/discount_test.go (14)
17-17: Migrating toDiscountsfield for test struct is consistent.
No issues identified.
22-26: Test coverage for valid percentage discount scenario is good.
30-34: Test coverage for valid usage discount scenario is good.
40-40: JSON serialization ofDiscountsis straightforward.
Uses standard library approach.
45-45: Unmarshalling into a zero-valueDiscountsstruct is correct.
49-49: Equality check confirms round-trip JSON correctness.
65-69: Percentage discount equality test (left side) is valid.
71-74: Percentage discount equality test (right side) mirrors the left side.
80-82: Differing discount type (percentage vs usage) ensures negative test coverage.
85-87: Confirms that usage discount differs from a percentage discount.
110-114: Valid percentage discount within constraints (0–100%).
118-125: Catches invalid discount exceeding 100%.
Properly expects an error.
127-135: Valid usage discount test is correct.
Ensures usage-based discount is recognized.
139-141: Detects negative usage discount as invalid.
Good coverage of edge cases.api/client/javascript/src/client/schemas.ts (20)
2330-2341: Looks good: correlation ID documentation improvements and discount reason union.
These clarifications for progressive billing help maintain discount consistency across invoices, and the updatedBillingDiscountReasonunion aligns well with the single-discount-per-type approach.
2356-2358: Well-structured introduction ofBillingDiscounts.
The correlation ID documentation clarifies usage in progressive billing, and consolidating percentage and usage discounts underBillingDiscountsis consistent with the new architecture.Also applies to: 2363-2369
3401-3463: Comprehensive addition of new discount types and correlation ID references.
The newDiscountPercentageandDiscountReason*types are clearly documented, and the correlation ID logic for progressive billing is consistent.
3478-3484: UnifiedDiscountstype.
Introducing a single type with optional percentage and usage fields simplifies handling multiple discount forms. This aligns with the PR’s single-discount-per-type goal.
4978-4978: Invoice line discounts reference.
ExposingInvoiceLineDiscountsin the invoice item schema maintains consistency with the new discount structure.
5197-5197:BillingDiscountsusage in invoice lines.
Linking the unified discount structure here ensures seamless discount handling for quantity-based lines.
5218-5218: Introduction ofInvoiceLineAmountDiscount.
Defining a clear amount-based discount type is consistent with the broader single-discount-per-type changes.
5247-5275: EnhancedInvoiceLineDiscounts.
Combiningamountandusagearrays in this structure elegantly supports multiple discount modalities on a single line.
5320-5368: New documentation forInvoiceLineUsageDiscount.
Details on timestamps, correlation ID, and usage quantity handling are thorough and align with progressive billing requirements.
5742-5742: Extended discounts field in the invoice item schema.
Allowing the line-level discount array fosters flexibility for lines that can have multiple discount entries.
5935-5935: OptionalBillingDiscountsaddition.
Applying the consolidated discount structure at this line level is in line with the new single-per-type approach.
7448-7448: AdoptingDiscountsin the rate card.
Including both percentage and usage discount fields here aligns with the rate card’s extended discount coverage.
7567-7567: Usage-based rate card discounts.
The newly introducedDiscountsobject ensures usage-based or percentage-based discounts can both be captured.
8587-8587: Subscription ItemDiscounts.
Extending the subscription item to accommodate both amount and usage discounts supports more granular discount configuration.
8646-8646: Plan-level discount unification.
Thediscountsfield now uses the unified structure, which helps maintain a consistent discount model.
8704-8704: Phase-based plan discount unification.
Implementingdiscountswith a single type clarifies discount logic in phased billing structures.
9264-9268: Exposure ofBillingDiscountsand reason fields.
Redefining the discount reason and usage aligns with the shift to a single discount data model.
9379-9387: New discount reasons andDiscountsexport.
ExportingDiscountReasonMaximumSpend,DiscountReasonRatecardPercentage,DiscountReasonRatecardUsage,DiscountUsage, andDiscountsextends the client’s coverage of the newly consolidated discount structures.
9479-9484: New exports for invoice line discounts.
InvoiceLineAmountDiscountandInvoiceLineDiscountsprovide improved clarity for line-level discount details.
9493-9494: Export ofInvoiceLineUsageDiscount.
This final addition ensures usage-based discounts are fully covered in the client schema exports.openmeter/billing/service/lineservice/discountpercentage.go (3)
19-26: Looks good for single-discount flow.
This approach correctly checks for a nil discount and safely returns without mutating further.
34-41: Ensure discount pointer usage remains safe.
Since we skip if discount is nil, dereferencing with*discountis guarded, and appending tol.Discounts.Amountis consistent with the new single discount approach.
69-83: Comprehensive percentage validation.
The check for discount bounds between 0% and 100% is straightforward and prevents invalid usage. Implementation appears correct.openmeter/ent/db/billinginvoicelineusagediscount_delete.go (1)
1-89: Standard Ent delete builder looks correct.
The generated file follows typical patterns for predicate-based deletion. No issues found.openmeter/billing/adapter/invoicelinediff.go (5)
60-62: Utility method for empty diffs.
Providing anIsEmpty()check is a helpful convenience for subsequent logic.
351-376: Centralized handling of line-dependent discounts.
Combining usage and amount discount diffs intooutis coherent. No major concerns.
378-381: Interface for diffable discounts.
Requiring standard methods likeGetIDandContentsEqualis a clean design for discount objects.
383-386: Result struct is clear.
The struct neatly encapsulates the constructed diff and affected line IDs.
423-476: Database vs. current discount sets.
The creation, deletion, and update steps are well-defined. The use of maps for IDs appears efficient.tools/migrate/migrations/20250411062903_billing-split-line-discounts.up.sql (6)
1-2: Confirm data migration or retention for usage discounts.
These lines remove usage discounts from the old table without migrating them. Verify that the deleted data is genuinely no longer needed or has already been migrated to a new store.
5-6: Multiple modifications in one ALTER statement look fine.
The statement drops a constraint, changes defaults, and modifies columns in a single command. This is valid syntax, but ensure no migration conflicts occur, especially if large data volumes exist.
7-8: Dropping the default after setting it temporarily.
You set a default of 0 for the "amount" column and then immediately remove it. If this was done to handle existing records, please confirm no new rows are inserted during the step.
10-26: New usage discounts table looks well-structured.
The table columns and primary key definition align with the single-discount-per-type approach. The foreign key constraint and referencing columns appear correct.
28-34: Index creation is consistent with the usage discount model.
These unique and non-unique indexes help ensure quick lookups by ID, namespace, and references. This is good for performance.
37-37: Verify the removal of the old billing_invoice_discounts table.
Dropping this table might remove data that was still relevant or not fully migrated to the new structure. Confirm data integrity and that references have been fully replaced.openmeter/ent/schema/billing.go (5)
22-23: New JSONStringValueScanner usage.
Defining scanners for*billing.Discountsand*billing.DiscountReasoncentralizes JSON (un)marshalling, improving consistency.
429-431: Separate edges for usage-based vs. amount-based discounts.
Definingline_usage_discountsandline_amount_discountsclarifies the distinction between discount types. Ensure all the existing code referencing line discounts has been updated to handle these new edges.
513-541: Introducing BillingInvoiceLineDiscountBase for shared discount fields.
Centralizing these fields under one mixin schema is a clean approach that consolidates common columns (line_id, description, etc.).
557-605: Field definitions with deprecated placeholders.
Including deprecated fields (like “type”, “quantity”, etc.) for backward compatibility is reasonable. Marking them clearly as deprecated is helpful in avoiding accidental usage.
627-686: Usage discount model introduced.
This new schema mirrors the usage discount DB table, reflecting the “single discount per type” approach. The custom value scanner references, reason details, and other fields align with the updated discount logic.openmeter/productcatalog/discount.go (4)
8-8: Using github.com/samber/lo for convenience utilities.
This library simplifies pointer usage (e.g.lo.ToPtr) and emptiness checks. Be sure it doesn't introduce unintended overhead.
26-38: PercentageDiscount validation boundaries.
Rejecting values outside [0,100] prevents invalid or nonsensical discounts. This is correct and well-handled.
114-116: Consolidated Discounts struct.
By storing either aPercentageDiscountorUsageDiscount, the code enforces a single discount per type. This matches the new approach.
118-190: Lifecycle methods for Discounts.
TheEqual,Clone,Validate,ValidateForPrice, andIsEmptymethods provide a complete set of operations to manage discount data. The usage oflo.IsEmptyis neat for quick checks.openmeter/billing/invoicelinediscount.go (30)
23-26: Struct field additions
These newly added fields (Description, ChildUniqueReferenceID, ExternalIDs, Reason) appear consistent with the updated discount structure.
32-33: Validation logic
EnsuringReason.Validate()is called and errors appended is a solid approach.
47-49: Getter for ChildUniqueReferenceID
Simple and clear method for retrieving the child reference ID.
52-53: LineDiscountBaseManaged
EmbeddingManagedModelWithIDaligns with the new managed model approach and ensures consistent ID tracking.
105-106: AmountLineDiscountManaged
Again, embeddingManagedModelWithIDtogether withAmountLineDiscountmaintains consistency for managed fields.
120-120: Equality check
ValidatingManagedModelWithIDequality is essential for accurate model comparison.
133-134: Clone method
Clones the embedded structs correctly, preventing unintended side effects.
138-140: ContentsEqual
Focuses on discount data equality rather than managed fields. Good for partial comparisons.
142-144: GetManagedFieldsWithID
Exposes embedded managed fields, facilitating ID reuse and change tracking.
146-151: WithManagedFieldsWithID
Allows updating managed fields while retaining the discount data.
153-159: AmountLineDiscountsManaged + Clone
Useslo.Mapto replicate items, ensuring an immutable approach to updating.
161-168: SumAmount
Sums amounts with rounding, a sensible approach for currency calculations.
170-178: GetByID
Collects discounts into a map keyed by ID. The O(n) approach is typical given the presumably small size.
180-188: GetDiscountByChildUniqueReferenceID
Performs a linear search by child reference ID. Straightforward for smaller arrays.
190-203: Mutate
Clones the collection before applying each mutator, preventing side effects on the original slice.
255-256: UsageLineDiscountManaged
Analogous to the amount discount approach, embedding managed fields and usage discount data.
270-279: Equal
Checks both the managed model and usage discount fields properly.
283-284: Clone
Mirrors the cloning logic used in amount discounts, ensuring consistent behavior.
288-289: ContentsEqual
Similar approach to compare usage discount content ignoring managed data.
292-293: GetManagedFieldsWithID
Simple accessor for retrieving the embedded managed model fields.
296-300: WithManagedFieldsWithID
Offers a clean way to reuse or reset managed fields.
303-304: UsageLineDiscountsManaged
Defines a slice of usage-based discount items.
305-305: LineDiscounts doc comment
Indicates a collection of line discounts aggregated together.
307-309: Interface conformance
Implementsmodels.Clonableandmodels.ValidatorforLineDiscounts.
312-315: LineDiscounts struct
Holds separate lists for amount-based and usage-based discounts.
317-330: Clone method
Clones both amount and usage slices to maintain immutability.
335-351: Validate method
Aggregates validation results across both discount lists, returning combined errors.
353-369: ReuseIDsFrom
Attempts to match existing discount entries by unique reference ID and reuse their IDs.
370-372: IsEmpty
Checks for an empty discount by verifying both slices are zero-length.
374-426: Utility functions for ID reuse
Implements the logic to reuse or clear managed fields based on child references.openmeter/ent/db/billinginvoicelineusagediscount_update.go (76)
1-19: File header and imports
Auto-generated by Ent; typically no manual edits needed.
21-26: BillingInvoiceLineUsageDiscountUpdate struct
Holds configuration and mutation logic for updates.
28-32: Where method
Appends predicates to filter the update operation.
34-38: SetUpdatedAt
Sets the timestamp for theupdated_atfield. Straightforward.
40-44: SetDeletedAt
Assigns a deletion timestamp, used for soft deletion.
46-52: SetNillableDeletedAt
Only setsdeleted_atif the given pointer is non-nil.
54-58: ClearDeletedAt
Clearsdeleted_at, unmarking the entity as deleted.
60-64: SetLineID
Sets the foreign key field for line association.
66-72: SetNillableLineID
Only sets line ID if not nil.
74-78: SetChildUniqueReferenceID
Assigns the unique reference ID for child references.
80-86: SetNillableChildUniqueReferenceID
Same logic, only sets if provided.
88-92: ClearChildUniqueReferenceID
Removes a previously set child reference ID.
94-98: SetDescription
Simple setter for thedescriptionfield.
100-106: SetNillableDescription
Setsdescriptiononly if non-nil.
108-112: ClearDescription
Clearsdescription.
114-118: SetReason
Assigns the enum-based discount reason.
120-126: SetNillableReason
Ensures reason is set only if pointer is not nil, avoiding unintended overrides.
128-132: SetInvoicingAppExternalID
Sets the external ID for the invoicing app.
134-140: SetNillableInvoicingAppExternalID
Only assigns external ID if provided.
142-146: ClearInvoicingAppExternalID
Clears the invoicing app external ID field.
148-152: SetQuantity
Stores the numeric quantity for usage-based discounts.
154-160: SetNillableQuantity
Sets quantity only if non-nil.
162-166: SetPreLinePeriodQuantity
Establishes a discount quantity before the line period.
168-174: SetNillablePreLinePeriodQuantity
Assignspre_line_period_quantityif provided.
176-180: ClearPreLinePeriodQuantity
Clears the previously set pre-line period quantity.
182-186: SetReasonDetails
Attaches an entireDiscountReasonobject.
188-192: ClearReasonDetails
Removes the reason details object.
194-198: SetBillingInvoiceLineID
Associates with aBillingInvoiceLineby ID.
200-203: SetBillingInvoiceLine
A convenience method that extracts ID from aBillingInvoiceLineentity.
205-208: Mutation
Exposes the underlying mutation object.
210-214: ClearBillingInvoiceLine
Removes the association to the billing invoice line.
216-220: Save
Executes the update query and returns the count of updated rows.
222-229: SaveX
Version ofSavethat panics on error, typical ent pattern.
231-235: Exec
Runs the update without returning the row count.
237-242: ExecX
Panics ifExecfails.
244-250: defaults
Setsupdated_atif not already provided.
252-268: check
Runs validation checks, e.g., reason validation and ensuring required edges are not cleared.
270-370: sqlSave
Core logic that constructs the SQL update spec, applies field changes and edges, then executes.
372-378: BillingInvoiceLineUsageDiscountUpdateOne
Builder for updating a single entity rather than multiple.
380-384: SetUpdatedAt
Same logic as the multi-update, but specific to a single record.
386-390: SetDeletedAt
Marks the record as deleted via timestamp.
392-398: SetNillableDeletedAt
Only setsdeleted_atif the value is non-nil.
400-404: ClearDeletedAt
Unsets thedeleted_atfield.
406-410: SetLineID
Sets the line relation by ID.
412-418: SetNillableLineID
Same as above, but guarded by nil checks.
420-424: SetChildUniqueReferenceID
Sets or updates child reference ID on the discount entity.
426-432: SetNillableChildUniqueReferenceID
Only assigns the child reference if non-nil.
434-438: ClearChildUniqueReferenceID
Clears the ID from the entity.
440-444: SetDescription
Sets the discount’s description.
446-452: SetNillableDescription
Assigns description only if not nil.
454-458: ClearDescription
Resets the description field.
460-464: SetReason
Sets the discount reason.
466-472: SetNillableReason
Omits assigning the reason if pointer is nil.
474-478: SetInvoicingAppExternalID
Sets the invoicing app’s external ID.
480-486: SetNillableInvoicingAppExternalID
Sets the external ID only if the pointer is non-nil.
488-492: ClearInvoicingAppExternalID
Removes external ID value from the record.
494-498: SetQuantity
Defines the usage discount quantity.
500-506: SetNillableQuantity
Same as SetQuantity, but guarded by nil checks.
508-512: SetPreLinePeriodQuantity
Assigns a discount quantity relevant to earlier usage in the line period.
514-520: SetNillablePreLinePeriodQuantity
Only sets the pre-line quantity if the pointer is non-nil.
522-526: ClearPreLinePeriodQuantity
Resets pre-line quantity to nil.
528-532: SetReasonDetails
Links additional structured discount reason details.
534-538: ClearReasonDetails
Removes reason details from the record.
540-544: SetBillingInvoiceLineID
Links to the invoice line by a given string ID.
546-549: SetBillingInvoiceLine
Convenience method: sets line ID from an entity.
551-554: Mutation
Exposes underlying mutation object.
556-560: ClearBillingInvoiceLine
Removes the line association.
562-566: Where
Attaches predicates for filtering the single-record update.
568-573: Select
Allows specifying which columns to return.
575-579: Save
Executes the update query and returns the updated entity.
581-588: SaveX
Panics ifSavefails, following Ent’s convenience pattern.
590-594: Exec
Runs the update without returning the updated entity.
596-601: ExecX
Panics ifExecfails.
603-609: defaults
Ensuresupdated_atis set to default if not set.
611-627: check
Validates reason enums, reason details, and ensures required edges aren’t improperly cleared.
629-749: sqlSave
Core update logic for the single-entity builder, building the spec and applying field/edge updates.openmeter/ent/db/billinginvoicelineusagediscount/where.go (16)
1-14: File header and imports
Auto-generated ent code for building predicates. Usually requires no manual changes.
15-69: ID-based predicates
These cover equality, inequality, containment, and case-folded checks for the primary key.
70-184: Namespace-based predicates
Allows filtering bynamespacewith multiple operators (EQ, NEQ, In, NotIn, Contains, etc.).
185-223: CreatedAt-based predicates
A variety of comparisons (EQ, NEQ, GT, etc.) to filter by creation time.
225-263: UpdatedAt-based predicates
Parallel to CreatedAt, includes EQ, NEQ, GT, GTE, etc. for update time.
265-315: DeletedAt-based predicates
Handles soft-deletion checks, including IsNil/NotNil for active vs. soft-deleted records.
315-379: LineID-based predicates
Covers line ID matching, substring checks, and case-folded variants.
385-453: ChildUniqueReferenceID-based predicates
Includes filters for presence/absence (IsNil/NotNil) and string comparisons.
455-528: Description-based predicates
EQ, NEQ, sub-string checks, IS NULL checks for discount descriptions.
530-558: Reason-based predicates
Covers enumerations for discount reason with In/NotIn checks.
560-633: InvoicingAppExternalID-based predicates
Filters external ID with contain/prefix/suffix, plus nil checks.
635-673: Quantity-based predicates
Covers decimal quantity comparisons and membership checks.
675-723: PreLinePeriodQuantity-based predicates
Similar to quantity, plus nil checks for optional usage.
725-733: ReasonDetailsIsNil / NotNil
Predicates to detect presence or absence of reason details.
735-756: HasBillingInvoiceLine / HasBillingInvoiceLineWith
Checks existence or matching of the related invoice line entity.
758-771: And, Or, Not
Logical composition operators for chaining multiple conditions.openmeter/ent/db/planratecard_create.go (1)
325-329: Implementation looks good and aligns with PR objectives.Adding validation for the
Discountsfield follows the same pattern used for other fields in this struct. This ensures that any discounts added to aPlanRateCardare properly validated before persisting to the database.openmeter/ent/db/planratecard_update.go (2)
323-327: Change is consistent with create operation validation.This validation logic for the
Discountsfield in the update path follows the same pattern as in the create path, ensuring consistency in how discounts are validated across operations.
806-810: Validation properly implemented for single-entity update.Adds the same discount validation to the single-entity update path, ensuring all update operations validate the discounts field consistently.
api/spec/src/productcatalog/discounts.tsp (1)
55-71: Good implementation of the new discount model structure.The new
Discountsmodel elegantly implements the "single discount per type" requirement by consolidating different discount types (percentage, usage) as optional properties in a single object rather than using an array of discount objects. This structural change supports the PR objective while maintaining clean separation of discount types.I like that the model is designed with future expansion in mind (commented out
amountfield) while keeping the current implementation focused on the immediate requirements.api/spec/src/productcatalog/subscription.tsp (2)
174-174: Type change aligns with new discount model.Changed the
discountsproperty type from what was likely an array of discount objects to the new consolidatedDiscountsmodel, ensuring consistency with the "single discount per type" approach throughout the codebase.
239-239: Consistent implementation of the new discount model.Changed the
discountsfield in theSubscriptionItemmodel to use the newDiscountstype, maintaining consistency with the changes made throughout the codebase.api/spec/src/productcatalog/ratecards.tsp (2)
117-119: Appropriate consolidation of discount typesThe change from
discounts?: DiscountPercentage[]todiscounts?: Discountsaligns with the PR objective of allowing only a single discount per type. This unified structure will support both percentage and usage values in one property.
161-162: Consistent implementation of consolidated discount structureThis change correctly matches the modification made to the
RateCardFlatFeemodel, ensuring consistency across rate card types. The newDiscountstype provides a cleaner representation of discounts.e2e/productcatalog_test.go (3)
188-190: Updated discount type matches new model structureThe switch from
api.DiscountUsagetoapi.DiscountPercentageproperly implements the new discount model. The use ofmodels.NewPercentage(10)correctly initializes the percentage value.
205-205: Proper assignment to the new Discounts structureThis line correctly assigns the discount to the new consolidated
Discountsstructure, using the appropriate field for the percentage discount.
284-285: Test assertions updated for new discount structureThe assertions have been properly updated to validate the presence and value of the percentage discount in the new structure. The use of
InexactFloat64()ensures proper decimal comparison.api/spec/src/billing/invoices/invoice.tsp (3)
616-616: Unified discount structure for invoice linesChanged from
discounts?: InvoiceLineDiscount[]todiscounts?: InvoiceLineDiscountsto align with the new single discount per type approach. This matches the architectural changes in the discount system.
715-715: Consistent discount structure in usage-based rate cardsProperly updated from
discounts?: BillingDiscount[]todiscounts?: BillingDiscountsto maintain consistency with the unified discount model throughout the system.
795-795: Updated discount structure for flat fee rate cardsChanged from
discounts?: BillingDiscountPercentage[]todiscounts?: BillingDiscounts, completing the consistent implementation of the discount structure across all relevant models.openmeter/ent/db/billinginvoiceline_create.go (5)
21-21: Added import for new discount typeAdded import for
billinginvoicelineusagediscountto support the separated discount tables approach.
417-430: New method for usage-based discount relationshipsThe new
AddLineUsageDiscountIDsandAddLineUsageDiscountsmethods properly implement the separation of usage discounts into their own table, as specified in the PR objectives.
432-445: Added methods for amount-based discount relationshipsThese new methods implement the handling of amount discounts, properly supporting the separation of discount types into different tables. This provides better type safety and database schema organization.
838-853: Updated database edge handling for usage discountsThe
createSpecmethod has been updated to correctly handle the new usage discount relationship. This ensures that database operations will properly maintain the relationships between invoice lines and their usage discounts.
854-869: Updated edge handling for amount-based discountsThe code correctly configures the database edge for amount discounts, using the appropriate table and column names for the relationship. This completes the implementation of the separated discount tables approach.
api/spec/src/billing/invoices/discounts.tsp (5)
24-24: Confirm adoption of the new discount reason type.
The shift toBillingDiscountReasonaligns with the single-discount-per-type approach. Ensure all references to old enums are cleaned up throughout the codebase and all usage sites are updated.Would you like a script to check for any lingering references to
InvoiceDiscountReason?
40-57: Great consolidation intoInvoiceLineDiscounts.
Separatingamountandusagefields in one structure clarifies discount application. This also paves the way for simpler expansions later. No issues found here.
60-83: Usage discount name and doc look consistent.
The newInvoiceLineUsageDiscountmodel name is intuitive. Verify that progressive billing references (e.g.,preLinePeriodQuantity) are validated upstream.
86-98: Amount-based discount updates look good.
Renaming toInvoiceLineAmountDiscountclarifies that it’s applied to monetary amounts, rather than usage metrics.
134-197: Robust typed union for discount reasons.
DefiningBillingDiscounts,DiscountReasonType, and the discriminated union fosters extensibility. Everything here appears consistent with the single-discount-per-type goal.openmeter/ent/db/billinginvoiceline_query.go (10)
20-20: New import for usage discount query is correct.
No issues with this addition; it’s necessary for the new usage discount features.
30-46: New fields for discount queries.
AddingwithLineUsageDiscountsandwithLineAmountDiscountsto the query struct is consistent with the new discount separation. Verify that older discount references are removed to avoid confusion.
193-213:QueryLineUsageDiscountsmethod looks correct.
The O2M edge declaration and pathing logic properly link usage discounts to invoice lines.
215-235:QueryLineAmountDiscountsmethod.
Similarly well-formed approach to the amount discount edge. Name is clear, matching the new schema structure.
489-505: Clone method updated for the new discount fields.
This ensures cloned queries also preserve discount-based relationships, preventing missed data in subsequent queries.
700-707:loadedTypesexpansion is correct.
Increasing the array size and indexing usage/amount discount edges ensures they are tracked during eager loading.
773-781: Lazy-load usage discount objects.
This integration withloadLineUsageDiscountsis consistent with the rest of the code. Confirm that no concurrency issues arise if discounts are loaded alongside lines.
782-789: Lazy-load amount discount objects.
Same approach as usage discounts; consistent and clean.
971-1000:loadLineUsageDiscountsmethod.
Implementation matches typical ent O2M loading patterns. Seems correct for usage-based relationship.
1015-1015: Correct field reference for line amount discounts.
Ensures your SELECT/WHERE is properly referencingbillinginvoiceline.LineAmountDiscountsColumn.openmeter/ent/db/billinginvoiceline.go (6)
117-120: Separation of usage and amount discounts in edges.
The new edge fields clarify the discount type at a glance. This improves readability of the domain model.
129-130: Expanded loaded types array.
This is consistent with the addition of new discount edges.
185-192:LineUsageDiscountsOrErraccessor method.
Providing an explicit “or error” method is helpful for distinguishing an unloaded edge vs. an empty relationship.
194-201:LineAmountDiscountsOrErraccessor method.
Again, matches the usage discount approach. You’ve enforced strongly typed accessor semantics.
536-539: Querying usage discounts at the entity level.
This collocates well with the remaining query methods, ensuring consistent API usage.
541-544: Querying amount discounts at the entity level.
Parallel to the usage discount logic. No issues found.openmeter/ent/db/billinginvoicelineusagediscount.go (6)
1-16: Standard Ent-generated package and import statements.
These lines appear to be automatically generated boilerplate for Ent. No issues noted.
18-49: New struct and edges for billing invoice line usage discounts.
The struct definition and edge configuration conform to Ent patterns. Field naming is clear and consistent.
73-93: scanValues function review.
Properly maps columns to the correct data types, leveraging NullScanner for decimals. This is a standard Ent approach, and looks correct.
95-191: assignValues function review.
All fields appear to be assigned correctly with type checks and error reporting for unexpected types. This follows typical Ent patterns and looks solid.
193-220: Value, QueryBillingInvoiceLine, Update, and Unwrap methods.
These are standard Ent helper methods. They appear correctly implemented with no evident issues.
222-280: String() method and final definitions.
Generates a helpful string representation. No issues discovered.openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (8)
94-97: New edge constants for usage and amount discounts.
Both constants are clear, consistent with naming conventions, and align with the single-discount-per-type restructuring.
135-148: Database table definitions for line usage and amount discounts.
Well-named constants for table and column references. These definitions accurately match the new discount entity structure.
484-489: ByLineUsageDiscountsCount ordering function.
Provides a way to order by the count of associated usage discounts. Follows Ent patterns for ordering by edge relationships.
491-496: ByLineUsageDiscounts ordering function.
Implements ordering by usage discount terms. Straightforward and adheres to Ent’s order-by-neighbor approach.
498-503: ByLineAmountDiscountsCount ordering function.
Similar to its usage-based counterpart, this function is properly set up for ordering by amount discount counts.
505-510: ByLineAmountDiscounts ordering function.
Aligns with Ent’s neighbor-based ordering, mirroring the usage discount approach. No issues identified.
567-573: newLineUsageDiscountsStep function.
Defines an O2M relationship from billing lines to usage discounts. Matches the newly introduced entity references without issues.
574-580: newLineAmountDiscountsStep function.
Complements the usage discount relationship with an amount discount relationship. Implementation is consistent and correct.openmeter/ent/db/client.go (12)
31-31: Added import for the new entity typeThe import of the new
billinginvoicelineusagediscountpackage enables working with the newly added entity type in the codebase.
93-94: Added client field for BillingInvoiceLineUsageDiscountThis change introduces a new client field for handling the
BillingInvoiceLineUsageDiscountentity, which aligns with the PR objective of separating unit and amount discounts into different tables.
171-171: Initialized the new client in the init methodThe initialization of the
BillingInvoiceLineUsageDiscountclient ensures it's properly set up when the main client is created.
303-303: Added the new client to transaction initializationThis ensures the new
BillingInvoiceLineUsageDiscountclient is available in transactions, keeping consistency with other entity clients.
362-362: Added the new client to BeginTx methodSimilar to the transaction initialization above, this ensures the client is properly set up when starting a transaction with options.
421-423: Updated hook registration to include the new entityThis modification ensures that hooks (mutation hooks) will be applied to the new
BillingInvoiceLineUsageDiscountentity as well.
442-444: Updated interceptor registration for the new entitySimilar to the hook registration, this ensures that interceptors (query interceptors) will be applied to the new entity.
487-488: Added mutation handling for the new entityThis change ensures that mutations (create, update, delete operations) on the new entity are properly handled.
2661-2675: Added query method for line usage discountsThis method enables querying the relationship between a
BillingInvoiceLineand its associatedBillingInvoiceLineUsageDiscountentities. The implementation follows the standard pattern for ent ORM relationship queries.
2677-2691: Renamed relationship to clarify discount typeThe relationship query method has been updated to specifically reference "line_amount_discounts" which clarifies the purpose of this relationship now that discounts have been split into separate types.
2915-3062: Added complete client implementation for BillingInvoiceLineUsageDiscountThis is the core implementation of the new client for managing usage-based discounts. It follows the standard pattern for ent ORM clients with methods for creating, querying, updating, and deleting entities. The implementation is consistent with other entity clients in the codebase.
7472-7494: Updated hooks and interceptors structuresThese updates ensure that the hooks and interceptors structures include the new entity, which is necessary for the proper functioning of hooks and interceptors with the new entity.
openmeter/ent/db/billinginvoicelinediscount_update.go (14)
114-118: Method for setting discount reason looks consistent.
No immediate issues; the method follows the standard builder pattern and leverages thebilling.DiscountReasonType.
120-126: Nillable setter logic is consistent.
This ensures null safety by checking the pointer before setting. No concerns here.
134-140: Nillable setter logic for InvoicingAppExternalID is straightforward.
Implementation is consistent with ent’s pattern.
142-146: Clearing the InvoicingAppExternalID field is handled correctly.
Helps maintain a consistent approach to optional fields.
182-186: Method for setting SourceDiscount.
The usage of abilling.DiscountReasonobject is clear and consistent. Ensure all validations are handled upstream/downstream.
188-192: ClearSourceDiscount approach is correct.
No further issues noted.
208-212: Clearing the 'type' field.
Ensures backward compatibility until the field is fully removed.
363-365: Sets the reason enum in the SQL save step.
No issues; properly keeps reason in sync with the builder.
366-371: Handling InvoicingAppExternalID in the SQL layer.
Implementation aligns with the mutation pattern, clearing or setting as appropriate.
397-408: Sets or clears quantity and preLinePeriodQuantity.
Both are marked as deprecated. Maintain only if needed for backward compatibility.
817-819: Sets the reason enum for a single-entity update (UpdateOne).
Judicious usage of ent’s field setting approach.
820-825: Sets or clears InvoicingAppExternalID in the UpdateOne builder.
Consistent with multi-entity builder approach.
848-850: Clears the 'type' field in the UpdateOne builder.
Implementation is consistent.
852-862: Sets or clears quantity and preLinePeriodQuantity in UpdateOne.
No immediate concerns; consistent with the rest of the code.openmeter/ent/db/billinginvoiceline_update.go (33)
20-20: Imports billinginvoicelineusagediscount package.
This import is needed for the new usage discount code references.
557-561: AddLineUsageDiscountIDs method.
No issues; typical ent pattern for adding edges by IDs.
563-570: AddLineUsageDiscounts method.
Appropriately calls AddLineUsageDiscountIDs after collecting IDs. Looks good.
572-576: AddLineAmountDiscountIDs method.
Maintains parallel structure for amount-based discounts.
578-585: AddLineAmountDiscounts method.
Similar approach as usage discounts. Straightforward.
652-656: ClearLineUsageDiscounts method.
Correctly delegates to the mutation to clear all usage discount edges.
658-662: RemoveLineUsageDiscountIDs method.
Implementation is consistent with standard ent approach for edge removal.
664-671: RemoveLineUsageDiscounts method.
No concerns; delegates removal with ID extraction.
673-677: ClearLineAmountDiscounts method.
Parallel approach for clearing edges for amount discounts.
679-683: RemoveLineAmountDiscountIDs method.
Typical ent edge removal pattern.
685-692: RemoveLineAmountDiscounts method.
Consistent pattern for removing discount edges by ID.
1044-1056: Clearing line_usage_discounts edges in sqlSave.
Ensures the O2M relationship is properly cleared when requested.
1057-1072: Removing line_usage_discounts edges by IDs (sqlSave).
Logic is appropriate for partial removal.
1073-1088: Adding line_usage_discounts edges in sqlSave.
Collects IDs and appends them to the spec for insertion.
1089-1101: Clearing line_amount_discounts edges (sqlSave).
Implements an O2M clear operation.
1102-1117: Removing line_amount_discounts edges by IDs (sqlSave).
Partial edge removal logic is consistent.
1118-1133: Adding line_amount_discounts edges in sqlSave.
Matches the approach for usage discounts.
1756-1761: AddLineUsageDiscountIDs (UpdateOne).
No concerns; aligns with multi-edge patterns.
1762-1769: AddLineUsageDiscounts (UpdateOne).
Collects IDs, then delegates to the prior method.
1771-1775: AddLineAmountDiscountIDs (UpdateOne).
Follows the same structure as usage discount.
1777-1784: AddLineAmountDiscounts (UpdateOne).
Fully consistent with usage discount approach.
1851-1855: ClearLineUsageDiscounts (UpdateOne).
Ok for removing all usage discount edges.
1857-1861: RemoveLineUsageDiscountIDs (UpdateOne).
Standard pattern for partial removal.
1863-1870: RemoveLineUsageDiscounts (UpdateOne).
Works as expected; no issues.
1872-1876: ClearLineAmountDiscounts (UpdateOne).
Clears the O2M edge for amount-based discounts.
1878-1882: RemoveLineAmountDiscountIDs (UpdateOne).
Checks for a valid slice, then removes.
1884-1891: RemoveLineAmountDiscounts (UpdateOne).
Implementation mirrors usage discount removal.
2273-2285: Clearing line_usage_discounts edges in UpdateOne sqlSave.
Ensures proper O2M behavior for usage discounts.
2286-2301: Removing line_usage_discounts edges by IDs in UpdateOne sqlSave.
Implementation aligns with standard ent approach.
2302-2317: Adding line_usage_discounts edges in UpdateOne sqlSave.
Same pattern as multi-edge usage discount addition in the main Update builder.
2318-2330: Clearing line_amount_discounts edges in UpdateOne sqlSave.
Follows the O2M clearing logic for the amount-based discount table.
2331-2346: Removing line_amount_discounts edges by IDs in UpdateOne sqlSave.
Removes partial edges, consistent with the ent approach.
2347-2362: Adding line_amount_discounts edges in UpdateOne sqlSave.
No concerns; parallels usage discount edge logic.openmeter/ent/db/billinginvoicelineusagediscount_create.go (2)
1-2: Auto-generated Ent codeNo issues found; this is typical Ent-generated scaffolding for creating an entity.
171-181: Valid mandatory edge to BillingInvoiceLineThis block properly enforces a mandatory reference to the parent
BillingInvoiceLine, aligning with the requirement that each discount must be associated with a line.openmeter/ent/db/billinginvoicelinediscount/where.go (38)
105-108: New InvoicingAppExternalID predicate is properly aligned with ent's pattern.
No concerns.
120-123: New Type predicate mirrors ent’s convention accurately.
No concerns.
545-549: ReasonEQ predicate follows typical ent usage.
No concerns.
551-555: ReasonNEQ predicate is correct and consistent.
No concerns.
557-564: ReasonIn predicate uses the correct approach for enumerating values.
No concerns.
566-573: ReasonNotIn predicate parallels the In version appropriately.
No concerns.
575-578: InvoicingAppExternalIDEQ predicate is well-defined.
No concerns.
580-583: InvoicingAppExternalIDNEQ predicate is correctly implemented.
No concerns.
585-588: InvoicingAppExternalIDIn predicate handles multiple string arguments properly.
No concerns.
590-593: InvoicingAppExternalIDNotIn predicate is consistent with its “In” counterpart.
No concerns.
595-598: InvoicingAppExternalIDGT predicate is logically correct.
No concerns.
600-603: InvoicingAppExternalIDGTE predicate meets typical ent usage.
No concerns.
605-608: InvoicingAppExternalIDLT predicate implements less-than check correctly.
No concerns.
610-613: InvoicingAppExternalIDLTE predicate aligns with ent’s standard approach.
No concerns.
615-618: InvoicingAppExternalIDContains uses the expected substring match.
No concerns.
620-623: InvoicingAppExternalIDHasPrefix predicate checks prefixes accurately.
No concerns.
625-628: InvoicingAppExternalIDHasSuffix predicate checks suffixes accurately.
No concerns.
630-633: InvoicingAppExternalIDIsNil predicate is consistent with ent’s null-check pattern.
No concerns.
635-638: InvoicingAppExternalIDNotNil predicate is correct for non-null conditions.
No concerns.
640-643: InvoicingAppExternalIDEqualFold handles case-insensitive equality.
No concerns.
645-648: InvoicingAppExternalIDContainsFold manages case-insensitive substring checks.
No concerns.
740-743: SourceDiscountIsNil predicate is suitably defined.
No concerns.
745-748: SourceDiscountNotNil predicate is suitably defined.
No concerns.
750-753: TypeEQ predicate is properly aligned with ent’s best practices.
No concerns.
755-758: TypeNEQ predicate is logically sound.
No concerns.
760-763: TypeIn predicate sets up an array-based match effectively.
No concerns.
765-768: TypeNotIn predicate complements the In logic appropriately.
No concerns.
770-773: TypeGT predicate is straightforward and correct.
No concerns.
775-778: TypeGTE predicate is straightforward and correct.
No concerns.
780-783: TypeLT predicate is aligned with the ent pattern for less-than checks.
No concerns.
785-788: TypeLTE predicate is aligned with ent’s standard approach.
No concerns.
790-793: TypeContains predicate accurately checks for substring matches.
No concerns.
795-798: TypeHasPrefix predicate is accurately implemented.
No concerns.
800-803: TypeHasSuffix predicate is accurately implemented.
No concerns.
805-808: TypeIsNil predicate is valid for null checks.
No concerns.
810-813: TypeNotNil predicate is valid for non-null checks.
No concerns.
815-818: TypeEqualFold predicate matches case-insensitively in a robust manner.
No concerns.
820-823: TypeContainsFold predicate correctly handles case-insensitive substring checks.
No concerns.openmeter/billing/service/lineservice/usagebasedline.go (3)
355-355: Update to use the newly structured discount types.The code has been modified to access the
Amountfield of theDiscountsstructure before callingSumAmount. This change aligns with the PR objective of restructuring discounts to allow a single discount per type, separating amount and usage discounts.
382-391: Updated discount creation to use the new discount structure.The code now correctly uses the new
AmountLineDiscountManagedtype instead of the previous generic discount creation method. This change aligns with the separation of discount types (amount vs. usage) as outlined in the PR objectives.
396-405: Updated the second discount creation to use the new discount structure.Similar to the previous change, this code now uses the new
AmountLineDiscountManagedtype for creating discounts. This ensures consistency in how discounts are represented throughout the codebase.openmeter/billing/adapter/invoicelinediff_test.go (19)
23-23: Field renamed to reflect the new discount structure.The field has been renamed from
DiscountstoAmountDiscountsto accurately represent its content and align with the PR objective of separating different discount types.
51-51: Updated test code to use the new discount structure.The test initialization now uses the new
newAmountDiscountsWithIDsfunction instead of the previous discount creation method.
87-89: Updated test expectation to use the new discount type.The test case expectation has been updated to use
AmountDiscountsinstead ofDiscountsto align with the new discount structure.
121-124: Updated test expectations for discount deletion.The discount deletion test expectation has been updated to use
AmountDiscountsinstead ofDiscountsto match the new structure.
179-179: Updated discount access pattern.The code now accesses discounts through the new structure, using
Discounts.Amount[0].IDinstead of a direct field access pattern.
194-198: Updated test expectations for discount updates.Test expectations for discount creation and deletion have been updated to use
AmountDiscountsinstead ofDiscounts.
208-208: Updated discount field access.The code now correctly accesses discounts through the
Amountfield on theDiscountsstructure.
227-227: Updated discount accessor pattern.The discount accessor pattern has been updated to reflect the new structure.
235-235: Updated test expectations for discount changes.The test expectations for discount changes have been updated to use
AmountDiscountsinstead ofDiscounts.
246-250: Field access updated for the discount structure.The discount field access pattern has been updated to match the new discount structure, accessing through the
Discounts.Amountfield.
257-261: Updated test expectations for detailed discount operations.The test expectations have been updated to reflect the new discount structure, ensuring correct generation and verification of test cases.
281-283: Updated test expectations for discount deletion.The test expectations for discount deletion have been updated to use
AmountDiscountsinstead ofDiscountsto match the new structure.
305-307: Updated test expectations for complex discount scenarios.The test expectations for complex discount scenarios involving deletion of parent lines have been updated to use
AmountDiscountsinstead ofDiscounts.
384-392: Updated helper function for discount ID mapping.The helper function for mapping discount IDs has been updated to work with the new
AmountLineDiscountManagedtype instead of generic discounts.
394-400: Updated diff helper function for discount types.The helper function for creating diffs of discount types has been updated to work with the new discount structure.
402-413: Added helper function for message prefixing.A new helper function
msgPrefixhas been added to improve test message formatting. This is a good addition that enhances test output readability.
418-420: Updated assertion helpers to use the new message prefix function.The assertion helpers have been updated to use the new
msgPrefixfunction for improved error messages.
430-430: Updated assertion helper for discount type.The assertion helper has been updated to check
AmountDiscountsinstead ofDiscounts.
472-485: Replaced discount creation function with a new version.The old
newDiscountsWithIDsfunction has been replaced withnewAmountDiscountsWithIDs, which creates discounts using the newLineDiscountsstructure with anAmountfield. This correctly aligns with the new discount structure.openmeter/billing/service/lineservice/priceunit_test.go (4)
188-202: Updated test discount structure to match new implementation.The test case has been updated to use the new discount structure with explicit
LineDiscountscontaining anAmountarray. This directly initializes the discount structure according to the new design instead of using factory methods.
209-214: Updated discount initialization to use direct struct creation.The discount initialization has been changed from a method-based approach to direct struct initialization, simplifying the code and making it more consistent with the new model structure.
233-235: Updated discount assignment to use the new structure.The discount assignment has been updated to use the new
Discountsstructure with aPercentagefield, correctly aligning with the PR's objective of structuring discounts by type.
249-272: Updated test expectations for discount calculations.The test expectations for discount calculations have been updated to use the new structure, correctly handling both percentage discounts and maximum spend discounts within the new discount model.
openmeter/ent/db/billinginvoicelinediscount_create.go (29)
111-113: Use ofbilling.DiscountReasonTypelooks consistent.
The transition tobilling.DiscountReasonTypeinSetReasonaligns with the new structure, and the existing validator ensures valid inputs.
123-129: Nillable external ID logic is correct.
This pattern follows the standard ent approach for optional fields.
131-135: Confirm if negative amounts are allowable.
If discounts should never be negative, consider validation or mention it in the code.
151-156: Source discount logic appears sound.
Thebilling.DiscountReasonvalidation is handled below, so no issues here.
157-162: Potential risk in using a raw string for the “type” field.
Consider an enum-like approach if you want to prevent invalid discount types.
163-170: Nillable type pattern is consistent.
It aligns well with the new single-discount approach.
289-290: Good enforcement ofline_idrequirement.
This ensures data integrity by rejecting incomplete discount records.
300-301: Enforcing requiredamountis beneficial.
Prevents logic errors from missing discount values.
374-378: Storing reason as an enum is commendable.
This helps maintain controlled discount reasons in the database.
379-381: InvoicingAppExternalID assignment is straightforward.
No issues found with the new field’s usage.
384-384: Amount property assignment is correct.
Successfully captures the discount amount for further usage.
398-408: Added logic fortype,quantity, andpre_line_period_quantity.
Each field is handled in line with the single-discount approach.
557-561: Upsert:SetReasonmirrors create logic.
Maintains consistency between creation and upsert flows.
563-567: Upsert:UpdateReasonis fine.
No conflicts in updating reason in the upsert scenario.
569-573: Upsert:SetInvoicingAppExternalIDmatches the create pattern.
Implementation is consistent across create and upsert.
575-579: Upsert:UpdateInvoicingAppExternalID.
Properly allows updating external ID in upsert contexts.
581-585: Upsert:ClearInvoicingAppExternalID.
Good to have a clear method for optional fields.
617-619: Upsert:SetSourceDiscountparallels create.
Ensures a unified approach to source discount assignment.
623-625: Upsert:UpdateSourceDiscountlogic is fine.
Keeps the discount reason in sync.
629-633: Upsert:ClearSourceDiscount.
Allows fully removing the discount reason, no concerns.
635-639: Upsert:SetTypereaffirms usage of a string field.
Consider validating or restricting possible values.
641-645: Upsert:UpdateType.
No issues in matching the create logic.
647-651: Upsert:ClearType.
Consistent approach to removing the discount type.
653-657: Upsert:SetQuantity.
Mirrors create behavior, no issues spotted.
659-663: Upsert:UpdateQuantity.
Straightforward logic for quantity adjustments.
665-669: Upsert:ClearQuantity.
Properly clears out the discount quantity if no longer needed.
671-675: Upsert:SetPreLinePeriodQuantity.
Aligns with the new discount structure for usage metrics.
677-681: Upsert:UpdatePreLinePeriodQuantity.
No concerns updating usage-based discount data.
683-687: Upsert:ClearPreLinePeriodQuantity.
Consistent clearing logic, no issues here.
7951efc to
31123fb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🔭 Outside diff range comments (1)
openmeter/ent/schema/billing.go (1)
543-605: 🛠️ Refactor suggestionEvaluate handling of new discount struct with deprecated fields
The newBillingInvoiceLineDiscountincludes fields marked deprecated. Consider isolating them or providing a clear migration path to avoid confusion long-term.
🧹 Nitpick comments (31)
openmeter/ent/db/billinginvoicelinediscount_update.go (4)
128-146: Consider validatingInvoicingAppExternalID.Since the
invoicing_app_external_idreferences external systems, add checks (e.g., length constraints, format checks) to ensure valid data is stored.
194-212:SetTypeintroduction is consistent but consider limiting possible values.Storing the discount
typeas a free-form string can lead to inconsistent data. If the set of discount types is known, consider using a string-enum or custom validation for better integrity.
552-570:InvoicingAppExternalIDsetters forUpdateOnemirror the multi-update approach.As above, consider adding validation for external IDs to prevent unforeseen issues (e.g., empty strings or invalid formats).
618-636:SetTypeinUpdateOnemaintains consistency with the main builder.Same consideration applies: enforce known discount types or apply validation to avoid inconsistent values in the database.
openmeter/billing/httpdriver/invoiceline.go (1)
428-490: Enhanced discount mapping with structured API response.The function now returns a structured
InvoiceLineDiscountsobject that separates amount and usage discounts, rather than a flat list. This provides better organization of discount data in API responses and supports the PR goal of allowing only a single discount per type.There's a small issue in the error message at line 483 - it says "amount discounts" when it should say "usage discounts" since it's in the usage discount mapping section.
- return nil, fmt.Errorf("failed to map amount discounts: %w", err) + return nil, fmt.Errorf("failed to map usage discounts: %w", err)api/openapi.yaml (8)
10588-10605: Clarify "BillingDiscountReason" Schema and Correlation ID Documentation.
The new block introduces theBillingDiscountReasonschema using aoneOfcomposition and a discriminator to select between discount reason types. The in-line documentation regarding correlation ID auto-generation is informative; however, consider rephrasing “setups the discount amounts might be incorrect” for improved clarity (e.g. “…or the discount amounts may be computed incorrectly if modified”).
10627-10643: Introduction of the "BillingDiscounts" Composite Schema.
This hunk adds theBillingDiscountsschema that consolidates both percentage and usage discount properties. This design aligns with the single discount per type approach. Please ensure that both properties are validated downstream and that any documentation or examples clearly illustrate the expected object structure.
12182-12202: Addition of a Correlation ID to "DiscountReasonRatecardPercentage".
The updated schema now introduces acorrelationIdproperty with a specific regex pattern and detailed description. Verify that the pattern is consistent with other discount schemas and consider revising the phrase “setups the discount amounts might be incorrect” for enhanced clarity.
12209-12233: Improved "DiscountReasonRatecardUsage" Schema with Usage and Correlation ID.
This block expands theDiscountReasonRatecardUsageschema by adding aquantityfield (with a note that it must be positive) and acorrelationIdfield similar to the percentage counterpart. Please ensure that the phrasing in the description is consistent and clear across both schemas.
12253-12264: Consolidated "Discounts" Schema Design.
A newDiscountsschema now aggregates theDiscountPercentageandDiscountUsagedefinitions. This consolidation supports the new single discount per type approach. Verify that both the percentage and usage paths are properly validated in processing logic.
14432-14436: Fix Typographical Error in Discounts Description.
The description “Discounts detailes applied to this line” contains a typo—“detailes” should be corrected to “details” for clarity and consistency.
14832-14851: "InvoiceLineDiscounts" Schema with Separated Discount Arrays.
The revisedInvoiceLineDiscountsschema cleanly divides amount-based and usage-based discounts into separate arrays. Ensure that this structure is handled correctly in any discount aggregation or rendering logic.
15552-15558: Consistent Discounts Reference with Repeated Typo.
Again, thediscountsfield description includes the typo “Discounts detailes applied to this line.” Please update to “details” to maintain consistency throughout the document.api/openapi.cloud.yaml (7)
10761-10778: Clarify and Improve Correlation ID Description in BillingDiscountReason
The new BillingDiscountReason schema is well structured with a discriminator and clear mappings. However, the multi‐line description for the correlation ID contains awkward phrasing (e.g. “setups the discount amounts might be incorrect”). Consider rewording it for clarity. For example: “If not provided, the invoicing engine will auto‐generate one. When editing an invoice line, please ensure the correlation ID remains unchanged; otherwise, discount amounts may be calculated incorrectly.”
10800-10816: Review of the BillingDiscounts Schema Definition
The BillingDiscounts object now cleanly aggregates both percentage and usage discounts. It would be beneficial to add a brief note explaining how the two properties interact if both are provided. Additionally, ensure the correlation ID guidance (as seen above) is consistent across all discount-related schemas.
12304-12328: Enhance DiscountReasonRatecardPercentage Details
The DiscountReasonRatecardPercentage schema now includes a correlationId field with a precise regex pattern. As in hunk 1, consider revising the correlationId description for readability and consistency. Additionally, the description “The reason for the discount is a ratecard percentage.” is clear, but a slight rewording (e.g. “indicates that the discount stems from a ratecard percentage”) might further improve clarity.
12334-12366: Consolidate and Clarify DiscountUsage Schema
The DiscountReasonRatecardUsage schema now includes a quantity property (with a note that it must be positive) and a correlationId. Again, the same phrasing issue in the correlationId description appears. Also, the new DiscountUsage schema is introduced immediately afterward; please verify that its intended purpose is distinct from any similarly named schemas and that the documentation clearly explains its role.
14364-14368: Fix Typographical Error in InvoiceLineDiscounts Description
The description “Discounts detailes applied to this line.” contains a typo (“detailes”). Please update it to “Discounts details applied to this line.”- Discounts detailes applied to this line. + Discounts details applied to this line.
14866-14939: Review Comprehensive InvoiceLineUsageDiscount Schema
The InvoiceLineUsageDiscount schema is detailed and covers various timestamps, identifiers, and discount reasoning. A minor grammatical improvement: change “an usage-based discount” to “a usage-based discount.” Consider updating the title for consistency.- InvoiceLineUsageDiscount represents an usage-based discount applied to the line. + InvoiceLineUsageDiscount represents a usage-based discount applied to the line.
15484-15491: Reapply Typo Correction in Discounts Description
This hunk again contains the typo “detailes” in the discounts property description. Please correct it as noted earlier.e2e/productcatalog_test.go (1)
284-286: Precision check for discount assertion.Using
InexactFloat64()to verify the 10% discount is acceptable for test assertions. However, if precise decimal validation is critical, consider verifying against an expectedDecimalor confirm that float rounding is acceptable.test/billing/adapter_test.go (1)
843-854: Helper function for discount lookup.
findAmountDiscountByDescriptionis a concise helper that clarifies test flow. Consider adding an inline comment or docstring explaining the fatal error for unrecognized descriptions to guide future maintainers.openmeter/ent/db/billinginvoiceline_create.go (2)
838-853: Creating O2M edges for usage-based discounts.
This block updates the create specification to link multiple usage-based discount rows (O2M). If the goal is strictly one usage discount per line, consider adding an application or schema-level safeguard to ensure only one usage-based discount can be attached.
854-859: Creating O2M edges for amount-based discounts.
These lines set up the relationship for attaching multiples of amount-based discounts. If the PR’s objective includes enforcing a single discount per type, you might add validations or migrations to constrain it at the data or application layer.openmeter/ent/db/billinginvoiceline_query.go (1)
566-586: Eager-loading usage & amount discounts
WithLineUsageDiscountsandWithLineAmountDiscountsenable precision in data fetching. Be mindful of performance when projects have large volumes of discount rows, as these joins may become intensive.openmeter/ent/db/billinginvoicelineusagediscount_delete.go (2)
33-40: Error handling approach.
ExecXpanics on error, which might be acceptable in CLI or testing contexts. In production code, consider capturing and returning errors.
84-88: ExecX panic pattern repeated.
Similar to previous comment aboutExecX. Generally fine for tests or short-running tasks, though less ideal in robust production scenarios.openmeter/ent/db/billinginvoicelineusagediscount_create.go (3)
193-200: SaveX panic usage.
Similar note as before: acceptable in testing or ephemeral contexts, but handle carefully in production code.
922-929: SaveX panic usage in bulk.
Consistent pattern with ent’s X methods for test or script usage.
1239-1244: ExecX in bulk.
Completes the pattern with a panic-on-error approach.openmeter/ent/db/billinginvoicelineusagediscount_update.go (1)
216-370: Sufficient error handling with potential for concurrency checks.The
Saveworkflow, including error handling viaNotFoundErrorandConstraintError, aligns with Ent’s idiomatic patterns. If concurrent updates are a concern, consider adding optimistic concurrency fields (e.g., a version/timestamp) or enabling advanced locking strategies. Otherwise, this block appears correct and maintainable.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
tools/migrate/migrations/atlas.sumis excluded by!**/*.sum
📒 Files selected for processing (96)
api/client/javascript/src/client/schemas.ts(20 hunks)api/convert.gen.go(0 hunks)api/openapi.cloud.yaml(19 hunks)api/openapi.yaml(20 hunks)api/spec/src/billing/invoices/discounts.tsp(4 hunks)api/spec/src/billing/invoices/invoice.tsp(3 hunks)api/spec/src/productcatalog/discounts.tsp(1 hunks)api/spec/src/productcatalog/ratecards.tsp(2 hunks)api/spec/src/productcatalog/subscription.tsp(2 hunks)e2e/productcatalog_test.go(4 hunks)openmeter/app/stripe/entity/app/invoice.go(2 hunks)openmeter/billing/adapter/invoicelinediff.go(2 hunks)openmeter/billing/adapter/invoicelinediff_test.go(16 hunks)openmeter/billing/adapter/invoicelinemapper.go(2 hunks)openmeter/billing/adapter/invoicelineprogressive.go(2 hunks)openmeter/billing/adapter/invoicelines.go(5 hunks)openmeter/billing/app.go(1 hunks)openmeter/billing/discount.go(4 hunks)openmeter/billing/httpdriver/deprecations.go(2 hunks)openmeter/billing/httpdriver/discounts.go(1 hunks)openmeter/billing/httpdriver/invoiceline.go(1 hunks)openmeter/billing/invoiceline.go(1 hunks)openmeter/billing/invoicelinediscount.go(9 hunks)openmeter/billing/service/discounts.go(1 hunks)openmeter/billing/service/lineservice/discountpercentage.go(3 hunks)openmeter/billing/service/lineservice/feeline.go(3 hunks)openmeter/billing/service/lineservice/feeline_test.go(2 hunks)openmeter/billing/service/lineservice/pricedynamic_test.go(1 hunks)openmeter/billing/service/lineservice/pricegraduatedtiered_test.go(1 hunks)openmeter/billing/service/lineservice/pricepackage_test.go(1 hunks)openmeter/billing/service/lineservice/priceunit_test.go(3 hunks)openmeter/billing/service/lineservice/pricevolumetiered_test.go(1 hunks)openmeter/billing/service/lineservice/usagebasedline.go(2 hunks)openmeter/billing/service/lineservice/usagebasedline_test.go(5 hunks)openmeter/ent/db/addonratecard_create.go(1 hunks)openmeter/ent/db/addonratecard_update.go(2 hunks)openmeter/ent/db/billinginvoicediscount.go(0 hunks)openmeter/ent/db/billinginvoicediscount/billinginvoicediscount.go(0 hunks)openmeter/ent/db/billinginvoicediscount/where.go(0 hunks)openmeter/ent/db/billinginvoicediscount_create.go(0 hunks)openmeter/ent/db/billinginvoicediscount_delete.go(0 hunks)openmeter/ent/db/billinginvoicediscount_query.go(0 hunks)openmeter/ent/db/billinginvoicediscount_update.go(0 hunks)openmeter/ent/db/billinginvoiceline.go(6 hunks)openmeter/ent/db/billinginvoiceline/billinginvoiceline.go(4 hunks)openmeter/ent/db/billinginvoiceline/where.go(1 hunks)openmeter/ent/db/billinginvoiceline_create.go(3 hunks)openmeter/ent/db/billinginvoiceline_query.go(10 hunks)openmeter/ent/db/billinginvoiceline_update.go(9 hunks)openmeter/ent/db/billinginvoicelinediscount.go(5 hunks)openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go(6 hunks)openmeter/ent/db/billinginvoicelinediscount/where.go(4 hunks)openmeter/ent/db/billinginvoicelinediscount_create.go(12 hunks)openmeter/ent/db/billinginvoicelinediscount_update.go(8 hunks)openmeter/ent/db/billinginvoicelineusagediscount.go(1 hunks)openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go(1 hunks)openmeter/ent/db/billinginvoicelineusagediscount/where.go(1 hunks)openmeter/ent/db/billinginvoicelineusagediscount_create.go(1 hunks)openmeter/ent/db/billinginvoicelineusagediscount_delete.go(1 hunks)openmeter/ent/db/billinginvoicelineusagediscount_query.go(1 hunks)openmeter/ent/db/billinginvoicelineusagediscount_update.go(1 hunks)openmeter/ent/db/client.go(11 hunks)openmeter/ent/db/ent.go(2 hunks)openmeter/ent/db/expose.go(1 hunks)openmeter/ent/db/hook/hook.go(1 hunks)openmeter/ent/db/migrate/schema.go(5 hunks)openmeter/ent/db/paginate.go(5 hunks)openmeter/ent/db/planratecard_create.go(1 hunks)openmeter/ent/db/planratecard_update.go(2 hunks)openmeter/ent/db/predicate/predicate.go(1 hunks)openmeter/ent/db/runtime.go(2 hunks)openmeter/ent/db/setorclear.go(3 hunks)openmeter/ent/db/subscriptionitem_create.go(1 hunks)openmeter/ent/db/subscriptionitem_update.go(2 hunks)openmeter/ent/db/tx.go(2 hunks)openmeter/ent/schema/billing.go(6 hunks)openmeter/ent/schema/productcatalog.go(0 hunks)openmeter/productcatalog/addon/ratecard_test.go(1 hunks)openmeter/productcatalog/discount.go(3 hunks)openmeter/productcatalog/discount_test.go(3 hunks)openmeter/productcatalog/http/mapping.go(5 hunks)openmeter/productcatalog/plan/ratecard_test.go(1 hunks)openmeter/productcatalog/ratecard.go(4 hunks)openmeter/productcatalog/ratecard_test.go(9 hunks)openmeter/productcatalog/subscription/http/mapping.go(1 hunks)openmeter/productcatalog/subscription/service/plan_test.go(1 hunks)openmeter/subscription/repo/mapping.go(1 hunks)openmeter/subscription/repo/subscriptionitemrepo.go(1 hunks)openmeter/subscription/testutils/ratecard.go(1 hunks)pkg/models/model.go(1 hunks)test/app/stripe/invoice_test.go(1 hunks)test/billing/adapter_test.go(3 hunks)test/billing/discount_test.go(4 hunks)test/billing/invoice_test.go(8 hunks)tools/migrate/migrations/20250411062903_billing-split-line-discounts.down.sql(1 hunks)tools/migrate/migrations/20250411062903_billing-split-line-discounts.up.sql(1 hunks)
💤 Files with no reviewable changes (9)
- openmeter/ent/schema/productcatalog.go
- openmeter/ent/db/billinginvoicediscount/where.go
- openmeter/ent/db/billinginvoicediscount_delete.go
- openmeter/ent/db/billinginvoicediscount_update.go
- api/convert.gen.go
- openmeter/ent/db/billinginvoicediscount_query.go
- openmeter/ent/db/billinginvoicediscount_create.go
- openmeter/ent/db/billinginvoicediscount.go
- openmeter/ent/db/billinginvoicediscount/billinginvoicediscount.go
🚧 Files skipped from review as they are similar to previous changes (40)
- openmeter/billing/service/lineservice/pricevolumetiered_test.go
- openmeter/subscription/repo/mapping.go
- openmeter/ent/db/planratecard_create.go
- openmeter/billing/invoiceline.go
- openmeter/subscription/repo/subscriptionitemrepo.go
- openmeter/productcatalog/plan/ratecard_test.go
- test/billing/discount_test.go
- openmeter/ent/db/addonratecard_create.go
- api/spec/src/productcatalog/subscription.tsp
- openmeter/ent/db/subscriptionitem_create.go
- openmeter/billing/adapter/invoicelineprogressive.go
- openmeter/productcatalog/addon/ratecard_test.go
- openmeter/ent/db/tx.go
- openmeter/ent/db/planratecard_update.go
- openmeter/ent/db/expose.go
- openmeter/productcatalog/subscription/http/mapping.go
- api/spec/src/productcatalog/discounts.tsp
- api/spec/src/productcatalog/ratecards.tsp
- openmeter/productcatalog/subscription/service/plan_test.go
- openmeter/app/stripe/entity/app/invoice.go
- pkg/models/model.go
- openmeter/ent/db/subscriptionitem_update.go
- openmeter/billing/service/lineservice/pricepackage_test.go
- openmeter/subscription/testutils/ratecard.go
- openmeter/productcatalog/ratecard_test.go
- openmeter/billing/httpdriver/deprecations.go
- openmeter/productcatalog/ratecard.go
- openmeter/ent/db/ent.go
- openmeter/billing/service/lineservice/usagebasedline.go
- api/spec/src/billing/invoices/invoice.tsp
- openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go
- openmeter/billing/service/lineservice/discountpercentage.go
- openmeter/ent/db/addonratecard_update.go
- openmeter/billing/adapter/invoicelines.go
- test/billing/invoice_test.go
- openmeter/billing/service/lineservice/usagebasedline_test.go
- openmeter/ent/db/billinginvoicelinediscount.go
- openmeter/ent/db/billinginvoicelineusagediscount.go
- tools/migrate/migrations/20250411062903_billing-split-line-discounts.down.sql
- tools/migrate/migrations/20250411062903_billing-split-line-discounts.up.sql
🧰 Additional context used
🧬 Code Graph Analysis (35)
test/app/stripe/invoice_test.go (7)
openmeter/billing/discount.go (1)
Discounts(78-81)api/api.gen.go (1)
Discounts(2020-2026)openmeter/productcatalog/discount.go (1)
Discounts(113-116)api/client/go/client.gen.go (1)
Discounts(1891-1897)openmeter/ent/db/billinginvoiceline/where.go (2)
Amount(102-104)Description(97-99)openmeter/ent/db/billinginvoicelinediscount/where.go (2)
Amount(111-113)Description(101-103)openmeter/ent/db/billinginvoicelineusagediscount/where.go (1)
Description(101-103)
openmeter/ent/db/predicate/predicate.go (2)
openmeter/ent/db/billinginvoicelineusagediscount.go (2)
BillingInvoiceLineUsageDiscount(19-51)BillingInvoiceLineUsageDiscount(74-93)openmeter/ent/schema/billing.go (5)
BillingInvoiceLineUsageDiscount(627-629)BillingInvoiceLineUsageDiscount(631-638)BillingInvoiceLineUsageDiscount(640-664)BillingInvoiceLineUsageDiscount(666-675)BillingInvoiceLineUsageDiscount(677-685)
e2e/productcatalog_test.go (4)
api/api.gen.go (3)
DiscountPercentage(1954-1957)Percentage(4688-4688)Discounts(2020-2026)pkg/models/percentage.go (2)
Percentage(9-11)NewPercentage(15-28)openmeter/billing/discount.go (1)
Discounts(78-81)openmeter/productcatalog/discount.go (1)
Discounts(113-116)
openmeter/billing/httpdriver/discounts.go (3)
openmeter/productcatalog/http/mapping.go (3)
AsDiscounts(523-545)AsPercentageDiscount(558-562)AsUsageDiscount(547-556)api/api.gen.go (3)
BillingDiscounts(1089-1095)Discounts(2020-2026)Percentage(4688-4688)openmeter/productcatalog/discount.go (3)
Discounts(113-116)PercentageDiscount(21-24)UsageDiscount(60-62)
openmeter/billing/service/discounts.go (3)
api/api.gen.go (2)
Percentage(4688-4688)Discounts(2020-2026)openmeter/billing/discount.go (1)
Discounts(78-81)openmeter/productcatalog/discount.go (1)
Discounts(113-116)
test/billing/adapter_test.go (2)
openmeter/billing/discount.go (4)
Discounts(78-81)NewDiscountReasonFrom(154-191)MaximumSpendDiscount(145-145)PercentageDiscount(24-28)openmeter/billing/invoicelinediscount.go (4)
LineDiscounts(312-315)AmountLineDiscountManaged(104-107)AmountLineDiscount(56-64)LineDiscountBase(22-27)
openmeter/billing/service/lineservice/pricegraduatedtiered_test.go (2)
openmeter/billing/discount.go (3)
Discounts(78-81)NewDiscountReasonFrom(154-191)MaximumSpendDiscount(145-145)openmeter/billing/invoicelinediscount.go (5)
LineDiscounts(312-315)AmountLineDiscountManaged(104-107)AmountLineDiscount(56-64)LineDiscountBase(22-27)LineMaximumSpendReferenceID(19-19)
openmeter/billing/service/lineservice/feeline_test.go (3)
openmeter/billing/discount.go (2)
PercentageDiscount(24-28)Discounts(78-81)openmeter/productcatalog/discount.go (2)
PercentageDiscount(21-24)Discounts(113-116)openmeter/billing/invoicelinediscount.go (3)
LineDiscounts(312-315)AmountLineDiscount(56-64)LineDiscountBase(22-27)
openmeter/billing/adapter/invoicelinemapper.go (1)
openmeter/billing/invoicelinediscount.go (5)
UsageLineDiscountManaged(254-257)LineDiscountBase(22-27)UsageLineDiscount(205-210)AmountLineDiscountManaged(104-107)AmountLineDiscount(56-64)
api/client/javascript/src/client/schemas.ts (4)
api/api.gen.go (12)
BillingDiscountReason(1067-1069)BillingDiscountUsage(1072-1086)BillingDiscounts(1089-1095)DiscountReasonMaximumSpend(1960-1962)DiscountReasonRatecardPercentage(1968-1981)DiscountReasonRatecardUsage(1987-2002)DiscountUsage(2012-2017)Discounts(2020-2026)InvoiceLineAmountDiscount(3344-3368)InvoiceLineAppExternalIds(3371-3377)InvoiceLineDiscounts(3380-3390)InvoiceLineUsageDiscount(3441-3470)api/client/go/client.gen.go (12)
BillingDiscountReason(965-967)BillingDiscountUsage(970-984)BillingDiscounts(987-993)DiscountReasonMaximumSpend(1831-1833)DiscountReasonRatecardPercentage(1839-1852)DiscountReasonRatecardUsage(1858-1873)DiscountUsage(1883-1888)Discounts(1891-1897)InvoiceLineAmountDiscount(3093-3117)InvoiceLineAppExternalIds(3120-3126)InvoiceLineDiscounts(3129-3139)InvoiceLineUsageDiscount(3190-3219)openmeter/billing/discount.go (1)
Discounts(78-81)openmeter/productcatalog/discount.go (1)
Discounts(113-116)
openmeter/productcatalog/discount_test.go (3)
openmeter/billing/discount.go (3)
Discounts(78-81)PercentageDiscount(24-28)UsageDiscount(49-53)api/api.gen.go (2)
Discounts(2020-2026)Percentage(4688-4688)openmeter/productcatalog/discount.go (3)
Discounts(113-116)PercentageDiscount(21-24)UsageDiscount(60-62)
openmeter/ent/db/billinginvoiceline/where.go (4)
openmeter/ent/db/predicate/predicate.go (3)
BillingInvoiceLine(65-65)BillingInvoiceLineUsageDiscount(93-93)BillingInvoiceLineDiscount(79-79)openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (5)
Table(105-105)LineUsageDiscountsTable(136-136)LineUsageDiscountsColumn(141-141)LineAmountDiscountsTable(143-143)LineAmountDiscountsColumn(148-148)openmeter/ent/db/billinginvoicelineusagediscount.go (2)
BillingInvoiceLineUsageDiscount(19-51)BillingInvoiceLineUsageDiscount(74-93)openmeter/ent/db/billinginvoicelinediscount.go (2)
BillingInvoiceLineDiscount(19-63)BillingInvoiceLineDiscount(86-105)
openmeter/billing/adapter/invoicelinediff_test.go (4)
openmeter/billing/discount.go (1)
Discounts(78-81)openmeter/productcatalog/discount.go (1)
Discounts(113-116)openmeter/billing/invoicelinediscount.go (3)
AmountLineDiscountManaged(104-107)LineDiscounts(312-315)AmountLineDiscount(56-64)pkg/models/model.go (1)
ManagedModelWithID(155-158)
openmeter/ent/db/billinginvoicelineusagediscount_query.go (6)
openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (6)
OrderOption(112-112)Table(47-47)FieldID(19-19)BillingInvoiceLineColumn(54-54)Label(17-17)FieldLineID(29-29)openmeter/ent/db/predicate/predicate.go (2)
BillingInvoiceLineUsageDiscount(93-93)BillingInvoiceLine(65-65)openmeter/ent/db/billinginvoiceline_query.go (1)
BillingInvoiceLineQuery(29-50)openmeter/ent/db/client.go (1)
BillingInvoiceLineClient(2474-2476)openmeter/ent/db/billinginvoiceline/where.go (2)
IDIn(32-34)ID(17-19)openmeter/ent/db/billinginvoicelineusagediscount/where.go (3)
LineID(91-93)IDIn(31-33)ID(16-18)
openmeter/billing/httpdriver/invoiceline.go (3)
openmeter/billing/invoicelinediscount.go (1)
LineDiscounts(312-315)api/api.gen.go (6)
InvoiceLineDiscounts(3380-3390)InvoiceLineAmountDiscount(3344-3368)InvoiceLineAppExternalIds(3371-3377)InvoiceLineUsageDiscount(3441-3470)BillingDiscountReason(1067-1069)Percentage(4688-4688)openmeter/billing/discount.go (4)
DiscountReason(147-152)MaximumSpendDiscountReason(131-131)RatecardPercentageDiscountReason(132-132)RatecardUsageDiscountReason(133-133)
openmeter/productcatalog/discount.go (9)
openmeter/billing/discount.go (1)
PercentageDiscount(24-28)pkg/models/percentage.go (1)
Percentage(9-11)openmeter/productcatalog/plan/adapter/adapter.go (1)
New(42-51)pkg/models/error.go (1)
NewNillableGenericValidationError(129-135)openmeter/billing/invoiceline.go (1)
Price(701-701)openmeter/productcatalog/price.go (1)
Price(84-91)pkg/equal/equal.go (1)
Equaler(9-11)pkg/models/equaler.go (1)
Equaler(3-6)pkg/models/clonable.go (1)
Clonable(3-5)
openmeter/productcatalog/http/mapping.go (5)
openmeter/billing/discount.go (1)
Discounts(78-81)api/client/javascript/src/client/schemas.ts (4)
Discounts(9386-9386)DiscountUsage(9385-9385)Percentage(9616-9616)DiscountPercentage(9378-9378)api/api.gen.go (4)
Discounts(2020-2026)DiscountUsage(2012-2017)Percentage(4688-4688)DiscountPercentage(1954-1957)openmeter/productcatalog/discount.go (1)
Discounts(113-116)api/client/go/client.gen.go (4)
Discounts(1891-1897)DiscountUsage(1883-1888)Percentage(4384-4384)DiscountPercentage(1825-1828)
openmeter/ent/db/billinginvoiceline_query.go (4)
openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (1)
OrderOption(285-285)openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (1)
OrderOption(123-123)openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (1)
OrderOption(112-112)openmeter/ent/db/billinginvoicelineusagediscount_query.go (1)
BillingInvoiceLineUsageDiscountQuery(21-32)
openmeter/ent/db/billinginvoiceline.go (4)
openmeter/ent/db/billinginvoicelineusagediscount.go (2)
BillingInvoiceLineUsageDiscount(19-51)BillingInvoiceLineUsageDiscount(74-93)openmeter/ent/db/billinginvoicelinediscount.go (2)
BillingInvoiceLineDiscount(19-63)BillingInvoiceLineDiscount(86-105)openmeter/ent/db/billinginvoicelineusagediscount_query.go (1)
BillingInvoiceLineUsageDiscountQuery(21-32)openmeter/ent/db/billinginvoicelinediscount_query.go (1)
BillingInvoiceLineDiscountQuery(21-32)
openmeter/ent/db/runtime.go (1)
openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (1)
ValueScanner(96-98)
openmeter/ent/db/billinginvoiceline_create.go (3)
openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (6)
Table(105-105)LineUsageDiscountsTable(136-136)LineUsageDiscountsColumn(141-141)FieldID(19-19)LineAmountDiscountsTable(143-143)LineAmountDiscountsColumn(148-148)openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (2)
Table(53-53)FieldID(19-19)openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (2)
Table(47-47)FieldID(19-19)
openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (2)
openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (3)
OrderOption(123-123)Table(53-53)FieldID(19-19)openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (3)
OrderOption(112-112)Table(47-47)FieldID(19-19)
openmeter/ent/schema/billing.go (3)
openmeter/ent/db/billinginvoicelineusagediscount.go (2)
BillingInvoiceLineUsageDiscount(19-51)BillingInvoiceLineUsageDiscount(74-93)openmeter/ent/db/billinginvoicelinediscount.go (2)
BillingInvoiceLineDiscount(19-63)BillingInvoiceLineDiscount(86-105)openmeter/ent/db/billinginvoiceline.go (2)
BillingInvoiceLine(27-103)BillingInvoiceLine(237-262)
openmeter/ent/db/billinginvoicelineusagediscount_delete.go (4)
openmeter/ent/db/ent.go (3)
IsConstraintError(361-367)ConstraintError(345-348)NotFoundError(278-280)openmeter/ent/db/mutation.go (1)
BillingInvoiceLineUsageDiscountMutation(18699-18721)openmeter/ent/db/predicate/predicate.go (1)
BillingInvoiceLineUsageDiscount(93-93)openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (3)
Table(47-47)FieldID(19-19)Label(17-17)
openmeter/ent/db/billinginvoicelinediscount_update.go (1)
openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (5)
FieldReason(35-35)FieldInvoicingAppExternalID(37-37)FieldType(45-45)FieldQuantity(47-47)FieldPreLinePeriodQuantity(49-49)
openmeter/ent/db/billinginvoiceline_update.go (2)
openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (1)
FieldID(19-19)openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (1)
FieldID(19-19)
openmeter/ent/db/migrate/schema.go (3)
openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (2)
Columns(173-206)Table(105-105)openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (2)
Columns(64-78)Table(53-53)openmeter/ent/db/billinginvoice/billinginvoice.go (2)
Columns(202-257)Table(142-142)
openmeter/ent/db/billinginvoicelinediscount_create.go (5)
openmeter/billing/discount.go (3)
DiscountReasonType(128-128)DiscountReasonType(136-142)DiscountReason(147-152)openmeter/billing/invoiceline.go (1)
LineID(20-20)openmeter/ent/db/ent.go (1)
ValidationError(253-256)openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (7)
FieldReason(35-35)FieldInvoicingAppExternalID(37-37)FieldAmount(39-39)FieldType(45-45)FieldQuantity(47-47)FieldPreLinePeriodQuantity(49-49)FieldSourceDiscount(43-43)openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (4)
FieldInvoicingAppExternalID(73-73)FieldAmount(35-35)FieldType(61-61)FieldQuantity(67-67)
openmeter/ent/db/setorclear.go (3)
openmeter/ent/db/billinginvoicelinediscount_update.go (2)
BillingInvoiceLineDiscountUpdate(22-26)BillingInvoiceLineDiscountUpdateOne(451-456)openmeter/billing/discount.go (1)
DiscountReason(147-152)openmeter/ent/db/billinginvoicelineusagediscount_update.go (2)
BillingInvoiceLineUsageDiscountUpdate(22-26)BillingInvoiceLineUsageDiscountUpdateOne(373-378)
openmeter/billing/invoicelinediscount.go (7)
openmeter/billing/invoiceline.go (1)
LineExternalIDs(235-237)openmeter/billing/discount.go (1)
DiscountReason(147-152)pkg/models/validator.go (1)
Validate(16-26)pkg/models/model.go (2)
ManagedModelWithID(155-158)ManagedModel(107-113)pkg/models/clonable.go (1)
Clonable(3-5)pkg/models/error.go (1)
NewNillableGenericValidationError(129-135)pkg/slicesx/map.go (1)
MapWithErr(23-47)
openmeter/ent/db/client.go (2)
openmeter/ent/db/billinginvoicelineusagediscount_query.go (1)
BillingInvoiceLineUsageDiscountQuery(21-32)openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (4)
Table(105-105)FieldID(19-19)LineUsageDiscountsTable(136-136)LineUsageDiscountsColumn(141-141)
openmeter/ent/db/billinginvoicelineusagediscount_create.go (4)
openmeter/ent/db/mutation.go (1)
BillingInvoiceLineUsageDiscountMutation(18699-18721)openmeter/billing/discount.go (3)
DiscountReasonType(128-128)DiscountReasonType(136-142)DiscountReason(147-152)openmeter/ent/db/billinginvoicelineusagediscount.go (2)
BillingInvoiceLineUsageDiscount(19-51)BillingInvoiceLineUsageDiscount(74-93)openmeter/billing/invoiceline.go (1)
LineID(20-20)
openmeter/ent/db/billinginvoicelinediscount/where.go (5)
openmeter/ent/db/predicate/predicate.go (1)
BillingInvoiceLineDiscount(79-79)openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (2)
FieldInvoicingAppExternalID(73-73)FieldType(61-61)openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (4)
FieldInvoicingAppExternalID(37-37)FieldType(45-45)FieldReason(35-35)FieldSourceDiscount(43-43)openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (2)
FieldInvoicingAppExternalID(37-37)FieldReason(35-35)openmeter/billing/discount.go (2)
DiscountReasonType(128-128)DiscountReasonType(136-142)
openmeter/ent/db/billinginvoicelineusagediscount_update.go (4)
openmeter/ent/db/mutation.go (1)
BillingInvoiceLineUsageDiscountMutation(18699-18721)openmeter/ent/db/predicate/predicate.go (2)
BillingInvoiceLineUsageDiscount(93-93)BillingInvoiceLine(65-65)openmeter/ent/db/billinginvoicelineusagediscount/where.go (8)
ID(16-18)UpdatedAt(81-83)DeletedAt(86-88)ChildUniqueReferenceID(96-98)Description(101-103)InvoicingAppExternalID(106-108)Quantity(111-113)PreLinePeriodQuantity(116-118)openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (13)
UpdateDefaultUpdatedAt(92-92)ReasonValidator(102-109)Columns(58-72)FieldID(19-19)FieldUpdatedAt(25-25)FieldDeletedAt(27-27)FieldChildUniqueReferenceID(31-31)FieldDescription(33-33)FieldReason(35-35)FieldInvoicingAppExternalID(37-37)FieldQuantity(39-39)FieldPreLinePeriodQuantity(41-41)FieldReasonDetails(43-43)
openmeter/ent/db/billinginvoicelineusagediscount/where.go (7)
openmeter/ent/db/billinginvoicelineusagediscount.go (2)
BillingInvoiceLineUsageDiscount(19-51)BillingInvoiceLineUsageDiscount(74-93)openmeter/ent/db/predicate/predicate.go (2)
BillingInvoiceLineUsageDiscount(93-93)BillingInvoiceLine(65-65)openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (9)
FieldID(19-19)FieldNamespace(21-21)FieldCreatedAt(25-25)FieldUpdatedAt(27-27)FieldDeletedAt(29-29)FieldChildUniqueReferenceID(75-75)FieldDescription(33-33)FieldInvoicingAppExternalID(73-73)FieldQuantity(67-67)openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (11)
FieldID(19-19)FieldNamespace(21-21)FieldCreatedAt(23-23)FieldUpdatedAt(25-25)FieldDeletedAt(27-27)FieldLineID(29-29)FieldChildUniqueReferenceID(31-31)FieldDescription(33-33)FieldInvoicingAppExternalID(37-37)FieldQuantity(47-47)FieldReason(35-35)openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (11)
FieldID(19-19)FieldNamespace(21-21)FieldCreatedAt(23-23)FieldUpdatedAt(25-25)FieldDeletedAt(27-27)FieldLineID(29-29)FieldChildUniqueReferenceID(31-31)FieldDescription(33-33)FieldInvoicingAppExternalID(37-37)FieldQuantity(39-39)FieldReason(35-35)openmeter/billing/invoiceline.go (1)
LineID(20-20)openmeter/billing/discount.go (2)
DiscountReasonType(128-128)DiscountReasonType(136-142)
⏰ Context from checks skipped due to timeout of 90000ms (7)
- GitHub Check: Test
- GitHub Check: Lint
- GitHub Check: E2E
- GitHub Check: Developer environment
- GitHub Check: CI
- GitHub Check: Commit hooks
- GitHub Check: Analyze (go)
🔇 Additional comments (349)
openmeter/ent/db/billinginvoiceline/where.go (2)
1896-1917: New edge functions properly implement the usage discounts relation.The implementation correctly adds predicates for querying
line_usage_discountsrelationships, following the architectural change to separate unit and amount discounts into different tables as mentioned in the PR objectives.
1919-1940: New edge functions properly implement the amount discounts relation.The implementation correctly adds predicates for the
line_amount_discountsrelationship, maintaining consistent naming patterns and implementation style with the rest of the codebase. These functions enable the new discount structure that allows only a single discount per type.openmeter/ent/db/migrate/schema.go (7)
777-777: Appropriate enum value update for the discount refactoring.The
reasonfield's enum values have been updated to includeratecard_percentageandratecard_usage, replacing the previous single valueratecard_discount. This change properly supports the new discount structure that allows for a single discount per type.
778-782: Good addition of fields to support the new discount model.The addition of
invoicing_app_external_id,source_discount, andtypefields provides necessary information for the new discount structure. Thesource_discountfield being a JSON type allows storing the complete discount information which is important for tracking the origin of calculated discounts.
794-794: Foreign key name updated to reflect amount-specific discounts.The foreign key symbol has been updated to
billing_invoice_line_discounts_billing_invoice_lines_line_amount_discounts, which clearly indicates that this table now specifically handles amount-based discounts as part of the separation of discount types.
826-841: Well-structured schema for new usage-based discounts table.Creating a separate table for usage-based discounts is a good design decision as it allows for more precise management of null and non-null flags within the database. The table structure properly includes all necessary fields to track usage-based discounts with appropriate types and constraints.
842-875: Well-defined table configuration for usage-based discounts.The table definition includes appropriate primary key, foreign key relationships to the invoice lines table, and well-thought-out indexes to ensure efficient querying. The index on
namespace_line_id_child_unique_reference_idwith the non-null constraint is particularly important for data integrity.
2308-2308: New usage discounts table properly added to schema tables list.The
BillingInvoiceLineUsageDiscountsTablehas been correctly added to theTablesslice, ensuring it will be properly handled during schema migrations and database operations.
2365-2365: Foreign key reference properly set for new table.The foreign key relationship for
BillingInvoiceLineUsageDiscountsTableis correctly initialized to reference theBillingInvoiceLinesTable, establishing the proper parent-child relationship between invoice lines and their usage-based discounts.openmeter/ent/db/billinginvoicelinediscount_create.go (9)
111-115: Method signature updated for SetReasonThe
SetReasonmethod has been modified to acceptbilling.DiscountReasonTypeinstead of the previous type, aligning with the new discount structure that supports a single discount per type. This change is consistent with the PR objectives.
117-129: New methods for invoicing app external ID handlingThese new methods for managing the
invoicing_app_external_idfield support integration with external invoicing systems. The addition of both required and nullable versions provides good flexibility for different usage scenarios.
131-135: Addition of required SetAmount methodThe
SetAmountmethod has been added as a required field (no nullable version), which aligns with the PR's goal of restructuring the discount representation. Making amount a required field ensures that all discounts have a properly defined value.
151-155: New SetSourceDiscount method addedThis method enables linking discounts to their source through the
billing.DiscountReasontype. This supports the new discount structure mentioned in the PR objectives, allowing for more detailed tracking of discount origins.
157-169: Type field handling updatedThe
SetTypeandSetNillableTypemethods now accept string values instead of a specific enum type. This change provides more flexibility in how discount types can be defined while maintaining the PR's goal of refactoring the discount structure.
289-302: Validation logic updated for required fieldsThe validation logic in the
checkmethod has been appropriately updated to:
- Ensure
line_idis required- Ensure
amountis requiredThese validation changes are consistent with the new discount structure, enforcing required fields while allowing flexibility for optional ones.
374-409: Updated field mapping in createSpecThe
createSpecmethod has been properly updated to handle all the modified and new fields:
Reasonwith the new typeInvoicingAppExternalIDas an optional fieldAmountas a required fieldType,Quantity, andPreLinePeriodQuantitywith proper type handlingThis ensures that all database fields are correctly populated when creating new discount records.
557-686: Comprehensive upsert methods for all fieldsA complete set of upsert methods has been implemented for all the modified and new fields, maintaining consistency with the create methods. This ensures that all operations (create, update, upsert) have the same capability and behavior when working with discount records.
1303-1454: Bulk upsert operations properly supportedAll the changes have been consistently applied to the bulk upsert operations as well, ensuring that both individual and batch processing use the same field types and validation rules. This maintains consistency throughout the API surface.
openmeter/ent/db/billinginvoicelinediscount_update.go (6)
114-126: Great use of typed enums forreason.The transition to
billing.DiscountReasonTypeand the associated validators ensures stronger type safety. This helps mitigate errors and clarifies the purpose of the field.
182-192:source_discountaddition looks good.The pattern of setting and clearing
source_discountaligns with Ent’s approach. Make sure the field is non-sensitive or properly masked if it may contain user data.
363-408: Field assignment insqlSavealigns with the updated schema.The logic updates each field with the correct
field.Type*based on your changes. This is in sync with the new approach forreason,invoicing_app_external_id,type,quantity, andpre_line_period_quantity. Ensure any migrations cover the new data types properly in production.Would you like to verify the related migration scripts to confirm they align with these field changes?
538-550:SetReasonmethods forUpdateOneare aligned with the main builder.Keeping these methods parallel to the multi-entity update builder is a good practice and helps maintain consistency across update paths.
606-616:SetSourceDiscountis properly mirrored inUpdateOne.The pointer-based approach with a validator is consistent. This helps ensure that only valid discount values enter the database.
817-862:sqlSaveforUpdateOnecorrectly uses the new fields.All newly added fields (
reason,invoicing_app_external_id,type,quantity, etc.) are persisted in alignment with the multi-update logic. The hooking intocheck()ensures they pass custom validators before final storage.test/app/stripe/invoice_test.go (1)
561-565: Updated loop to match new discount structureThe code now iterates over
line.Discounts.Amountarray instead of the previous genericline.Discountsstructure, and useslo.FromPtrOrto safely handle potential nil descriptions. This change aligns with the new discount model that separates amount and usage discounts.openmeter/billing/service/lineservice/pricedynamic_test.go (1)
188-201: Refactored discount structure in testThe test case now uses the new
LineDiscountsstructure with anAmountslice ofAmountLineDiscountManagedobjects, replacing the previous flat discount approach. This correctly reflects the refactored discount model that separates different discount types. The reason is also properly constructed usingNewDiscountReasonFrom.openmeter/billing/app.go (1)
219-228: Updated discount handling to use new structureThe merge process now correctly processes amount and usage discounts as separate collections, iterating over
line.Discounts.Amountandline.Discounts.Usagerespectively. This change properly supports the new discount model that allows for single discount per type while maintaining the external ID assignment logic.openmeter/billing/httpdriver/discounts.go (1)
34-62: Redesigned AsDiscounts function for new discount structureThe function signature has been updated to accept a pointer to
api.BillingDiscountsinstead of a slice ofapi.BillingDiscount, reflecting the new model that separates discount types. The implementation now:
- Handles nil input safely
- Processes percentage and usage discounts separately when present
- Maintains error handling for usage discount conversion
This change correctly implements the new discount model while providing backward compatibility through proper nil checking.
openmeter/ent/db/predicate/predicate.go (1)
92-104: New predicate type for BillingInvoiceLineUsageDiscount added correctly.This new predicate type and its error-handling function follow the established pattern in the codebase. The
BillingInvoiceLineUsageDiscountpredicate will be used with the SQL selector in query builders, and the error handling function properly checks for nil errors before executing the predicate.openmeter/ent/db/runtime.go (1)
504-533: Schema initialization for BillingInvoiceLineUsageDiscount is properly configured.The initialization code properly sets up the validators, defaults, and value scanners for the new entity type. The implementation follows the same pattern as other entities in the file, ensuring consistency throughout the codebase.
openmeter/billing/service/lineservice/feeline.go (2)
41-71: Updated to handle single discount per type instead of multiple discounts.The implementation has been refactored to align with the new discount structure that allows only a single discount per type. The function now retrieves a single discount object rather than a collection, simplifying the discount handling logic.
Points to note:
- Line 44: Now gets a single discount rather than a collection
- Line 49: Condition checks for nil discount rather than empty collection
- Line 65: Uses a single discount for calculation
- Line 70: Appends to the Amount field of l.line.Discounts
84-85: Totals calculation updated to match new discount structure.The DiscountsTotal calculation has been updated to sum the Amount field of the Discounts structure, which matches the new data model where discounts are consolidated by type.
openmeter/billing/service/discounts.go (2)
11-29: Simplified discount correlation ID generation.The function has been refactored to be more straightforward, directly checking if each discount type is present and then generating or validating its correlation ID. This approach is cleaner and more maintainable than the previous implementation.
31-42: Well-designed helper function for correlation ID generation.The new
generateCorrelationIDfunction encapsulates the logic for either generating a new correlation ID or validating an existing one. This reduces code duplication and improves maintainability.The function properly:
- Generates a new ULID if no correlation ID is provided
- Validates existing correlation IDs to ensure they're valid ULIDs
- Returns descriptive errors for invalid IDs
openmeter/ent/db/hook/hook.go (1)
168-178: Addition of BillingInvoiceLineUsageDiscountFunc supports the discount structure refactoring.This new hook function accommodates the separation of unit and amount discounts into different tables, which aligns with the PR objective of modifying the discount structure. This change allows more precise management of null and non-null flags within the database.
openmeter/billing/service/lineservice/pricegraduatedtiered_test.go (1)
258-292: Updated discount structure implementation enhances clarity and organization.The test code has been updated to use the new
LineDiscountsstructure which provides better organization by separating amount and usage-based discounts. The previous approach likely used a simpler structure, but this change allows for more precise discount management, aligning with the PR objective to allow single discount per type.openmeter/billing/adapter/invoicelinemapper.go (4)
163-163: Safe default initialization of RateCardDiscounts.Changed from potentially returning
nilto returning an emptybilling.Discounts{}object, which prevents nil pointer errors when accessing this field later in the code.
213-228: Improved discount handling with type-specific processing.The discount handling has been refactored to separate usage-based and amount-based discounts, with proper error handling for each type. This supports the PR objective of splitting discount types into different tables, providing better organization and error reporting.
233-269: New mapping function for usage-based discounts.This function handles the conversion from database model to domain model for invoice line usage discounts, with special handling for legacy maximum spend discounts. The error handling for missing reason details ensures data integrity.
271-307: New mapping function for amount-based discounts.This function handles the conversion from database model to domain model for invoice line amount discounts, with special handling for legacy discounts. The error handling for missing source discount details ensures data integrity during the transition to the new structure.
openmeter/billing/httpdriver/invoiceline.go (1)
492-532: New function to handle discount reason mapping to API format.This function properly handles the conversion of various discount reason types to their API representations, with appropriate error handling for unknown types. This ensures consistent representation of discount reasons across the API.
openmeter/billing/service/lineservice/feeline_test.go (3)
22-27: Updated discount structure to use a single rate card discountThe code now uses a single
RateCardDiscountof typebilling.PercentageDiscountinstead of an array of discounts, which aligns with the PR objective to permit only a single discount per type.
32-48: Updated expected JSON structure to use the new discount modelThe expected JSON comparison has been updated to use the new
LineDiscountsstructure with properly nestedAmountarray ofAmountLineDiscountManagedobjects. This is consistent with the unified discount handling approach.
69-71: Updated line base to use the new Discounts structureThe
RateCardDiscountsfield inLineBasenow uses the newbilling.Discountsstructure with a pointer to the cloned discount, which matches the PR objective of restructuring discounts.openmeter/billing/service/lineservice/priceunit_test.go (4)
188-201: Updated discount structure for maximum spend discountThe code now uses the new
LineDiscountsstructure with properly nestedAmountarray for the maximum spend discount calculation. This ensures consistency with the new discount model.
209-214: Simplified percentage discount initializationThe discount is now initialized directly as a struct rather than through a function call, making the code more explicit about the discount structure. The inclusion of a
CorrelationIDfield also improves traceability of discounts.
233-235: Updated discount assignment to use the new Discounts structureThe code now uses
billing.Discountswith aPercentagefield pointing to the discount object, aligning with the PR objective of having a single discount per type.
249-271: Updated expected discounts structure for combined discount scenarioThe test case for combined discounts (percentage + maximum spend) now uses the new
LineDiscountsstructure with anAmountarray. This properly represents the case where multiple amount discounts can still be applied while maintaining the single-discount-per-type model.openmeter/billing/adapter/invoicelinediff_test.go (21)
3-5: Added appropriate importsThe code now imports the
fmtpackage for string formatting and themodelspackage which contains theManagedModelWithIDstruct used in the refactored discount structure.Also applies to: 13-14
23-23: Renamed discount field to be more specificThe field has been renamed from
DiscountstoAmountDiscountsto clearly indicate it's specifically for amount-based discounts rather than generic discounts, improving code clarity.
51-51: Updated discount initialization for test caseUpdated to use
newAmountDiscountsWithIDsinstead of the previous function to initialize discounts, which aligns with the new discount structure.
87-89: Updated field reference to match the renamed fieldField reference has been updated from
DiscountstoAmountDiscountsto maintain consistency with the struct field renaming.
121-124: Updated field reference in child diff expectationField reference has been updated from
DiscountstoAmountDiscountsin the child diff expectation test case for deletion scenarios.
179-179: Updated discount access patternNow accessing discount ID through the new structure with
.Discounts.Amount[0].ID, which reflects the new nested discount organization.
194-198: Updated field reference for create/delete diff expectationsField reference has been updated from
DiscountstoAmountDiscountsin the test case expectations for when discounts are both created and deleted.
208-208: Updated discount clearing patternNow setting
Discounts.Amount = nilinstead of clearing the old direct discounts array, reflecting the new structure where amount discounts are in a specific field.
216-218: Updated field reference for discount deletion testField reference has been updated from
DiscountstoAmountDiscountsin the test case for discount deletion.
227-227: Updated discount amount access patternNow accessing discount amount through the new structure with
.Discounts.Amount[0].Amount, matching the new nested organization.
235-237: Updated field reference for discount update testField reference has been updated from
DiscountstoAmountDiscountsin the test case for discount updates.
246-249: Updated discount access and modificationNow accessing discounts via
.Discounts.Amountand modifying fields on the discount objects directly, which aligns with the new structure.
257-260: Updated field reference for discount create/delete testField reference has been updated from
DiscountstoAmountDiscountsin the test expectations for creating and deleting discounts.
281-283: Updated field reference for deletion with deletedAtField reference has been updated from
DiscountstoAmountDiscountsin the test case for deleting items using thedeletedAtfield.
305-307: Updated field reference for parent deletion testField reference has been updated from
DiscountstoAmountDiscountsin the test case where a parent line with children is deleted.
384-392: Updated discount mapping function to use specific typeFunction now explicitly works with
AmountLineDiscountManagedtype instead of a generic discount type, which improves type safety and code clarity.
394-394: Updated diff mapping function to use specific typeFunction signature now explicitly uses
AmountLineDiscountManagedtype, which aligns with the more specific discount handling approach.
402-413: Added helper function for error message formattingAdded a new
msgPrefixutility function that enhances error message formatting by properly prefixing messages, which improves test failure diagnostics.
418-420: Updated error message formatting for diff comparisonsNow using the new
msgPrefixfunction to generate better formatted error messages when diffs don't match expectations.
430-430: Updated diff verification to use specific discount typeChanged to use
AmountDiscountsandmapLineDiscountDiffToIDsfunction for comparing discount diffs, which aligns with the renamed fields and functions.
472-485: Reimplemented discount creation function for new structureThe
newAmountDiscountsWithIDsfunction now creates aLineDiscountsstructure with anAmountfield containingAmountLineDiscountManagedobjects. This properly implements the new discount model where discounts are organized by type.api/openapi.yaml (13)
12151-12173: Enhanced "DiscountPercentage" and "DiscountReasonMaximumSpend" Schemas.
TheDiscountPercentageschema now enforces a requiredpercentagebounded between 0 and 100, and theDiscountReasonMaximumSpendschema defines a clear enum value. Both changes improve schema strictness and consistency.
12234-12241: "DiscountUsage" Schema Definition.
The newly addedDiscountUsageschema minimally requires a numericquantity. Confirm that downstream billing logic correctly interprets this value for usage-based discounts.
14723-14727: "InvoiceFlatFeeRateCard" Discounts Reference Update.
Thediscountsfield now referencesBillingDiscounts, which aligns with the refactored discount model. Please confirm that flat fee implementations enforce the intended constraint (e.g. only percentage discounts, if that is the underlying business logic).
14763-14773: Addition of "InvoiceLineAmountDiscount" Schema.
This hunk introduces theInvoiceLineAmountDiscountschema with required fields such ascreatedAt,updatedAt,id,reason, andamount. The schema appears well-defined; please verify that invoice line calculations are updated to utilize this new schema.
14798-14803: "reason" Property Now References the New Discount Schema.
Changing thereasonproperty to referenceBillingDiscountReasonenhances consistency across discount definitions.
14937-15005: Robust Definition of "InvoiceLineUsageDiscount" Schema.
This new schema includes detailed metadata (timestamps, IDs, correlation, and descriptive fields) for usage-based discounts. It is well-documented—please double-check that the semantic meaning of fields (likepreLinePeriodQuantity) is consistently applied in your billing engine.
15839-15843: Updated Discounts in "InvoiceUsageBasedRateCard".
Thediscountsproperty now points toBillingDiscounts, ensuring schema consistency across rate card types. Confirm that the usage-based rate card logic reflects this structural update.
17960-17967: "Discounts" Reference in Rate Card for Flat Fee.
Here thediscountsproperty now uses the unifiedDiscountsschema with a note that only percentage discounts are supported for flat fee rate cards. Ensure that validation logic enforces this restriction.
18115-18121: "Discounts" Field Update in Rate Card Schema.
The schema now referencesDiscountsfor rate cards, maintaining the new abstraction. Verify that any business rules regarding which discount types are permitted on a given rate card are correctly enforced.
19368-19374: Integration of "Discounts" in Price Details.
Thediscountsfield in the pricing section now referencesDiscounts, and the property titles and descriptions are updated accordingly. Double-check that the provided empty example forPrice(i.e.{}) is intentional.
19487-19494: "Discounts" Field in Plan Schema.
The plan schema now includes adiscountsproperty referencingDiscountsalong with a locally unique identifier. Please verify that the pattern for the resource identifier remains valid in the context of the updated discount model.
19527-19533: Plan Schema: Inclusion of Discounts with Duration.
The addition of adiscountsfield within the plan’s duration details is consistent with the refactored model. Ensure that the documentation comprehensively explains how these discounts interact with the plan’s duration and pricing.
19609-19615: "Discounts" Reference Consistency in Plan Schema.
The final hunk updates thediscountsproperty in the plan schema to referenceDiscountsand includes a title and description. Confirm that any related fields (such asactiveFrom) are validated together with the new discount structure.openmeter/productcatalog/http/mapping.go (6)
75-75: Improved discount handling in FlatFeeRateCardThe code now directly passes discounts through the new
FromDiscountsfunction, simplifying the implementation by removing intermediate conversion steps. This change aligns with the PR's objective to update the discount structure into a unified format that supports both percentage and usage values.
107-107: Consistent discount handling across rate card typesThe discount handling in UsageBasedRateCard now matches the approach used in FlatFeeRateCard, ensuring consistent behavior across different rate card types. This consistency is important for maintainability.
320-339: Well-structured function for discount conversionThe
FromDiscountsfunction has been updated to return a pointer toapi.Discountsinstead of a slice and error. This change properly implements the new discount structure that permits a single discount per type (either percentage or usage).The function correctly:
- Returns nil for empty discounts
- Properly maps both usage and percentage discount types
- Uses a more type-safe approach with dedicated fields
This simplifies error handling in the calling code while maintaining the necessary functionality.
459-465: Proper bidirectional discount conversion in FlatFeeRateCardThe discount conversion is now handled through the updated
AsDiscountsfunction with appropriate error handling. This ensures that any conversion issues are properly reported and managed.
513-519: Consistent discount handling in AsUsageBasedRateCardThe discount handling in the
AsUsageBasedRateCardfunction mirrors the approach used inAsFlatFeeRateCard, ensuring consistent implementation across different rate card types.
523-544: Comprehensive discount conversion logicThe
AsDiscountsfunction effectively handles the conversion from API discount models to internal discount models with:
- Proper null handling (returns empty structure for nil input)
- Independent processing of usage and percentage discounts
- Appropriate error handling for conversion failures
- Clear structure that parallels the
FromDiscountsimplementationThis function completes the bidirectional conversion needed for the new discount format.
api/openapi.cloud.yaml (12)
12272-12300: Validate Discount Percentage and DiscountReason Schemas
The DiscountPercentage schema now explicitly requires a percentage between 0 and 100, which is appropriate. Similarly, DiscountReasonMaximumSpend and DiscountReasonRatecardPercentage correctly require a type property. Please verify that these naming conventions align with the overall refactoring strategy and that all related documentation is updated.
12375-12390: Review Discounts Aggregator Schema
The newly introduced Discounts schema aggregates percentage and usage discount objects. This approach simplifies discount handling by consolidating both types. Consider clarifying in the description how the full discount is computed if both properties are populated.
14653-14660: Confirm Updated Discounts Reference in InvoiceFlatFeeRateCard
The InvoiceFlatFeeRateCard now references BillingDiscounts for its discounts property. This update appears consistent with the new discount structure. Ensure that any related documentation in the client or backend systems is updated accordingly.
14692-14704: Review New InvoiceLineAmountDiscount Schema
The newly defined InvoiceLineAmountDiscount schema correctly mandates required fields such as createdAt, updatedAt, id, reason, and amount. The properties follow the expected format. No issues were found in this hunk.
14730-14736: Verify Reason Property Reference Update
Updating the reason property to reference BillingDiscountReason improves consistency across discount schemas. Please ensure that this change is reflected in any consuming services or documentation.
14742-14784: Assess InvoiceLineDiscounts and External IDs Update
The changes in this section add InvoiceLineAppExternalIds and redefine InvoiceLineDiscounts to include both amount and usage arrays. The multi-line descriptions (using |-) enhance readability. Overall, the changes look consistent with the new discount model.
15769-15776: Confirm Discounts Reference in InvoiceUsageBasedRateCard
The InvoiceUsageBasedRateCard now references BillingDiscounts for the discounts property. The description is clear, and the update aligns with the new rate card structure.
17785-17792: Verify Consistent Schema Naming for Rate Card Discounts
In this section, the discounts property references the unified Discounts schema (instead of BillingDiscounts as seen elsewhere). Please ensure that the naming difference between BillingDiscounts and Discounts is intentional and clearly documented. If they are meant to be the same, consider unifying the naming to avoid confusion.
17934-17941: Ensure Uniform Discount Schema References on Rate Cards
Similar to the previous hunk, the discounts property here references Discounts. Confirm that using Discounts (and not BillingDiscounts) in rate card definitions is deliberate and that downstream systems expect this schema.
19214-19221: Validate Discounts Integration in Price Schema
The pricing schema now includes a discounts property referencing Discounts. This integration appears consistent and clear.
19295-19302: Review Discounts in Plan Definition
The discounts property under the plan now references Discounts. The description “The discounts on the plan.” is clear but consider adding an example or further detail if needed in future iterations.
19377-19384: Confirm Discounts Usage in Resource Identifier Schema
The discounts property is again updated to reference Discounts. The definitions are consistent; however, verify that the use of the Discounts schema (across multiple components) is uniformly implemented across your API documentation and backend logic.openmeter/productcatalog/discount_test.go (9)
17-27: Successfully implemented tests for the new Discounts structure with PercentageDiscountThe test case has been properly updated to use the new
Discountsstructure, correctly initializing thePercentagefield with a pointer to aPercentageDiscount. This matches the structure definition shown in the relevant code snippets, ensuring compatibility with the updated API schema.
30-35: Test case properly handles UsageDiscount initializationThe test case correctly initializes the
Usagefield with a pointer to aUsageDiscountwith the appropriate quantity value. The structure matches the updated code design shown in the relevant snippets.
40-49: JSON serialization/deserialization tests updated appropriatelyThe changes correctly update the JSON marshaling and unmarshaling operations to work with the new
Discountstype. The test properly initializes an emptyDiscountsstruct for unmarshaling and correctly asserts equality between the original and deserialized structures.
58-75: Equality test cases properly refactored for the new Discounts structureThe test cases for equality checks have been correctly updated to use the new
Discountsstructure with pointers to discount types. This refactoring maintains the original test's intent while adapting to the new API design.
78-90: Difference test case updated correctlyThe test case correctly tests inequality between different discount types by comparing a
Discountswith aPercentagefield to one with aUsagefield. This properly verifies that the equality comparison functions as expected between different discount configurations.
111-117: Validation test refactored appropriatelyThe validation test case now correctly initializes a
Discountsstruct with aPercentagefield, ensuring compatibility with the new API structure. The test continues to validate that a 50% discount is considered valid.
120-126: Invalid percentage test case correctly updatedThe test case properly validates that a percentage discount exceeding 100% is considered invalid, using the new
Discountsstructure. This ensures that the validation logic still works correctly with the refactored types.
127-135: Added test case for valid usage discountA new test case has been added to verify that a usage discount with a positive quantity is considered valid. This enhances test coverage by ensuring that both discount types are properly validated.
136-144: Added test case for invalid usage discountA new test case has been added to verify that a usage discount with a negative quantity is correctly identified as invalid. This enhances test coverage and ensures that the validation logic properly handles invalid usage discounts.
openmeter/billing/discount.go (12)
76-81: New Discounts struct properly implements the Clonable interfaceThe
Discountsstruct has been added with proper field types that match the structure in the product catalog. The compiler validation ensures that it correctly implements themodels.Clonableinterface, which is important for proper object copying.
83-95: Clone method properly implemented for deep copyingThe
Clonemethod correctly creates a newDiscountsinstance with deep copies of thePercentageandUsagefields, properly handling nil pointers. This ensures that mutations to the cloned object don't affect the original.
97-99: IsEmpty method implemented correctlyThe
IsEmptymethod leverages thelo.IsEmptyfunction to check if theDiscountsobject is empty. This is a concise and effective implementation.
101-111: ValidateForPrice method handles validation delegation properlyThe method correctly delegates validation to either the
PercentageorUsagediscount'sValidateForPricemethod if present, providing proper validation for the combined structure. The method also correctly handles the case when neither discount type is present.
113-124: Updated discountReason interface with new method signaturesThe interface now includes methods for checking the discount type and converting to specific discount types. This enhances type safety by providing explicit methods for type conversion.
128-142: Well-structured enum for discount reason typesThe
DiscountReasonTypeenum is defined with clear constant values and aValuesmethod that returns all possible values. This is useful for validation and serialization purposes.
144-152: Added MaximumSpendDiscount type and updated DiscountReason structThe
MaximumSpendDiscounttype has been added to represent maximum spend induced discounts. TheDiscountReasonstruct has been updated with a new type field to discriminate between different discount reason types.
154-191: NewDiscountReasonFrom function updated to handle all discount typesThe function has been updated to handle all discount types, including the new
MaximumSpendDiscounttype. The function correctly sets the appropriate type field and initializes the corresponding discount field.
193-229: MarshalJSON method updated for all discount reason typesThe method now properly handles all discount reason types, including the new
MaximumSpendDiscountReason. The serialization creates appropriate structures based on the discount type, ensuring correct JSON representation.
231-264: UnmarshalJSON method updated for all discount reason typesThe method has been updated to correctly deserialize all discount reason types from JSON, setting the appropriate fields based on the type. The method includes proper error handling for invalid JSON.
266-300: Added type accessor and conversion methods for DiscountReasonNew methods have been added to access the discount reason type and convert to specific discount types (
AsRatecardPercentage,AsRatecardUsage, andAsMaximumSpend). These methods enhance type safety by providing explicit conversions with proper error handling.
302-313: Added Validate method for DiscountReasonThe method correctly delegates validation to the appropriate discount type, with proper error handling for invalid discount types. This ensures that all discount reasons are properly validated.
api/spec/src/billing/invoices/discounts.tsp (8)
24-24: Updated InvoiceDiscountBase to use BillingDiscountReasonThe
reasonfield in theInvoiceDiscountBasemodel has been updated to use the newBillingDiscountReasontype instead of the removedInvoiceDiscountReasonenum. This aligns with the PR objective to restructure discounts.
43-57: Added InvoiceLineDiscounts model to organize discounts by typeA new model
InvoiceLineDiscountshas been added to represent discounts applied to invoice lines, organized by type (amount or usage). This aligns with the PR objective to allow a single discount per type by providing clear separation between discount types.
64-82: Renamed and updated InvoiceLineUsageDiscount modelThe model has been renamed from
InvoiceLineDiscountUsagetoInvoiceLineUsageDiscountfor improved clarity and consistency. The model maintains all the necessary fields fromInvoiceDiscountBaseand adds usage-specific fields.
88-98: Renamed and updated InvoiceLineAmountDiscount modelThe model has been renamed from
InvoiceLineDiscountAmounttoInvoiceLineAmountDiscountfor improved clarity and consistency. This naming convention better describes the purpose of the model.
139-149: Added BillingDiscounts model to consolidate discount typesA new model
BillingDiscountshas been added to consolidate percentage and usage discounts into a single structure. This aligns with the PR objective to modify the discount structure to permit only a single discount per type.
154-159: Added DiscountReasonType enum for discount categorizationA new enum
DiscountReasonTypehas been added to categorize discount reasons, with values for maximum spend, ratecard percentage, and ratecard usage. This enhances type safety and clarity in discount reason representation.
164-170: Added BillingDiscountReason union with discriminated valuesA new union
BillingDiscountReasonhas been added with discriminated values based on thetypefield, allowing for clear differentiation between different discount reason types. This improves type safety and clarity.
175-196: Added specific models for different discount reason typesThree new models have been added for different discount reason types:
DiscountReasonMaximumSpend,DiscountReasonRatecardPercentage, andDiscountReasonRatecardUsage. Each model includes the appropriate fields and type discriminator. This ensures proper typing for different discount reasons.openmeter/billing/adapter/invoicelinediff.go (7)
60-62: Added IsEmpty method to diff structThe
IsEmptymethod has been added to thediffstruct to check if there are any items to delete, update, or create. This is a useful utility method that simplifies condition checks throughout the code.
64-72: Replaced discountWithLine with generic withLine structThe
discountWithLinestruct has been replaced with a genericwithLine[T any]struct and appropriate type aliases. This improves code reuse and type safety for different types of discounts.
80-81: Updated invoiceLineDiff struct for separate discount typesThe
invoiceLineDiffstruct has been updated to replace theDiscountsfield with separateUsageDiscountsandAmountDiscountsfields using the new generic types. This aligns with the PR objective to separate different discount types.
351-375: Updated handleLineDependantEntities for separate discount handlingThe function has been updated to handle usage and amount discounts separately, first checking the database state of discounts and then processing each discount type individually. This aligns with the PR objective to modify the discount structure.
378-386: Added diffable interface and handleLineDiscountsResult structA new
diffable[T any]interface has been added to define the requirements for types that can be diffed, along with ahandleLineDiscountsResult[T]struct to hold the results of diffing. This enhances code clarity and type safety.
388-421: Refactored handleLineDiscounts to be genericThe
handleLineDiscountsfunction has been refactored to be generic, allowing it to work with any type that implements thediffable[T]interface. This improves code reuse and type safety.
423-476: Refactored handleLineDiscountUpdate to be genericThe
handleLineDiscountUpdatefunction has been refactored to be generic, with proper error handling and type conversions. The function correctly identifies discounts that need to be created, updated, or deleted.openmeter/ent/schema/billing.go (5)
22-23: Consider verifying JSON scanning logic
Implementation looks good, but please ensure these new JSON scanners handle all edge cases (e.g., null values, empty objects, large discount sets) to avoid downstream parsing errors.
429-431: Confirm references to new discount edges
The newly introduced edges separating usage-based and amount-based discounts seem aligned with the refactor goals. Please verify that all references in queries, resolvers, and tests have been updated to reflect these new edge names.
513-515: Introducing a base discount struct is a solid step
This shared base struct cleanly factors out fields common to multiple discount types.
517-541: Check enumerations and JSON fields for consistency
Please confirm that the 'reason' enum usage and the 'source_discount' JSON field remain consistent across their consumers.
627-685: Usage discount struct appears consistent
No apparent issues with this usage-based discount structure; it aligns well with the design.openmeter/ent/db/paginate.go (4)
494-539: Pagination for flat-fee line config
Implementation follows the established pattern and looks correct.
542-587: Pagination for invoice lines
This method is consistent with other paginated query patterns.
590-635: Pagination for line discounts
Logic mirrors existing pagination structure and appears correct.
638-683: Pagination for usage-based line discounts
This function consistently applies the pagination approach used throughout the codebase.openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (6)
94-97: New edge labels for usage and amount discounts
Separating usage- vs. amount-based discount edges helps clarify discount types and references.
135-148: Distinct tables and columns for discount types
Defining separate inverse tables and columns for usage vs. amount discounts supports the broader discount refactor.
484-496: Ordering by line usage discounts
The neighbor-based ordering logic here aligns well with ENT’s approach.
498-510: Ordering by line amount discounts
Implementation parallels the usage discounts approach, ensuring consistency.
567-573: Usage discount step function
No issues; the O2M edge logic looks standard and correct.
575-580: Amount discount step function
Implementation is consistent with the usage discount step, preserving clarity in the discount architecture.openmeter/productcatalog/discount.go (16)
8-8: Import is correctly added forlopackage.The
lopackage is imported to use its helper functions for collection operations, which is needed for theCloneandIsEmptymethods later in the code.
26-32: Method signature change on PercentageDiscount.Hash aligns with refactoring.The method signature has been changed from a pointer receiver to a value receiver. This approach is consistent with the immutable nature of the struct and ensures safer handling in concurrent environments.
34-42: Validation logic properly retained in PercentageDiscount.Validate.The validation logic ensures percentage values remain between 0 and 100, maintaining business logic integrity while simplifying the overall discount structure.
44-46: Simplified ValidateForPrice method correctly forwards to Validate.This change simplifies the code by delegating to the standard Validate method, which is appropriate since percentage discounts have the same validation rules regardless of price type.
48-52: PercentageDiscount.Clone method correctly implements deep copying.The method properly creates a new instance with the same value, maintaining the immutability pattern expected in the codebase.
64-70: UsageDiscount.Hash implementation follows the pattern established for PercentageDiscount.The method signature has been changed to use a value receiver, consistent with the changes to PercentageDiscount.
72-80: UsageDiscount.Validate correctly enforces positive quantity requirement.The validation ensures that usage discounts cannot have negative values, which is a crucial business rule.
82-99: UsageDiscount.ValidateForPrice logic improved.The method now calls
Validate()first, following the DRY principle, and then performs price-specific validations. The check for flat price compatibility is appropriately maintained.
101-105: UsageDiscount.Clone correctly implements deep copying.The method creates a new instance with the same values, consistent with the cloning pattern elsewhere in the codebase.
110-110: Added Validator interface implementation for Discounts.The code correctly adds the Validator interface implementation for the Discounts type, which is necessary for the new validation method added below.
113-116: Core redesign: Discounts refactored to allow single discount per type.The Discounts type has been completely redesigned from an array of multiple discounts to a struct with exactly one optional discount of each type. This aligns with the PR objective to allow only a single discount per type.
118-128: Equal method updated to work with the new Discounts structure.The method now correctly compares the two optional discount pointers using the
equal.HasherPtrEqualhelper, which safely handles nil pointers and proper equality comparison.
130-142: Clone method properly handles the new Discounts structure.The method correctly creates a deep copy of the Discounts struct, using
lo.ToPtrto convert the cloned values to pointers. This ensures proper immutability and prevents unintended side effects when modifying cloned objects.
144-164: New Validate method added for Discounts.The method properly handles nil receiver checks and validates both discount types if they exist. The error messages are appropriately prefixed with the discount type for clarity in error reporting.
166-186: ValidateForPrice correctly checks both discount types against the price.The method now uses the new
IsEmpty()helper to check if any discounts exist before requiring a price. It then validates each discount type against the price if they exist, providing clear error messages.
188-190: IsEmpty helper method added to check if Discounts is empty.The method delegates to
lo.IsEmpty(), which properly checks if all fields in the struct are zero values, including nil pointers. This provides a clean way to check if no discounts are defined.openmeter/ent/db/client.go (13)
31-31: Import added for the new BillingInvoiceLineUsageDiscount moduleThis import is correctly added to support the new discount structure that separates unit and amount discounts into different tables, as outlined in the PR objectives.
93-94: Addition of BillingInvoiceLineUsageDiscount client to the Client structThis field properly adds the client for the new BillingInvoiceLineUsageDiscount entity, which is a key part of the refactoring to allow only a single discount per type.
171-171: Initialization of BillingInvoiceLineUsageDiscount client in the init methodThe initialization is correctly implemented, ensuring the new client is properly set up when a new Client instance is created.
303-303: Adding BillingInvoiceLineUsageDiscount to the Tx methodThe BillingInvoiceLineUsageDiscount client is correctly added to the transaction configuration, ensuring consistent transaction management.
362-362: Adding BillingInvoiceLineUsageDiscount to the BeginTx methodSimilar to the Tx method, this ensures proper transaction management for the new discount entity.
421-423: Including BillingInvoiceLineUsageDiscount in the Use methodThis properly adds hook support for the new client, ensuring that mutation hooks can be applied to the BillingInvoiceLineUsageDiscount entities.
443-445: Including BillingInvoiceLineUsageDiscount in the Intercept methodThis correctly adds interceptor support for the new client, ensuring that query interceptors can be applied to queries for BillingInvoiceLineUsageDiscount entities.
487-488: Adding mutation support for BillingInvoiceLineUsageDiscountThis properly adds support for handling mutations (creations, updates, deletions) of BillingInvoiceLineUsageDiscount entities to the Mutate method.
2661-2675: Added QueryLineUsageDiscounts method to BillingInvoiceLineClientThis new method correctly implements the ability to query usage discounts associated with a billing invoice line, using the appropriate edge and table configuration.
The implementation follows the same pattern as other query methods and correctly sets up the SQL graph path for the relationship.
2677-2678: Modified QueryLineAmountDiscounts to use LineAmountDiscountsTableThis change updates the edge name used in the QueryLineAmountDiscounts method to reflect the new separation of discounts into different tables. The method now correctly uses the "line_amount_discounts" edge for amount discounts.
Also applies to: 2685-2685
7472-7493: Updated hooks and interceptors structures to include BillingInvoiceLineUsageDiscountThese changes correctly update the internal structures used to track hooks and interceptors for each client type, ensuring that the new BillingInvoiceLineUsageDiscount client is properly included.
2915-3062: Implementation of BillingInvoiceLineUsageDiscountClient methodsThe implementation of the BillingInvoiceLineUsageDiscountClient is thorough and complete, providing all necessary methods for creating, reading, updating, and deleting BillingInvoiceLineUsageDiscount entities. The client follows the same pattern as other clients in the codebase, ensuring consistency.
Key methods include:
- Create/CreateBulk/MapCreateBulk for entity creation
- Update/UpdateOne/UpdateOneID for entity updates
- Delete/DeleteOne/DeleteOneID for entity deletion
- Query/Get/GetX for entity retrieval
- QueryBillingInvoiceLine for navigating relationships
- Hooks/Interceptors for extension points
- mutate for handling mutations
This comprehensive implementation ensures that the new discount structure can be fully managed through the client API.
1-7496:Details
❓ Verification inconclusive
Verify the discount structure transition in the database
The code changes appropriately implement the separation of unit and amount discounts into different tables, as mentioned in the PR objectives. However, it would be valuable to ensure that there's a migration plan to handle existing data.
Consider verifying that:
- There's a database migration script to create the new table structure
- There's a data migration strategy to move existing discounts to the appropriate new tables
- Application code that previously used the combined discount structure is updated to use the separated structure
🏁 Script executed:
#!/bin/bash # Let's examine the database migration scripts to verify proper handling of discount tables # First, check for migration files related to discounts fd migration --exec grep -l "discount|LineDiscount" {}Length of output: 107
I'll run a new script that restricts the search to files only, to see if any migration scripts mention discount adjustments:
🏁 Script executed:
#!/bin/bash # Re-run the migration script search command focusing on files only. fd -t f migration | xargs grep -Hin "discount\|LineDiscount"Length of output: 62
Action Required: Confirm Discount Migration Strategy
The latest verification using automated file searches did not locate any migration scripts referencing “discount” or “LineDiscount.” While the code changes in the client file clearly separate unit and amount discounts, it’s unclear if a corresponding migration has been implemented.
Please verify that:
- A migration script exists to create the new table structure for the separated discount types.
- A data migration strategy is in place to move any existing discount information into the appropriate new tables.
- All parts of the code that previously depended on a combined discount structure have been updated to work with the new separated structure.
If these migration changes are handled outside of what was searched, kindly confirm manually that the migration plan covers these aspects.
openmeter/ent/db/setorclear.go (5)
1136-1141: Consistent nil-check pattern for invoicing external ID.
These lines follow the establishedSetOrClearpattern correctly, returningClearInvoicingAppExternalID()when the input isnil.
1143-1148: Verified one-entity variant.
Same pattern as the multi-entity version above. Implementation looks consistent and maintains clarity.
1164-1176: Selective discount reason field management.
The logic for setting or clearingSourceDiscountfits well, closely mirroring otherSetOrClearmethods. Ensure that upstream code calling these functions properly handles thenilcase if needed.
1178-1190: New method to set or clear discount type.
Looks correct and consistent with otherSetOrClearimplementations, returning the cleared state whenvalue == nil. Carefully verify that any existing references to discount type are updated to reflect this new workflow.
1220-1303: Addition ofSetOrClearmethods for usage-based line discounts.
All newly introduced usage-discount methods (e.g.,SetOrClearDeletedAt,SetOrClearChildUniqueReferenceID, etc.) maintain the same nil-check pattern used elsewhere. This uniform approach is good for consistency. No apparent logical errors.openmeter/billing/invoicelinediscount.go (20)
23-26: Expanded discount base fields.
Adding or exposingChildUniqueReferenceID,ExternalIDs, andReasonintoLineDiscountBaseextends the discount details. Implementation is straightforward.
32-33: Validation ofReason.
The additional validation call ensures discount reasons aren’t silently ignored. This is a good practice to catch improper discount usage early.
47-49: Universal accessor forChildUniqueReferenceID.
Introducing this getter aligns with the new discount reuse mechanism. Code is concise and correct.
52-53: Integration withManagedModelWithID.
EmbeddingManagedModelWithIDintoLineDiscountBaseManagedcentralizes metadata (like creation timestamps). This looks consistent with the rest of the codebase.
105-107: Managed version of amount discount.
The embeddedAmountLineDiscountplusManagedModelWithIDprovides a clean approach for storing discount details with an ID. Implementation is consistent with established patterns.
120-122: Equality check for managed discount.
CheckingManagedModelWithIDequality is important for ensuring the correct match of persistent IDs. Implementation is correct.
133-135: Cloning logic for managed discount.
The approach of shallow-cloning theManagedModelWithIDand deeper cloning of the embedded discount ensures safe duplication. Good job.
138-140:ContentsEqualhelper method.
Separating content equality from full equality (which includes ID/t timestamps) is a useful pattern. Implementation logically fits.
143-151: Helper for reassigning managed fields.
WithManagedFieldsWithIDreuses existing discount content with new ID fields. This is beneficial for partial object updates without losing discount data.
153-203: Collection ofAmountLineDiscountManaged.
Methods likeClone,SumAmount,GetByID, etc., add essential bulk operations on discounts. The usage oflo.Mapfor immutability is consistent with best practices.
255-257: Usage-based discount withManagedModelWithID.
Mirrors the structure of the amount-based discount. Implementation remains consistent.
288-290: Usage-based discount content equality.
Again, splitting content equality from ID equality helps maintain or reuse objects more flexibly.
292-301: Methods for retrieving and updating managed fields in usage-based discount.
Follows the standard pattern used by the other discount types. Straightforward approach.
303-310: Introduction ofUsageLineDiscountsManagedslice type.
Creating a dedicated slice type for usage-line discounts helps unify logic for validations and ID reassignments.
312-333:LineDiscountsstruct to group amount & usage discounts.
This central struct is an effective consolidation of discount data. The usage of separate fields forAmountvs.Usageis clear.
335-351:Validatemethod forLineDiscounts.
Iterating overAmountandUsagediscounts ensures no discount is overlooked. Good error accumulation pattern.
353-369:ReuseIDsFrommethod to reassign persistent IDs.
By matchingChildUniqueReferenceID, existing discounts can keep IDs, preventing duplication. This addresses typical invoice-line discount reusability scenarios.
370-372:IsEmptycheck.
Simple function to confirm if no discounts exist – minimal but handy. Implementation is correct.
374-378:entityWithReusableIDsinterface.
A flexible approach that generalizes ID-reuse for different discount entities.
380-425:ReuseIDsFromgeneric function.
Applies a neat approach for bridging new discount data with existing records. Code is thorough, checks forChildUniqueReferenceID != nil, and merges IDs.openmeter/ent/db/billinginvoicelinediscount/where.go (6)
105-108: Initial helper forInvoicingAppExternalID.
This depicts the basic equality check. Implementation is aligned with existing naming and usage patterns in the ent-based predicates.
120-123: Base predicate forType.
Introduces a direct equality check on thetypefield, consistent with Ent’s approach to generating predicate methods.
545-573:Reason*predicates for discount reason type.
These new methods (EQ, NEQ, In, NotIn) expand the filtering capabilities on discount reasons. They closely match patterns from other fields.
575-648: ExpandedInvoicingAppExternalIDpredicate set.
Supports advanced queries (e.g., GT, LT, Contains, HasPrefix) for external ID. This thoroughly covers typical use cases for partial matching.
740-749:SourceDiscountnil checks.
The ability to check whethersource_discountis set or not can be vital for queries that filter out lines lacking an underlying discount reason. No issues found.
750-823: Comprehensive set ofTypequeries.
Complete coverage for comparisons, null checks, prefix/suffix checks, and case-insensitive matching. This is consistent with other string fields in ent.openmeter/ent/db/billinginvoicelineusagediscount/where.go (2)
1-14: Code generation acknowledged.This file appears to be auto-generated by Ent (as indicated by the header comment). Typically, no manual modifications are required. All predicates and struct definitions align with Ent’s default patterns for building query filters.
758-771: Logical composition functions (And, Or, Not) are standard.These methods are standard Ent code for combining predicates. They look correct and consistent with typical Ent usage, generating clean SQL expressions without duplication.
e2e/productcatalog_test.go (1)
188-206: Verify discount initialization logic.The introduction of
DiscountPercentagewithmodels.NewPercentage(10)and assigning it toDiscounts.Percentageis aligned with the single-discount-per-type approach. This straightforward pattern cleanly sets a 10% discount.test/billing/adapter_test.go (4)
647-682: Comprehensive discount setup on child lines.Here, multiple amount-based discounts are constructed for the detailed child line. This reflects the new single-discount-per-type approach, though the test covers multiple discrete amounts. The logic is clear, attaching each discount with a unique description or reference ID.
694-713: Cleaning managed fields before mutation.Removing
ManagedModelWithIDfields for test comparisons is a good approach to ensure that auto-generated or database-managed fields do not interfere with test validation.
720-769: Reusing existing discount ID and adjusting discount amounts.Searching for and retaining the ID of the manual discount prevents the creation of duplicate database entities. This ensures stable references and correct discount evolution rather than insertion of new discounts.
788-841: Validating persisted discount updates.The step-by-step validation of updated discounts (e.g., verifying updated descriptions, ensuring partial updates persist IDs) confirms correct reuse of existing discount records. This is a thorough approach favorable for regression coverage.
openmeter/ent/db/billinginvoiceline_create.go (5)
21-21: New import for usage-based discounts.
This import line references the newly introducedbillinginvoicelineusagediscountpackage. It appears consistent with the changes enabling usage-based discounts.
417-421: Method added for linking usage-discount IDs.
This method,AddLineUsageDiscountIDs, correctly follows Ent’s pattern for adding a one-to-many edge based on usage-discount IDs. No issues noted.
423-430: Method added for linking usage-discount entities.
AddLineUsageDiscountsproperly collects discount entity IDs and defers toAddLineUsageDiscountIDs. Implementation seems straightforward.
432-436: Method added for linking amount-discount IDs.
AddLineAmountDiscountIDsmirrors its usage-discount counterpart and cleanly adds the related edges. Looks good.
438-445: Method added for linking amount-discount entities.
AddLineAmountDiscountsproperly iterates over the discount objects to gather IDs and delegate toAddLineAmountDiscountIDs. Implementation is consistent.api/client/javascript/src/client/schemas.ts (14)
2330-2332: Enhanced documentation for correlation ID is valuableThe updated documentation clarifies the importance of maintaining the same correlation ID during invoice edits, particularly in progressive billing scenarios. This helps prevent incorrect discount calculations.
2337-2341: Good addition of structured discount reason typeAdding the
BillingDiscountReasonunion type provides a clear structure for different discount reason types, making the API more consistent and easier to understand.
2363-2369: Well-structured BillingDiscounts type supports the single discount per type goalThe new
BillingDiscountstype elegantly consolidates both percentage and usage discounts into a single structure with optional fields for each, directly implementing the PR's goal of allowing a single discount per type.
3399-3405: Improved DiscountPercentage type with better documentationThe enhanced
DiscountPercentagetype with better documentation improves clarity for API consumers.
3406-3463: Comprehensive discount reason types with appropriate metadataThe addition of structured discount reason types (
DiscountReasonMaximumSpend,DiscountReasonRatecardPercentage, andDiscountReasonRatecardUsage) with discriminator properties and correlation IDs provides a robust framework for tracking the origin and purpose of discounts throughout the system.
3478-3484: Consistent Discounts type aligns with overall architectureThe
Discountstype follows the same pattern asBillingDiscounts, maintaining consistency in the codebase while supporting the single discount per type approach.
4978-4978: Updated discounts property type for invoice linesThe change to use
InvoiceLineDiscountstype reflects the new structure for representing discounts on invoice lines, supporting the separation of amount and usage discounts.
5197-5197: Updated discounts type for consistencyChanging to
BillingDiscountstype ensures consistency across the API for discount representations.
5218-5219: Improved naming of InvoiceLineAmountDiscountRenaming from
InvoiceLineDiscountAmounttoInvoiceLineAmountDiscountimproves clarity and consistency with the naming pattern of other discount types.
5247-5247: Updated reason property typeChanged to use the new
BillingDiscountReasonunion type for better type safety and clarity.
5258-5275: Well-designed InvoiceLineDiscounts structureThe
InvoiceLineDiscountstype effectively organizes discounts by category (amount vs. usage), with clear documentation explaining how each type affects the invoice line calculation. This supports the PR objective while maintaining the array representation for calculated discounts.
5320-5368: Comprehensive InvoiceLineUsageDiscount typeThe new
InvoiceLineUsageDiscounttype provides a complete structure for representing usage-based discounts on invoice lines, including all necessary metadata and progressive billing support via thepreLinePeriodQuantityfield.
5742-5742: Consistent updates to discount property typesAll discount property types have been updated consistently throughout the schema to use the new structured discount types, ensuring a cohesive implementation of the single discount per type approach.
Also applies to: 5935-5935, 7448-7448, 7567-7567, 8587-8587, 8646-8646, 8704-8704
9264-9267: Complete exports for all new typesAll newly introduced types are properly exported, making them available for use by API consumers. This ensures the changes are fully accessible throughout the codebase.
Also applies to: 9379-9386, 9479-9483, 9493-9494
openmeter/ent/db/billinginvoicelineusagediscount_query.go (3)
20-32: Well-structured query builder
The struct aligns with ent's standard patterns for query builders, providing targeted methods for filtering and ordering.
65-85: Verify edge definitions
“QueryBillingInvoiceLine” relies on the M2O edge linkingBillingInvoiceLineUsageDiscounttoBillingInvoiceLine. Confirm that the schema definition for this relationship is correct and enforced at the database level.
187-295: Test coverage for multiple fetch methods
Methods likeAll,IDs,Exist, andClonehandle various query scenarios. Ensure comprehensive tests exist for edge cases such as no matches and unusually large result sets to guarantee reliability.openmeter/ent/db/billinginvoiceline_query.go (4)
20-20: Import for usage discount
The added import forbillinginvoicelineusagediscountis consistent with the newly integrated usage discount features.
31-46: New fields for usage & amount discounts
Fields likewithLineUsageDiscountsandwithLineAmountDiscountsexpand the query builder to handle discount retrieval. Confirm that any required migrations or schema changes are fully synchronized.
193-235: Dedicated queries for usage & amount discounts
The methodsQueryLineUsageDiscountsandQueryLineAmountDiscountsare clear entry points for retrieving their respective discounts. Double-check that the edgesline_usage_discountsandline_amount_discountsare declared correctly in the schema.
490-509: Clone method updated
Adding the new discount-related fields inCloneensures that all query parameters are fully copied. This looks good for maintaining consistent query behavior.openmeter/ent/db/billinginvoiceline.go (4)
117-120: Introducing separate discount edges
LineUsageDiscountsandLineAmountDiscountsclarify the distinction between usage-based and amount-based discounts. This naming reduces confusion and aligns with the single discount per type requirement.
129-130: Expanding loadedTypes
Increasing the loadedTypes array from 9 to 10 accounts for the new discount edges. Verify array indexing to ensure no off-by-one errors.
185-201: New edge retrieval methods
LineUsageDiscountsOrErrandLineAmountDiscountsOrErrenhance clarity and error handling if edges were not preloaded. This pattern promotes safer downstream usage.
536-544: Query methods for discount edges
QueryLineUsageDiscountsandQueryLineAmountDiscountsgive consumers straightforward ways to fetch usage or amount discounts. The separation matches the redesigned discount model.openmeter/ent/db/billinginvoicelineusagediscount_delete.go (8)
1-14: No issues with the generated boilerplate.
This section contains standard Ent-generated headers and package imports.
15-20: Struct naming and layout are clear.
BillingInvoiceLineUsageDiscountDeletecorrectly encapsulates the mutation and hooks related to deleting these entities.
22-26: Flexible predicate design.
TheWheremethod allows chaining of predicates for selective deletion. This is consistent with Ent patterns.
28-31: Deletion execution logic.
Execlooks standard: it delegates to hook processing before actual SQL execution.
42-57: Constraint error handling.
sqlgraph.DeleteNodesreturns a constraint error if the deletion violates references. Wrapping it inConstraintErroris standard for Ent, and there's no apparent issue.
59-62: Single-entity delete builder.
BillingInvoiceLineUsageDiscountDeleteOneis a standard Ent pattern for operating on a single node.
64-68: Consistent method naming.
TheWheremethod parallels the multiple-entity builder usage—keeps code structure uniform.
70-82: NotFoundError usage.
Returning aNotFoundErrorif zero rows are deleted is good practice for single-entity delete requests.openmeter/ent/db/billinginvoiceline_update.go (8)
20-20: New import for usage discounts.
Line 20 adds"github.com/openmeterio/openmeter/openmeter/ent/db/billinginvoicelineusagediscount". This aligns with the single-discount-per-type refactor.
557-570: Usage discount edge additions.
AddLineUsageDiscountIDsandAddLineUsageDiscountsprovide clarity for attaching usage discounts to a line.
572-585: Amount discount edge additions.
Similarly,AddLineAmountDiscountIDsandAddLineAmountDiscountshandle amount-based discounts. This separation matches the PR’s single-discount-per-type approach.
652-671: Removing usage discounts.
ClearLineUsageDiscounts,RemoveLineUsageDiscountIDs, andRemoveLineUsageDiscountsensure that usage discounts can be fully or selectively detached from the invoice line.
673-692: Removing amount discounts.
ClearLineAmountDiscounts,RemoveLineAmountDiscountIDs, andRemoveLineAmountDiscountsprovide counterpart functionalities for amount-based discounts.
1044-1088: O2M edge clearing for usage discounts.
WhenLineUsageDiscountsClearedis set, the code properly constructs theO2Medge specification forbillinginvoicelineusagediscount.
1090-1133: Optional usage discount removals.
The logic with_spec.Edges.Clearand_spec.Edges.Addis a standard Ent approach for removing or adding references. No obvious concurrency or data race issues.
2318-2362: Amount discount edge updates.
Equivalent logic for line amount discounts, matching the usage discount logic. The pairing ensures uniform handling of each discount type.openmeter/ent/db/billinginvoicelineusagediscount/billinginvoicelineusagediscount.go (8)
1-14: Generated file header.
Contains canonical Ent definitions; no issues spotted.
15-55: Enum definitions and table/field constants.
Correspond to thebilling_invoice_line_usage_discountsschema. All references align with the PR’s discount separation.
57-82: Column array and validity checks.
ColumnsandValidColumnare standard Ent patterns for ensuring queries target valid fields.
84-99: Default & value scanner structures.
NamespaceValidator,DefaultCreatedAt,DefaultUpdatedAt, andValueScannerforreason_detailsare typical for initialization and custom marshalling.
101-109: Enum validation forReason.
It enforces consistent discount reason types. This is in line with the single discount type usage.
111-133: OrderOption definitions.
Providing multiple ordering functions for precise query sorting is standard. No performance or readability issues found.
139-177: ByField ordering expansions.
ByLineID,ByChildUniqueReferenceID, etc., match the newly introduced fields. This is consistent.
179-191: Neighbor-based ordering viaByBillingInvoiceLineField.
Focuses on the M2O relationship withbilling_invoice_lines. Implementation follows Ent’s neighbor-based ordering approach.openmeter/ent/db/billinginvoicelineusagediscount_create.go (73)
1-14: Boilerplate generation.
Standard code comments and package references. No concerns.
21-27: Struct definition.
BillingInvoiceLineUsageDiscountCreateorganizes mutation hooks, conflict strategy, and the config for creating usage discounts.
29-33: SetNamespace method.
namespaceis required for the discount entity, consistent with the rest of the codebase.
35-47: CreatedAt field methods.
Allows explicit setting or nillable assignment. No performance or correctness issues.
49-61: UpdatedAt field methods.
Same pattern asCreatedAt, ensuring consistency in date fields.
63-75: DeletedAt field methods.
Supports soft-deletion or archival logic. Good for partial invoice record retention.
77-81: SetLineID.
Essential for linking to theBillingInvoiceLine. This matches the new discount architecture.
83-95: ChildUniqueReferenceID.
Helps track usage discount children. Graceful handling of nil for optional references.
97-109: Description field logic.
Optional field for discount clarifications or user notes.
111-115: SetReason method.
Valid discount reason ensures alignment with allowed discount types.
117-129: InvoicingAppExternalID.
Permits external system references; properly nillable.
131-135: SetQuantity.
Crucial for usage-based discount tracking. No issues.
137-149: PreLinePeriodQuantity.
Supports usage calculations for partial/look-back discount logic.
151-155: ReasonDetails.
Extracts additional structured discount data. The approach is consistent with ent's JSON scanning.
157-169: ID field setting.
Permits manual ID overrides, else defaults. Good for advanced use cases.
171-180: BillingInvoiceLine edges.
SetBillingInvoiceLineIDandSetBillingInvoiceLineconnect usage discounts to their parent line.
182-185: Mutation retrieval.
TheMutation()method is standard for advanced or custom logic.
187-191: Save method hooking.
Delegates towithHooksfor any pre- or post-create steps. Ent best practice.
202-213: Exec/ExecX usage.
Same pattern as Save/SaveX, all standard Ent convenience methods.
215-229: defaults method.
Ensures timestamp and ID fields have default values if not set. Aligned with the new discount entity approach.
231-270: check method validations.
ThrowsValidationErrorfor missing required fields and edges. Enforces business logic: usage discount must have a reason, quantity, and linked invoice line.
272-296: sqlSave method.
Conducts the final DB insert; wraps constraint errors. Looks correct and consistent with Ent’s pattern.
298-374: createSpec logic.
Binds each user-specified field, adds edge forbilling_invoice_line, and marshals the JSONreason_details.
376-397: OnConflict and upsert strategy.
Allows advanced conflict resolution. Well-aligned with the introduction of single discount entries.
399-410: OnConflictColumns convenience.
Lets callers specify columns to match on for upserts. No issues.
412-417:BillingInvoiceLineUsageDiscountUpsertOnestruct.
Helper for "upsert" usage with a single discount.
419-423:BillingInvoiceLineUsageDiscountUpsertstruct.
Wraps anUpdateSetfor partial overrides on conflict.
425-453: Field update methods in upsert.
SetUpdatedAt(),UpdateUpdatedAt(),ClearDeletedAt(), etc. reflect typical upsert behavior.
455-465: LineID upsert logic.
Ensures the discount properly associates or re-associates to an invoice line upon conflict.
467-483: ChildUniqueReferenceID overrides.
Optional clearing or setting is consistent with the discount structure.
485-501: Description upsert.
Allows the discount description to be replaced or removed. No issues.
503-513: Reason upsert logic.
Stays consistent with the single discount reason approach.
515-531: InvoicingAppExternalID upsert.
Same pattern for updating or clearing external references.
533-543: Quantity upsert.
Allows re-specifying usage quantity on conflict.
545-561: PreLinePeriodQuantity upsert.
Can re-initialize usage discount’s pre-line figure if the row is re-inserted.
563-579: ReasonDetails upsert.
Lets advanced discount structure be updated or cleared.
581-606: Reuse create logic for "UpdateNewValues".
UpdateNewValuesmerges newly set fields, skipping ID/namespace/CreatedAt if already set.
608-617: Ignore & DoNothing for conflicts.
Ent’s built-in ways to handle uniqueness constraints.
619-624: DoNothing config.
Applies only to SQLite/PostgreSQL, consistent with typical Ent disclaimers.
626-633: Update logic in UpsertOne.
Allows the user to set custom conflict resolutions for each field, bridging auto-resolved merges with user overrides.
635-647: Helper methods for upsert updates.
Inline convenience calls for setting or clearing fields.
649-668: Similar approach forDeletedAt.
All upsert variations remain consistent.
670-682: line_id upsert methods.
Again, paralleling the logic from simpler fields.
684-703: child_unique_reference_id upsert methods.
Same pattern, no concerns.
705-724: description upsert methods.
No concurrency or logic issues.
726-738: reason upsert methods.
Inserting or updating the discount reason is consistent with single discount usage.
740-759: invoicing_app_external_id upsert methods.
Same approach for external references.
761-773: quantity upsert methods.
Re-applies usage discount quantity.
775-787: pre_line_period_quantity upsert methods.
Re-applies or clears pre-line usage quantity.
789-815: reason_details upsert methods.
JSON-based discount detail management.
817-830: Exec and ID retrieval in upsert.
ID()returns the newly inserted or updated discount ID, except in MySQL which lacksRETURNING.
832-853: IDX convenience method.
WrapsID()with a panic on error pattern. Fine for test usage.
855-861: Bulk creation struct.
BillingInvoiceLineUsageDiscountCreateBulkallows multiple usage discounts insertion.
863-920: Bulk Save logic.
Orchestrates a batched insert, each builder running defaults and passing acreateSpec. No concurrency issues evident.
931-942: Bulk Exec methods.
Same approach, returning or panicking on error.
944-964: Bulk OnConflict.
Applying conflict logic for multiple entities at once. Good design for batched usage.
966-976: OnConflictColumns for bulk.
Similar to single upsert approach, but extended for multiple rows.
979-983: BillingInvoiceLineUsageDiscountUpsertBulk struct.
Wrapper for advanced conflict resolution across multiple usage discount rows.
985-1012: UpdateNewValues for multiple discount create.
Resolves with new values across all batched discount creations.
1014-1023: Ignore logic in bulk upsert.
Same pattern as single-entity upsert.
1025-1030: DoNothing in bulk.
Ensures no conflict resolution for batch inserts in PostgreSQL/SQLite.
1032-1039: Update override for bulk upsert.
Lets the developer set custom resolution logic on each field for all rows.
1041-1053: Helper methods for updated_at.
Same approach repeated for each field in the discount struct.
1055-1074: deleted_at updates for bulk.
No concerns; pattern remains the same.
1076-1088: line_id upsert in bulk.
Assign or re-assign usage discount lines in multi-row context.
1090-1109: child_unique_reference_id in bulk.
Optional references are consistently managed.
1111-1130: description in bulk upsert.
Exact parity with single-row logic.
1132-1144: reason for each discount in batch.
No issues.
1146-1165: invoicing_app_external_id in batch.
Clear or override if needed.
1167-1179: quantity in bulk.
Same approach.
1181-1200: pre_line_period_quantity in batch.
Mirrors single discount handling.
1202-1221: reason_details in batch.
Upsert behavior repeated for discount details.
1223-1237: Exec logic in UpsertBulk.
Ensures that the user sets the conflict logic on the bulk builder, not on each single sub-builder.openmeter/ent/db/billinginvoicelineusagediscount_update.go (4)
21-214: Well-structured update builder for multi-entity updates.All setter, nillable setter, and clearer methods neatly follow Ent's design patterns and maintain good readability. The reliance on an internal mutation for state management is clear and consistent. No immediate issues or code smells found in these sections.
372-602: Single-entity update builder duplicates multi-entity logic effectively.This one-entity update builder mirrors the multi-entity version in a conventional manner, providing straightforward usage for updating a single record. No novel issues detected, as the code reuses the same mutation patterns and validations.
603-750: Validation checks and default field handling are appropriate.Automatically setting
updated_atwithUpdateDefaultUpdatedAt()ensures the timestamp is always fresh. The validator calls are consistent with the logic used for multi-entity updates. Everything is properly wrapped in Ent’s standardsqlSaveflow.
1-750:Details
❓ Verification inconclusive
Optional verification of test coverage.
These new methods appear correct, but to ensure comprehensive coverage, you could verify that relevant integration or unit tests exist for all field-updating paths (e.g., clearing fields, nillable setters, validation, and edge clearing).
🏁 Script executed:
#!/bin/bash # Description: Search for test references to the newly introduced Update methods. # Look for tests that call these new builder methods. rg -A 10 "BillingInvoiceLineUsageDiscountUpdate\|BillingInvoiceLineUsageDiscountUpdateOne" --glob '*_test.go'Length of output: 111
Action: Verify Test Coverage for BillingInvoiceLineUsageDiscount Update Methods
The updated builder methods look correct overall; however, the automated search for tests referencing
BillingInvoiceLineUsageDiscountUpdateandBillingInvoiceLineUsageDiscountUpdateOnedid not yield any results. Please manually verify that integration or unit tests are in place that cover:
- Nillable setters (e.g.,
SetNillableDeletedAt,SetNillableLineID, etc.)- Field clearing functions (e.g.,
ClearDeletedAt,ClearDescription,ClearBillingInvoiceLine)- Validation logic in both update builders
If tests for these paths are missing or incomplete, consider adding them to ensure comprehensive coverage.
| field.Other("quantity", alpacadecimal.Decimal{}). | ||
| SchemaType(map[string]string{ | ||
| dialect.Postgres: "jsonb", | ||
| "postgres": "numeric", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "postgres": "numeric", | |
| dialect.Postgres: "numeric", |
|
Comments will be addressed in seperate pr. |
Overview
This patch changes the plan/subscription/invoicing discount to allow a single discount per type, by changing the discount field of the ratecard to this:
Ripple effect on invoicing side
The invoicing actually uses this data to calculate, so the line's ratecard discount have been altered to have the same notion.
The calculated discounts (e.g. how many units we have deducted, how much money we have discounted) on the invoice line remain an array, as there can be multiple amount or unit discounts:
The DiscountReason is still an union type on the LineDiscount, as that's a valid use case-for that: it allows us to correlate which discount/commitment caused the specific invoice line to be created.
DB Changes
This split of unit/amount discounts also necessitated/allowed different db tables for the two. This is beneficial as we can now properly set the null/non null flags.
The remaining field rename and table rename is to be done in a separate PR.
Summary by CodeRabbit
New Features
Refactoring