Skip to content

Conversation

@turip
Copy link
Member

@turip turip commented Apr 6, 2025

Overview

This patch adds the discount reason to the database that can signify if a discount is due to the max amount or a ratecard.

Besides the patch unitifies certain metadata field usage inside the InvoiceLineDiscount API type to reduce duplicates.

Summary by CodeRabbit

  • New Features

    • Enhanced discount details by introducing a mandatory reason field that clearly categorizes discount types.
    • Added supplementary metadata to discount information for improved clarity and tracking.
  • Chores

    • Updated API schemas, database structures, and associated tests to support the new discount details.
    • Implemented SQL migrations to add and manage the new reason column in the billing invoice line discounts table.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Apr 6, 2025

📝 Walkthrough

Walkthrough

This pull request introduces a new discount reason across the system by adding an InvoiceDiscountReason enum (or LineDiscountReason in Go) with values "maximum_spend" and "ratecard_discount". The optional discount code field is replaced with a required reason field in various API schemas, business logic, database entities, and migration scripts. Additional properties, such as externalIds and rateCardDiscount, have been added to enhance discount details, and relevant tests have been updated to reflect these changes.

Changes

File(s) Change Summary
api/client/.../schemas.ts, api/openapi.cloud.yaml, api/openapi.yaml, api/spec/src/billing/invoices/discounts.tsp Introduced InvoiceDiscountReason enum; replaced optional code with required reason field; added externalIds and rateCardDiscount properties in discount objects.
openmeter/billing/adapter/invoicelinemapper.go, openmeter/billing/adapter/invoicelines.go, openmeter/billing/httpdriver/invoiceline.go, openmeter/billing/invoiceline.go, openmeter/billing/service/lineservice/usagebasedline.go, openmeter/billing/service/lineservice/usagebasedline_test.go Added Reason field to discount structures and mappings; removed legacy Code; introduced a new LineDiscountReason type with constants and a Values() method; updated invoice line processing and tests with SetReason calls.
openmeter/ent/db/billinginvoicelinediscount.go, openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go, openmeter/ent/db/billinginvoicelinediscount/where.go, openmeter/ent/db/billinginvoicelinediscount_create.go, openmeter/ent/db/billinginvoicelinediscount_update.go, openmeter/ent/db/migrate/schema.go, openmeter/ent/db/mutation.go, openmeter/ent/schema/billing.go Integrated a reason field into database models and mutation logic; added validators, setters, ordering functions, and predicates; updated the schema and migration definitions to include a new enum column for discount reason.
tools/migrate/migrations/20250406215430_billing-line-discount-reason.{up,down}.sql SQL migration scripts to add a new "reason" column (with an initial default of 'maximum_spend' that is later dropped) and a corresponding rollback script to drop the column.
test/billing/adapter_test.go Updated discount handling tests to include and verify the new Reason field in discount objects.

Possibly related PRs

  • feat: persist rate card discounts #2588: Involves modifications to discount-related structures, introducing new properties for handling discount reasons and rate card discounts, aligning with the changes in this PR.
  • feat: invoice discounts api v2 #2576: Focuses on the integration of the InvoiceDiscountReason enum into discount objects, which is closely related to the restructuring implemented in this PR.

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
Failed executing command with 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/20250406215430_billing-line-discount-reason.down.sql

User Error: No dialect was specified. You must configure a dialect or specify one on the command line using --dialect after the command. Available dialects:
ansi, athena, bigquery, clickhouse, databricks, db2, duckdb, exasol, greenplum, hive, impala, mariadb, materialize, mysql, oracle, postgres, redshift, snowflake, soql, sparksql, sqlite, starrocks, teradata, trino, tsql, vertica

tools/migrate/migrations/20250406215430_billing-line-discount-reason.up.sql

User Error: No dialect was specified. You must configure a dialect or specify one on the command line using --dialect after the command. Available dialects:
ansi, athena, bigquery, clickhouse, databricks, db2, duckdb, exasol, greenplum, hive, impala, mariadb, materialize, mysql, oracle, postgres, redshift, snowflake, soql, sparksql, sqlite, starrocks, teradata, trino, tsql, vertica

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@turip turip force-pushed the feat/add-discount-reason branch from 2772421 to 4e076ae Compare April 6, 2025 21:56
@turip turip added release-note/misc Miscellaneous changes area/billing labels Apr 6, 2025
@turip turip force-pushed the feat/add-discount-reason branch 2 times, most recently from cc437a7 to fe90ce9 Compare April 6, 2025 22:08
@turip turip marked this pull request as ready for review April 6, 2025 22:09
@turip turip requested a review from a team as a code owner April 6, 2025 22:09
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
openmeter/ent/schema/billing.go (1)

519-521: Consider adding a default value to the enum field.

The new reason field is properly defined as an enum field that uses the billing.LineDiscountReason type. Since this field appears to be required (not marked as optional or nullable), consider adding a default value to ensure that existing records are properly handled during migration.

Example:

field.Enum("reason").
	GoType(billing.LineDiscountReason("")).
+	Default(string(billing.LineDiscountReasonRatecardDiscount))
openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (1)

90-98: LGTM: Validator added for reason field with minor improvement opportunity

The ReasonValidator function properly validates that the reason field contains only allowed values.

Consider using the defined constants LineDiscountReasonMaximumSpend and LineDiscountReasonRatecardDiscount instead of string literals in the validation switch for better maintainability, unless this is a limitation of the code generation tool.

api/spec/src/billing/invoices/discounts.tsp (1)

1-124: Consider future extensibility of discount reasons.

The current enum has two values (maximumSpend and ratecardDiscount). If you anticipate additional discount types in the future, ensure your implementation and database migrations are designed to accommodate extensions easily.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4529975 and fe90ce9.

⛔ Files ignored due to path filters (1)
  • tools/migrate/migrations/atlas.sum is excluded by !**/*.sum
📒 Files selected for processing (21)
  • api/client/javascript/src/client/schemas.ts (4 hunks)
  • api/openapi.cloud.yaml (5 hunks)
  • api/openapi.yaml (5 hunks)
  • api/spec/src/billing/invoices/discounts.tsp (2 hunks)
  • openmeter/billing/adapter/invoicelinemapper.go (1 hunks)
  • openmeter/billing/adapter/invoicelines.go (1 hunks)
  • openmeter/billing/httpdriver/invoiceline.go (1 hunks)
  • openmeter/billing/invoiceline.go (2 hunks)
  • openmeter/billing/service/lineservice/usagebasedline.go (2 hunks)
  • openmeter/billing/service/lineservice/usagebasedline_test.go (10 hunks)
  • openmeter/ent/db/billinginvoicelinediscount.go (5 hunks)
  • openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (5 hunks)
  • openmeter/ent/db/billinginvoicelinediscount/where.go (2 hunks)
  • openmeter/ent/db/billinginvoicelinediscount_create.go (7 hunks)
  • openmeter/ent/db/billinginvoicelinediscount_update.go (7 hunks)
  • openmeter/ent/db/migrate/schema.go (3 hunks)
  • openmeter/ent/db/mutation.go (8 hunks)
  • openmeter/ent/schema/billing.go (1 hunks)
  • test/billing/adapter_test.go (3 hunks)
  • tools/migrate/migrations/20250406215430_billing-line-discount-reason.down.sql (1 hunks)
  • tools/migrate/migrations/20250406215430_billing-line-discount-reason.up.sql (1 hunks)
🧰 Additional context used
🧬 Code Definitions (10)
openmeter/billing/httpdriver/invoiceline.go (3)
api/api.gen.go (1)
  • InvoiceDiscountReason (3023-3023)
api/client/go/client.gen.go (1)
  • InvoiceDiscountReason (2763-2763)
api/client/javascript/src/client/schemas.ts (1)
  • InvoiceDiscountReason (9040-9041)
openmeter/billing/adapter/invoicelines.go (4)
api/api.gen.go (1)
  • Discount (1925-1927)
api/client/go/client.gen.go (1)
  • Discount (1790-1792)
api/client/javascript/src/client/schemas.ts (1)
  • Discount (8961-8961)
openmeter/productcatalog/discount.go (1)
  • Discount (53-57)
openmeter/ent/schema/billing.go (1)
openmeter/billing/invoiceline.go (2)
  • LineDiscountReason (729-729)
  • LineDiscountReason (736-741)
openmeter/billing/service/lineservice/usagebasedline.go (1)
openmeter/billing/invoiceline.go (1)
  • LineDiscountReasonMaximumSpend (732-732)
openmeter/billing/service/lineservice/usagebasedline_test.go (1)
openmeter/billing/invoiceline.go (1)
  • LineDiscountReasonMaximumSpend (732-732)
test/billing/adapter_test.go (1)
openmeter/billing/invoiceline.go (2)
  • LineDiscountReasonMaximumSpend (732-732)
  • LineDiscountReasonRatecardDiscount (733-733)
openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (1)
openmeter/billing/invoiceline.go (2)
  • LineDiscountReason (729-729)
  • LineDiscountReason (736-741)
openmeter/ent/db/migrate/schema.go (2)
openmeter/ent/db/billinginvoiceline/billinginvoiceline.go (1)
  • Columns (165-198)
openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (1)
  • Columns (53-65)
api/client/javascript/src/client/schemas.ts (2)
api/client/go/client.gen.go (1)
  • InvoiceDiscountReason (2763-2763)
api/api.gen.go (1)
  • InvoiceDiscountReason (3023-3023)
openmeter/ent/db/billinginvoicelinediscount_create.go (2)
openmeter/billing/invoiceline.go (2)
  • LineDiscountReason (729-729)
  • LineDiscountReason (736-741)
openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (2)
  • ReasonValidator (91-98)
  • FieldReason (30-30)
⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: Quickstart
  • GitHub Check: E2E
  • GitHub Check: CI
  • GitHub Check: Lint
  • GitHub Check: Developer environment
  • GitHub Check: Commit hooks
  • GitHub Check: Test
  • GitHub Check: Build
  • GitHub Check: Analyze (go)
🔇 Additional comments (78)
tools/migrate/migrations/20250406215430_billing-line-discount-reason.down.sql (1)

1-2: LGTM: The down migration correctly drops the reason column.

The SQL statement properly reverses the changes made in the up migration by removing the "reason" column from the "billing_invoice_line_discounts" table.

openmeter/billing/adapter/invoicelinemapper.go (1)

218-218: LGTM: Reason field correctly added to LineDiscount struct.

The addition of the discount.Reason field to the LineDiscount struct correctly implements the mapping from the database entity to the business model. This addition aligns with the PR objective of introducing a discount reason field.

tools/migrate/migrations/20250406215430_billing-line-discount-reason.up.sql (1)

1-3: LGTM: Migration properly adds reason column with appropriate defaults.

The migration follows best practices by:

  1. Adding the "reason" column with a default value of 'maximum_spend' to ensure existing records have a valid value
  2. Making the column NOT NULL to enforce data integrity
  3. Dropping the default value to require explicit reason values for future entries

This approach ensures a smooth transition for existing data while enforcing proper validation for new records.

openmeter/billing/service/lineservice/usagebasedline.go (2)

980-980: LGTM: Maximum spend discount reason correctly added.

The addition of the Reason field set to billing.LineDiscountReasonMaximumSpend properly identifies the discount type for 100% discounts that occur when maximum spend has been reached.


990-990: LGTM: Partial maximum spend discount reason correctly added.

The addition of the Reason field set to billing.LineDiscountReasonMaximumSpend properly identifies the discount type for partial discounts that occur when maximum spend is partially exceeded.

openmeter/billing/adapter/invoicelines.go (1)

192-192: Good addition of the new required field.

The SetReason method call ensures that the discount reason is properly set during the creation of invoice line discounts. This aligns with the PR objective to add discount reasons to the database.

openmeter/ent/db/billinginvoicelinediscount.go (5)

13-13: LGTM - Appropriate import added.

The new import for the billing package is correctly added to support the LineDiscountReason type.


33-34: LGTM - New field properly added to struct.

The Reason field is correctly defined with the appropriate type billing.LineDiscountReason in the BillingInvoiceLineDiscount struct.


76-77: LGTM - Field properly added to scanValues.

The FieldReason is correctly included in the list of string fields for scanning values from SQL rows.


132-137: LGTM - Field properly handled in assignValues.

The new field is correctly handled in the assignValues method with proper type checking and conversion from SQL value to the Go type.


223-225: LGTM - Field properly included in String representation.

The Reason field is correctly included in the string representation of the BillingInvoiceLineDiscount struct.

openmeter/billing/httpdriver/invoiceline.go (1)

451-451:

Details

❓ Verification inconclusive

Verify this change doesn't break existing API consumers.

The Code field has been replaced with Reason in the API representation. While this aligns with the PR objective to unify the usage of metadata fields, ensure that all API consumers are updated to use the new field name, especially if they rely on the previous Code field.

Run this script to find any references to the old field name in the codebase:


🏁 Script executed:

#!/bin/bash
# Search for references to the old Code field
echo "Searching for references to the old 'Code' field in API consumers..."
rg "InvoiceLineDiscountAmount.*Code" --type ts
rg "InvoiceLineDiscount.*Code" --type ts
echo ""
echo "Searching for references to the old field in API tests..."
rg "Code.*InvoiceLineDiscount" --type go

Length of output: 423


Action Required: Verify API Consumer Updates for Field Name Change

The code now uses the Reason field instead of the previous Code field (see openmeter/billing/httpdriver/invoiceline.go, line 451). While our automated searches for the old Code references in both TypeScript consumers and Go test files didn't return any results, the absence of output warrants a manual review to confirm that all API consumers have been fully updated.

  • File Affected: openmeter/billing/httpdriver/invoiceline.go (line 451)
  • Change: Replaced Code with Reason (e.g., Reason: api.InvoiceDiscountReason(discount.Reason))

Next Steps:
Please manually verify that no consumer code or API tests still rely on the old Code field to ensure the change won’t break existing integrations.

openmeter/billing/service/lineservice/usagebasedline_test.go (7)

408-408: LGTM: Reason field properly added for maximum spend discount

The addition of the Reason field set to billing.LineDiscountReasonMaximumSpend correctly identifies this discount as one applied due to maximum spend limit being reached.


593-593: LGTM: Reason field correctly specified for dynamic pricing maximum spend discount

Appropriate use of LineDiscountReasonMaximumSpend for this discount that's applied when exceeding the maximum spend threshold in the dynamic pricing test.


835-835: LGTM: Reason field properly added for package price maximum spend discount

The Reason field correctly uses LineDiscountReasonMaximumSpend for the discount applied when package pricing exceeds the maximum spend limit.


1240-1240: LGTM: Reason field added to tiered volume calculation discount

The Reason field is correctly set to LineDiscountReasonMaximumSpend for this discount applied in tiered volume calculations when the maximum spend is reached.


1490-1490: LGTM: Reason field added for graduated tiered discount

Consistent use of LineDiscountReasonMaximumSpend for this maximum spend discount in graduated tiered pricing test, maintaining the pattern established throughout the file.


1505-1505: LGTM: Reason field added for second tier graduated discount

Proper addition of the Reason field with LineDiscountReasonMaximumSpend for another tier of the graduated tiered pricing discount.


1562-1562: LGTM: Consistent reason field implementation in discount overage tests

The Reason field is correctly added to the discount structure in the TestAddDiscountForOverage function, using the appropriate maximum spend value.

test/billing/adapter_test.go (6)

647-647: LGTM: Reason field added to first test discount with maximum spend reason

The Reason field is correctly set to billing.LineDiscountReasonMaximumSpend for this discount that's related to maximum spend constraints, as indicated by its reference ID.


653-653: LGTM: Reason field added to second test discount with maximum spend reason

Appropriate assignment of LineDiscountReasonMaximumSpend to this discount that's also related to maximum spend constraints with a different reference ID.


658-658: LGTM: Reason field added to manual discount with ratecard discount reason

The Reason field correctly uses billing.LineDiscountReasonRatecardDiscount for this manual discount, showing proper differentiation between discount types.


687-687: LGTM: Reason field preserved in discount update

The Reason field with LineDiscountReasonMaximumSpend is properly included in the discount update, ensuring the reason is maintained through the update process.


700-700: LGTM: Reason field maintained with proper value during discount update

The second updated discount correctly maintains LineDiscountReasonRatecardDiscount as its reason during the update operation.


705-705: LGTM: Reason field added to new test discount

New manual discount correctly includes the Reason field with LineDiscountReasonRatecardDiscount, validating that new discounts can be created with the required reason field.

openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (3)

29-30: LGTM: Field constant added for reason database field

The FieldReason constant is properly defined to represent the "reason" field in the database schema.


60-60: LGTM: Reason field added to database columns list

The FieldReason is correctly added to the Columns slice, ensuring it's included in database operations.


133-136: LGTM: Order function added for reason field

The ByReason function properly provides a way to order query results by the new "reason" field, following the pattern used for other fields.

openmeter/billing/invoiceline.go (3)

729-734: LGTM: LineDiscountReason type and constants defined

The new LineDiscountReason type is properly defined as a string-based enum with appropriate constants for "maximum_spend" and "ratecard_discount" values, clearly identifying the possible reasons for discounts.


736-741: LGTM: Values method implemented for LineDiscountReason

The Values() method properly returns a slice containing all valid values for the LineDiscountReason type, following the pattern used for other enum types in the codebase.


754-754: LGTM: Reason field added to LineDiscount struct

The Reason field of type LineDiscountReason is properly added to the LineDiscount struct. The field is correctly marked as required (no omitempty tag), aligning with the PR objective of replacing an optional code field with a required reason field.

api/spec/src/billing/invoices/discounts.tsp (3)

7-14: Good addition of the InvoiceDiscountReason enum.

The new enum provides better type safety and clarity compared to using a string field. The naming follows conventions well with camelCase for enum members and snake_case for actual values.


41-52: Good refactoring of externalIds and rateCardDiscount.

Moving these fields from child models to the base model improves code organization by reducing duplication and maintaining consistency. The fields are properly documented with appropriate visibility settings.


32-33:

Details

✅ Verification successful

Verify migration strategy for breaking change.

Replacing an optional code string field with a required reason enum field is a breaking change. Ensure there's a proper migration strategy to populate this field for existing records.


🏁 Script executed:

#!/bin/bash
# Check for migration files related to this change
echo "Checking for migration files..."
fd -e sql -e go ".*discount.*reason.*" | grep -i migration

Length of output: 287


Migration strategy verified – Migration scripts detected for discount reason update.

The existence of both the up and down migration files:

  • tools/migrate/migrations/20250406215430_billing-line-discount-reason.up.sql
  • tools/migrate/migrations/20250406215430_billing-line-discount-reason.down.sql

confirms that a migration strategy has been implemented for the breaking change. Please ensure that these scripts correctly update existing records by converting the optional code string field to the required reason enum field.

api/openapi.cloud.yaml (5)

13816-13821: New InvoiceDiscountReason Schema Added:
The new schema definition for InvoiceDiscountReason is correctly defined as a string enum with the values maximum_spend and ratecard_discount. The description “Reason code.” is concise and helpful. Ensure that any documentation or client code referencing discount reasons is updated to reflect this change.


14282-14288: Including the New “reason” Field in Required List:
The addition of the reason property to the required fields list (line 14285) in the relevant component helps enforce that every discount object includes this critical information. Verify that any API client validations or downstream processing logic are updated accordingly.


14313-14337: Enhancing Discount Object with New Properties:
This hunk adds the reason field (using an allOf reference to InvoiceDiscountReason), as well as externalIds and rateCardDiscount properties, to the discount object. The use of allOf for schema composition is appropriate, and marking these fields as read-only ensures they aren’t unintentionally modified. Ensure that the removal of the old code field (if applicable) is consistently handled across all API documentation and client implementations.


14344-14357: Updating InvoiceLineDiscountUsage Schema:
The insertion of the reason property into the required fields list for InvoiceLineDiscountUsage is consistent with the changes made for discount amounts. This improvement unifies the discount metadata and strengthens data consistency. It’s recommended to verify that all consumers of this API update their payloads to include the new required field.


14382-14406: Completing Discount Usage Object Updates:
Here, the discount usage object now includes the new reason field—again using an allOf reference to InvoiceDiscountReason—as well as the externalIds and rateCardDiscount properties. The consistent pattern between the discount amount and discount usage schemas improves clarity and maintainability. Double-check any client-side integrations to ensure they properly handle these new, read-only fields.

openmeter/ent/db/billinginvoicelinediscount/where.go (5)

11-11: Import correctly added for the new LineDiscountReason type.

The billing package import has been properly added to use the LineDiscountReason enum type.


375-379: Well-implemented equality predicate.

The ReasonEQ function follows the established pattern in this generated file, correctly applying the equality predicate on the new "reason" field.


381-385: Well-implemented not-equal predicate.

The ReasonNEQ function maintains consistency with other predicate functions in this file, properly implementing the not-equal operation.


387-394: Correctly implemented "In" predicate with proper type conversion.

The ReasonIn function properly converts the typed LineDiscountReason values to a slice of any type before passing to sql.FieldIn, which is the correct pattern for handling enum types in SQL queries.


396-403: Correctly implemented "NotIn" predicate with proper type conversion.

The ReasonNotIn function follows the same pattern as ReasonIn, maintaining consistency with other similar functions in the file while properly handling the enum type conversion.

api/openapi.yaml (5)

13890-13895: New InvoiceDiscountReason Schema Definition Added.

The schema is correctly defined as a string type with the enumerated values maximum_spend and ratecard_discount and includes a clear description ("Reason code."). This aligns with the PR objective of adding a standardized discount reason.


14356-14362: Updated Required Fields to Include reason.

The required list now includes the reason field, ensuring that every discount amount object must specify a discount reason. Please verify that all client-side and backend validations are updated to set this field accordingly.


14390-14408: Consistent Addition of Metadata in Discount Amount Schema.

The discount amount object now integrates the reason property referencing InvoiceDiscountReason, along with the new externalIds and rateCardDiscount properties. All added properties are marked as read-only and use the appropriate $ref pointers. This consistent approach enhances clarity and reduces duplication across the API schemas.


14418-14431: Enforced reason as Required in Discount Usage.

The discount usage object’s required fields now include reason, reinforcing the need to always provide a discount reason. This update promotes consistency across the API. Please ensure that any data creation flows or client logic that instantiate this object are updated to provide a valid reason.


14456-14480: Consistent Schema Enhancements for Discount Usage.

The discount usage object now features the reason property (referencing InvoiceDiscountReason), along with externalIds and rateCardDiscount fields defined via allOf. This mirrors the changes made in the discount amount schema, ensuring uniformity in the API. Verify that the updated documentation and client integrations reflect these enhancements.

openmeter/ent/db/migrate/schema.go (3)

818-818: Added new enum field for discount reason tracking

The new reason field is correctly defined as an enum type with the values "maximum_spend" and "ratecard_discount", aligning with the PR objectives to distinguish between different discount types.


833-834: Updated foreign key column reference to maintain integrity

The foreign key reference has been properly updated to reflect the new column order after adding the reason field.


852-857: Updated index definitions to include new reason column

The index definitions have been properly updated to accommodate the new column position, maintaining database integrity.

openmeter/ent/db/billinginvoicelinediscount_update.go (7)

15-15: Added import for billing package

Appropriate import for the billing package that contains the LineDiscountReason type needed for the new field.


74-86: Added setter methods for the new reason field

These methods follow the established pattern for field setters in the codebase:

  • SetReason sets the reason directly
  • SetNillableReason sets the reason only if the provided pointer is not nil

Good implementation that maintains consistency with the existing codebase style.


222-226: Added validation for the reason field

The validation properly checks that the reason value adheres to the constraints defined by the ReasonValidator function, ensuring data integrity.


254-256: Included reason field in SQL update operations

This ensures the reason field will be properly persisted to the database when an update operation is performed.


367-379: Added reason setters to UpdateOne builder

Consistent implementation of the same setter methods for the UpdateOne variant, maintaining the pattern used throughout the codebase.


528-532: Added validation to UpdateOne builder

Validation logic is correctly mirrored in the UpdateOne struct's check method, ensuring data integrity is maintained for both update paths.


577-579: Included reason field in SQL update operations for UpdateOne

Similar to the multi-update variant, this ensures the reason field will be properly persisted to the database during single-entity updates.

openmeter/ent/db/mutation.go (8)

18088-18088: LGTM: New field addition aligned with PR objectives.

The addition of the reason field of type *billing.LineDiscountReason to the BillingInvoiceLineDiscountMutation struct correctly implements the discount reason functionality described in the PR objectives.


18398-18432: LGTM: Well-implemented accessor methods for the new reason field.

The implementation of SetReason, Reason, OldReason, and ResetReason methods follows the established pattern in the codebase. The OldReason method correctly includes validation to ensure it's only called during an UpdateOne operation and requires a valid ID, with appropriate error messages for different failure cases.


18691-18691: LGTM: Proper capacity adjustment.

The capacity of the fields slice has been increased from 9 to 10 to accommodate the new reason field, ensuring efficient memory allocation.


18707-18709: LGTM: Correctly included in Fields method.

The new reason field is properly added to the list of fields when it's been modified, following the established pattern for other fields.


18740-18741: LGTM: Properly included in Field method.

The case for the reason field is correctly added to the Field method, allowing access to the field value by name.


18769-18770: LGTM: Properly included in OldField method.

The case for the reason field is correctly added to the OldField method, allowing access to the previous field value by name.


18823-18829: LGTM: Correctly implemented in SetField method.

The case for setting the reason field is properly added to the SetField method, including appropriate type checking to ensure the value is of the correct type.


18949-18951: LGTM: Properly included in ResetField method.

The case for the reason field is correctly added to the ResetField method, allowing for resetting changes to this field by name.

openmeter/ent/db/billinginvoicelinediscount_create.go (7)

16-16: Correctly added billing package import.

The import for the billing package is necessary to access the LineDiscountReason type used in the new methods.


83-87: Well-implemented SetReason method.

The SetReason method follows the same pattern as other setter methods in this file, maintaining consistency with the codebase. It correctly sets the reason field in the mutation and returns the builder for method chaining.


230-237: Proper validation for the new required reason field.

The validation logic correctly:

  1. Checks that the reason field is present (making it required)
  2. Validates the value using the ReasonValidator to ensure it's either "maximum_spend" or "ratecard_discount"

This is consistent with the PR objectives of adding a discount reason field.


296-299: Correctly implemented reason field in createSpec.

The implementation properly sets the reason field in both the database operation specification and the returned node object, following the pattern used for other fields.


427-437: Well-implemented SetReason and UpdateReason methods for upsert operations.

These methods properly implement:

  1. Setting a specific value for the reason field
  2. Using the value provided in the create operation

This maintains consistency with how other fields are handled in upsert operations.


608-620: Consistent implementation of SetReason and UpdateReason for single upsert.

The methods follow the established pattern for field operations in the BillingInvoiceLineDiscountUpsertOne struct, ensuring consistency throughout the codebase.


969-981: Properly implemented SetReason and UpdateReason for bulk upsert operations.

The implementation for bulk operations correctly follows the pattern used for other fields, ensuring a consistent API across the codebase.

api/client/javascript/src/client/schemas.ts (4)

4755-4759: Well-structured enum definition for discount reasons.

The new InvoiceDiscountReason enum clearly defines the two possible discount reason types ('maximum_spend' and 'ratecard_discount'), which aligns with the PR objective of indicating whether a discount is applied due to reaching the maximum amount or as a result of a rate card.


5165-5171: Consistent schema changes applied to both discount types.

The same changes have been applied to both discount schemas (amount-based and usage-based), ensuring consistency across the API. This unified approach to metadata fields fulfills the stated PR objective.


9040-9041: Appropriate type export.

Exporting the InvoiceDiscountReason type makes it available for use by consumers of this API client, which is necessary for proper type checking when working with the updated discount schemas.


5116-5122:

Details

❓ Verification inconclusive

Good enhancement of the invoice line discount schema.

The changes appropriately replace the optional code field with a required reason field, ensuring that all discounts now have a standardized reason. The additional fields (externalIds and rateCardDiscount) provide valuable context about the discount's origin and related systems.


🏁 Script executed:

#!/bin/bash
# Verify that all consumers of this API are updated to handle the required reason field
# instead of the optional code field that was previously used

# Check for any references to discount code in the codebase
echo "Checking for references to discount code that might need updating:"
rg "discount.*code" --type ts --type go

Length of output: 184


API Consumer Update Verification Required for Invoice Discount Schema Changes

The invoice discount schema update looks solid. The previously optional code field has been replaced with a required reason field, ensuring standardized discount reasons across the application. Additionally, the inclusion of externalIds and rateCardDiscount provides valuable context regarding the discount's origin and related systems.

Since our automated search (rg "discount.*code" --type ts --type go) did not yield any results, there is low confidence in its completeness. Please manually verify that all consumers of this API have been updated to handle the required reason field, ensuring that no legacy references to the old code field remain.

  • File: api/client/javascript/src/client/schemas.ts (lines 5116-5122)
  • Change: Replace the optional code field with a required reason field and add the new externalIds and rateCardDiscount fields.

@turip turip enabled auto-merge (squash) April 6, 2025 22:15
@turip turip force-pushed the feat/add-discount-reason branch from fe90ce9 to 4cf7f1d Compare April 7, 2025 07:24
Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fe90ce9 and 4cf7f1d.

⛔ Files ignored due to path filters (1)
  • tools/migrate/migrations/atlas.sum is excluded by !**/*.sum
📒 Files selected for processing (21)
  • api/client/javascript/src/client/schemas.ts (4 hunks)
  • api/openapi.cloud.yaml (5 hunks)
  • api/openapi.yaml (5 hunks)
  • api/spec/src/billing/invoices/discounts.tsp (2 hunks)
  • openmeter/billing/adapter/invoicelinemapper.go (1 hunks)
  • openmeter/billing/adapter/invoicelines.go (1 hunks)
  • openmeter/billing/httpdriver/invoiceline.go (1 hunks)
  • openmeter/billing/invoiceline.go (2 hunks)
  • openmeter/billing/service/lineservice/usagebasedline.go (2 hunks)
  • openmeter/billing/service/lineservice/usagebasedline_test.go (10 hunks)
  • openmeter/ent/db/billinginvoicelinediscount.go (5 hunks)
  • openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (5 hunks)
  • openmeter/ent/db/billinginvoicelinediscount/where.go (2 hunks)
  • openmeter/ent/db/billinginvoicelinediscount_create.go (7 hunks)
  • openmeter/ent/db/billinginvoicelinediscount_update.go (7 hunks)
  • openmeter/ent/db/migrate/schema.go (3 hunks)
  • openmeter/ent/db/mutation.go (8 hunks)
  • openmeter/ent/schema/billing.go (1 hunks)
  • test/billing/adapter_test.go (3 hunks)
  • tools/migrate/migrations/20250406215430_billing-line-discount-reason.down.sql (1 hunks)
  • tools/migrate/migrations/20250406215430_billing-line-discount-reason.up.sql (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (14)
  • tools/migrate/migrations/20250406215430_billing-line-discount-reason.down.sql
  • openmeter/billing/adapter/invoicelines.go
  • openmeter/ent/db/billinginvoicelinediscount.go
  • test/billing/adapter_test.go
  • openmeter/billing/httpdriver/invoiceline.go
  • tools/migrate/migrations/20250406215430_billing-line-discount-reason.up.sql
  • openmeter/billing/adapter/invoicelinemapper.go
  • openmeter/billing/service/lineservice/usagebasedline_test.go
  • openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go
  • api/client/javascript/src/client/schemas.ts
  • openmeter/billing/service/lineservice/usagebasedline.go
  • openmeter/billing/invoiceline.go
  • openmeter/ent/db/migrate/schema.go
  • api/openapi.yaml
🧰 Additional context used
🧬 Code Definitions (2)
openmeter/ent/schema/billing.go (1)
openmeter/billing/invoiceline.go (2)
  • LineDiscountReason (729-729)
  • LineDiscountReason (736-741)
openmeter/ent/db/billinginvoicelinediscount/where.go (4)
openmeter/billing/invoiceline.go (2)
  • LineDiscountReason (729-729)
  • LineDiscountReason (736-741)
openmeter/ent/db/billinginvoicelinediscount.go (2)
  • BillingInvoiceLineDiscount (19-47)
  • BillingInvoiceLineDiscount (70-85)
openmeter/ent/schema/billing.go (5)
  • BillingInvoiceLineDiscount (500-502)
  • BillingInvoiceLineDiscount (504-510)
  • BillingInvoiceLineDiscount (512-541)
  • BillingInvoiceLineDiscount (543-552)
  • BillingInvoiceLineDiscount (554-562)
openmeter/ent/db/billinginvoicelinediscount/billinginvoicelinediscount.go (1)
  • FieldReason (30-30)
⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: Test
  • GitHub Check: Quickstart
  • GitHub Check: Lint
  • GitHub Check: E2E
  • GitHub Check: Developer environment
  • GitHub Check: CI
  • GitHub Check: Commit hooks
  • GitHub Check: Build
  • GitHub Check: Analyze (go)
🔇 Additional comments (33)
api/openapi.cloud.yaml (5)

13816-13821: New InvoiceDiscountReason Schema Addition
The new schema definition for InvoiceDiscountReason is correctly added with a string type and an enum limited to maximum_spend and ratecard_discount. The description "Reason code." is concise and clear.


14282-14288: Include 'reason' in Required Properties
The required properties list for the discount component now includes reason, ensuring that a discount reason is mandatory. This update aligns well with replacing the previous code field in the API schema.


14313-14334: Integration of New Discount-Related Properties in InvoiceLineDiscountAmount
The changes add the reason, externalIds, and rateCardDiscount properties into the discount amount component. By using allOf references to the existing schemas (InvoiceDiscountReason, InvoiceLineAppExternalIds, and Discount), consistency is maintained. Please verify that downstream systems using this schema are updated accordingly.


14344-14357: Addition of 'reason' to InvoiceLineDiscountUsage Required Fields
Including the reason field in the required list for InvoiceLineDiscountUsage solidifies the schema's consistency across discount components. This ensures that every discount usage record includes a discount reason, as intended by the new feature.


14382-14406: Updating Discount Properties in InvoiceLineDiscountUsage
The updates within this discount object now embed the reason, externalIds, and rateCardDiscount properties—each referencing their appropriate schemas and marked as read-only. These modifications provide a clearer, unified structure for discount-related data.

api/spec/src/billing/invoices/discounts.tsp (3)

7-14: Well-designed enum for discount reasons.

The newly added InvoiceDiscountReason enum properly defines the two supported discount reason types with clear and specific values, enhancing type safety throughout the system.


32-33: Good enhancement to type safety.

Changing from an optional string code to a required enum reason improves type safety by restricting the possible values and making the field required, which enforces consistent data throughout the application.


41-52: Effective consolidation of metadata fields.

Moving externalIds and rateCardDiscount to the base model successfully unifies these fields, reducing duplication as mentioned in the PR objectives. This change improves maintainability and consistency.

openmeter/ent/db/billinginvoicelinediscount/where.go (2)

11-11: Appropriate import added.

The import of the billing package is necessary for using the LineDiscountReason type in the new predicate functions.


375-403: Well-implemented predicates for the new reason field.

The four new predicate functions for the "reason" field (ReasonEQ, ReasonNEQ, ReasonIn, ReasonNotIn) follow the established pattern in this generated file. The implementation correctly handles type conversion for the variadic functions and maintains consistency with other predicates.

openmeter/ent/db/mutation.go (9)

18088-18088: New field addition aligns with PR objectives.

Adding the reason field of type *billing.LineDiscountReason is an appropriate implementation for tracking discount reasons, which matches the PR objective to indicate whether a discount is applied due to maximum amount or rate card.


18398-18432: LGTM! Well-implemented accessor methods for the new reason field.

All necessary accessor methods for the reason field are properly implemented following the codebase's pattern:

  • SetReason for setting the field
  • Reason for retrieving the current value
  • OldReason for fetching the previous value with proper validation
  • ResetReason for clearing changes

The error handling in OldReason is thorough, with clear error messages for invalid scenarios.


18691-18691: Capacity adjustment for the new field.

Increasing the capacity of the fields slice from 9 to 10 properly accounts for the new reason field, improving memory allocation efficiency.


18707-18709: LGTM! Fields method properly updated.

The Fields method is correctly updated to include the reason field when it has been set, maintaining consistency in the mutation tracking logic.


18740-18741: Field method properly handles the new reason field.

The Field method is appropriately updated to handle requests for the reason field value.


18769-18770: OldField method correctly updated.

The OldField method now properly handles the reason field by calling OldReason when needed.


18823-18829: SetField implementation is robust.

The SetField method is correctly updated with proper type checking for the reason field, ensuring type safety and consistency.


18949-18951: ResetField method properly updated.

The ResetField method is correctly enhanced to handle resetting the reason field.


18088-18829:

Details

❓ Verification inconclusive

Verify database schema updates and enum validation.

The mutation code appears well-implemented, but I recommend verifying:

  1. That corresponding database schema migrations exist to add this field to the database
  2. That LineDiscountReason enum validation is handled appropriately elsewhere

These validations would ensure complete implementation of the feature.


🏁 Script executed:

#!/bin/bash
# Check for corresponding schema updates in migration files
echo "Checking for database migration files that add the reason field:"
fd -e go -e sql "migration|schema" | xargs grep -l "reason.*LineDiscountReason" | head -5

# Check for LineDiscountReason enum definition
echo -e "\nChecking for LineDiscountReason enum definition:"
fd -g "*billing*" -g "*.go" | xargs grep -l "type LineDiscountReason" | head -3

# Check for enum validation if it exists
echo -e "\nChecking for validation of LineDiscountReason values:"
fd -g "*billing*" -g "*.go" | xargs grep -A 10 -B 3 "LineDiscountReason.*valid" | head -15

Length of output: 825


Action Required: Verify Database Migrations and Enum Validations

  • Confirm that the schema migration files include the necessary update to add the new field (linked to LineDiscountReason).
  • Ensure that the definition and validation logic for the LineDiscountReason enum are correctly implemented in the billing-related code.
  • Note: Our automated search encountered errors (e.g., invalid search paths), so please verify these points manually.
openmeter/ent/db/billinginvoicelinediscount_update.go (7)

15-15: Properly added the required import for LineDiscountReason.

The import for the billing package is correctly added to support the new reason field.


74-86: Good implementation of the reason field setters for BillingInvoiceLineDiscountUpdate.

The implementation follows the same pattern as other fields in the struct, with both direct setter and nil-safe setter methods.


222-226: Validation logic correctly implemented for the reason field.

The check method properly validates the reason field when provided, using the ReasonValidator function from the billinginvoicelinediscount package.


254-256: SQL save operation correctly handles the reason field.

The reason field is properly included in the SQL update specification when present in the mutation.


367-379: Setter methods for BillingInvoiceLineDiscountUpdateOne properly implemented.

Both SetReason and SetNillableReason methods are correctly added to the UpdateOne struct, following the same pattern as other fields.


528-532: Validation logic properly implemented in the UpdateOne check method.

The check method for BillingInvoiceLineDiscountUpdateOne correctly validates the reason field when provided.


577-579: SQL save for UpdateOne correctly handles the reason field.

The reason field is properly included in the SQL update specification for the UpdateOne operation.

openmeter/ent/db/billinginvoicelinediscount_create.go (7)

16-16: Properly added the required import for LineDiscountReason.

The import for the billing package is correctly added to support the new reason field.


83-87: SetReason method correctly implemented for BillingInvoiceLineDiscountCreate.

The method follows the same pattern as other field setters in the struct.


230-237: Validation properly makes reason a required field with validation.

The check method ensures that:

  1. The reason field is present (required)
  2. The value passes the ReasonValidator

This aligns perfectly with the PR objective of adding a meaningful discount reason to the database.


296-299: CreateSpec correctly includes the reason field.

The reason field is properly added to the SQL creation specification, ensuring it will be stored in the database.


427-437: Upsert operations properly handle the reason field.

Both SetReason and UpdateReason methods are correctly implemented for the BillingInvoiceLineDiscountUpsert struct.


608-620: UpsertOne operations properly implement reason field methods.

The BillingInvoiceLineDiscountUpsertOne struct correctly implements SetReason and UpdateReason methods.


969-981: UpsertBulk operations properly implement reason field methods.

The BillingInvoiceLineDiscountUpsertBulk struct correctly implements SetReason and UpdateReason methods, maintaining consistency across all operation types.

@turip turip merged commit 1793379 into main Apr 7, 2025
27 checks passed
@turip turip deleted the feat/add-discount-reason branch April 7, 2025 08:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants