@powerhousedao/service-offering 1.0.0-dev.4 → 1.0.0-dev.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/document-models/facet/v1/actions.d.ts +3 -1
- package/dist/document-models/facet/v1/actions.d.ts.map +1 -1
- package/dist/document-models/facet/v1/gen/controller.d.ts +4 -0
- package/dist/document-models/facet/v1/gen/controller.d.ts.map +1 -0
- package/dist/document-models/facet/v1/gen/controller.js +3 -0
- package/dist/document-models/facet/v1/gen/document-model.d.ts.map +1 -1
- package/dist/document-models/facet/v1/gen/document-model.js +31 -7
- package/dist/document-models/facet/v1/gen/document-schema.d.ts +6 -6
- package/dist/document-models/facet/v1/gen/index.d.ts +1 -0
- package/dist/document-models/facet/v1/gen/index.d.ts.map +1 -1
- package/dist/document-models/facet/v1/gen/index.js +1 -0
- package/dist/document-models/facet/v1/gen/option-management/error.d.ts +27 -1
- package/dist/document-models/facet/v1/gen/option-management/error.d.ts.map +1 -1
- package/dist/document-models/facet/v1/gen/option-management/error.js +23 -1
- package/dist/document-models/facet/v1/gen/ph-factories.js +2 -2
- package/dist/document-models/facet/v1/gen/schema/types.d.ts +2 -2
- package/dist/document-models/facet/v1/gen/schema/types.d.ts.map +1 -1
- package/dist/document-models/facet/v1/gen/schema/zod.js +2 -2
- package/dist/document-models/facet/v1/gen/utils.js +2 -2
- package/dist/document-models/facet/v1/module.d.ts +1 -1
- package/dist/document-models/facet/v1/module.d.ts.map +1 -1
- package/dist/document-models/facet/v1/module.js +4 -1
- package/dist/document-models/resource-instance/v1/actions.d.ts +4 -1
- package/dist/document-models/resource-instance/v1/actions.d.ts.map +1 -1
- package/dist/document-models/resource-instance/v1/gen/configuration-management/error.d.ts +34 -1
- package/dist/document-models/resource-instance/v1/gen/configuration-management/error.d.ts.map +1 -1
- package/dist/document-models/resource-instance/v1/gen/configuration-management/error.js +32 -1
- package/dist/document-models/resource-instance/v1/gen/controller.d.ts +4 -0
- package/dist/document-models/resource-instance/v1/gen/controller.d.ts.map +1 -0
- package/dist/document-models/resource-instance/v1/gen/controller.js +3 -0
- package/dist/document-models/resource-instance/v1/gen/document-model.d.ts.map +1 -1
- package/dist/document-models/resource-instance/v1/gen/document-model.js +222 -70
- package/dist/document-models/resource-instance/v1/gen/document-schema.d.ts +0 -6
- package/dist/document-models/resource-instance/v1/gen/document-schema.d.ts.map +1 -1
- package/dist/document-models/resource-instance/v1/gen/index.d.ts +1 -0
- package/dist/document-models/resource-instance/v1/gen/index.d.ts.map +1 -1
- package/dist/document-models/resource-instance/v1/gen/index.js +1 -0
- package/dist/document-models/resource-instance/v1/gen/instance-management/actions.d.ts +6 -2
- package/dist/document-models/resource-instance/v1/gen/instance-management/actions.d.ts.map +1 -1
- package/dist/document-models/resource-instance/v1/gen/instance-management/creators.d.ts +3 -2
- package/dist/document-models/resource-instance/v1/gen/instance-management/creators.d.ts.map +1 -1
- package/dist/document-models/resource-instance/v1/gen/instance-management/creators.js +2 -1
- package/dist/document-models/resource-instance/v1/gen/instance-management/error.d.ts +98 -1
- package/dist/document-models/resource-instance/v1/gen/instance-management/error.d.ts.map +1 -1
- package/dist/document-models/resource-instance/v1/gen/instance-management/error.js +112 -1
- package/dist/document-models/resource-instance/v1/gen/instance-management/operations.d.ts +2 -1
- package/dist/document-models/resource-instance/v1/gen/instance-management/operations.d.ts.map +1 -1
- package/dist/document-models/resource-instance/v1/gen/ph-factories.d.ts.map +1 -1
- package/dist/document-models/resource-instance/v1/gen/ph-factories.js +0 -2
- package/dist/document-models/resource-instance/v1/gen/reducer.d.ts.map +1 -1
- package/dist/document-models/resource-instance/v1/gen/reducer.js +6 -1
- package/dist/document-models/resource-instance/v1/gen/schema/types.d.ts +3 -3
- package/dist/document-models/resource-instance/v1/gen/schema/types.d.ts.map +1 -1
- package/dist/document-models/resource-instance/v1/gen/schema/zod.d.ts +2 -1
- package/dist/document-models/resource-instance/v1/gen/schema/zod.d.ts.map +1 -1
- package/dist/document-models/resource-instance/v1/gen/schema/zod.js +5 -3
- package/dist/document-models/resource-instance/v1/gen/utils.d.ts.map +1 -1
- package/dist/document-models/resource-instance/v1/gen/utils.js +0 -2
- package/dist/document-models/resource-instance/v1/module.d.ts +1 -1
- package/dist/document-models/resource-instance/v1/module.d.ts.map +1 -1
- package/dist/document-models/resource-instance/v1/module.js +4 -1
- package/dist/document-models/resource-instance/v1/src/reducers/configuration-management.d.ts.map +1 -1
- package/dist/document-models/resource-instance/v1/src/reducers/configuration-management.js +57 -53
- package/dist/document-models/resource-instance/v1/src/reducers/instance-management.d.ts.map +1 -1
- package/dist/document-models/resource-instance/v1/src/reducers/instance-management.js +57 -21
- package/dist/document-models/resource-instance/v1/tests/instance-management.test.js +11 -1
- package/dist/document-models/resource-template/v1/actions.d.ts +3 -1
- package/dist/document-models/resource-template/v1/actions.d.ts.map +1 -1
- package/dist/document-models/resource-template/v1/gen/audience-management/error.d.ts +20 -1
- package/dist/document-models/resource-template/v1/gen/audience-management/error.d.ts.map +1 -1
- package/dist/document-models/resource-template/v1/gen/audience-management/error.js +16 -1
- package/dist/document-models/resource-template/v1/gen/controller.d.ts +4 -0
- package/dist/document-models/resource-template/v1/gen/controller.d.ts.map +1 -0
- package/dist/document-models/resource-template/v1/gen/controller.js +3 -0
- package/dist/document-models/resource-template/v1/gen/document-model.d.ts.map +1 -1
- package/dist/document-models/resource-template/v1/gen/document-model.js +207 -89
- package/dist/document-models/resource-template/v1/gen/document-schema.d.ts +12 -12
- package/dist/document-models/resource-template/v1/gen/facet-targeting/error.d.ts +27 -1
- package/dist/document-models/resource-template/v1/gen/facet-targeting/error.d.ts.map +1 -1
- package/dist/document-models/resource-template/v1/gen/facet-targeting/error.js +23 -1
- package/dist/document-models/resource-template/v1/gen/index.d.ts +1 -0
- package/dist/document-models/resource-template/v1/gen/index.d.ts.map +1 -1
- package/dist/document-models/resource-template/v1/gen/index.js +1 -0
- package/dist/document-models/resource-template/v1/gen/option-group-management/error.d.ts +27 -1
- package/dist/document-models/resource-template/v1/gen/option-group-management/error.d.ts.map +1 -1
- package/dist/document-models/resource-template/v1/gen/option-group-management/error.js +23 -1
- package/dist/document-models/resource-template/v1/gen/ph-factories.js +3 -3
- package/dist/document-models/resource-template/v1/gen/schema/types.d.ts +4 -4
- package/dist/document-models/resource-template/v1/gen/schema/types.d.ts.map +1 -1
- package/dist/document-models/resource-template/v1/gen/schema/zod.js +4 -4
- package/dist/document-models/resource-template/v1/gen/service-management/error.d.ts +51 -1
- package/dist/document-models/resource-template/v1/gen/service-management/error.d.ts.map +1 -1
- package/dist/document-models/resource-template/v1/gen/service-management/error.js +49 -1
- package/dist/document-models/resource-template/v1/gen/utils.js +3 -3
- package/dist/document-models/resource-template/v1/module.d.ts +1 -1
- package/dist/document-models/resource-template/v1/module.d.ts.map +1 -1
- package/dist/document-models/resource-template/v1/module.js +4 -1
- package/dist/document-models/resource-template/v1/src/reducers/option-group-management.d.ts.map +1 -1
- package/dist/document-models/resource-template/v1/src/reducers/option-group-management.js +2 -21
- package/dist/document-models/service-offering/v1/actions.d.ts +3 -1
- package/dist/document-models/service-offering/v1/actions.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/gen/controller.d.ts +4 -0
- package/dist/document-models/service-offering/v1/gen/controller.d.ts.map +1 -0
- package/dist/document-models/service-offering/v1/gen/controller.js +3 -0
- package/dist/document-models/service-offering/v1/gen/document-model.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/gen/document-model.js +421 -199
- package/dist/document-models/service-offering/v1/gen/document-schema.d.ts +9 -9
- package/dist/document-models/service-offering/v1/gen/index.d.ts +1 -0
- package/dist/document-models/service-offering/v1/gen/index.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/gen/index.js +1 -0
- package/dist/document-models/service-offering/v1/gen/offering/error.d.ts +41 -1
- package/dist/document-models/service-offering/v1/gen/offering/error.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/gen/offering/error.js +37 -1
- package/dist/document-models/service-offering/v1/gen/option-groups/error.d.ts +55 -1
- package/dist/document-models/service-offering/v1/gen/option-groups/error.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/gen/option-groups/error.js +53 -1
- package/dist/document-models/service-offering/v1/gen/ph-factories.js +3 -3
- package/dist/document-models/service-offering/v1/gen/schema/types.d.ts +134 -61
- package/dist/document-models/service-offering/v1/gen/schema/types.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/gen/schema/zod.d.ts +35 -10
- package/dist/document-models/service-offering/v1/gen/schema/zod.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/gen/schema/zod.js +182 -64
- package/dist/document-models/service-offering/v1/gen/services/error.d.ts +20 -1
- package/dist/document-models/service-offering/v1/gen/services/error.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/gen/services/error.js +16 -1
- package/dist/document-models/service-offering/v1/gen/tiers/error.d.ts +100 -1
- package/dist/document-models/service-offering/v1/gen/tiers/error.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/gen/tiers/error.js +106 -1
- package/dist/document-models/service-offering/v1/gen/utils.js +4 -4
- package/dist/document-models/service-offering/v1/module.d.ts +1 -1
- package/dist/document-models/service-offering/v1/module.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/module.js +4 -1
- package/dist/document-models/service-offering/v1/src/reducers/offering.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/src/reducers/offering.js +20 -12
- package/dist/document-models/service-offering/v1/src/reducers/option-groups.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/src/reducers/option-groups.js +157 -39
- package/dist/document-models/service-offering/v1/src/reducers/services.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/src/reducers/services.js +17 -14
- package/dist/document-models/service-offering/v1/src/reducers/tiers.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/src/reducers/tiers.js +111 -78
- package/dist/document-models/service-offering/v1/src/utils.d.ts +60 -1
- package/dist/document-models/service-offering/v1/src/utils.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/src/utils.js +173 -1
- package/dist/document-models/service-offering/v1/tests/option-groups.test.js +1 -1
- package/dist/document-models/service-offering/v1/utils.d.ts +3 -0
- package/dist/document-models/service-offering/v1/utils.d.ts.map +1 -1
- package/dist/document-models/subscription-instance/v1/actions.d.ts +3 -1
- package/dist/document-models/subscription-instance/v1/actions.d.ts.map +1 -1
- package/dist/document-models/subscription-instance/v1/gen/controller.d.ts +4 -0
- package/dist/document-models/subscription-instance/v1/gen/controller.d.ts.map +1 -0
- package/dist/document-models/subscription-instance/v1/gen/controller.js +3 -0
- package/dist/document-models/subscription-instance/v1/gen/document-model.d.ts.map +1 -1
- package/dist/document-models/subscription-instance/v1/gen/document-model.js +488 -246
- package/dist/document-models/subscription-instance/v1/gen/document-schema.d.ts +3 -3
- package/dist/document-models/subscription-instance/v1/gen/index.d.ts +1 -0
- package/dist/document-models/subscription-instance/v1/gen/index.d.ts.map +1 -1
- package/dist/document-models/subscription-instance/v1/gen/index.js +1 -0
- package/dist/document-models/subscription-instance/v1/gen/metrics/error.d.ts +73 -1
- package/dist/document-models/subscription-instance/v1/gen/metrics/error.d.ts.map +1 -1
- package/dist/document-models/subscription-instance/v1/gen/metrics/error.js +86 -1
- package/dist/document-models/subscription-instance/v1/gen/ph-factories.js +1 -1
- package/dist/document-models/subscription-instance/v1/gen/schema/types.d.ts +199 -82
- package/dist/document-models/subscription-instance/v1/gen/schema/types.d.ts.map +1 -1
- package/dist/document-models/subscription-instance/v1/gen/schema/zod.d.ts +22 -12
- package/dist/document-models/subscription-instance/v1/gen/schema/zod.d.ts.map +1 -1
- package/dist/document-models/subscription-instance/v1/gen/schema/zod.js +230 -84
- package/dist/document-models/subscription-instance/v1/gen/service/error.d.ts +62 -1
- package/dist/document-models/subscription-instance/v1/gen/service/error.d.ts.map +1 -1
- package/dist/document-models/subscription-instance/v1/gen/service/error.js +60 -1
- package/dist/document-models/subscription-instance/v1/gen/service-group/error.d.ts +39 -1
- package/dist/document-models/subscription-instance/v1/gen/service-group/error.d.ts.map +1 -1
- package/dist/document-models/subscription-instance/v1/gen/service-group/error.js +39 -1
- package/dist/document-models/subscription-instance/v1/gen/subscription/error.d.ts +55 -1
- package/dist/document-models/subscription-instance/v1/gen/subscription/error.d.ts.map +1 -1
- package/dist/document-models/subscription-instance/v1/gen/subscription/error.js +51 -1
- package/dist/document-models/subscription-instance/v1/gen/utils.js +2 -2
- package/dist/document-models/subscription-instance/v1/module.d.ts +1 -1
- package/dist/document-models/subscription-instance/v1/module.d.ts.map +1 -1
- package/dist/document-models/subscription-instance/v1/module.js +4 -1
- package/dist/document-models/subscription-instance/v1/src/reducers/customer.d.ts.map +1 -1
- package/dist/document-models/subscription-instance/v1/src/reducers/customer.js +1 -0
- package/dist/document-models/subscription-instance/v1/src/reducers/metrics.d.ts.map +1 -1
- package/dist/document-models/subscription-instance/v1/src/reducers/metrics.js +70 -45
- package/dist/document-models/subscription-instance/v1/src/reducers/service-group.d.ts.map +1 -1
- package/dist/document-models/subscription-instance/v1/src/reducers/service-group.js +108 -30
- package/dist/document-models/subscription-instance/v1/src/reducers/service.d.ts.map +1 -1
- package/dist/document-models/subscription-instance/v1/src/reducers/service.js +108 -39
- package/dist/document-models/subscription-instance/v1/src/reducers/subscription.d.ts.map +1 -1
- package/dist/document-models/subscription-instance/v1/src/reducers/subscription.js +193 -35
- package/dist/editors/resource-instance-editor/editor.d.ts.map +1 -1
- package/dist/editors/resource-instance-editor/editor.js +13 -3
- package/dist/editors/service-offering-editor/components/ResourceTemplateSelector.d.ts.map +1 -1
- package/dist/editors/service-offering-editor/components/ResourceTemplateSelector.js +4 -2
- package/dist/editors/service-offering-editor/components/ServiceCatalog.d.ts.map +1 -1
- package/dist/editors/service-offering-editor/components/ServiceCatalog.js +189 -32
- package/dist/editors/service-offering-editor/components/TheMatrix.d.ts +1 -1
- package/dist/editors/service-offering-editor/components/TheMatrix.d.ts.map +1 -1
- package/dist/editors/service-offering-editor/components/TheMatrix.js +295 -140
- package/dist/editors/service-offering-editor/components/TierDefinition.d.ts.map +1 -1
- package/dist/editors/service-offering-editor/components/TierDefinition.js +2 -0
- package/dist/editors/service-offering-editor/components/TierPricingOptionsPanel.js +3 -3
- package/dist/editors/service-offering-editor/components/pricing-utils.d.ts.map +1 -1
- package/dist/editors/service-offering-editor/components/pricing-utils.js +26 -7
- package/dist/editors/subscription-instance-editor/components/BillingPanel.d.ts.map +1 -1
- package/dist/editors/subscription-instance-editor/components/BillingPanel.js +4 -4
- package/dist/editors/subscription-instance-editor/components/CustomerInfo.d.ts.map +1 -1
- package/dist/editors/subscription-instance-editor/components/CustomerInfo.js +3 -2
- package/dist/editors/subscription-instance-editor/components/ImportServiceConfigButton.d.ts +3 -0
- package/dist/editors/subscription-instance-editor/components/ImportServiceConfigButton.d.ts.map +1 -1
- package/dist/editors/subscription-instance-editor/components/ImportServiceConfigButton.js +12 -0
- package/dist/editors/subscription-instance-editor/components/MetricActions.d.ts.map +1 -1
- package/dist/editors/subscription-instance-editor/components/MetricActions.js +4 -2
- package/dist/editors/subscription-instance-editor/components/MockDataButton.d.ts.map +1 -1
- package/dist/editors/subscription-instance-editor/components/MockDataButton.js +214 -2
- package/dist/editors/subscription-instance-editor/components/OperatorNotes.js +1 -1
- package/dist/editors/subscription-instance-editor/components/ServicesPanel.d.ts.map +1 -1
- package/dist/editors/subscription-instance-editor/components/ServicesPanel.js +9 -20
- package/dist/editors/subscription-instance-editor/components/SubscriptionActions.d.ts.map +1 -1
- package/dist/editors/subscription-instance-editor/components/SubscriptionActions.js +8 -9
- package/dist/editors/subscription-instance-editor/components/SubscriptionHeader.d.ts.map +1 -1
- package/dist/editors/subscription-instance-editor/components/SubscriptionHeader.js +1 -1
- package/dist/editors/subscription-instance-editor/components/billing-utils.d.ts +14 -6
- package/dist/editors/subscription-instance-editor/components/billing-utils.d.ts.map +1 -1
- package/dist/editors/subscription-instance-editor/components/billing-utils.js +19 -23
- package/dist/editors/subscription-instance-editor/components/mapOfferingToSubscription.d.ts +16 -2
- package/dist/editors/subscription-instance-editor/components/mapOfferingToSubscription.d.ts.map +1 -1
- package/dist/editors/subscription-instance-editor/components/mapOfferingToSubscription.js +155 -6
- package/dist/powerhouse.manifest.json +29 -3
- package/dist/style.css +14 -0
- package/dist/subgraphs/resources-services/resolvers.d.ts +1 -1
- package/dist/subgraphs/resources-services/resolvers.d.ts.map +1 -1
- package/dist/subgraphs/resources-services/resolvers.js +272 -158
- package/dist/subgraphs/resources-services/schema.d.ts.map +1 -1
- package/dist/subgraphs/resources-services/schema.js +107 -41
- package/package.json +22 -18
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { MetricActions } from "./MetricActions.js";
|
|
3
|
-
import { formatCurrency as fmtCurrency } from "./billing-utils.js";
|
|
4
|
-
function UsageBar({ serviceId, metric, dispatch, isOperator, customerName,
|
|
3
|
+
import { formatCurrency as fmtCurrency, formatBillingCycleSuffix, formatDiscountBadge, } from "./billing-utils.js";
|
|
4
|
+
function UsageBar({ serviceId, metric, dispatch, isOperator, customerName, }) {
|
|
5
5
|
const freeLimit = metric.freeLimit ?? metric.limit ?? 0;
|
|
6
6
|
const paidLimit = metric.paidLimit ?? null;
|
|
7
7
|
const displayLimit = paidLimit ?? freeLimit;
|
|
@@ -17,35 +17,24 @@ function UsageBar({ serviceId, metric, dispatch, isOperator, customerName, curre
|
|
|
17
17
|
return "si-usage-bar__fill--normal";
|
|
18
18
|
};
|
|
19
19
|
const isOverFree = metric.currentUsage > freeLimit && freeLimit > 0;
|
|
20
|
-
return (_jsxs("div", { className: "si-metric", children: [_jsxs("div", { className: "si-metric__header", children: [_jsx("span", { className: "si-metric__name", children: metric.name }), _jsxs("span", { className: "si-metric__value", children: [metric.currentUsage.toLocaleString(), displayLimit > 0 && ` / ${displayLimit.toLocaleString()}`, _jsxs("span", { className: "si-metric__unit", children: [" ", metric.unitName] })] })] }), _jsxs("div", { className: "si-metric__body", children: [displayLimit > 0 && (_jsxs("div", { className: "si-usage-bar", children: [paidLimit != null && freeLimit > 0 && freeLimit < paidLimit && (_jsx("div", { className: "si-usage-bar__free-marker", style: { left: `${freePortion}%` }, title: `${freeLimit.toLocaleString()} free` })), _jsx("div", { className: `si-usage-bar__fill ${getBarColor()}`, style: { width: `${percentage}%` }, role: "progressbar", "aria-valuenow": metric.currentUsage, "aria-valuemin": 0, "aria-valuemax": displayLimit })] })), _jsx(MetricActions, { serviceId: serviceId, metric: metric, dispatch: dispatch, isOperator: isOperator, customerName: customerName })] }), paidLimit != null && freeLimit > 0 && freeLimit !== paidLimit && (_jsxs("p", { className: "si-metric__paid-limit", children: [freeLimit.toLocaleString(), " free \u00B7 ", paidLimit.toLocaleString(), " max", metric.unitCost
|
|
20
|
+
return (_jsxs("div", { className: "si-metric", children: [_jsxs("div", { className: "si-metric__header", children: [_jsx("span", { className: "si-metric__name", children: metric.name }), _jsxs("span", { className: "si-metric__value", children: [metric.currentUsage.toLocaleString(), displayLimit > 0 && ` / ${displayLimit.toLocaleString()}`, _jsxs("span", { className: "si-metric__unit", children: [" ", metric.unitName] })] })] }), _jsxs("div", { className: "si-metric__body", children: [displayLimit > 0 && (_jsxs("div", { className: "si-usage-bar", children: [paidLimit != null && freeLimit > 0 && freeLimit < paidLimit && (_jsx("div", { className: "si-usage-bar__free-marker", style: { left: `${freePortion}%` }, title: `${freeLimit.toLocaleString()} free` })), _jsx("div", { className: `si-usage-bar__fill ${getBarColor()}`, style: { width: `${percentage}%` }, role: "progressbar", "aria-valuenow": metric.currentUsage, "aria-valuemin": 0, "aria-valuemax": displayLimit })] })), _jsx(MetricActions, { serviceId: serviceId, metric: metric, dispatch: dispatch, isOperator: isOperator, customerName: customerName })] }), paidLimit != null && freeLimit > 0 && freeLimit !== paidLimit && (_jsxs("p", { className: "si-metric__paid-limit", children: [freeLimit.toLocaleString(), " free \u00B7 ", paidLimit.toLocaleString(), " max", metric.unitCost && (_jsxs("span", { children: [" · ", "overage:", " ", fmtCurrency(metric.unitCost.amount, metric.unitCost.currency), "/", metric.unitName] }))] })), isOverFree && metric.unitCost && (_jsxs("div", { className: "si-metric__overage", children: [_jsx("strong", { children: (metric.currentUsage - freeLimit).toLocaleString() }), " ", metric.unitName, " over free limit"] })), (metric.nextUsageReset || metric.usageResetPeriod) && (_jsxs("p", { className: "si-metric__reset", children: [metric.usageResetPeriod && (_jsxs("span", { className: "si-metric__reset-period", children: [metric.usageResetPeriod.charAt(0) +
|
|
21
21
|
metric.usageResetPeriod.slice(1).toLowerCase(), " ", "reset"] })), metric.nextUsageReset && (_jsxs("span", { children: [metric.usageResetPeriod ? " · " : "Resets ", new Date(metric.nextUsageReset).toLocaleDateString()] }))] }))] }));
|
|
22
22
|
}
|
|
23
|
-
function ServiceCard({ service, mode, dispatch, customerName,
|
|
24
|
-
return (_jsxs("div", { className: "si-service-card", children: [_jsxs("div", { className: "si-service-card__header", children: [_jsx("h4", { className: "si-service-card__name", children: service.name || "Service" }), service.customValue && (_jsx("span", { className: "si-service-card__custom-value", children: service.customValue }))] }), service.description && (_jsx("p", { className: "si-service-card__desc", children: service.description })), service.metrics.length > 0 && (_jsx("div", { className: "si-service-card__metrics", children: service.metrics.map((metric) => (_jsx(UsageBar, { serviceId: service.id, metric: metric, dispatch: dispatch, isOperator: mode === "operator", customerName: customerName
|
|
23
|
+
function ServiceCard({ service, mode, dispatch, customerName, }) {
|
|
24
|
+
return (_jsxs("div", { className: "si-service-card", children: [_jsxs("div", { className: "si-service-card__header", children: [_jsx("h4", { className: "si-service-card__name", children: service.name || "Service" }), service.customValue && (_jsx("span", { className: "si-service-card__custom-value", children: service.customValue }))] }), service.description && (_jsx("p", { className: "si-service-card__desc", children: service.description })), service.metrics.length > 0 && (_jsx("div", { className: "si-service-card__metrics", children: service.metrics.map((metric) => (_jsx(UsageBar, { serviceId: service.id, metric: metric, dispatch: dispatch, isOperator: mode === "operator", customerName: customerName }, metric.id))) }))] }));
|
|
25
25
|
}
|
|
26
26
|
export function ServicesPanel({ document, dispatch, mode, }) {
|
|
27
27
|
const state = document.state.global;
|
|
28
|
-
|
|
29
|
-
const allGroupedServiceIds = new Set(state.serviceGroups.flatMap((g) => g.services));
|
|
30
|
-
const standaloneServices = state.services.filter((s) => !allGroupedServiceIds.has(s.id));
|
|
28
|
+
// Split groups into recurring (non-optional) and add-ons (optional)
|
|
31
29
|
const recurringGroups = state.serviceGroups.filter((g) => !g.optional);
|
|
32
30
|
const addonGroups = state.serviceGroups.filter((g) => g.optional);
|
|
33
|
-
const hasRecurring =
|
|
31
|
+
const hasRecurring = state.services.length > 0 || recurringGroups.length > 0;
|
|
34
32
|
const hasAddons = addonGroups.length > 0;
|
|
35
|
-
const recurringServiceCount =
|
|
33
|
+
const recurringServiceCount = state.services.length +
|
|
36
34
|
recurringGroups.reduce((acc, g) => acc + g.services.length, 0);
|
|
37
35
|
const addonServiceCount = addonGroups.reduce((acc, g) => acc + g.services.length, 0);
|
|
38
36
|
if (!hasRecurring && !hasAddons) {
|
|
39
37
|
return (_jsxs("div", { className: "si-panel", children: [_jsx("div", { className: "si-panel__header", children: _jsx("h3", { className: "si-panel__title", children: "Services" }) }), _jsxs("div", { className: "si-empty", children: [_jsx("svg", { className: "si-empty__icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.5, children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4" }) }), _jsx("p", { className: "si-empty__text", children: "No services configured" })] })] }));
|
|
40
38
|
}
|
|
41
|
-
|
|
42
|
-
.map((id) => state.services.find((s) => s.id === id))
|
|
43
|
-
.filter((s) => s != null);
|
|
44
|
-
return (_jsxs(_Fragment, { children: [hasRecurring && (_jsxs("div", { className: "si-panel", children: [_jsxs("div", { className: "si-panel__header", children: [_jsx("h3", { className: "si-panel__title", children: "Recurring Services" }), _jsxs("span", { className: "si-panel__count", children: [recurringServiceCount, " services"] })] }), standaloneServices.length > 0 && (_jsx("div", { className: "si-services-grid", children: standaloneServices.map((service) => (_jsx(ServiceCard, { service: service, mode: mode, dispatch: dispatch, customerName: state.customerName, currency: currency }, service.id))) })), recurringGroups.map((group) => {
|
|
45
|
-
const groupServices = resolveGroupServices(group.services);
|
|
46
|
-
return (_jsxs("div", { className: "si-service-group", children: [_jsxs("div", { className: "si-service-group__header", children: [_jsx("h4", { className: "si-service-group__name", children: group.name }), group.recurringCost && (_jsx("span", { className: "si-service-group__price", children: fmtCurrency(group.recurringCost.amount, group.recurringCost.currency) }))] }), _jsx("div", { className: "si-services-grid", children: groupServices.map((service) => (_jsx(ServiceCard, { service: service, mode: mode, dispatch: dispatch, customerName: state.customerName, currency: currency }, service.id))) })] }, group.id));
|
|
47
|
-
})] })), hasAddons && (_jsxs("div", { className: "si-panel", children: [_jsxs("div", { className: "si-panel__header", children: [_jsx("h3", { className: "si-panel__title", children: "Add-ons" }), _jsxs("span", { className: "si-panel__count", children: [addonGroups.length, " groups, ", addonServiceCount, " services"] })] }), addonGroups.map((group) => {
|
|
48
|
-
const groupServices = resolveGroupServices(group.services);
|
|
49
|
-
return (_jsxs("div", { className: "si-service-group", children: [_jsxs("div", { className: "si-service-group__header", children: [_jsx("h4", { className: "si-service-group__name", children: group.name }), _jsx("span", { className: "si-badge si-badge--violet si-badge--sm", children: "Optional" }), group.recurringCost && (_jsx("span", { className: "si-service-group__price", children: fmtCurrency(group.recurringCost.amount, group.recurringCost.currency) }))] }), _jsx("div", { className: "si-services-grid", children: groupServices.map((service) => (_jsx(ServiceCard, { service: service, mode: mode, dispatch: dispatch, customerName: state.customerName, currency: currency }, service.id))) })] }, group.id));
|
|
50
|
-
})] }))] }));
|
|
39
|
+
return (_jsxs(_Fragment, { children: [hasRecurring && (_jsxs("div", { className: "si-panel", children: [_jsxs("div", { className: "si-panel__header", children: [_jsx("h3", { className: "si-panel__title", children: "Recurring Services" }), _jsxs("span", { className: "si-panel__count", children: [recurringServiceCount, " services"] })] }), state.services.length > 0 && (_jsx("div", { className: "si-services-grid", children: state.services.map((service) => (_jsx(ServiceCard, { service: service, mode: mode, dispatch: dispatch, customerName: state.customerName }, service.id))) })), recurringGroups.map((group) => (_jsxs("div", { className: "si-service-group", children: [_jsxs("div", { className: "si-service-group__header", children: [_jsx("h4", { className: "si-service-group__name", children: group.name }), group.recurringCost && (_jsxs("span", { className: "si-service-group__price", children: [group.recurringCost.discount && (_jsxs(_Fragment, { children: [_jsx("span", { className: "si-service-group__original-price", children: fmtCurrency(group.recurringCost.discount.originalAmount, group.recurringCost.currency) }), _jsx("span", { className: "si-service-group__discount-badge", children: formatDiscountBadge(group.recurringCost.discount) })] })), fmtCurrency(group.recurringCost.amount, group.recurringCost.currency), formatBillingCycleSuffix(group.recurringCost.billingCycle)] }))] }), _jsx("div", { className: "si-services-grid", children: group.services.map((service) => (_jsx(ServiceCard, { service: service, mode: mode, dispatch: dispatch, customerName: state.customerName }, service.id))) })] }, group.id)))] })), hasAddons && (_jsxs("div", { className: "si-panel", children: [_jsxs("div", { className: "si-panel__header", children: [_jsx("h3", { className: "si-panel__title", children: "Add-ons" }), _jsxs("span", { className: "si-panel__count", children: [addonGroups.length, " groups, ", addonServiceCount, " services"] })] }), addonGroups.map((group) => (_jsxs("div", { className: "si-service-group", children: [_jsxs("div", { className: "si-service-group__header", children: [_jsx("h4", { className: "si-service-group__name", children: group.name }), _jsx("span", { className: "si-badge si-badge--violet si-badge--sm", children: "Optional" }), group.recurringCost && (_jsxs("span", { className: "si-service-group__price", children: [group.recurringCost.discount && (_jsxs(_Fragment, { children: [_jsx("span", { className: "si-service-group__original-price", children: fmtCurrency(group.recurringCost.discount.originalAmount, group.recurringCost.currency) }), _jsx("span", { className: "si-service-group__discount-badge", children: formatDiscountBadge(group.recurringCost.discount) })] })), fmtCurrency(group.recurringCost.amount, group.recurringCost.currency), formatBillingCycleSuffix(group.recurringCost.billingCycle)] }))] }), _jsx("div", { className: "si-services-grid", children: group.services.map((service) => (_jsx(ServiceCard, { service: service, mode: mode, dispatch: dispatch, customerName: state.customerName }, service.id))) })] }, group.id)))] }))] }));
|
|
51
40
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubscriptionActions.d.ts","sourceRoot":"","sources":["../../../../editors/subscription-instance-editor/components/SubscriptionActions.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SubscriptionActions.d.ts","sourceRoot":"","sources":["../../../../editors/subscription-instance-editor/components/SubscriptionActions.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EACV,0BAA0B,EAC1B,4BAA4B,EAC7B,MAAM,uEAAuE,CAAC;AAC/E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAS5C,UAAU,wBAAwB;IAChC,QAAQ,EAAE,4BAA4B,CAAC;IACvC,QAAQ,EAAE,gBAAgB,CAAC,0BAA0B,CAAC,CAAC;IACvD,IAAI,EAAE,QAAQ,CAAC;CAChB;AAsED,wBAAgB,mBAAmB,CAAC,EAClC,QAAQ,EACR,QAAQ,EACR,IAAI,GACL,EAAE,wBAAwB,2CA2P1B"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useCallback } from "react";
|
|
3
|
-
import { generateId } from "document-model/core";
|
|
4
3
|
import { activateSubscription, pauseSubscription, resumeSubscription, cancelSubscription, renewExpiringSubscription, } from "../../../document-models/subscription-instance/v1/gen/subscription/creators.js";
|
|
5
4
|
function ConfirmModal({ isOpen, title, message, confirmLabel, confirmVariant = "primary", onConfirm, onCancel, showReasonInput, reason, onReasonChange, }) {
|
|
6
5
|
if (!isOpen)
|
|
@@ -19,32 +18,32 @@ export function SubscriptionActions({ document, dispatch, mode, }) {
|
|
|
19
18
|
// Operator direct actions
|
|
20
19
|
const handleActivate = useCallback(() => {
|
|
21
20
|
dispatch(activateSubscription({
|
|
22
|
-
|
|
21
|
+
activatedSince: new Date().toISOString(),
|
|
23
22
|
}));
|
|
24
23
|
}, [dispatch]);
|
|
25
24
|
const handleOperatorPause = useCallback(() => {
|
|
26
25
|
dispatch(pauseSubscription({
|
|
27
|
-
|
|
26
|
+
pausedSince: new Date().toISOString(),
|
|
28
27
|
}));
|
|
29
28
|
setConfirmAction(null);
|
|
30
29
|
}, [dispatch]);
|
|
31
30
|
const handleOperatorResume = useCallback(() => {
|
|
32
31
|
dispatch(resumeSubscription({
|
|
33
|
-
|
|
32
|
+
timestamp: new Date().toISOString(),
|
|
34
33
|
}));
|
|
35
34
|
setConfirmAction(null);
|
|
36
35
|
}, [dispatch]);
|
|
37
36
|
const handleOperatorCancel = useCallback(() => {
|
|
38
37
|
dispatch(cancelSubscription({
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
cancelledSince: new Date().toISOString(),
|
|
39
|
+
cancellationReason: reason || null,
|
|
41
40
|
}));
|
|
42
41
|
setConfirmAction(null);
|
|
43
42
|
setReason("");
|
|
44
43
|
}, [dispatch, reason]);
|
|
45
44
|
const handleOperatorRenew = useCallback(() => {
|
|
46
45
|
dispatch(renewExpiringSubscription({
|
|
47
|
-
|
|
46
|
+
timestamp: new Date().toISOString(),
|
|
48
47
|
}));
|
|
49
48
|
setConfirmAction(null);
|
|
50
49
|
}, [dispatch]);
|
|
@@ -70,12 +69,12 @@ export function SubscriptionActions({ document, dispatch, mode, }) {
|
|
|
70
69
|
handleOperatorCancel,
|
|
71
70
|
handleOperatorRenew,
|
|
72
71
|
]);
|
|
73
|
-
const
|
|
72
|
+
const isPending = state.status === "PENDING";
|
|
74
73
|
const isActive = state.status === "ACTIVE";
|
|
75
74
|
const isPaused = state.status === "PAUSED";
|
|
76
75
|
const isExpiring = state.status === "EXPIRING";
|
|
77
76
|
const isCancelled = state.status === "CANCELLED";
|
|
78
|
-
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "si-actions", children: mode === "operator" && (_jsxs("div", { className: "si-actions__buttons", children: [
|
|
77
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "si-actions", children: mode === "operator" && (_jsxs("div", { className: "si-actions__buttons", children: [isPending && (_jsxs("button", { type: "button", className: "si-btn si-btn--sm si-btn--success", onClick: handleActivate, children: [_jsx("svg", { className: "si-btn__icon", viewBox: "0 0 20 20", fill: "currentColor", children: _jsx("path", { fillRule: "evenodd", d: "M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z", clipRule: "evenodd" }) }), "Activate"] })), isActive && (_jsxs("button", { type: "button", className: "si-btn si-btn--sm si-btn--warning", onClick: () => setConfirmAction("pause"), children: [_jsx("svg", { className: "si-btn__icon", viewBox: "0 0 20 20", fill: "currentColor", children: _jsx("path", { fillRule: "evenodd", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z", clipRule: "evenodd" }) }), "Pause"] })), isPaused && (_jsxs("button", { type: "button", className: "si-btn si-btn--sm si-btn--success", onClick: () => setConfirmAction("resume"), children: [_jsx("svg", { className: "si-btn__icon", viewBox: "0 0 20 20", fill: "currentColor", children: _jsx("path", { fillRule: "evenodd", d: "M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z", clipRule: "evenodd" }) }), "Resume"] })), isExpiring && (_jsxs("button", { type: "button", className: "si-btn si-btn--sm si-btn--primary", onClick: () => setConfirmAction("renew"), children: [_jsx("svg", { className: "si-btn__icon", viewBox: "0 0 20 20", fill: "currentColor", children: _jsx("path", { fillRule: "evenodd", d: "M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z", clipRule: "evenodd" }) }), "Renew"] })), !isCancelled && (_jsxs("button", { type: "button", className: "si-btn si-btn--sm si-btn--danger-ghost", onClick: () => setConfirmAction("cancel"), children: [_jsx("svg", { className: "si-btn__icon", viewBox: "0 0 20 20", fill: "currentColor", children: _jsx("path", { fillRule: "evenodd", d: "M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z", clipRule: "evenodd" }) }), "Cancel"] }))] })) }), _jsx(ConfirmModal, { isOpen: confirmAction === "pause", title: "Pause Subscription", message: "Are you sure you want to pause this subscription? Services will be temporarily suspended.", confirmLabel: "Pause Subscription", confirmVariant: "warning", onConfirm: handleConfirm, onCancel: () => {
|
|
79
78
|
setConfirmAction(null);
|
|
80
79
|
setReason("");
|
|
81
80
|
} }), _jsx(ConfirmModal, { isOpen: confirmAction === "resume", title: "Resume Subscription", message: "Are you sure you want to resume this subscription? Services will be reactivated.", confirmLabel: "Resume Subscription", confirmVariant: "primary", onConfirm: handleConfirm, onCancel: () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubscriptionHeader.d.ts","sourceRoot":"","sources":["../../../../editors/subscription-instance-editor/components/SubscriptionHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EACV,0BAA0B,EAC1B,4BAA4B,EAC7B,MAAM,uEAAuE,CAAC;AAC/E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAiD5C,UAAU,uBAAuB;IAC/B,QAAQ,EAAE,4BAA4B,CAAC;IACvC,QAAQ,EAAE,gBAAgB,CAAC,0BAA0B,CAAC,CAAC;IACvD,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,QAAQ,EACR,IAAI,GACL,EAAE,uBAAuB,
|
|
1
|
+
{"version":3,"file":"SubscriptionHeader.d.ts","sourceRoot":"","sources":["../../../../editors/subscription-instance-editor/components/SubscriptionHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EACV,0BAA0B,EAC1B,4BAA4B,EAC7B,MAAM,uEAAuE,CAAC;AAC/E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAiD5C,UAAU,uBAAuB;IAC/B,QAAQ,EAAE,4BAA4B,CAAC;IACvC,QAAQ,EAAE,gBAAgB,CAAC,0BAA0B,CAAC,CAAC;IACvD,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,QAAQ,EACR,IAAI,GACL,EAAE,uBAAuB,2CAkJzB"}
|
|
@@ -40,7 +40,7 @@ export function SubscriptionHeader({ document, dispatch, mode, }) {
|
|
|
40
40
|
year: "numeric",
|
|
41
41
|
});
|
|
42
42
|
};
|
|
43
|
-
return (_jsxs("div", { className: "si-header", children: [_jsxs("div", { className: "si-header__main", children: [_jsxs("div", { className: "si-header__title-row", children: [
|
|
43
|
+
return (_jsxs("div", { className: "si-header", children: [_jsxs("div", { className: "si-header__main", children: [_jsxs("div", { className: "si-header__title-row", children: [_jsxs("div", { className: "si-header__info", children: [state.resource?.thumbnailUrl && (_jsx("img", { src: state.resource.thumbnailUrl, alt: "", className: "si-header__thumbnail" })), _jsxs("div", { children: [_jsx("h1", { className: "si-header__title", children: state.resource?.label || state.tierName || "Subscription" }), state.tierName && state.resource?.label && (_jsxs("p", { className: "si-header__subtitle", children: [state.tierName, " Tier"] }))] })] }), _jsx(StatusBadge, { status: state.status })] }), _jsxs("div", { className: "si-header__meta", children: [mode === "operator" && state.customerName && (_jsxs("div", { className: "si-header__meta-item", children: [_jsx("span", { className: "si-header__meta-label", children: "Customer" }), _jsx("span", { className: "si-header__meta-value", children: state.customerName })] })), state.createdAt && (_jsxs("div", { className: "si-header__meta-item", children: [_jsx("span", { className: "si-header__meta-label", children: "Created" }), _jsx("span", { className: "si-header__meta-value", children: formatDate(state.createdAt) })] })), state.activatedSince && (_jsxs("div", { className: "si-header__meta-item", children: [_jsx("span", { className: "si-header__meta-label", children: "Active Since" }), _jsx("span", { className: "si-header__meta-value", children: formatDate(state.activatedSince) })] })), _jsxs("div", { className: "si-header__meta-item", children: [_jsx("span", { className: "si-header__meta-label", children: "Auto-Renew" }), _jsx("span", { className: "si-header__meta-value", style: {
|
|
44
44
|
color: state.autoRenew
|
|
45
45
|
? "var(--si-emerald-600)"
|
|
46
46
|
: "var(--si-slate-400)",
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import type { SubscriptionInstanceState, ServiceMetric } from "../../../document-models/subscription-instance/v1/gen/schema/types.js";
|
|
1
|
+
import type { SubscriptionInstanceState, ServiceMetric, DiscountInfo } from "../../../document-models/subscription-instance/v1/gen/schema/types.js";
|
|
2
2
|
export declare function formatCurrency(amount: number, currency: string): string;
|
|
3
3
|
export declare function formatDate(date: string | null | undefined): string;
|
|
4
4
|
export declare function formatBillingCycleSuffix(cycle: string | null | undefined): string;
|
|
5
5
|
export declare const BILLING_CYCLE_LABELS: Record<string, string>;
|
|
6
|
-
export declare function formatDiscountBadge(discount:
|
|
7
|
-
discountType: string;
|
|
8
|
-
discountValue: number;
|
|
9
|
-
}): string;
|
|
6
|
+
export declare function formatDiscountBadge(discount: DiscountInfo): string;
|
|
10
7
|
export declare function getDiscountSourceLabel(source: string): string;
|
|
11
8
|
export interface MetricOverage {
|
|
12
9
|
metricId: string;
|
|
@@ -20,13 +17,17 @@ export interface MetricOverage {
|
|
|
20
17
|
unitCostCurrency: string;
|
|
21
18
|
projectedCost: number;
|
|
22
19
|
}
|
|
23
|
-
export declare function computeMetricOverage(metric: ServiceMetric
|
|
20
|
+
export declare function computeMetricOverage(metric: ServiceMetric): MetricOverage | null;
|
|
24
21
|
export interface GroupBillingBreakdown {
|
|
25
22
|
groupId: string;
|
|
26
23
|
groupName: string;
|
|
27
24
|
optional: boolean;
|
|
25
|
+
/** Group-level recurring cost (fixed cost) */
|
|
28
26
|
recurringAmount: number | null;
|
|
29
27
|
recurringCurrency: string;
|
|
28
|
+
recurringCycle: string | null;
|
|
29
|
+
discount: DiscountInfo | null;
|
|
30
|
+
/** Dynamic costs from service metrics */
|
|
30
31
|
metricOverages: MetricOverage[];
|
|
31
32
|
dynamicTotal: number;
|
|
32
33
|
}
|
|
@@ -39,12 +40,19 @@ export interface SetupCostLine {
|
|
|
39
40
|
}
|
|
40
41
|
export interface BillingBreakdown {
|
|
41
42
|
currency: string;
|
|
43
|
+
/** Sum of group recurring costs */
|
|
42
44
|
fixedTotal: number;
|
|
45
|
+
/** Sum of metric overage projections */
|
|
43
46
|
dynamicTotal: number;
|
|
47
|
+
/** fixedTotal + dynamicTotal */
|
|
44
48
|
projectedTotal: number;
|
|
49
|
+
/** Standalone service recurring costs (not in groups) */
|
|
45
50
|
standaloneFixedTotal: number;
|
|
51
|
+
/** Breakdown per service group */
|
|
46
52
|
groupBreakdowns: GroupBillingBreakdown[];
|
|
53
|
+
/** Standalone services with metrics */
|
|
47
54
|
standaloneOverages: MetricOverage[];
|
|
55
|
+
/** All setup costs */
|
|
48
56
|
setupLines: SetupCostLine[];
|
|
49
57
|
setupTotal: number;
|
|
50
58
|
billingCycle: string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"billing-utils.d.ts","sourceRoot":"","sources":["../../../../editors/subscription-instance-editor/components/billing-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EACzB,aAAa,
|
|
1
|
+
{"version":3,"file":"billing-utils.d.ts","sourceRoot":"","sources":["../../../../editors/subscription-instance-editor/components/billing-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EACzB,aAAa,EACb,YAAY,EACb,MAAM,uEAAuE,CAAC;AAI/E,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKvE;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAOlE;AAUD,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC/B,MAAM,CAGR;AAED,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMvD,CAAC;AAIF,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAKlE;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAW7D;AAID,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,aAAa,GACpB,aAAa,GAAG,IAAI,CAuBtB;AAID,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,8CAA8C;IAC9C,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAC;IAC9B,yCAAyC;IACzC,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,mCAAmC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,YAAY,EAAE,MAAM,CAAC;IACrB,gCAAgC;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,yDAAyD;IACzD,oBAAoB,EAAE,MAAM,CAAC;IAC7B,kCAAkC;IAClC,eAAe,EAAE,qBAAqB,EAAE,CAAC;IACzC,uCAAuC;IACvC,kBAAkB,EAAE,aAAa,EAAE,CAAC;IACpC,sBAAsB;IACtB,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,yBAAyB,GAC/B,gBAAgB,CAuGlB"}
|
|
@@ -52,48 +52,41 @@ export function getDiscountSourceLabel(source) {
|
|
|
52
52
|
return "Discount";
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
|
-
export function computeMetricOverage(metric
|
|
55
|
+
export function computeMetricOverage(metric) {
|
|
56
56
|
const freeLimit = metric.freeLimit ?? metric.limit ?? 0;
|
|
57
57
|
const paidLimit = metric.paidLimit ?? null;
|
|
58
58
|
if (freeLimit <= 0 && paidLimit == null)
|
|
59
59
|
return null;
|
|
60
60
|
if (metric.currentUsage <= freeLimit)
|
|
61
61
|
return null;
|
|
62
|
-
if (metric.unitCost
|
|
62
|
+
if (!metric.unitCost)
|
|
63
63
|
return null;
|
|
64
64
|
const excess = metric.currentUsage - freeLimit;
|
|
65
|
-
const projectedCost = excess * metric.unitCost;
|
|
65
|
+
const projectedCost = excess * metric.unitCost.amount;
|
|
66
66
|
return {
|
|
67
67
|
metricId: metric.id,
|
|
68
68
|
metricName: metric.name,
|
|
69
|
-
unitName: metric.unitName
|
|
69
|
+
unitName: metric.unitName,
|
|
70
70
|
currentUsage: metric.currentUsage,
|
|
71
71
|
freeLimit,
|
|
72
72
|
paidLimit,
|
|
73
73
|
excess,
|
|
74
|
-
unitCostAmount: metric.unitCost,
|
|
75
|
-
unitCostCurrency: currency,
|
|
74
|
+
unitCostAmount: metric.unitCost.amount,
|
|
75
|
+
unitCostCurrency: metric.unitCost.currency,
|
|
76
76
|
projectedCost,
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
79
|
export function computeBillingBreakdown(state) {
|
|
80
80
|
const currency = state.globalCurrency || state.tierCurrency || "USD";
|
|
81
81
|
const billingCycle = state.selectedBillingCycle || null;
|
|
82
|
+
// Group breakdowns
|
|
82
83
|
const groupBreakdowns = [];
|
|
83
84
|
const setupLines = [];
|
|
84
|
-
const allGroupedServiceIds = new Set();
|
|
85
|
-
for (const group of state.serviceGroups) {
|
|
86
|
-
for (const svcId of group.services) {
|
|
87
|
-
allGroupedServiceIds.add(svcId);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
85
|
for (const group of state.serviceGroups) {
|
|
91
86
|
const metricOverages = [];
|
|
92
|
-
const
|
|
93
|
-
const groupServices = state.services.filter((svc) => groupServiceIds.has(svc.id));
|
|
94
|
-
for (const svc of groupServices) {
|
|
87
|
+
for (const svc of group.services) {
|
|
95
88
|
for (const metric of svc.metrics) {
|
|
96
|
-
const overage = computeMetricOverage(metric
|
|
89
|
+
const overage = computeMetricOverage(metric);
|
|
97
90
|
if (overage)
|
|
98
91
|
metricOverages.push(overage);
|
|
99
92
|
}
|
|
@@ -105,40 +98,43 @@ export function computeBillingBreakdown(state) {
|
|
|
105
98
|
optional: group.optional,
|
|
106
99
|
recurringAmount: group.recurringCost?.amount ?? null,
|
|
107
100
|
recurringCurrency: group.recurringCost?.currency ?? currency,
|
|
101
|
+
recurringCycle: group.recurringCost?.billingCycle ?? billingCycle,
|
|
102
|
+
discount: group.recurringCost?.discount ?? null,
|
|
108
103
|
metricOverages,
|
|
109
104
|
dynamicTotal,
|
|
110
105
|
});
|
|
106
|
+
// Collect setup costs from group level
|
|
111
107
|
if (group.setupCost) {
|
|
112
108
|
setupLines.push({
|
|
113
109
|
name: group.name,
|
|
114
110
|
amount: group.setupCost.amount,
|
|
115
111
|
currency: group.setupCost.currency,
|
|
116
|
-
paid: !!group.setupCost.
|
|
112
|
+
paid: !!group.setupCost.paymentDate,
|
|
117
113
|
source: "group",
|
|
118
114
|
});
|
|
119
115
|
}
|
|
120
|
-
|
|
116
|
+
// Collect setup costs from services in group
|
|
117
|
+
for (const svc of group.services) {
|
|
121
118
|
if (svc.setupCost) {
|
|
122
119
|
setupLines.push({
|
|
123
120
|
name: `${svc.name || "Service"} (${group.name})`,
|
|
124
121
|
amount: svc.setupCost.amount,
|
|
125
122
|
currency: svc.setupCost.currency,
|
|
126
|
-
paid: !!svc.setupCost.
|
|
123
|
+
paid: !!svc.setupCost.paymentDate,
|
|
127
124
|
source: "service",
|
|
128
125
|
});
|
|
129
126
|
}
|
|
130
127
|
}
|
|
131
128
|
}
|
|
129
|
+
// Standalone services (not in groups)
|
|
132
130
|
const standaloneOverages = [];
|
|
133
131
|
let standaloneFixedTotal = 0;
|
|
134
132
|
for (const svc of state.services) {
|
|
135
|
-
if (allGroupedServiceIds.has(svc.id))
|
|
136
|
-
continue;
|
|
137
133
|
if (svc.recurringCost) {
|
|
138
134
|
standaloneFixedTotal += svc.recurringCost.amount;
|
|
139
135
|
}
|
|
140
136
|
for (const metric of svc.metrics) {
|
|
141
|
-
const overage = computeMetricOverage(metric
|
|
137
|
+
const overage = computeMetricOverage(metric);
|
|
142
138
|
if (overage)
|
|
143
139
|
standaloneOverages.push(overage);
|
|
144
140
|
}
|
|
@@ -147,7 +143,7 @@ export function computeBillingBreakdown(state) {
|
|
|
147
143
|
name: svc.name || "Service",
|
|
148
144
|
amount: svc.setupCost.amount,
|
|
149
145
|
currency: svc.setupCost.currency,
|
|
150
|
-
paid: !!svc.setupCost.
|
|
146
|
+
paid: !!svc.setupCost.paymentDate,
|
|
151
147
|
source: "service",
|
|
152
148
|
});
|
|
153
149
|
}
|
|
@@ -1,18 +1,32 @@
|
|
|
1
1
|
import type { ServiceOfferingState } from "../../../document-models/service-offering/v1/gen/schema/types.js";
|
|
2
|
+
import type { PriceBreakdown } from "../../../document-models/service-offering/v1/src/utils.js";
|
|
2
3
|
import type { InitializeSubscriptionInput, BillingCycle as SIBillingCycle } from "../../../document-models/subscription-instance/v1/gen/schema/types.js";
|
|
3
4
|
export interface MapOfferingOptions {
|
|
5
|
+
/** The service offering state to import from */
|
|
4
6
|
offering: ServiceOfferingState;
|
|
7
|
+
/** The selected tier ID */
|
|
5
8
|
tierId: string;
|
|
9
|
+
/** The selected global billing cycle */
|
|
6
10
|
selectedBillingCycle: SIBillingCycle;
|
|
11
|
+
/** Customer info */
|
|
7
12
|
customerId?: string;
|
|
8
13
|
customerName?: string;
|
|
9
14
|
customerEmail?: string;
|
|
15
|
+
/** Timestamp for createdAt */
|
|
10
16
|
createdAt: string;
|
|
17
|
+
/** Computed price breakdown from getUserSelectionPriceBreakdown */
|
|
18
|
+
priceBreakdown: PriceBreakdown;
|
|
11
19
|
}
|
|
12
20
|
/**
|
|
13
21
|
* Maps a Service Offering state to an InitializeSubscriptionInput.
|
|
14
|
-
* This
|
|
15
|
-
*
|
|
22
|
+
* This is a one-time snapshot — the SI lives independently after creation.
|
|
23
|
+
*
|
|
24
|
+
* Logic:
|
|
25
|
+
* 1. Find the selected tier and resolve pricing from priceBreakdown
|
|
26
|
+
* 2. Map option group breakdowns from priceBreakdown as service groups
|
|
27
|
+
* 3. Map add-on breakdowns from priceBreakdown as optional service groups
|
|
28
|
+
* 4. Map remaining standalone services with tier service levels and usage limits
|
|
29
|
+
* 5. Calculate tier price from breakdown or service group sums (CALCULATED) or manual price
|
|
16
30
|
*/
|
|
17
31
|
export declare function mapOfferingToSubscription(options: MapOfferingOptions): InitializeSubscriptionInput;
|
|
18
32
|
//# sourceMappingURL=mapOfferingToSubscription.d.ts.map
|
package/dist/editors/subscription-instance-editor/components/mapOfferingToSubscription.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mapOfferingToSubscription.d.ts","sourceRoot":"","sources":["../../../../editors/subscription-instance-editor/components/mapOfferingToSubscription.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mapOfferingToSubscription.d.ts","sourceRoot":"","sources":["../../../../editors/subscription-instance-editor/components/mapOfferingToSubscription.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,oBAAoB,EAIrB,MAAM,kEAAkE,CAAC;AAC1E,OAAO,KAAK,EACV,cAAc,EAEf,MAAM,2DAA2D,CAAC;AACnE,OAAO,KAAK,EACV,2BAA2B,EAM3B,YAAY,IAAI,cAAc,EAC/B,MAAM,uEAAuE,CAAC;AAE/E,MAAM,WAAW,kBAAkB;IACjC,gDAAgD;IAChD,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,wCAAwC;IACxC,oBAAoB,EAAE,cAAc,CAAC;IACrC,oBAAoB;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8BAA8B;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,cAAc,EAAE,cAAc,CAAC;CAChC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,kBAAkB,GAC1B,2BAA2B,CA4E7B"}
|
|
@@ -1,17 +1,47 @@
|
|
|
1
|
+
import { generateId } from "document-model/core";
|
|
1
2
|
/**
|
|
2
3
|
* Maps a Service Offering state to an InitializeSubscriptionInput.
|
|
3
|
-
* This
|
|
4
|
-
*
|
|
4
|
+
* This is a one-time snapshot — the SI lives independently after creation.
|
|
5
|
+
*
|
|
6
|
+
* Logic:
|
|
7
|
+
* 1. Find the selected tier and resolve pricing from priceBreakdown
|
|
8
|
+
* 2. Map option group breakdowns from priceBreakdown as service groups
|
|
9
|
+
* 3. Map add-on breakdowns from priceBreakdown as optional service groups
|
|
10
|
+
* 4. Map remaining standalone services with tier service levels and usage limits
|
|
11
|
+
* 5. Calculate tier price from breakdown or service group sums (CALCULATED) or manual price
|
|
5
12
|
*/
|
|
6
13
|
export function mapOfferingToSubscription(options) {
|
|
7
|
-
const { offering, tierId, selectedBillingCycle, customerId, customerName, customerEmail, createdAt, } = options;
|
|
14
|
+
const { offering, tierId, selectedBillingCycle, customerId, customerName, customerEmail, createdAt, priceBreakdown, } = options;
|
|
8
15
|
const tier = offering.tiers.find((t) => t.id === tierId);
|
|
9
16
|
if (!tier) {
|
|
10
17
|
throw new Error(`Tier ${tierId} not found in offering`);
|
|
11
18
|
}
|
|
12
|
-
const currency = tier.pricing
|
|
13
|
-
const pricingMode = tier.pricingMode;
|
|
14
|
-
|
|
19
|
+
const currency = priceBreakdown.tierCurrency || tier.pricing.currency;
|
|
20
|
+
const pricingMode = tier.pricingMode || "MANUAL_OVERRIDE";
|
|
21
|
+
// Track which services are accounted for in groups
|
|
22
|
+
const groupedServiceIds = new Set();
|
|
23
|
+
// 1. Map option group and add-on breakdowns from priceBreakdown as service groups
|
|
24
|
+
const serviceGroups = [];
|
|
25
|
+
mapBreakdownGroups(offering, tier, priceBreakdown, currency, groupedServiceIds, serviceGroups);
|
|
26
|
+
// 3. Map remaining standalone services (not in any group or option group)
|
|
27
|
+
const standaloneServices = offering.services
|
|
28
|
+
.filter((s) => !groupedServiceIds.has(s.id))
|
|
29
|
+
.filter((svc) => {
|
|
30
|
+
const level = tier.serviceLevels.find((sl) => sl.serviceId === svc.id);
|
|
31
|
+
return (level &&
|
|
32
|
+
level.level !== "NOT_INCLUDED" &&
|
|
33
|
+
level.level !== "NOT_APPLICABLE");
|
|
34
|
+
})
|
|
35
|
+
.map((svc) => mapServiceToInput(svc, tier, currency, selectedBillingCycle));
|
|
36
|
+
// Calculate tier price
|
|
37
|
+
let tierPrice;
|
|
38
|
+
if (pricingMode === "CALCULATED") {
|
|
39
|
+
tierPrice = serviceGroups.reduce((sum, grp) => sum + (grp.recurringAmount ?? 0), 0);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
tierPrice =
|
|
43
|
+
priceBreakdown.tierCycleTotal ?? tier.pricing.amount ?? undefined;
|
|
44
|
+
}
|
|
15
45
|
return {
|
|
16
46
|
customerId: customerId ?? undefined,
|
|
17
47
|
customerName: customerName ?? undefined,
|
|
@@ -24,6 +54,125 @@ export function mapOfferingToSubscription(options) {
|
|
|
24
54
|
tierPricingMode: pricingMode,
|
|
25
55
|
selectedBillingCycle,
|
|
26
56
|
globalCurrency: currency,
|
|
57
|
+
autoRenew: true,
|
|
27
58
|
createdAt,
|
|
59
|
+
services: standaloneServices,
|
|
60
|
+
serviceGroups,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Maps price breakdown option group and add-on breakdowns
|
|
65
|
+
* into subscription service groups.
|
|
66
|
+
*/
|
|
67
|
+
function mapBreakdownGroups(offering, tier, breakdown, globalCurrency, groupedServiceIds, serviceGroups) {
|
|
68
|
+
// Non-add-on option groups (regular + setup)
|
|
69
|
+
const allOptionGroupBreakdowns = [
|
|
70
|
+
...breakdown.optionGroupBreakdowns,
|
|
71
|
+
...breakdown.setupGroupBreakdowns,
|
|
72
|
+
];
|
|
73
|
+
for (const ogBreakdown of allOptionGroupBreakdowns) {
|
|
74
|
+
const og = offering.optionGroups.find((g) => g.id === ogBreakdown.optionGroupId);
|
|
75
|
+
if (!og || og.isAddOn)
|
|
76
|
+
continue;
|
|
77
|
+
const services = offering.services.filter((s) => s.optionGroupId === og.id);
|
|
78
|
+
if (services.length === 0)
|
|
79
|
+
continue;
|
|
80
|
+
services.forEach((s) => groupedServiceIds.add(s.id));
|
|
81
|
+
serviceGroups.push({
|
|
82
|
+
id: generateId(),
|
|
83
|
+
name: og.name,
|
|
84
|
+
optional: false,
|
|
85
|
+
costType: og.costType ?? undefined,
|
|
86
|
+
recurringAmount: ogBreakdown.recurringAmount || undefined,
|
|
87
|
+
recurringCurrency: ogBreakdown.currency || globalCurrency,
|
|
88
|
+
recurringBillingCycle: ogBreakdown.effectiveBillingCycle,
|
|
89
|
+
recurringDiscount: mapBreakdownDiscount(ogBreakdown.discount, og.discountMode === "INHERIT_TIER"
|
|
90
|
+
? "TIER_INHERITED"
|
|
91
|
+
: "GROUP_INDEPENDENT"),
|
|
92
|
+
setupAmount: ogBreakdown.setupCost ?? undefined,
|
|
93
|
+
setupCurrency: ogBreakdown.setupCostCurrency ?? undefined,
|
|
94
|
+
services: services.map((svc) => mapServiceToInput(svc, tier, globalCurrency, ogBreakdown.effectiveBillingCycle)),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
// Add-on option groups
|
|
98
|
+
for (const aoBreakdown of breakdown.addOnBreakdowns) {
|
|
99
|
+
const og = offering.optionGroups.find((g) => g.id === aoBreakdown.optionGroupId);
|
|
100
|
+
if (!og)
|
|
101
|
+
continue;
|
|
102
|
+
const services = offering.services.filter((s) => s.optionGroupId === og.id);
|
|
103
|
+
if (services.length === 0)
|
|
104
|
+
continue;
|
|
105
|
+
services.forEach((s) => groupedServiceIds.add(s.id));
|
|
106
|
+
serviceGroups.push({
|
|
107
|
+
id: generateId(),
|
|
108
|
+
name: og.name,
|
|
109
|
+
optional: true,
|
|
110
|
+
costType: og.costType ?? undefined,
|
|
111
|
+
recurringAmount: aoBreakdown.recurringAmount || undefined,
|
|
112
|
+
recurringCurrency: aoBreakdown.currency || globalCurrency,
|
|
113
|
+
recurringBillingCycle: aoBreakdown.selectedBillingCycle,
|
|
114
|
+
recurringDiscount: mapBreakdownDiscount(aoBreakdown.discount, og.discountMode === "INHERIT_TIER"
|
|
115
|
+
? "TIER_INHERITED"
|
|
116
|
+
: "GROUP_INDEPENDENT"),
|
|
117
|
+
setupAmount: aoBreakdown.setupCost ?? undefined,
|
|
118
|
+
setupCurrency: aoBreakdown.setupCostCurrency ?? undefined,
|
|
119
|
+
services: services.map((svc) => mapServiceToInput(svc, tier, globalCurrency, aoBreakdown.selectedBillingCycle)),
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Maps a single service from the offering to an InitializeServiceInput.
|
|
125
|
+
* Includes name, description, customValue from tier service levels,
|
|
126
|
+
* billing cycle, and usage metrics.
|
|
127
|
+
*/
|
|
128
|
+
function mapServiceToInput(svc, tier, globalCurrency, billingCycle) {
|
|
129
|
+
const level = tier.serviceLevels.find((sl) => sl.serviceId === svc.id);
|
|
130
|
+
const metrics = mapUsageLimits(svc.id, tier.usageLimits, globalCurrency);
|
|
131
|
+
return {
|
|
132
|
+
id: generateId(),
|
|
133
|
+
name: svc.title,
|
|
134
|
+
description: svc.description ?? null,
|
|
135
|
+
customValue: level?.customValue ?? null,
|
|
136
|
+
recurringBillingCycle: billingCycle,
|
|
137
|
+
metrics,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Maps a resolved discount from the price breakdown to a DiscountInfoInitInput,
|
|
142
|
+
* or returns undefined if no discount.
|
|
143
|
+
*/
|
|
144
|
+
function mapBreakdownDiscount(discount, source) {
|
|
145
|
+
if (!discount)
|
|
146
|
+
return undefined;
|
|
147
|
+
return {
|
|
148
|
+
originalAmount: discount.originalAmount,
|
|
149
|
+
discountType: discount.discountType,
|
|
150
|
+
discountValue: discount.discountValue,
|
|
151
|
+
source,
|
|
28
152
|
};
|
|
29
153
|
}
|
|
154
|
+
/**
|
|
155
|
+
* Maps usage limits from the tier to InitializeMetricInput for a given service.
|
|
156
|
+
*/
|
|
157
|
+
function mapUsageLimits(serviceId, usageLimits, globalCurrency) {
|
|
158
|
+
const limits = usageLimits.filter((ul) => ul.serviceId === serviceId);
|
|
159
|
+
return limits.map((ul) => {
|
|
160
|
+
// Map SO's UsageResetCycle to SI's ResetPeriod (skip "NONE")
|
|
161
|
+
const usageResetPeriod = ul.resetCycle && ul.resetCycle !== "NONE"
|
|
162
|
+
? ul.resetCycle
|
|
163
|
+
: undefined;
|
|
164
|
+
return {
|
|
165
|
+
id: generateId(),
|
|
166
|
+
name: ul.metric,
|
|
167
|
+
unitName: ul.unitName ?? "units",
|
|
168
|
+
limit: ul.freeLimit ?? ul.paidLimit ?? null,
|
|
169
|
+
freeLimit: ul.freeLimit ?? null,
|
|
170
|
+
paidLimit: ul.paidLimit ?? null,
|
|
171
|
+
currentUsage: 0,
|
|
172
|
+
usageResetPeriod,
|
|
173
|
+
unitCostAmount: ul.unitPrice ?? undefined,
|
|
174
|
+
unitCostCurrency: ul.unitPriceCurrency ?? globalCurrency,
|
|
175
|
+
unitCostBillingCycle: usageResetPeriod ? "MONTHLY" : undefined,
|
|
176
|
+
};
|
|
177
|
+
});
|
|
178
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "
|
|
2
|
+
"name": "@powerhousedao/service-offering",
|
|
3
3
|
"description": "",
|
|
4
4
|
"category": "",
|
|
5
5
|
"publisher": {
|
|
@@ -28,8 +28,34 @@
|
|
|
28
28
|
"name": "SubscriptionInstance"
|
|
29
29
|
}
|
|
30
30
|
],
|
|
31
|
-
"editors": [
|
|
31
|
+
"editors": [
|
|
32
|
+
{
|
|
33
|
+
"id": "resource-instance-editor",
|
|
34
|
+
"name": "Resource Instance Editor",
|
|
35
|
+
"documentTypes": ["powerhouse/resource-instance"]
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"id": "resource-template-editor",
|
|
39
|
+
"name": "Resource Template Editor",
|
|
40
|
+
"documentTypes": ["powerhouse/resource-template"]
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"id": "service-offering-editor",
|
|
44
|
+
"name": "Service Offering Editor",
|
|
45
|
+
"documentTypes": ["powerhouse/service-offering"]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"id": "subscription-instance-editor",
|
|
49
|
+
"name": "Subscription Instance Editor",
|
|
50
|
+
"documentTypes": ["powerhouse/subscription-instance"]
|
|
51
|
+
}
|
|
52
|
+
],
|
|
32
53
|
"apps": [],
|
|
33
|
-
"subgraphs": [
|
|
54
|
+
"subgraphs": [
|
|
55
|
+
{
|
|
56
|
+
"id": "resources-services",
|
|
57
|
+
"name": "Resources & Services"
|
|
58
|
+
}
|
|
59
|
+
],
|
|
34
60
|
"importScripts": []
|
|
35
61
|
}
|