Skip to content

Conversation

@GAlexIHU
Copy link
Contributor

@GAlexIHU GAlexIHU commented Apr 16, 2025

Overview

Implement create flow for subscription addons with the following constraints:

  • If a subscription already has any addon, it returns NotImplemented
  • Plan-Addon linking is not checked as its not yet on main

Notable contents:

  • Merge logic for extend type RateCards
  • E2E create flow + retrieval
  • Deletes old SubscriptionAddonRateCard with linking tables => we won's store the linking as that's not really meaningful. The RateCards are loaded from the addon, and the API response is populated by an in-mem calculation. (this might later change after restore is implemented)
  • Checks that edit is not possible if an addon is applied

Summary by CodeRabbit

  • New Features

    • Introduced subscription addon support with API endpoints for creation, listing, and retrieval.
    • Added workflow for adding addons to subscriptions with validation and state synchronization.
    • Extended subscription timing and state machine to handle addon changes.
  • Improvements

    • Simplified addon rate card handling by deriving rate cards from addons instead of direct assignment.
    • Enhanced error handling and validation in addon-related operations.
    • Preserved annotations when modifying subscription items through addons.
    • Updated documentation and diagrams to reflect addon model changes.
  • Removals

    • Removed all subscription addon rate card entities, links, database tables, APIs, and internal logic.
    • Deleted legacy addon rate card management and affected subscription item tracking.
  • Tests

    • Added tests for addon workflows and error cases.
    • Refactored test utilities for streamlined addon and subscription creation.
  • Chores

    • Updated OpenAPI specs and client libraries to align with new addon data models and endpoints.

@GAlexIHU GAlexIHU self-assigned this Apr 16, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Apr 16, 2025

📝 Walkthrough

Walkthrough

This change removes the entire "subscription addon rate card" feature from the codebase. It deletes all database schemas, entities, repositories, service logic, and API fields related to subscription addon rate cards and their item links. The migration scripts drop the associated tables. The code, API models, and tests are refactored to eliminate references to rate cards within subscription addons, including input fields, validation, and mapping logic. The remaining subscription addon functionality is preserved and refactored to work without rate card associations, and the workflow for adding addons is updated accordingly. Related documentation and diagrams are also updated to reflect the simplified model.

Changes

Files/Paths Change Summary
Database Schema, Entities, and Migration Removed all code, schema, and migration logic for subscription_addon_rate_cards and subscription_addon_rate_card_item_links tables, including their Go entity models, query/update builders, predicates, hooks, and associated edge definitions in AddonRateCard, SubscriptionAddon, and SubscriptionItem.
openmeter/ent/schema/addon.go, openmeter/ent/schema/subscription.go, openmeter/ent/schema/subscription_addon.go Removed edges and schemas related to subscription addon rate cards and their item links.
openmeter/subscription/addon/addonratecard.go, openmeter/subscription/addon/repository.go, openmeter/subscription/addon/repo/subscriptionaddonratecard.go, openmeter/subscription/addon/repo/transaction.go Deleted all domain models, repository interfaces, and implementations for subscription addon rate cards.
openmeter/subscription/addon/service/service.go, openmeter/subscription/addon/service/change_test.go, openmeter/subscription/addon/service/create_test.go, openmeter/subscription/addon/service/list_test.go Removed all logic and tests for handling rate cards during subscription addon creation, validation, and listing.
openmeter/subscription/addon/addon.go Removed RateCards field from CreateSubscriptionAddonInput and related validation logic.
openmeter/subscription/addon/repo/mapping.go Refactored mapping logic to use only AddonRateCard entities, removing dependency on subscription addon rate cards.
openmeter/subscription/addon/ratecard.go Introduced a simplified struct for SubscriptionAddonRateCard containing only the underlying AddonRateCard.
openmeter/subscription/addon/http/mapping.go Updated mapping functions to remove handling of affected subscription item IDs and rate card associations.
openmeter/subscription/addon/README.md Updated ER diagram and documentation to remove references to rate card item links and simplify relationships.
API and Client Types Refactored API schemas and client types to remove inline or referenced rate card fields from subscription addon models and creation/update inputs.
api/api.gen.go, api/client/go/client.gen.go, api/client/javascript/src/client/schemas.ts, api/openapi.cloud.yaml, api/openapi.yaml, api/spec/src/productcatalog/subscriptionaddon.tsp Updated API and OpenAPI schemas to remove rate card associations from subscription addon models.
Tests and Utilities Removed or refactored tests and helpers to eliminate usage of rate card fields in subscription addon creation and validation.
openmeter/subscription/testutils/service.go, openmeter/subscription/testutils/helpers.go, openmeter/subscription/testutils/compare.go, openmeter/subscription/addon/diff/apply_test.go Updated or removed test helpers and assertions to reflect the absence of rate card associations in subscription addons.
Other Affected Areas Updated server/router setup, service wiring, and documentation to remove or adapt to the absence of subscription addon rate cards.
app/common/subscription.go, cmd/server/main.go, cmd/server/wire_gen.go, openmeter/server/router/router.go, openmeter/server/router/subscriptionaddon.go, openmeter/server/server_test.go, test/billing/subscription_suite.go Refactored service initialization and router configuration to remove dependencies on rate card repositories and services.

Possibly related PRs

  • openmeterio/openmeter#2604: Refactored the SubscriptionAddon struct's Addon field to use a named struct type encapsulating fields including InstanceType, which is closely related to the management of addon-related fields being refactored or removed in this PR.

  • openmeterio/openmeter#2536: Introduced the initial API types and routes for SubscriptionAddon, including struct definitions and fields that are directly modified or removed in this PR.

  • openmeterio/openmeter#2626: Introduced and added comprehensive support for subscription addons, including their rate cards and related entities, with full schema, client, and repository implementations. This PR removes or rolls back that feature, making the changes directly related but opposite in purpose and content.

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


🪧 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 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.

@GAlexIHU GAlexIHU added the release-note/feature Release note: Exciting New Features label Apr 16, 2025
@GAlexIHU GAlexIHU changed the base branch from main to galexi/addons-2-diff April 16, 2025 13:45
@GAlexIHU GAlexIHU force-pushed the galexi/addons-2-diff branch from ba81ffd to a6414bf Compare April 16, 2025 13:46
@GAlexIHU GAlexIHU marked this pull request as ready for review April 16, 2025 13:50
@GAlexIHU GAlexIHU requested a review from a team as a code owner April 16, 2025 13:50
Base automatically changed from galexi/addons-2-diff to main April 16, 2025 17:15
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: 4

🔭 Outside diff range comments (1)
api/openapi.yaml (1)

19828-19850: 🛠️ Refactor suggestion

Obsolete SubscriptionAddonRateCard schema remains—consider removal or deprecation

The SubscriptionAddonRateCard schema is still present, even though the PR and AI summary state that rate card linkage for subscription addons has been removed. If this schema is no longer used in any API request/response, it should be removed or marked as deprecated to avoid confusion and reduce maintenance burden.

If you intend to keep it for backward compatibility, add a deprecated: true flag and a comment explaining its status.

♻️ Duplicate comments (3)
api/spec/src/productcatalog/subscriptionaddon.tsp (1)

80-113: New SubscriptionAddonAddon model looks good

Extracting the addon properties into a separate model improves modularity and reusability. The model preserves all the original fields and metadata annotations.

openmeter/subscription/addon/diff/affected.go (1)

14-40: Consider simplifying the nested loops to improve code readability.

The current implementation has 4 levels of nested loops, which can make the code difficult to understand and maintain. Consider extracting some of the logic into helper functions to reduce nesting depth.

For example, you could refactor the inner loops into a separate function:

func GetAffectedItemIDs(view subscription.SubscriptionView, addon subscriptionaddon.SubscriptionAddon) map[string][]string {
	affected := map[string][]string{}

	for _, inst := range addon.GetInstances() {
		instPer := inst.CadencedModel.AsPeriod()

		for _, rc := range inst.RateCards {
			rcKey := rc.AddonRateCard.RateCard.Key()
-
-			for _, p := range view.Phases {
-				for _, items := range p.ItemsByKey {
-					for _, item := range items {
-						if item.Spec.RateCard.Key() != rcKey {
-							continue
-						}
-
-						itemPer := item.SubscriptionItem.CadencedModel.AsPeriod()
-
-						if instPer.Intersection(itemPer) != nil {
-							if _, ok := affected[rcKey]; !ok {
-								affected[rcKey] = []string{}
-							}
-
-							affected[rcKey] = append(affected[rcKey], item.SubscriptionItem.ID)
-						}
-					}
-				}
-			}
+			findAffectedItems(view, rcKey, instPer, affected)
		}
	}

	// Let's dedupe
	return lo.MapEntries(affected, func(key string, value []string) (string, []string) {
		return key, lo.Uniq(value)
	})
}

+func findAffectedItems(view subscription.SubscriptionView, rcKey string, instPer time.Period, affected map[string][]string) {
+	for _, p := range view.Phases {
+		for _, items := range p.ItemsByKey {
+			for _, item := range items {
+				if item.Spec.RateCard.Key() != rcKey {
+					continue
+				}
+
+				itemPer := item.SubscriptionItem.CadencedModel.AsPeriod()
+
+				if instPer.Intersection(itemPer) != nil {
+					if _, ok := affected[rcKey]; !ok {
+						affected[rcKey] = []string{}
+					}
+
+					affected[rcKey] = append(affected[rcKey], item.SubscriptionItem.ID)
+				}
+			}
+		}
+	}
+}
openmeter/subscription/testutils/helpers.go (1)

18-36: Write out public function name in comment

The function CreateSubscriptionFromPlan is public but lacks a proper documentation comment explaining its purpose, parameters, and return values. Consider adding a doc comment following Go conventions.

+// CreateSubscriptionFromPlan creates a subscription from the given plan input with a specified start time.
+// It returns the created plan and subscription view.
 func CreateSubscriptionFromPlan(t *testing.T, deps *SubscriptionDependencies, planInp plan.CreatePlanInput, startAt time.Time) (subscription.Plan, subscription.SubscriptionView) {
🧹 Nitpick comments (16)
openmeter/subscription/workflow/service/subscription.go (1)

78-87: Added validation to prevent editing subscriptions with addons.

This new check prevents users from editing subscriptions that have addons attached, which aligns with the PR objective that states "the implementation includes a check that prevents editing if an addon is already applied to a subscription." The error message is clear and appropriate.

One suggestion would be to provide more details in the error message about why this limitation exists and what alternatives users might have.

Consider enhancing the error message to provide more context:

-		return subscription.SubscriptionView{}, models.NewGenericForbiddenError(fmt.Errorf("subscription with addons cannot be edited"))
+		return subscription.SubscriptionView{}, models.NewGenericForbiddenError(fmt.Errorf("subscription with addons cannot be edited - please remove addons first before making changes"))
openmeter/subscription/addon/compatible.go (1)

9-10: Consider documenting validation purpose

The validateRateCards function provides important compatibility checking between rate cards. Consider adding a function comment that explains the purpose and criteria for validation.

-// TODO: this will be moved to different package
-func validateRateCards(source, target productcatalog.RateCard) error {
+// TODO: this will be moved to different package
+// validateRateCards ensures that the source rate card (from an addon) is compatible
+// with the target rate card by checking key equality, price types, payment terms,
+// and entitlement template types.
+func validateRateCards(source, target productcatalog.RateCard) error {
openmeter/subscription/addon/addon.go (1)

23-28: Consider addressing the TODO comment.

There's a TODO comment about potentially breaking up the Addon field into AddonID + AddonMeta. This might be worth considering as it would potentially improve the model design.

Consider addressing the TODO comment about breaking up the Addon field into separate components for cleaner design, either in this PR or tracking it for future work.

openmeter/subscription/workflow/service/addon.go (1)

28-28: Consider implementing subscription-level locking
The TODO comment highlights potential concurrency issues. Without a subscription lock, concurrent calls might create conflicts or duplicate addons.

openmeter/productcatalog/ratecard.go (1)

372-377: Duplicate approach to ChangeMeta
The logic here is identical to the FlatFeeRateCard. Consider unifying them in a shared helper to reduce repetition.

-func (r *UsageBasedRateCard) ChangeMeta(fn func(m RateCardMeta) (RateCardMeta, error)) error {
-	var err error
-	r.RateCardMeta, err = fn(r.RateCardMeta)
-	if err != nil {
-		return err
-	}
-	return r.Validate()
-}
+// Potential approach: unify in a shared function, e.g.:
+func applyChangeMeta(r *RateCardMeta, fn func(m RateCardMeta) (RateCardMeta, error)) error {
+    newMeta, err := fn(*r)
+    if err != nil {
+       return err
+    }
+    *r = newMeta
+    return r.Validate()
+}
openmeter/subscription/addon/http/handler.go (3)

31-36: Consider validating configuration in the constructor.

While the constructor correctly follows the factory pattern, it might be beneficial to validate that required dependencies are not nil before creating the handler. This would prevent potential nil pointer panics at runtime.

 func NewHandler(config HandlerConfig, options ...httptransport.HandlerOption) Handler {
+	// Validate required dependencies
+	if config.SubscriptionAddonService == nil {
+		panic("SubscriptionAddonService is required")
+	}
+	if config.SubscriptionWorkflowService == nil {
+		panic("SubscriptionWorkflowService is required")
+	}
+	if config.NamespaceDecoder == nil {
+		panic("NamespaceDecoder is required")
+	}
+	if config.Logger == nil {
+		config.Logger = slog.Default()
+	}
+
 	return &handler{
 		HandlerConfig: config,
 		Options:       options,
 	}
 }

43-50: Improve error message specificity in resolveNamespace.

The current error message when namespace resolution fails is generic. A more specific error message would help with debugging and could provide more context about what went wrong.

 func (h *handler) resolveNamespace(ctx context.Context) (string, error) {
 	ns, ok := h.NamespaceDecoder.GetNamespace(ctx)
 	if !ok {
-		return "", commonhttp.NewHTTPError(http.StatusInternalServerError, errors.New("internal server error"))
+		return "", commonhttp.NewHTTPError(http.StatusInternalServerError, errors.New("failed to resolve namespace from context"))
 	}
 
 	return ns, nil
 }

1-15: Add godoc comments to improve code documentation.

Adding godoc comments for the package, interface, and important functions would improve the documentation and make the code more maintainable. This is especially important for public APIs.

+// Package httpdriver provides HTTP handlers for subscription addon operations.
 package httpdriver
 
 import (
 	"context"
 	"errors"
 	"log/slog"
 	"net/http"
 
 	"github.com/openmeterio/openmeter/openmeter/namespace/namespacedriver"
 	"github.com/openmeterio/openmeter/openmeter/subscription"
 	subscriptionaddon "github.com/openmeterio/openmeter/openmeter/subscription/addon"
 	subscriptionworkflow "github.com/openmeterio/openmeter/openmeter/subscription/workflow"
 	"github.com/openmeterio/openmeter/pkg/framework/commonhttp"
 	"github.com/openmeterio/openmeter/pkg/framework/transport/httptransport"
 )

Similarly, add comments for the Handler interface and key methods.

openmeter/subscription/addon/http/get.go (1)

40-52: Consider handling different error types specifically.

The error handling doesn't distinguish between different types of errors (e.g., not found vs. internal server error). This limits the ability to provide appropriate HTTP status codes to clients.

Consider enhancing error handling:

 			res, err := h.SubscriptionAddonService.Get(ctx, req.SubscriptionAddonID)
 			if err != nil {
+				// Handle specific error types with appropriate status codes
+				if errors.Is(err, subscription.ErrSubscriptionAddonNotFound) {
+					return GetSubscriptionAddonResponse{}, httptransport.NewError(http.StatusNotFound, err.Error())
+				}
 				return GetSubscriptionAddonResponse{}, err
 			}
openmeter/subscription/addon/extend.go (2)

34-55: Review price merging logic for potential fallback or rounding concerns.

Merging flat prices by summing amounts and overwriting the payment term is logically sound. Consider whether:

  1. Additional rounding rules or currency precision checks are required.
  2. Different price types (beyond flat) must be supported soon.
    Overall, this block is well-structured with a clear fallback error for unsupported types.

81-81: Consider implementing 'Restore' or remove the placeholder.

Returning a not implemented error is an acceptable temporary placeholder, but it may cause confusion for callers if they mistakenly expect restore functionality. Either add explanatory docs or remove the method if it's not planned soon.

openmeter/subscription/addon/http/create.go (1)

27-48: Validate request payload for required fields.

Here, the request body is simply decoded, and namespace resolution is enforced. Consider additional validation for the addon input, especially if certain fields are mandatory. This helps ensure robust error handling before calling downstream services.

openmeter/subscription/addon/http/mapping.go (2)

36-48: Consider enhancing error message for missing instances

The error message "no instances found" could be more descriptive to aid debugging. Consider including the addon ID or other identifying information.

-		return api.SubscriptionAddon{}, errors.New("no instances found")
+		return api.SubscriptionAddon{}, fmt.Errorf("no instances found for subscription addon ID: %s", addon.ID)

49-53: Consider adding validation for empty periods array

The code assumes pers[0] exists when creating the union of periods. While the preceding check ensures the array isn't empty, it would be more robust to handle this case explicitly in the Reduce function.

-	union := lo.Reduce(pers, func(agg timeutil.OpenPeriod, item timeutil.OpenPeriod, _ int) timeutil.OpenPeriod {
-		return agg.Union(item)
-	}, pers[0])
+	// Start with first period as initial value, or create empty result if no periods
+	var initialPeriod timeutil.OpenPeriod
+	if len(pers) > 0 {
+		initialPeriod = pers[0]
+	}
+	
+	union := lo.Reduce(pers, func(agg timeutil.OpenPeriod, item timeutil.OpenPeriod, _ int) timeutil.OpenPeriod {
+		return agg.Union(item)
+	}, initialPeriod)
openmeter/subscription/testutils/helpers.go (2)

38-64: Add explanation for "use workflow service instead" comment

The comment "For most cases, use the workflow service instead!" doesn't explain why. Consider explaining the specific scenarios where this helper should or shouldn't be used.

-// For most cases, use the workflow service instead!
+// CreateMultiInstanceAddonForSubscription creates an addon with multiple quantity changes.
+// Note: This bypasses workflow validations and should only be used for testing edge cases.
+// For standard use cases, use the workflow service's AddAddon method instead.
 func CreateMultiInstanceAddonForSubscription(t *testing.T, deps *SubscriptionDependencies, subID models.NamespacedID, addonInp addon.CreateAddonInput, quants []subscriptionaddon.CreateSubscriptionAddonQuantityInput) (addon.Addon, subscriptionaddon.SubscriptionAddon) {

66-86: Explain "hacky" approach and provide alternatives

The comment describes the approach as "a bit hacky" but doesn't explain why or suggest better alternatives. Consider clarifying the comment to help future developers understand the limitations.

-// this is a bit hacky, we reuse the addon's effective period as cadence for the subscriptionaddon
-// For most cases, use the workflow service instead!
+// CreateAddonForSubscription creates a subscription addon using the addon's effective period
+// to determine its activation timeline. This approach simplifies testing but doesn't mirror
+// how addons would typically be activated in production code.
+// 
+// Note: This bypasses workflow validations. For standard use cases, use the
+// workflow service's AddAddon method instead.
 func CreateAddonForSubscription(t *testing.T, deps *SubscriptionDependencies, subID models.NamespacedID, addonInp addon.CreateAddonInput) (addon.Addon, subscriptionaddon.SubscriptionAddon) {
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 5719d5d and b7182ed.

⛔ Files ignored due to path filters (1)
  • tools/migrate/migrations/atlas.sum is excluded by !**/*.sum
📒 Files selected for processing (102)
  • api/api.gen.go (5 hunks)
  • api/client/go/client.gen.go (5 hunks)
  • api/client/javascript/src/client/schemas.ts (5 hunks)
  • api/openapi.cloud.yaml (4 hunks)
  • api/openapi.yaml (4 hunks)
  • api/spec/src/productcatalog/subscriptionaddon.tsp (2 hunks)
  • app/common/subscription.go (5 hunks)
  • cmd/billing-worker/wire_gen.go (1 hunks)
  • cmd/jobs/internal/wire_gen.go (1 hunks)
  • cmd/server/main.go (1 hunks)
  • cmd/server/wire_gen.go (1 hunks)
  • openmeter/ent/db/addonratecard.go (1 hunks)
  • openmeter/ent/db/addonratecard/addonratecard.go (0 hunks)
  • openmeter/ent/db/addonratecard/where.go (0 hunks)
  • openmeter/ent/db/addonratecard_create.go (0 hunks)
  • openmeter/ent/db/addonratecard_query.go (3 hunks)
  • openmeter/ent/db/addonratecard_update.go (0 hunks)
  • openmeter/ent/db/client.go (4 hunks)
  • openmeter/ent/db/ent.go (0 hunks)
  • openmeter/ent/db/expose.go (0 hunks)
  • openmeter/ent/db/hook/hook.go (0 hunks)
  • openmeter/ent/db/migrate/schema.go (0 hunks)
  • openmeter/ent/db/paginate.go (0 hunks)
  • openmeter/ent/db/predicate/predicate.go (0 hunks)
  • openmeter/ent/db/runtime.go (0 hunks)
  • openmeter/ent/db/setorclear.go (0 hunks)
  • openmeter/ent/db/subscriptionaddon.go (3 hunks)
  • openmeter/ent/db/subscriptionaddon/subscriptionaddon.go (0 hunks)
  • openmeter/ent/db/subscriptionaddon/where.go (0 hunks)
  • openmeter/ent/db/subscriptionaddon_create.go (0 hunks)
  • openmeter/ent/db/subscriptionaddon_query.go (1 hunks)
  • openmeter/ent/db/subscriptionaddon_update.go (0 hunks)
  • openmeter/ent/db/subscriptionaddonratecard.go (0 hunks)
  • openmeter/ent/db/subscriptionaddonratecard/subscriptionaddonratecard.go (0 hunks)
  • openmeter/ent/db/subscriptionaddonratecard/where.go (0 hunks)
  • openmeter/ent/db/subscriptionaddonratecard_create.go (0 hunks)
  • openmeter/ent/db/subscriptionaddonratecard_delete.go (0 hunks)
  • openmeter/ent/db/subscriptionaddonratecard_query.go (0 hunks)
  • openmeter/ent/db/subscriptionaddonratecard_update.go (0 hunks)
  • openmeter/ent/db/subscriptionaddonratecarditemlink.go (0 hunks)
  • openmeter/ent/db/subscriptionaddonratecarditemlink/subscriptionaddonratecarditemlink.go (0 hunks)
  • openmeter/ent/db/subscriptionaddonratecarditemlink/where.go (0 hunks)
  • openmeter/ent/db/subscriptionaddonratecarditemlink_create.go (0 hunks)
  • openmeter/ent/db/subscriptionaddonratecarditemlink_delete.go (0 hunks)
  • openmeter/ent/db/subscriptionaddonratecarditemlink_query.go (0 hunks)
  • openmeter/ent/db/subscriptionaddonratecarditemlink_update.go (0 hunks)
  • openmeter/ent/db/subscriptionitem.go (1 hunks)
  • openmeter/ent/db/subscriptionitem/subscriptionitem.go (0 hunks)
  • openmeter/ent/db/subscriptionitem/where.go (0 hunks)
  • openmeter/ent/db/subscriptionitem_create.go (0 hunks)
  • openmeter/ent/db/subscriptionitem_query.go (3 hunks)
  • openmeter/ent/db/subscriptionitem_update.go (0 hunks)
  • openmeter/ent/db/tx.go (0 hunks)
  • openmeter/ent/schema/addon.go (0 hunks)
  • openmeter/ent/schema/subscription.go (0 hunks)
  • openmeter/ent/schema/subscription_addon.go (0 hunks)
  • openmeter/productcatalog/ratecard.go (3 hunks)
  • openmeter/server/router/router.go (5 hunks)
  • openmeter/server/router/subscriptionaddon.go (1 hunks)
  • openmeter/server/server_test.go (4 hunks)
  • openmeter/subscription/addon/README.md (2 hunks)
  • openmeter/subscription/addon/addon.go (3 hunks)
  • openmeter/subscription/addon/addonratecard.go (0 hunks)
  • openmeter/subscription/addon/compatible.go (1 hunks)
  • openmeter/subscription/addon/diff/addon.go (2 hunks)
  • openmeter/subscription/addon/diff/affected.go (1 hunks)
  • openmeter/subscription/addon/diff/apply.go (2 hunks)
  • openmeter/subscription/addon/diff/apply_test.go (14 hunks)
  • openmeter/subscription/addon/extend.go (1 hunks)
  • openmeter/subscription/addon/extend_test.go (1 hunks)
  • openmeter/subscription/addon/http/create.go (1 hunks)
  • openmeter/subscription/addon/http/get.go (1 hunks)
  • openmeter/subscription/addon/http/handler.go (1 hunks)
  • openmeter/subscription/addon/http/list.go (1 hunks)
  • openmeter/subscription/addon/http/mapping.go (1 hunks)
  • openmeter/subscription/addon/ratecard.go (1 hunks)
  • openmeter/subscription/addon/repo/mapping.go (2 hunks)
  • openmeter/subscription/addon/repo/subscriptionaddon.go (1 hunks)
  • openmeter/subscription/addon/repo/subscriptionaddonratecard.go (0 hunks)
  • openmeter/subscription/addon/repo/transaction.go (0 hunks)
  • openmeter/subscription/addon/repository.go (0 hunks)
  • openmeter/subscription/addon/service/change_test.go (0 hunks)
  • openmeter/subscription/addon/service/create_test.go (1 hunks)
  • openmeter/subscription/addon/service/list_test.go (0 hunks)
  • openmeter/subscription/addon/service/service.go (2 hunks)
  • openmeter/subscription/patch/patch_test.go (2 hunks)
  • openmeter/subscription/service/sync_test.go (1 hunks)
  • openmeter/subscription/state.go (2 hunks)
  • openmeter/subscription/testutils/compare.go (1 hunks)
  • openmeter/subscription/testutils/helpers.go (1 hunks)
  • openmeter/subscription/testutils/service.go (1 hunks)
  • openmeter/subscription/timing.go (1 hunks)
  • openmeter/subscription/workflow/service.go (3 hunks)
  • openmeter/subscription/workflow/service/addon.go (1 hunks)
  • openmeter/subscription/workflow/service/addon_test.go (1 hunks)
  • openmeter/subscription/workflow/service/service.go (1 hunks)
  • openmeter/subscription/workflow/service/subscription.go (2 hunks)
  • openmeter/subscription/workflow/service/subscription_test.go (5 hunks)
  • pkg/models/error.go (1 hunks)
  • test/billing/subscription_suite.go (3 hunks)
  • tools/migrate/migrations/20250416094534_delete-subsadd-ratecards.down.sql (1 hunks)
  • tools/migrate/migrations/20250416094534_delete-subsadd-ratecards.up.sql (1 hunks)
💤 Files with no reviewable changes (44)
  • openmeter/ent/db/ent.go
  • openmeter/ent/schema/subscription.go
  • openmeter/subscription/addon/addonratecard.go
  • openmeter/ent/db/subscriptionaddon/where.go
  • openmeter/ent/schema/addon.go
  • openmeter/ent/db/subscriptionaddon_create.go
  • openmeter/ent/db/tx.go
  • openmeter/ent/db/predicate/predicate.go
  • openmeter/subscription/addon/service/list_test.go
  • openmeter/subscription/addon/repository.go
  • openmeter/ent/db/expose.go
  • openmeter/subscription/addon/repo/transaction.go
  • openmeter/ent/db/subscriptionitem/subscriptionitem.go
  • openmeter/ent/db/addonratecard_create.go
  • openmeter/subscription/addon/service/change_test.go
  • openmeter/ent/db/subscriptionaddonratecarditemlink_delete.go
  • openmeter/ent/db/runtime.go
  • openmeter/ent/db/subscriptionitem_create.go
  • openmeter/ent/db/subscriptionitem/where.go
  • openmeter/subscription/addon/repo/subscriptionaddonratecard.go
  • openmeter/ent/db/addonratecard/addonratecard.go
  • openmeter/ent/db/addonratecard/where.go
  • openmeter/ent/db/subscriptionaddonratecard/subscriptionaddonratecard.go
  • openmeter/ent/db/subscriptionaddon/subscriptionaddon.go
  • openmeter/ent/db/subscriptionaddonratecarditemlink.go
  • openmeter/ent/db/subscriptionaddonratecard_delete.go
  • openmeter/ent/db/subscriptionaddon_update.go
  • openmeter/ent/db/subscriptionaddonratecarditemlink/where.go
  • openmeter/ent/db/subscriptionaddonratecarditemlink/subscriptionaddonratecarditemlink.go
  • openmeter/ent/db/paginate.go
  • openmeter/ent/db/subscriptionaddonratecard_create.go
  • openmeter/ent/db/migrate/schema.go
  • openmeter/ent/schema/subscription_addon.go
  • openmeter/ent/db/subscriptionaddonratecard/where.go
  • openmeter/ent/db/subscriptionaddonratecard.go
  • openmeter/ent/db/subscriptionaddonratecarditemlink_create.go
  • openmeter/ent/db/setorclear.go
  • openmeter/ent/db/subscriptionaddonratecarditemlink_query.go
  • openmeter/ent/db/subscriptionaddonratecard_update.go
  • openmeter/ent/db/subscriptionaddonratecard_query.go
  • openmeter/ent/db/hook/hook.go
  • openmeter/ent/db/addonratecard_update.go
  • openmeter/ent/db/subscriptionitem_update.go
  • openmeter/ent/db/subscriptionaddonratecarditemlink_update.go
🧰 Additional context used
🧬 Code Graph Analysis (23)
openmeter/subscription/testutils/compare.go (1)
openmeter/subscription/subscriptionspec.go (2)
  • CreateSubscriptionItemPlanInput (553-557)
  • CreateSubscriptionItemCustomerInput (598-602)
openmeter/subscription/addon/repo/subscriptionaddon.go (1)
openmeter/ent/db/addon_query.go (1)
  • AddonQuery (24-37)
openmeter/subscription/timing.go (1)
openmeter/subscription/state.go (1)
  • SubscriptionActionChangeAddons (42-42)
openmeter/server/router/subscriptionaddon.go (4)
openmeter/server/router/router.go (1)
  • Router (194-216)
openmeter/subscription/addon/http/list.go (1)
  • ListSubscriptionAddonsParams (17-19)
openmeter/subscription/addon/http/create.go (1)
  • CreateSubscriptionAddonParams (16-18)
openmeter/subscription/addon/http/get.go (1)
  • GetSubscriptionAddonParams (15-18)
openmeter/subscription/addon/diff/addon.go (2)
openmeter/subscription/apply.go (2)
  • NewAppliesToSpec (35-39)
  • ApplyContext (13-15)
pkg/models/error.go (1)
  • NewGenericNotImplementedError (171-173)
openmeter/subscription/addon/ratecard.go (3)
openmeter/ent/db/addonratecard.go (2)
  • AddonRateCard (21-63)
  • AddonRateCard (99-122)
openmeter/ent/db/predicate/predicate.go (1)
  • AddonRateCard (24-24)
openmeter/ent/schema/addon.go (5)
  • AddonRateCard (87-89)
  • AddonRateCard (91-95)
  • AddonRateCard (97-111)
  • AddonRateCard (113-125)
  • AddonRateCard (127-140)
openmeter/subscription/addon/compatible.go (2)
openmeter/productcatalog/ratecard.go (1)
  • RateCard (29-41)
openmeter/productcatalog/entitlement.go (1)
  • EntitlementTemplate (34-39)
cmd/server/wire_gen.go (1)
app/common/subscription.go (1)
  • NewSubscriptionServices (41-112)
openmeter/subscription/patch/patch_test.go (2)
openmeter/subscription/subscriptionspec.go (1)
  • CreateSubscriptionItemPlanInput (553-557)
openmeter/productcatalog/ratecard.go (2)
  • RateCard (29-41)
  • RateCardMeta (52-83)
openmeter/subscription/addon/service/service.go (1)
pkg/models/error.go (1)
  • NewGenericValidationError (138-140)
cmd/jobs/internal/wire_gen.go (3)
app/common/productcatalog.go (1)
  • NewAddonService (74-94)
cmd/jobs/internal/wire.go (1)
  • Application (35-62)
app/common/subscription.go (1)
  • NewSubscriptionServices (41-112)
cmd/billing-worker/wire_gen.go (2)
app/common/productcatalog.go (1)
  • NewAddonService (74-94)
app/common/subscription.go (1)
  • NewSubscriptionServices (41-112)
openmeter/server/router/router.go (5)
openmeter/subscription/workflow/service.go (1)
  • Service (12-19)
openmeter/subscription/service.go (1)
  • Service (10-31)
openmeter/subscription/addon/http/handler.go (3)
  • Handler (17-21)
  • NewHandler (31-36)
  • HandlerConfig (23-29)
pkg/framework/transport/httptransport/options.go (1)
  • WithErrorHandler (29-33)
pkg/framework/transport/httptransport/handler.go (1)
  • ErrorHandler (73-75)
openmeter/subscription/addon/http/handler.go (6)
openmeter/subscription/addon/http/create.go (1)
  • CreateSubscriptionAddonHandler (24-24)
openmeter/subscription/addon/http/list.go (1)
  • ListSubscriptionAddonsHandler (24-24)
openmeter/subscription/addon/http/get.go (1)
  • GetSubscriptionAddonHandler (24-24)
openmeter/subscription/workflow/service.go (1)
  • Service (12-19)
pkg/framework/transport/httptransport/options.go (1)
  • HandlerOption (19-21)
pkg/framework/commonhttp/errors.go (1)
  • NewHTTPError (35-41)
api/client/javascript/src/client/schemas.ts (2)
api/api.gen.go (2)
  • SubscriptionAddonAddon (5730-5742)
  • SubscriptionAddonAddonUpdate (5745-5745)
api/client/go/client.gen.go (2)
  • SubscriptionAddonAddon (5278-5290)
  • SubscriptionAddonAddonUpdate (5293-5293)
openmeter/subscription/addon/extend_test.go (5)
openmeter/productcatalog/ratecard.go (3)
  • RateCardMeta (52-83)
  • FlatFeeRateCard (211-218)
  • RateCard (29-41)
openmeter/subscription/testutils/feature.go (1)
  • ExampleFeatureKey (13-13)
openmeter/productcatalog/price.go (3)
  • NewPriceFrom (363-385)
  • InAdvancePaymentTerm (20-20)
  • InArrearsPaymentTerm (21-21)
openmeter/productcatalog/entitlement.go (5)
  • EntitlementTemplate (34-39)
  • NewEntitlementTemplateFrom (230-246)
  • BooleanEntitlementTemplate (393-396)
  • StaticEntitlementTemplate (352-360)
  • MeteredEntitlementTemplate (253-273)
openmeter/testutils/time.go (1)
  • GetISODuration (19-26)
openmeter/subscription/testutils/helpers.go (8)
openmeter/subscription/testutils/service.go (1)
  • SubscriptionDependencies (38-52)
openmeter/productcatalog/plan/service.go (1)
  • CreatePlanInput (98-101)
openmeter/subscription/workflow/service.go (2)
  • CreateSubscriptionWorkflowInput (21-25)
  • ChangeSubscriptionWorkflowInput (27-32)
openmeter/subscription/timing.go (1)
  • Timing (14-17)
openmeter/productcatalog/addon/service.go (1)
  • CreateAddonInput (98-101)
openmeter/subscription/addon/quantity.go (1)
  • CreateSubscriptionAddonQuantityInput (25-28)
openmeter/subscription/addon/addon.go (1)
  • CreateSubscriptionAddonInput (105-112)
openmeter/productcatalog/effectiveperiod.go (1)
  • EffectivePeriod (19-25)
openmeter/ent/db/addonratecard_query.go (6)
openmeter/ent/db/ent.go (2)
  • QueryContext (65-65)
  • Interceptor (68-68)
openmeter/ent/db/addonratecard/addonratecard.go (1)
  • OrderOption (143-143)
openmeter/ent/db/addonratecard.go (2)
  • AddonRateCard (21-63)
  • AddonRateCard (99-122)
openmeter/ent/db/predicate/predicate.go (1)
  • AddonRateCard (24-24)
openmeter/ent/db/addon_query.go (1)
  • AddonQuery (24-37)
openmeter/ent/db/feature_query.go (1)
  • FeatureQuery (24-37)
openmeter/subscription/addon/diff/apply_test.go (5)
openmeter/subscription/testutils/helpers.go (3)
  • CreateSubscriptionFromPlan (18-36)
  • CreateAddonForSubscription (68-86)
  • CreateMultiInstanceAddonForSubscription (39-64)
openmeter/subscription/testutils/plan.go (2)
  • GetExamplePlanInput (72-80)
  • BuildTestPlan (51-70)
openmeter/subscription/testutils/addon.go (2)
  • GetExampleAddonInput (89-91)
  • BuildAddonForTesting (16-41)
openmeter/productcatalog/effectiveperiod.go (1)
  • EffectivePeriod (19-25)
openmeter/testutils/time.go (1)
  • GetISODuration (19-26)
openmeter/ent/db/subscriptionitem_query.go (7)
openmeter/ent/db/ent.go (2)
  • QueryContext (65-65)
  • Interceptor (68-68)
openmeter/ent/db/subscriptionitem/subscriptionitem.go (1)
  • OrderOption (159-159)
openmeter/ent/db/predicate/predicate.go (1)
  • SubscriptionItem (239-239)
openmeter/ent/db/subscriptionitem.go (2)
  • SubscriptionItem (21-73)
  • SubscriptionItem (120-147)
openmeter/ent/db/subscriptionphase_query.go (1)
  • SubscriptionPhaseQuery (24-37)
openmeter/ent/db/entitlement_query.go (1)
  • EntitlementQuery (26-41)
openmeter/ent/db/billinginvoiceline_query.go (1)
  • BillingInvoiceLineQuery (29-50)
app/common/subscription.go (4)
openmeter/subscription/addon/repo/subscriptionaddon.go (1)
  • NewSubscriptionAddonRepo (23-27)
openmeter/subscription/addon/repo/subscriptionaddonquantity.go (1)
  • NewSubscriptionAddonQuantityRepo (18-22)
openmeter/subscription/testutils/service.go (1)
  • NewService (54-178)
openmeter/subscription/workflow/service/service.go (1)
  • WorkflowServiceConfig (11-18)
api/client/go/client.gen.go (8)
api/client/javascript/src/client/schemas.ts (4)
  • Addon (9423-9423)
  • SubscriptionAddonAddon (9869-9870)
  • AddonInstanceType (9425-9425)
  • SubscriptionAddonAddonUpdate (9871-9872)
api/api.gen.go (4)
  • Addon (776-828)
  • SubscriptionAddonAddon (5730-5742)
  • AddonInstanceType (856-856)
  • SubscriptionAddonAddonUpdate (5745-5745)
openmeter/ent/db/predicate/predicate.go (1)
  • Addon (10-10)
openmeter/ent/db/subscriptionitem/where.go (1)
  • Key (105-107)
openmeter/ent/db/plan/where.go (2)
  • Key (99-101)
  • Version (109-111)
openmeter/ent/db/planphase/where.go (1)
  • Key (100-102)
openmeter/ent/db/customer/where.go (1)
  • Key (137-139)
openmeter/ent/db/subscriptionphase/where.go (1)
  • Key (94-96)
api/api.gen.go (8)
api/client/javascript/src/client/schemas.ts (4)
  • Addon (9423-9423)
  • SubscriptionAddonAddon (9869-9870)
  • AddonInstanceType (9425-9425)
  • SubscriptionAddonAddonUpdate (9871-9872)
openmeter/ent/db/predicate/predicate.go (1)
  • Addon (10-10)
api/client/go/client.gen.go (4)
  • Addon (696-748)
  • SubscriptionAddonAddon (5278-5290)
  • AddonInstanceType (776-776)
  • SubscriptionAddonAddonUpdate (5293-5293)
openmeter/ent/db/subscriptionitem/where.go (1)
  • Key (105-107)
openmeter/ent/db/plan/where.go (2)
  • Key (99-101)
  • Version (109-111)
openmeter/ent/db/planphase/where.go (1)
  • Key (100-102)
openmeter/ent/db/customer/where.go (1)
  • Key (137-139)
openmeter/ent/db/subscriptionphase/where.go (1)
  • Key (94-96)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: E2E
  • GitHub Check: CI
  • GitHub Check: Analyze (go)
🔇 Additional comments (161)
tools/migrate/migrations/20250416094534_delete-subsadd-ratecards.up.sql (1)

1-4: Schema cleanup looks good.

The migration properly drops the tables related to subscription addon rate cards as part of the broader refactoring to remove this feature from the codebase. The order of operations is correct - first dropping the link table that depends on the main table, then dropping the main table itself.

tools/migrate/migrations/20250416094534_delete-subsadd-ratecards.down.sql (1)

1-34: Down migration correctly recreates tables.

The down migration script properly recreates both tables with all necessary schema elements (primary keys, foreign keys, constraints, and indexes). The order is reversed from the up migration - first creating the main table, then the link table that depends on it. This ensures a clean rollback if needed.

pkg/models/error.go (1)

192-192: Documentation fix approved.

The comment correction accurately describes the function's behavior, now correctly stating that it returns true if the error is a GenericNotImplementedError.

cmd/server/main.go (1)

176-176: Integration of SubscriptionAddonService looks good.

Adding the subscription addon service to the router configuration properly integrates it into the application's HTTP handling pipeline, allowing subscription addon functionality to be exposed via the API.

openmeter/subscription/workflow/service/service.go (2)

5-7: LGTM: Import added for subscription addon package.

The import for the subscription addon package is correctly added to support the new dependency.


11-14: LGTM: Added AddonService field to WorkflowServiceConfig.

The WorkflowServiceConfig struct is appropriately extended with an AddonService field of type subscriptionaddon.Service. This change enables the workflow service to interact with subscription addons, which aligns with the PR objective of implementing the subscription addon creation flow.

cmd/server/wire_gen.go (1)

251-251: LGTM: Updated dependency injection for subscription services.

The addonService parameter is correctly added to the common.NewSubscriptionServices function call, ensuring the addon service is properly wired into the subscription services. This change is consistent with the function signature in app/common/subscription.go and ensures the addon service dependency is available throughout the subscription workflow.

openmeter/subscription/testutils/compare.go (1)

178-179: Improved error messages for test assertions.

The error messages for assertion failures now include the item key and phase key, providing better context for diagnosing test failures when comparing subscription item inputs.

openmeter/subscription/addon/ratecard.go (1)

1-9: LGTM: Clean implementation of the new SubscriptionAddonRateCard struct

The struct is simple, well-organized, and correctly imports the required package. The JSON tag is properly defined. This aligns with the broader refactoring that replaces the previous entity-based implementation with a lightweight wrapper.

openmeter/subscription/state.go (2)

36-43: New subscription action added correctly

The new SubscriptionActionChangeAddons constant is properly added and follows the same naming and formatting conventions as existing action constants.


87-89: State machine correctly configured for addon changes

The state machine configuration is appropriately updated to allow the new SubscriptionActionChangeAddons action as a reentry transition when a subscription is active. This ensures addon changes can be made without changing the subscription's active status.

openmeter/subscription/timing.go (1)

174-181: Timing validation appropriately handles addon changes

The timing validation logic correctly validates the new SubscriptionActionChangeAddons action by ensuring the subscription view isn't nil, while allowing any timing option for addon changes. This implementation aligns with the broader subscription addon workflow.

openmeter/subscription/addon/repo/subscriptionaddon.go (1)

117-128: Improved eager loading with nested relationship

Good refactoring of the query to use nested loading of rate cards through the addon relation instead of loading them separately. This change:

  1. Improves query efficiency
  2. Aligns with the broader removal of direct SubscriptionAddonRateCard entities
  3. Maintains the same functionality while simplifying the data access pattern

This approach properly loads rate cards through the addon relationship hierarchy.

openmeter/subscription/service/sync_test.go (1)

317-320: Updated function callback signature to match interface changes.

The return type of the callback function has been updated to return (productcatalog.RateCardMeta, error) instead of just productcatalog.RateCardMeta, which aligns with changes to the ChangeMeta method in the RateCard interface. This ensures error propagation is handled properly.

openmeter/subscription/patch/patch_test.go (2)

51-54: Updated function callback signature to match interface changes.

The callback now correctly returns both the metadata and an error value, aligning with the updated interface for ChangeMeta.


112-115: Updated function callback signature to match interface changes.

The callback now correctly returns both the metadata and an error value, aligning with the updated interface for ChangeMeta.

cmd/billing-worker/wire_gen.go (1)

231-241: Added initialization of addon service for subscription workflow.

The addon service is now properly initialized and passed to the subscription services initialization, which aligns with the PR's objective of implementing the subscription addon creation flow. The error handling pattern correctly follows the existing pattern in the file.

openmeter/subscription/addon/diff/addon.go (1)

73-76: Improved error handling by replacing panic with structured error.

This change appropriately replaces a panic with a proper error return mechanism, making the code more robust and maintainable. Using models.NewGenericNotImplementedError provides a consistent error type that can be handled by callers.

openmeter/subscription/addon/README.md (2)

11-11: Documentation update reflects architectural change.

The relationship description has been updated to indicate that rate cards are now "calculated from Addon" rather than directly stored, which aligns with the removal of subscription addon rate card entities from the codebase.


37-40: Good addition of quirks documentation.

The new "Quirks" section provides valuable information about potential edge cases in feature resolution. This helps developers understand expected behavior when addons create new subscription items.

cmd/jobs/internal/wire_gen.go (1)

237-247: Proper dependency initialization for subscription addon service.

The code now correctly initializes the addon service before passing it to the subscription service. The error handling and cleanup logic is thorough and follows the same pattern as other service initializations in this file.

openmeter/subscription/testutils/service.go (1)

156-161: Test workflow service updated to include addon service dependency.

The workflow service initialization has been properly updated to include the subscription addon service as a dependency, which aligns with the changes in the main codebase. This ensures tests will correctly reflect the production behavior.

openmeter/server/router/subscriptionaddon.go (4)

6-7: Import looks good

The import for the subscription addon HTTP driver looks appropriate.


12-14: Implementation looks correct

The ListSubscriptionAddons method correctly delegates to the handler with the appropriate parameters. This implementation follows the router pattern consistently used throughout the codebase.


20-22: Implementation looks correct

The CreateSubscriptionAddon method correctly delegates to the handler with the appropriate parameters.


28-31: Implementation looks correct

The GetSubscriptionAddon method correctly delegates to the handler with the appropriate parameters, passing both the subscription ID and subscription addon ID.

openmeter/subscription/addon/compatible.go (3)

11-13: Key validation looks good

The key validation ensures that rate cards with different keys can't be combined, which is important for maintaining data integrity.


18-31: Price type validation looks good

The validation for price types and payment terms is thorough and properly handles the special case for flat price types.


33-35: Entitlement template validation looks good

The validation for entitlement template types ensures only compatible templates can be combined.

api/spec/src/productcatalog/subscriptionaddon.tsp (1)

19-19: Updated to use the new model

The addon property now references the new SubscriptionAddonAddon model instead of an inline definition, which improves code modularity.

openmeter/ent/db/addonratecard.go (1)

73-73: Removed subscription addon rate cards edge

The loadedTypes array size has been reduced from 3 to 2 boolean values, reflecting the removal of the subscription_addon_rate_cards edge. This aligns with the broader refactoring to eliminate the subscription addon rate card feature from the codebase.

test/billing/subscription_suite.go (5)

24-25: Good addition of addon repository imports.

The new imports for addon repository and service are appropriately added to support the subscription addon functionality.


33-35: Proper import organization for subscription addon components.

These imports correctly add the necessary subscription addon modules (domain model, repository, and service) that will be needed for the test suite.


48-48: Well-structured addition of SubscriptionAddonService to the mixin.

The SubscriptionAddonService field is appropriately added to the SubscriptionMixin struct to make the addon service accessible in tests.


135-159: Correctly implemented addon initialization in SetupSuite.

The code properly initializes:

  1. The addon repository with necessary configuration
  2. The addon service with proper dependencies
  3. The subscription addon repositories
  4. The subscription addon service with all required dependencies

This initialization follows the same pattern as other services in the test suite and ensures proper dependency injection.


168-168: Proper dependency injection of addon service into workflow.

The SubscriptionAddonService is correctly passed to the workflow service, ensuring that the workflow can orchestrate operations involving subscription addons.

app/common/subscription.go (6)

10-11: Well-organized imports for addon functionality.

The imports are properly structured to include all necessary addon-related components: the product catalog addon domain model, subscription addon domain model, repository, and service.

Also applies to: 17-19


33-39: The TODO comment should be addressed.

There's a TODO comment to "break up to multiple initializers" that should be addressed, as this initialization is becoming increasingly complex with the addition of addons.

Consider breaking this large initializer into smaller, more focused initializers for better maintainability. This could be tracked separately but should be addressed in a future PR.


48-49: Good addition of addon service parameter.

The addonService parameter is properly added to the NewSubscriptionServices function, maintaining consistency with how other services are injected.


72-82: Well-structured initialization of subscription addon components.

The code correctly:

  1. Initializes the subscription addon repositories
  2. Creates a new subscription addon service with proper configuration
  3. Injects all necessary dependencies (transaction manager, logger, addon service, subscription service, repositories)

This follows the established pattern for service initialization in the application.


84-89: Proper injection of addon service into workflow service.

The addon service is correctly passed to the subscription workflow service, allowing the workflow to coordinate operations involving subscription addons.


106-111: Complete wiring of addon service in return value.

The subscription addon service is correctly included in the returned SubscriptionServiceWithWorkflow struct, making it accessible to consumers of this initialization function.

openmeter/subscription/addon/addon.go (3)

6-7: Good addition of time import for new functionality.

The time package is appropriately imported to support the new GetInstanceAt method that accepts a time parameter.


32-47: Well-implemented GetInstanceAt method.

This new method provides a convenient way to retrieve the subscription addon instance active at a specific time, which is helpful for time-based operations and queries. The implementation is clean and follows the pattern of other time-based retrieval methods.


111-112: Simplification of the CreateSubscriptionAddonInput structure.

Removing the RateCards field from the input aligns with the architectural change to rely on the addon's own rate cards rather than managing them separately. This simplifies the API and reduces duplication.

openmeter/ent/db/subscriptionaddon.go (4)

53-53: Correct adjustment of loadedTypes array size.

The loadedTypes array size is properly reduced from [4]bool to [3]bool following the removal of the RateCards edge. This ensures the array size matches the actual number of edges.


70-74: Proper index update in QuantitiesOrErr method.

The index used to check if the Quantities edge was loaded is correctly updated from [2] to [1] after the removal of the RateCards edge.


79-85: Correct index update in AddonOrErr method.

The index used to check if the Addon edge was loaded is properly updated from [3] to [2] after the removal of the RateCards edge.


1-243:

Details

✅ Verification successful

Verify consistent removal of rate cards across the entire entity code.

The rate cards edge has been removed from the SubscriptionAddonEdges struct and related methods have been adjusted. However, it would be good to verify that all related code (predicates, where clauses, etc.) has been consistently updated throughout the generated Ent code.


🏁 Script executed:

#!/bin/bash
# Search for any remaining references to rate cards in the subscription addon entity code
grep -r "rate_?cards\|RateCards" --include="*.go" openmeter/ent/db/subscriptionaddon* || echo "No remaining references found"

Length of output: 672


Rate Cards Removal Consistency Verified

The removal of the rate cards edge and its associated code from the SubscriptionAddon entity has been fully validated. A thorough search across all related files (including predicates, where clauses, and query methods) returned no remaining references, which confirms that the changes have been consistently applied throughout the generated Ent code.

openmeter/subscription/addon/diff/affected.go (1)

43-45: LGTM!

Good use of the lo library for deduplicating map values.

openmeter/ent/db/subscriptionitem.go (1)

85-85: LGTM!

The change to adjust the loadedTypes array size from 4 to 3 elements is consistent with the removal of the "subscription_addon_rate_card_items" edge from the database schema.

openmeter/subscription/addon/service/service.go (2)

47-47: LGTM!

Good improvement to use models.NewGenericValidationError for input validation errors, providing better error classification.


68-74: LGTM!

This change simplifies the subscription retrieval to just get the view of a subscription, which aligns with removing the rate card functionality while still validating that the subscription exists.

openmeter/subscription/workflow/service.go (2)

18-18: LGTM!

Good addition of the AddAddon method to the workflow service interface to support the subscription addon creation flow.


34-54: LGTM!

Well-structured input type with appropriate validation rules that ensure the addon ID is provided and the initial quantity is positive.

openmeter/subscription/workflow/service/addon.go (12)

20-23: No concerns with the new AddAddon method signature
The signature is well-defined to accept the needed subscription ID and workflow input.


24-26: Input validation usage is consistent
Ensuring early validation helps maintain clear error handling.


50-69: Restoring subscription spec approach
Reverting the spec to a clean state before applying new diffs ensures consistent data. This logic is sound and reduces the risk of compounding errors.


70-80: Timing validation logic
Validating the timing before applying the addon ensures that changes align with the subscription lifecycle.


81-97: Creation of subscription addon
The logic correctly handles the creation outcome and checks for a nil return to prevent unexpected nil pointer issues.


98-106: Reverting and syncing diffs
Reapplying the restored diffs helps maintain consistent subscription states. This step is crucial for correct billing calculations.


107-117: Applying diff from the newly created addon
Applying the new addon's diff ensures the spec reflects the latest state. Good use of domain logic for subscription changes.


118-127: Subscription update after diff reapplication
Calling Update on the subscription after finalizing diffs is a sensible approach to keep database records aligned with memory.


128-132: Storing final purchase result
Returning the updated subscription view and newly created addon together is convenient for downstream usage.


133-135: Error propagated from transaction
Gracefully returning the transactional error ensures clear failure states if anything goes awry.


137-138: Final return statement
Clean and straightforward return for the success path.


145-160:

Details

✅ Verification successful

Ensure hasAddons function is used consistently
This helper function accurately detects non-zero quantity addons. Double-check it's used in all places where the logic is needed. Otherwise some calls might inadvertently skip this check.


🏁 Script executed:

#!/bin/bash
# Searching for references to hasAddons function to confirm usage.
rg -A 3 "hasAddons"

Length of output: 800


Action: Consistently Apply hasAddons in Subscription Workflows

The hasAddons helper function correctly detects non-zero quantity addons. Our search confirms that it’s defined in openmeter/subscription/workflow/service/addon.go and is consistently used in openmeter/subscription/workflow/service/subscription.go where the check is required. Please continue to ensure that any new or related flows that handle addons integrate this function to maintain uniform logic across the codebase.

openmeter/productcatalog/ratecard.go (2)

37-37: Improved error handling in ChangeMeta
Changing the signature to include an error return is beneficial for controlling validations within the meta update.


228-233: ChangeMeta implementation for FlatFeeRateCard
This is a straightforward pass-through that properly handles the error returned from the callback. Looks good!

openmeter/subscription/addon/service/create_test.go (1)

203-203: Reference to RateCards appears to contradict the summary
The summary mentions removing references to rate cards, but this test still checks for them.

Likely an incorrect or invalid review comment.

openmeter/subscription/addon/http/handler.go (3)

17-21: Clean interface design for subscription addon HTTP operations.

The Handler interface is well-defined with clear method signatures that correspond to the specific operations (create, list, get). This follows good API design principles by exposing only the necessary operations and returning specific handler types that can be found in other files.


23-29: Proper dependency injection pattern in HandlerConfig.

The configuration struct follows good dependency injection practices by explicitly declaring all required dependencies. This approach makes the handler testable and the dependencies clear. The inclusion of both the addon-specific service and the workflow service indicates proper separation of concerns in the architecture.


1-50: Overall implementation aligns well with the PR objectives.

The implementation provides a well-structured foundation for managing subscription addons through HTTP endpoints, which aligns with the PR objectives. The design follows clean architecture principles with proper separation of concerns, making it maintainable and extensible for future enhancements mentioned in the PR description, such as plan-addon linking.

api/client/go/client.gen.go (5)

5235-5241: Refactored Addon field to use named struct type

The Addon field has been changed from an embedded anonymous struct to the named struct type SubscriptionAddonAddon. This change improves type safety and readability.


5274-5294: New type definitions for SubscriptionAddonAddon structures

These new type definitions extract the subscription addon properties into reusable named types:

  1. SubscriptionAddonAddon: A struct containing basic addon reference data (id, instanceType, key, version)
  2. SubscriptionAddonAddonUpdate: A type alias for map[string]interface{} for flexible updates

This refactoring aligns with the removal of subscription addon rate cards by providing a cleaner interface for addon references without the rate card dependencies.


5301-5307: Updated Addon field in SubscriptionAddonCreate

Similar to the earlier change, the Addon field in the SubscriptionAddonCreate struct now uses the named SubscriptionAddonAddon type, providing consistency across related structures.


5349-5355: Updated Addon field in SubscriptionAddonUpdate

The Addon field now uses a pointer to SubscriptionAddonAddonUpdate, maintaining the optional nature of this field (with omitempty). This change provides a flexible update mechanism while maintaining type consistency.


36753-37287: Updated Swagger specification

The embedded Swagger specification has been updated to reflect the structural changes made to the API types. This ensures that the client documentation and code generation remain in sync with the actual implementation.

openmeter/server/router/router.go (5)

54-55: Properly added imports for subscription addon functionality.

These imports provide the necessary subscription addon types and HTTP driver packages required for the added functionality.


105-105: Good addition of SubscriptionAddonService to Config struct.

This field allows the router to accept the subscription addon service as a dependency.


179-189: Properly validates subscription service dependencies.

The validation checks ensure that all required subscription-related services (workflow, service, and addon) are provided before the router is initialized.


204-204: Added subscription addon handler field to Router struct.

This field will hold the initialized subscription addon HTTP handler.


365-374: Well-structured subscription addon handler initialization.

The handler is properly initialized with all required dependencies:

  • SubscriptionAddonService for addon operations
  • SubscriptionWorkflowService for workflow operations
  • SubscriptionService for core subscription functionality
  • NamespaceDecoder for multi-tenancy support
  • Logger for structured logging
  • Error handler for consistent error management

The implementation follows the same pattern as other handlers in the router.

openmeter/subscription/workflow/service/subscription_test.go (5)

63-89: Good test coverage for subscription item annotations.

This test ensures that all created subscription items have the proper ownership annotations, which is essential for tracking item ownership and origin within the system.


277-277: Properly added AddonService dependency to workflow service.

The workflow service now correctly includes the AddonService dependency, which is necessary for the subscription addons functionality.


977-977: Added SubsDeps field to test dependencies struct.

This field provides access to subscription-related dependencies in test cases, allowing for better organization and reuse of setup code.


1079-1082: Updated ChangeMeta signature to include error return.

The function signature now properly returns an error alongside the modified meta, which improves error handling.


1015-1049: Excellent test for addon-related edit restrictions.

This test verifies a key constraint mentioned in the PR objectives: a subscription with an addon should not be editable. The test:

  1. Creates a subscription
  2. Adds an addon to the subscription
  3. Attempts to edit the subscription
  4. Verifies that the edit fails with a GenericForbiddenError

This test case ensures that the implementation correctly enforces the business rule that subscriptions with addons cannot be edited.

api/api.gen.go (6)

5687-5693: Type change improves structure clarity.

The change from an inline anonymous struct to a dedicated SubscriptionAddonAddon type for the Addon field enhances code readability and type consistency.


5729-5742: Good extraction of the add-on properties into a dedicated type.

Centralizing the add-on properties in a dedicated type improves code organization and reuse. The extracted fields (Id, InstanceType, Key, and Version) match the core properties needed from the complete Addon type (as seen in the relevant code snippets).


5744-5745: Type alias for addon updates provides flexibility.

Defining SubscriptionAddonAddonUpdate as a map type allows for flexible partial updates while maintaining type information in the API.


5753-5756: Consistent type usage in creation model.

Good to see consistent use of the new SubscriptionAddonAddon type across related structs, including here in the SubscriptionAddonCreate model.


5801-5804: Proper pointer usage for optional update fields.

Using a pointer to SubscriptionAddonAddonUpdate with the omitempty tag is appropriate for this update field, as it allows clients to indicate whether they want to update the addon info or leave it unchanged.


16726-17285: Updated Swagger specification aligns with code changes.

The API specification has been updated to reflect the new type structure. This ensures consistency between the implementation and API documentation.

openmeter/subscription/addon/http/get.go (2)

15-24: Well-structured type definitions for API consistency.

The type definitions follow a clean pattern with proper separation of URL parameters, internal request structure with namespaced IDs, and response types. This maintains consistency with the rest of the codebase's HTTP handlers.


27-59: Verify that the subscription addon belongs to the specified subscription.

The handler correctly retrieves both the subscription addon and subscription view, but doesn't explicitly verify that the addon belongs to the specified subscription. This could potentially allow retrieving an addon from one subscription while specifying a different subscription ID in the URL.

Consider modifying the service call to verify this relationship:

-			res, err := h.SubscriptionAddonService.Get(ctx, req.SubscriptionAddonID)
+			res, err := h.SubscriptionAddonService.Get(ctx, req.SubscriptionID, req.SubscriptionAddonID)

Or add a validation check after retrieving both resources:

 			view, err := h.SubscriptionService.GetView(ctx, req.SubscriptionID)
 			if err != nil {
 				return GetSubscriptionAddonResponse{}, err
 			}
 
+			// Verify addon belongs to the subscription
+			if res.SubscriptionID != req.SubscriptionID {
+				return GetSubscriptionAddonResponse{}, fmt.Errorf("subscription addon does not belong to the specified subscription")
+			}
+
 			return MapSubscriptionAddonToResponse(view, *res)
api/client/javascript/src/client/schemas.ts (6)

8361-8361: LGTM: Proper refactoring to use a dedicated type.

The change replaces an inline addon definition with a reference to the new dedicated SubscriptionAddonAddon schema. This improves maintainability and type consistency throughout the codebase.


8408-8432: LGTM: Well-defined schema with proper documentation.

The newly introduced SubscriptionAddonAddon schema properly encapsulates addon properties with appropriate JSDoc comments, making the schema more maintainable and reusable. This follows good TypeScript practices by creating a dedicated type rather than repeating the same structure in multiple places.


8433-8434: Verify empty record type is sufficient for updates.

The SubscriptionAddonAddonUpdate type is defined as an empty record (Record<string, never>), which suggests no properties can be updated on an addon. Ensure this aligns with your intended update behavior.

This differs from the Go implementation which uses a flexible map[string]interface{} for updates. If addon properties should be updatable, consider using a partial type instead:

-SubscriptionAddonAddonUpdate: Record<string, never>
+SubscriptionAddonAddonUpdate: Partial<components['schemas']['SubscriptionAddonAddon']>

8468-8468: LGTM: Consistent use of the new schema type.

Good implementation using the dedicated SubscriptionAddonAddon type in the SubscriptionAddonCreate schema.


8548-8548: LGTM: Optional update field properly typed.

The addon field is correctly marked as optional using the ? modifier and references the appropriate update type. This ensures type safety when submitting partial updates.


8869-8872: LGTM: Proper type exports for the new schema types.

The new type aliases are correctly exported, making them available for consumers of this module.

openmeter/subscription/addon/repo/mapping.go (3)

55-56: Model change: Rate cards now accessed through Addon entity

The subscription addon model has been refactored to access rate cards through the Addon entity rather than directly from the subscription addon. This aligns with the removal of the subscription addon rate card feature from the codebase.


73-90: Function updated to use AddonRateCard instead of SubscriptionAddonRateCard

The signature and implementation of this function have been updated to work with AddonRateCard entities instead of the now-removed SubscriptionAddonRateCard entities. This change is consistent with the overall refactoring to simplify the data model.

The implementation correctly:

  1. Handles nil entity cases
  2. Maps to the domain model using addonrepo.FromAddonRateCardRow
  3. Performs additional nil checking on the mapped value

95-97: Updated function signature to match entity type change

This function signature has been updated to match the change from SubscriptionAddonRateCard to AddonRateCard entities, maintaining consistency with the changes to the underlying data model.

openmeter/subscription/addon/http/list.go (2)

16-25: Well-structured types for subscription addon listing

The types are clearly defined with appropriate namespacing and separation of concerns between parameter extraction, request model, and response model.


27-65: New handler implements complete subscription addon listing flow

This handler correctly:

  1. Resolves the namespace from the context
  2. Constructs a properly namespaced request
  3. Calls the service layer to fetch subscription addons
  4. Retrieves the subscription view for context
  5. Maps domain models to API responses
  6. Handles errors appropriately at each step
  7. Sets the correct HTTP status code

The implementation follows the project's handler pattern and maintains proper separation of concerns.

openmeter/ent/db/subscriptionaddon_query.go (1)

447-452: Updated loadedTypes array size to reflect removed edge

The array size has been reduced from 4 to 3 elements, corresponding to the removal of the "rate_cards" edge from the SubscriptionAddon entity. This change is consistent with the broader refactoring to simplify the subscription addon model by removing the subscription addon rate card feature.

api/openapi.cloud.yaml (5)

19303-19386: Refactoring to reusable schema for addon property is correct and improves maintainability.

The change from inline object definitions to referencing the new SubscriptionAddonAddon schema for the addon property in SubscriptionAddon is correct, improves schema reuse, and aligns with best practices for OpenAPI specifications. The new schema is well-defined and encapsulates the required fields and constraints.


19428-19443: Refactoring to reusable schema for addon property in creation model is correct.

The use of the new SubscriptionAddonAddon schema for the addon property in SubscriptionAddonCreate is correct and consistent with the changes in the main model. This improves maintainability and ensures consistency across API models.


19522-19537: Refactoring to reusable schema for addon property in update model is correct.

The use of the new SubscriptionAddonAddonUpdate schema for the addon property in SubscriptionAddonUpdate is correct and prepares the API for future extensibility. The placeholder schema is acceptable for now.


19352-19387: New SubscriptionAddonAddon schema is well-defined and appropriate.

The new SubscriptionAddonAddon schema is well-defined, with all required fields and constraints for referencing an add-on. This centralizes the definition and improves consistency across the API.


19388-19390: New SubscriptionAddonAddonUpdate schema is a valid placeholder.

The new SubscriptionAddonAddonUpdate schema is currently empty, which is acceptable as a placeholder for future extensibility in update operations.

openmeter/subscription/addon/extend.go (6)

7-11: Ensure consistent import usage and dependency management.

The introduction of "github.com/samber/lo" for pointer manipulation (line 7) and direct references to models and entitlement (lines 9,11) appear valid. However, verify that the introduction of these imports aligns with project conventions and that the library versions (if pinned) are compatible with the rest of the codebase.

Do you want me to run a script to confirm there are no conflicting or outdated references to lo, models, or entitlement in other files?


17-20: Validate pointer-based reflection approach.

Checking reflect.TypeOf(target) for nil is a sensible way to ensure the caller supplies a valid pointer. This guards against runtime errors when performing reflection-based modifications.


22-22: Enforce pointer usage for rate card changes.

The kind check for Ptr is essential to ensure ChangeMeta can be safely applied. This is a correct approach to prevent accidentally calling Apply on non-pointer rate cards.


26-27: Skip early when no price or entitlement template to merge.

Early return if both Price and EntitlementTemplate are nil is efficient and clear. This avoids unnecessary operations when there is effectively nothing to apply.


30-32: Confirm rate card compatibility validation coverage.

The call to validateRateCards(a.AddonRateCard.RateCard, target) is pivotal for ensuring consistent rate card structures. Confirm that unit tests thoroughly cover scenarios of incompatible rate cards to prevent runtime errors downstream.


56-75: Metered entitlement merging is comprehensive but consider additional templates.

The logic for merging the IssueAfterReset fields via lo.ToPtr is straightforward. If new entitlement types are introduced, ensure the switch statement is extended consistently. The distinct handling for boolean vs. metered is a good approach, but keep in mind future expansion needs.

openmeter/subscription/addon/http/create.go (3)

1-14: Check request decoding and error handling consistency.

The new package (httpdriver) and imports look consistent with the project structure. Ensure that error-handling patterns (like fmt.Errorf) align with how your codebase typically wraps or logs contextual details.


15-25: Structure for request, response, and handler types is concise.

Using clear typed structs (CreateSubscriptionAddonParams, CreateSubscriptionAddonRequest, etc.) for the addon creation workflow is helpful. The typed approach improves maintainability and helps avoid confusion between different creation flows.


49-65: Leverage structured response encoding with adequate error reporting.

Returning def, err provides a clear way to bubble up issues from h.SubscriptionWorkflowService.AddAddon. The final mapping (MapSubscriptionAddonToResponse(view, add)) is straightforward. Optionally, consider logging creation success/failure for audit trails.

api/openapi.yaml (5)

19687-19690: Refactored addon property to reusable component—good improvement

The addon property in SubscriptionAddon now references the new SubscriptionAddonAddon component, which centralizes and enforces the structure for add-on info. This improves schema reuse, maintainability, and type safety. The change is consistent with the PR objectives and AI summary.


19812-19815: Consistent use of reusable component in SubscriptionAddonCreate

The addon property in SubscriptionAddonCreate now references the same SubscriptionAddonAddon component, ensuring consistency between creation and retrieval models. This is a best practice for OpenAPI schema design.


19906-19909: Correct use of update-specific component in SubscriptionAddonUpdate

The addon property in SubscriptionAddonUpdate now references SubscriptionAddonAddonUpdate, which is a type alias for update operations. This maintains clarity and separation between create/read and update models, and is a good API design pattern.


19736-19771: New SubscriptionAddonAddon component is well-defined

The new SubscriptionAddonAddon component is clearly defined with required fields (id, key, version, instanceType) and appropriate descriptions. This centralizes the add-on info structure and improves maintainability and validation.


19772-19773: SubscriptionAddonAddonUpdate is defined as a type alias—OK

The SubscriptionAddonAddonUpdate component is defined as an object with a description, serving as a type alias for update operations. This is acceptable for OpenAPI and code generation purposes.

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

26-33: Clean removal of subscription addon rate card references from the query struct.

The changes correctly remove all subscription addon rate card related fields from the SubscriptionItemQuery struct as part of the broader effort to remove this feature from the codebase.


322-334: Properly updated clone method to match the modified struct fields.

The Clone method has been correctly updated to reflect the changes to the struct fields, maintaining consistency in the codebase.


448-452: Correctly updated loadedTypes array size.

The loadedTypes array size has been updated from 4 to 3 elements to reflect the removal of the subscription addon rate card items edge, ensuring proper array initialization.

openmeter/subscription/addon/diff/apply_test.go (3)

49-54: Good refactoring to use shared test utilities.

The test now uses subscriptiontestutils package functions instead of local helper functions, improving code reuse and maintainability.


533-534: Enhanced test coverage with annotation preservation validation.

New assertion verifies that annotations are preserved after applying diffs, which is an important requirement when merging rate cards.


544-544: Consistent validation of annotation preservation.

Similar to the earlier check, this assertion ensures annotations remain unchanged across different segments of the timeline, providing thorough test coverage.

openmeter/subscription/workflow/service/addon_test.go (5)

40-69: Comprehensive test for input validation.

Good test case that verifies invalid inputs are properly rejected with appropriate validation errors, ensuring the API behaves correctly when receiving improper requests.


71-101: Test aligns with the PR's key constraint.

This test properly verifies that when a subscription already has an addon, the system returns a NotImplemented response, which is one of the key constraints mentioned in the PR objectives.


103-150: Complete end-to-end test for successful addon creation.

This test thoroughly validates that the subscription is correctly synchronized with the new addon's contents, including a manual verification of the expected changes using the diff and apply mechanisms.


152-180: Proper conflict detection test.

The test correctly verifies that attempting to add the same addon twice results in a conflict error, ensuring data integrity in the system.


184-195: Useful helper function for test normalization.

The stripFeatureIDs function elegantly solves the comparison problem when feature IDs aren't known in advance, making the tests more robust and less brittle.

openmeter/server/server_test.go (5)

53-53: Added import for subscription addon package.

Proper inclusion of the subscription addon package import to support the new service interfaces and implementations.


479-479: Added NoopSubscriptionAddonService to test server setup.

This change properly integrates the new subscription addon service into the test server setup, ensuring tests can run with the new functionality.


520-520: Properly configured router with the subscription addon service.

The subscription addon service is correctly assigned to the router configuration, ensuring API routes can use the service.


1212-1214: Implemented AddAddon method in NoopSubscriptionWorkflowService.

The workflow service interface implementation is correctly extended with the new AddAddon method, maintaining interface compatibility.


1216-1236: Added NoopSubscriptionAddonService implementation.

Comprehensive no-op implementation of the subscriptionaddon.Service interface with all the required methods, providing a good foundation for testing.

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

24-30: Confirmed removal of subscription addon rate cards edge

I can see the withSubscriptionAddonRateCards field has been removed from the AddonRateCardQuery struct, which aligns with the PR objective of removing the old subscription addon rate card entities and their linking tables.


411-414: Adjustment of loadedTypes array size

The loadedTypes array size has been correctly adjusted from 3 to 2 elements to reflect the removal of the subscription addon rate cards edge query capability.


298-305: Proper cleanup in Clone method

The Clone method has been appropriately updated to remove the withSubscriptionAddonRateCards field, ensuring that cloned query builders don't attempt to retain references to the removed edge.

openmeter/subscription/addon/extend_test.go (9)

19-29: Good test setup with reusable test data

The test file properly initializes common test data that will be reused across multiple test cases, making the tests more maintainable and readable.


31-48: Thorough validation testing for edge cases

Good tests for handling nil or non-pointer targets, which are important edge cases that could lead to runtime panics if not handled properly.


50-98: Comprehensive type compatibility validation tests

These tests ensure proper validation when merging rate cards with incompatible price types, entitlement types, or keys, which is critical for maintaining data integrity.


100-119: Test for no-op scenario when nothing to merge

This test verifies that when an addon rate card has no entitlement or price, the target rate card remains unchanged, which is an important boundary case.


121-145: Validation of payment term compatibility

Good test to ensure that addon rate cards with different payment terms cannot be merged, preventing potential billing inconsistencies.


147-170: Comprehensive price merging test cases

These tests thoroughly verify the price merging behavior, including:

  1. Preserving target price when addon has no price
  2. Adding addon price to target price (flat fee addition)
  3. Adding addon price when target has no price

This ensures the extend functionality correctly handles all price merging scenarios.

Also applies to: 172-198, 200-223


225-243: Thorough entitlement merging tests

These tests verify the entitlement merging behavior for different scenarios:

  1. Adding addon entitlement to target
  2. Preserving target entitlement when addon has none
  3. Correctly handling metered entitlements and combining their values

The test in lines 290-322 specifically verifies that issueAfterReset values are properly accumulated across multiple applies, which is critical for ensuring correct entitlement calculations.

Also applies to: 245-263, 265-322


325-367: Well-implemented test helper type

The nonPointerRateCard type provides a clean way to test the pointer validation in the Apply method. All interface methods are appropriately implemented.


369-375: Useful test factory function

The getTestAddonRateCard function encapsulates the creation of test objects, making the tests more readable and maintainable.

openmeter/subscription/addon/http/mapping.go (3)

20-34: Clean API request to workflow input mapping

The function properly maps the API request fields to the internal workflow input structure, including handling of optional metadata. This follows a clear and consistent mapping pattern.


56-71: Good error handling for rate card conversion

The implementation properly handles errors during rate card conversion and provides clear error messages that include the underlying cause, which will be helpful for troubleshooting.


73-101: Well-structured API response mapping

The function creates a comprehensive API response with all necessary fields, including metadata, timing information, and quantity details. The use of lo.EmptyableToPtr ensures that empty metadata is handled correctly.

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

422-423: Clean removal of SubscriptionAddonRateCard references

The code removes references to SubscriptionAddonRateCard entity in the Use and Intercept methods, which is consistent with the PR's removal of the subscription addon rate card feature.

Also applies to: 443-444


7271-7272: Consistent removal in hooks and interceptors structures

The SubscriptionAddonRateCard entity has been properly removed from the hooks and interceptors structures. This aligns with the overall objective of removing the subscription addon rate card feature from the codebase.

Also applies to: 7284-7285


1-7312:

Details

❓ Verification inconclusive

Verify downstream impact of entity removal

While the entity removal from the database client is clean, the removal of SubscriptionAddonRateCard and related entities may impact other components that previously relied on these entities.

Consider thoroughly testing all subscription addon related functionality to ensure there are no regressions or unexpected behaviors.


🏁 Script executed:

#!/bin/bash
# Description: Check for any remaining references to the removed entities in the codebase

echo "Checking for remaining references to SubscriptionAddonRateCard..."
rg -i "SubscriptionAddonRateCard" --type go

echo "Checking for remaining references to SubscriptionAddonRateCardItemLink..."
rg -i "SubscriptionAddonRateCardItemLink" --type go

echo "Checking database schema migration scripts for related tables..."
rg -i "subscription_addon_rate_card" --type sql

Length of output: 14912


Action Required: Verify Downstream Impact from Residual References

The script output shows that multiple components—such as subscription addon modules, mapping functions, API generators, and even migration scripts—still reference SubscriptionAddonRateCard (and SubscriptionAddonRateCardItemLink). Although the ent client appears to have removed these entities from the database client layer (as evidenced by the migration scripts dropping the related tables), the higher-level code still depends on them.

Please ensure that:

  • Any remaining references are either updated or refactored so that they no longer assume the presence of these entities.
  • All subscription addon functionality (including tests, API mappings, and related domain logic) is thoroughly exercised to catch regressions or unexpected behaviors.
  • Coordination is maintained with both the migration changes and the upper-layer domain code to ensure consistency across the stack.

@GAlexIHU GAlexIHU merged commit 3299d2a into main Apr 16, 2025
27 checks passed
@GAlexIHU GAlexIHU deleted the galexi/addons-3 branch April 16, 2025 18:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note/feature Release note: Exciting New Features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants