@dainamite/billing 0.17.0
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/CHANGELOG.md +658 -0
- package/LICENSE +21 -0
- package/README.md +77 -0
- package/dist/modules/billing/acl.js +20 -0
- package/dist/modules/billing/acl.js.map +7 -0
- package/dist/modules/billing/api/accounts/route.js +182 -0
- package/dist/modules/billing/api/accounts/route.js.map +7 -0
- package/dist/modules/billing/api/export/account/[id]/route.js +170 -0
- package/dist/modules/billing/api/export/account/[id]/route.js.map +7 -0
- package/dist/modules/billing/api/invoices/[id]/route.js +85 -0
- package/dist/modules/billing/api/invoices/[id]/route.js.map +7 -0
- package/dist/modules/billing/api/invoices/add-line/route.js +69 -0
- package/dist/modules/billing/api/invoices/add-line/route.js.map +7 -0
- package/dist/modules/billing/api/invoices/edit-line/route.js +78 -0
- package/dist/modules/billing/api/invoices/edit-line/route.js.map +7 -0
- package/dist/modules/billing/api/invoices/post/route.js +74 -0
- package/dist/modules/billing/api/invoices/post/route.js.map +7 -0
- package/dist/modules/billing/api/invoices/remove-line/route.js +69 -0
- package/dist/modules/billing/api/invoices/remove-line/route.js.map +7 -0
- package/dist/modules/billing/api/invoices/route.js +109 -0
- package/dist/modules/billing/api/invoices/route.js.map +7 -0
- package/dist/modules/billing/api/items/bulk/route.js +74 -0
- package/dist/modules/billing/api/items/bulk/route.js.map +7 -0
- package/dist/modules/billing/api/items/route.js +224 -0
- package/dist/modules/billing/api/items/route.js.map +7 -0
- package/dist/modules/billing/api/openapi.js +25 -0
- package/dist/modules/billing/api/openapi.js.map +7 -0
- package/dist/modules/billing/api/run-outcomes/route.js +122 -0
- package/dist/modules/billing/api/run-outcomes/route.js.map +7 -0
- package/dist/modules/billing/api/runs/retry-failed/route.js +70 -0
- package/dist/modules/billing/api/runs/retry-failed/route.js.map +7 -0
- package/dist/modules/billing/api/runs/route.js +143 -0
- package/dist/modules/billing/api/runs/route.js.map +7 -0
- package/dist/modules/billing/api/test-invoices/wipe/route.js +65 -0
- package/dist/modules/billing/api/test-invoices/wipe/route.js.map +7 -0
- package/dist/modules/billing/api/usage/route.js +138 -0
- package/dist/modules/billing/api/usage/route.js.map +7 -0
- package/dist/modules/billing/backend/billing/accounts/[id]/page.js +402 -0
- package/dist/modules/billing/backend/billing/accounts/[id]/page.js.map +7 -0
- package/dist/modules/billing/backend/billing/accounts/[id]/page.meta.js +25 -0
- package/dist/modules/billing/backend/billing/accounts/[id]/page.meta.js.map +7 -0
- package/dist/modules/billing/backend/billing/accounts/create/page.js +82 -0
- package/dist/modules/billing/backend/billing/accounts/create/page.js.map +7 -0
- package/dist/modules/billing/backend/billing/accounts/create/page.meta.js +25 -0
- package/dist/modules/billing/backend/billing/accounts/create/page.meta.js.map +7 -0
- package/dist/modules/billing/backend/billing/accounts/page.js +173 -0
- package/dist/modules/billing/backend/billing/accounts/page.js.map +7 -0
- package/dist/modules/billing/backend/billing/accounts/page.meta.js +18 -0
- package/dist/modules/billing/backend/billing/accounts/page.meta.js.map +7 -0
- package/dist/modules/billing/backend/billing/invoices/[id]/page.js +500 -0
- package/dist/modules/billing/backend/billing/invoices/[id]/page.js.map +7 -0
- package/dist/modules/billing/backend/billing/invoices/[id]/page.meta.js +25 -0
- package/dist/modules/billing/backend/billing/invoices/[id]/page.meta.js.map +7 -0
- package/dist/modules/billing/backend/billing/invoices/page.js +187 -0
- package/dist/modules/billing/backend/billing/invoices/page.js.map +7 -0
- package/dist/modules/billing/backend/billing/invoices/page.meta.js +18 -0
- package/dist/modules/billing/backend/billing/invoices/page.meta.js.map +7 -0
- package/dist/modules/billing/backend/billing/items/[id]/page.js +265 -0
- package/dist/modules/billing/backend/billing/items/[id]/page.js.map +7 -0
- package/dist/modules/billing/backend/billing/items/[id]/page.meta.js +25 -0
- package/dist/modules/billing/backend/billing/items/[id]/page.meta.js.map +7 -0
- package/dist/modules/billing/backend/billing/items/create/page.js +90 -0
- package/dist/modules/billing/backend/billing/items/create/page.js.map +7 -0
- package/dist/modules/billing/backend/billing/items/create/page.meta.js +25 -0
- package/dist/modules/billing/backend/billing/items/create/page.meta.js.map +7 -0
- package/dist/modules/billing/backend/billing/items/page.js +208 -0
- package/dist/modules/billing/backend/billing/items/page.js.map +7 -0
- package/dist/modules/billing/backend/billing/items/page.meta.js +18 -0
- package/dist/modules/billing/backend/billing/items/page.meta.js.map +7 -0
- package/dist/modules/billing/backend/billing/runs/[id]/page.js +293 -0
- package/dist/modules/billing/backend/billing/runs/[id]/page.js.map +7 -0
- package/dist/modules/billing/backend/billing/runs/[id]/page.meta.js +21 -0
- package/dist/modules/billing/backend/billing/runs/[id]/page.meta.js.map +7 -0
- package/dist/modules/billing/backend/billing/runs/page.js +341 -0
- package/dist/modules/billing/backend/billing/runs/page.js.map +7 -0
- package/dist/modules/billing/backend/billing/runs/page.meta.js +18 -0
- package/dist/modules/billing/backend/billing/runs/page.meta.js.map +7 -0
- package/dist/modules/billing/backend/billing/usage/create/page.js +100 -0
- package/dist/modules/billing/backend/billing/usage/create/page.js.map +7 -0
- package/dist/modules/billing/backend/billing/usage/create/page.meta.js +25 -0
- package/dist/modules/billing/backend/billing/usage/create/page.meta.js.map +7 -0
- package/dist/modules/billing/ce.js +56 -0
- package/dist/modules/billing/ce.js.map +7 -0
- package/dist/modules/billing/cli.js +67 -0
- package/dist/modules/billing/cli.js.map +7 -0
- package/dist/modules/billing/commands/accounts.js +157 -0
- package/dist/modules/billing/commands/accounts.js.map +7 -0
- package/dist/modules/billing/commands/index.js +6 -0
- package/dist/modules/billing/commands/index.js.map +7 -0
- package/dist/modules/billing/commands/invoices.js +401 -0
- package/dist/modules/billing/commands/invoices.js.map +7 -0
- package/dist/modules/billing/commands/items.js +317 -0
- package/dist/modules/billing/commands/items.js.map +7 -0
- package/dist/modules/billing/commands/runs.js +123 -0
- package/dist/modules/billing/commands/runs.js.map +7 -0
- package/dist/modules/billing/commands/usage.js +88 -0
- package/dist/modules/billing/commands/usage.js.map +7 -0
- package/dist/modules/billing/components/AccountForm.js +420 -0
- package/dist/modules/billing/components/AccountForm.js.map +7 -0
- package/dist/modules/billing/components/DetailFields.js +37 -0
- package/dist/modules/billing/components/DetailFields.js.map +7 -0
- package/dist/modules/billing/components/ItemForm.js +440 -0
- package/dist/modules/billing/components/ItemForm.js.map +7 -0
- package/dist/modules/billing/components/LineFormDialog.js +195 -0
- package/dist/modules/billing/components/LineFormDialog.js.map +7 -0
- package/dist/modules/billing/components/UsageForm.js +262 -0
- package/dist/modules/billing/components/UsageForm.js.map +7 -0
- package/dist/modules/billing/data/entities.js +433 -0
- package/dist/modules/billing/data/entities.js.map +7 -0
- package/dist/modules/billing/data/entityIds.js +12 -0
- package/dist/modules/billing/data/entityIds.js.map +7 -0
- package/dist/modules/billing/data/validators.js +396 -0
- package/dist/modules/billing/data/validators.js.map +7 -0
- package/dist/modules/billing/di.js +6 -0
- package/dist/modules/billing/di.js.map +7 -0
- package/dist/modules/billing/events.js +35 -0
- package/dist/modules/billing/events.js.map +7 -0
- package/dist/modules/billing/i18n/en.json +336 -0
- package/dist/modules/billing/i18n/pl.json +336 -0
- package/dist/modules/billing/index.js +17 -0
- package/dist/modules/billing/index.js.map +7 -0
- package/dist/modules/billing/lib/billPeriod.js +101 -0
- package/dist/modules/billing/lib/billPeriod.js.map +7 -0
- package/dist/modules/billing/lib/billRunEngine.js +256 -0
- package/dist/modules/billing/lib/billRunEngine.js.map +7 -0
- package/dist/modules/billing/lib/billRunLabel.js +8 -0
- package/dist/modules/billing/lib/billRunLabel.js.map +7 -0
- package/dist/modules/billing/lib/idempotency.js +13 -0
- package/dist/modules/billing/lib/idempotency.js.map +7 -0
- package/dist/modules/billing/lib/invoiceStatus.js +38 -0
- package/dist/modules/billing/lib/invoiceStatus.js.map +7 -0
- package/dist/modules/billing/lib/invoiceWriter.js +153 -0
- package/dist/modules/billing/lib/invoiceWriter.js.map +7 -0
- package/dist/modules/billing/lib/itemSelector.js +77 -0
- package/dist/modules/billing/lib/itemSelector.js.map +7 -0
- package/dist/modules/billing/lib/seeds/demo.js +130 -0
- package/dist/modules/billing/lib/seeds/demo.js.map +7 -0
- package/dist/modules/billing/lib/tenantLock.js +32 -0
- package/dist/modules/billing/lib/tenantLock.js.map +7 -0
- package/dist/modules/billing/lib/usageRater.js +150 -0
- package/dist/modules/billing/lib/usageRater.js.map +7 -0
- package/dist/modules/billing/lib/usageRunner.js +82 -0
- package/dist/modules/billing/lib/usageRunner.js.map +7 -0
- package/dist/modules/billing/migrations/Migration20260519000000_billing.js +144 -0
- package/dist/modules/billing/migrations/Migration20260519000000_billing.js.map +7 -0
- package/dist/modules/billing/setup.js +190 -0
- package/dist/modules/billing/setup.js.map +7 -0
- package/dist/modules/billing/subscribers/payment-captured-to-paid.js +47 -0
- package/dist/modules/billing/subscribers/payment-captured-to-paid.js.map +7 -0
- package/dist/modules/billing/translations.js +5 -0
- package/dist/modules/billing/translations.js.map +7 -0
- package/dist/modules/billing/workers/reap-stale-bill-runs.js +31 -0
- package/dist/modules/billing/workers/reap-stale-bill-runs.js.map +7 -0
- package/package.json +148 -0
- package/src/modules/billing/__integration__/TC-BILL-001.spec.ts +116 -0
- package/src/modules/billing/__integration__/TC-BILL-002.spec.ts +169 -0
- package/src/modules/billing/__integration__/TC-BILL-003.spec.ts +28 -0
- package/src/modules/billing/__integration__/meta.ts +4 -0
- package/src/modules/billing/__tests__/commands/invoices.test.ts +464 -0
- package/src/modules/billing/__tests__/commands/itemsBulk.test.ts +284 -0
- package/src/modules/billing/__tests__/lib/billPeriod.test.ts +131 -0
- package/src/modules/billing/__tests__/lib/billRunEngine.test.ts +561 -0
- package/src/modules/billing/__tests__/lib/idempotency.test.ts +81 -0
- package/src/modules/billing/__tests__/lib/invoiceStatus.test.ts +97 -0
- package/src/modules/billing/__tests__/lib/invoiceWriter.test.ts +119 -0
- package/src/modules/billing/__tests__/lib/itemSelector.test.ts +192 -0
- package/src/modules/billing/__tests__/lib/seedsDemo.test.ts +86 -0
- package/src/modules/billing/__tests__/lib/tenantLock.test.ts +126 -0
- package/src/modules/billing/__tests__/lib/usageRater.test.ts +190 -0
- package/src/modules/billing/__tests__/package-isolation.test.ts +223 -0
- package/src/modules/billing/__tests__/setup.test.ts +107 -0
- package/src/modules/billing/__tests__/validators.test.ts +594 -0
- package/src/modules/billing/acl.ts +16 -0
- package/src/modules/billing/api/accounts/route.ts +198 -0
- package/src/modules/billing/api/export/account/[id]/route.ts +233 -0
- package/src/modules/billing/api/invoices/[id]/route.ts +143 -0
- package/src/modules/billing/api/invoices/add-line/route.ts +74 -0
- package/src/modules/billing/api/invoices/edit-line/route.ts +97 -0
- package/src/modules/billing/api/invoices/post/route.ts +97 -0
- package/src/modules/billing/api/invoices/remove-line/route.ts +75 -0
- package/src/modules/billing/api/invoices/route.ts +167 -0
- package/src/modules/billing/api/items/bulk/route.ts +92 -0
- package/src/modules/billing/api/items/route.ts +255 -0
- package/src/modules/billing/api/openapi.ts +33 -0
- package/src/modules/billing/api/run-outcomes/route.ts +149 -0
- package/src/modules/billing/api/runs/retry-failed/route.ts +88 -0
- package/src/modules/billing/api/runs/route.ts +170 -0
- package/src/modules/billing/api/test-invoices/wipe/route.ts +87 -0
- package/src/modules/billing/api/usage/route.ts +148 -0
- package/src/modules/billing/backend/billing/accounts/[id]/page.meta.ts +23 -0
- package/src/modules/billing/backend/billing/accounts/[id]/page.tsx +574 -0
- package/src/modules/billing/backend/billing/accounts/create/page.meta.ts +23 -0
- package/src/modules/billing/backend/billing/accounts/create/page.tsx +101 -0
- package/src/modules/billing/backend/billing/accounts/page.meta.ts +16 -0
- package/src/modules/billing/backend/billing/accounts/page.tsx +222 -0
- package/src/modules/billing/backend/billing/invoices/[id]/page.meta.ts +23 -0
- package/src/modules/billing/backend/billing/invoices/[id]/page.tsx +613 -0
- package/src/modules/billing/backend/billing/invoices/page.meta.ts +16 -0
- package/src/modules/billing/backend/billing/invoices/page.tsx +245 -0
- package/src/modules/billing/backend/billing/items/[id]/page.meta.ts +23 -0
- package/src/modules/billing/backend/billing/items/[id]/page.tsx +366 -0
- package/src/modules/billing/backend/billing/items/create/page.meta.ts +23 -0
- package/src/modules/billing/backend/billing/items/create/page.tsx +110 -0
- package/src/modules/billing/backend/billing/items/page.meta.ts +16 -0
- package/src/modules/billing/backend/billing/items/page.tsx +272 -0
- package/src/modules/billing/backend/billing/runs/[id]/page.meta.ts +19 -0
- package/src/modules/billing/backend/billing/runs/[id]/page.tsx +404 -0
- package/src/modules/billing/backend/billing/runs/page.meta.ts +16 -0
- package/src/modules/billing/backend/billing/runs/page.tsx +426 -0
- package/src/modules/billing/backend/billing/usage/create/page.meta.ts +23 -0
- package/src/modules/billing/backend/billing/usage/create/page.tsx +120 -0
- package/src/modules/billing/ce.ts +74 -0
- package/src/modules/billing/cli.ts +89 -0
- package/src/modules/billing/commands/accounts.ts +205 -0
- package/src/modules/billing/commands/index.ts +13 -0
- package/src/modules/billing/commands/invoices.ts +542 -0
- package/src/modules/billing/commands/items.ts +438 -0
- package/src/modules/billing/commands/runs.ts +166 -0
- package/src/modules/billing/commands/usage.ts +118 -0
- package/src/modules/billing/components/AccountForm.tsx +517 -0
- package/src/modules/billing/components/DetailFields.tsx +60 -0
- package/src/modules/billing/components/ItemForm.tsx +558 -0
- package/src/modules/billing/components/LineFormDialog.tsx +253 -0
- package/src/modules/billing/components/UsageForm.tsx +326 -0
- package/src/modules/billing/data/entities.ts +533 -0
- package/src/modules/billing/data/entityIds.ts +25 -0
- package/src/modules/billing/data/validators.ts +562 -0
- package/src/modules/billing/di.ts +14 -0
- package/src/modules/billing/events.ts +47 -0
- package/src/modules/billing/i18n/en.json +336 -0
- package/src/modules/billing/i18n/pl.json +336 -0
- package/src/modules/billing/index.ts +22 -0
- package/src/modules/billing/lib/billPeriod.ts +181 -0
- package/src/modules/billing/lib/billRunEngine.ts +416 -0
- package/src/modules/billing/lib/billRunLabel.ts +14 -0
- package/src/modules/billing/lib/idempotency.ts +46 -0
- package/src/modules/billing/lib/invoiceStatus.ts +61 -0
- package/src/modules/billing/lib/invoiceWriter.ts +260 -0
- package/src/modules/billing/lib/itemSelector.ts +154 -0
- package/src/modules/billing/lib/seeds/demo.ts +199 -0
- package/src/modules/billing/lib/tenantLock.ts +87 -0
- package/src/modules/billing/lib/usageRater.ts +250 -0
- package/src/modules/billing/lib/usageRunner.ts +189 -0
- package/src/modules/billing/migrations/Migration20260519000000_billing.ts +175 -0
- package/src/modules/billing/setup.ts +252 -0
- package/src/modules/billing/subscribers/payment-captured-to-paid.ts +89 -0
- package/src/modules/billing/translations.ts +9 -0
- package/src/modules/billing/workers/reap-stale-bill-runs.ts +57 -0
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const BILLING_ITEM_TYPES = ["one_time", "recurring", "usage"];
|
|
3
|
+
const BILL_CYCLES = ["weekly", "monthly", "quarterly", "annually"];
|
|
4
|
+
const BILL_RUN_TRIGGERS = ["schedule", "manual"];
|
|
5
|
+
const BILL_RUN_STATUSES = ["running", "completed", "partial_failure", "failed"];
|
|
6
|
+
const BILL_RUN_OUTCOME_STATUSES = [
|
|
7
|
+
"success",
|
|
8
|
+
"success_with_warnings",
|
|
9
|
+
"skipped_existing_draft",
|
|
10
|
+
"failed"
|
|
11
|
+
];
|
|
12
|
+
const DRAFT_INVOICE_EDIT_ACTIONS = ["line_added", "line_removed", "line_edited"];
|
|
13
|
+
const INVOICE_STATUSES = ["draft", "posted", "paid", "void"];
|
|
14
|
+
const WEEKLY_ANCHORS = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"];
|
|
15
|
+
const billCycleAnchorSchema = z.string().min(1).refine(
|
|
16
|
+
(val) => {
|
|
17
|
+
if (WEEKLY_ANCHORS.includes(val.toLowerCase())) return true;
|
|
18
|
+
const n = Number.parseInt(val, 10);
|
|
19
|
+
return Number.isInteger(n) && n >= 1 && n <= 28;
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
message: "bill_cycle_anchor must be 1\u201328 (monthly/quarterly/annually) or mon\u2013sun (weekly)"
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
const numericNonNegative = z.number().finite().nonnegative();
|
|
26
|
+
const numericAny = z.number().finite();
|
|
27
|
+
const rateJsonOneTime = z.object({ amount: numericAny }).strict();
|
|
28
|
+
const rateJsonRecurring = z.object({ unit_price: numericNonNegative }).strict();
|
|
29
|
+
const rateJsonUsageSimple = z.object({ unit_price: numericNonNegative }).strict();
|
|
30
|
+
const tierWithUnitPrice = z.object({
|
|
31
|
+
up_to: z.union([z.number().int().positive(), z.null()]),
|
|
32
|
+
unit_price: numericNonNegative
|
|
33
|
+
}).strict();
|
|
34
|
+
const tierWithFlatAmount = z.object({
|
|
35
|
+
up_to: z.union([z.number().int().positive(), z.null()]),
|
|
36
|
+
flat_amount: numericNonNegative
|
|
37
|
+
}).strict();
|
|
38
|
+
const tiersUnitPrice = z.array(tierWithUnitPrice).min(1, "tiers must be a non-empty array");
|
|
39
|
+
const tiersFlatAmount = z.array(tierWithFlatAmount).min(1, "tiers must be a non-empty array");
|
|
40
|
+
function refineTierProgression(tiers, ctx) {
|
|
41
|
+
const openTopCount = tiers.filter((t) => t.up_to === null).length;
|
|
42
|
+
if (openTopCount !== 1) {
|
|
43
|
+
ctx.addIssue({
|
|
44
|
+
code: z.ZodIssueCode.custom,
|
|
45
|
+
message: "tiers must contain exactly one open-ended top tier (up_to: null)"
|
|
46
|
+
});
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (tiers[tiers.length - 1].up_to !== null) {
|
|
50
|
+
ctx.addIssue({
|
|
51
|
+
code: z.ZodIssueCode.custom,
|
|
52
|
+
message: "the open-ended top tier (up_to: null) must be the last entry"
|
|
53
|
+
});
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
for (let i = 1; i < tiers.length - 1; i++) {
|
|
57
|
+
const prev = tiers[i - 1].up_to;
|
|
58
|
+
const curr = tiers[i].up_to;
|
|
59
|
+
if (prev !== null && curr !== null && curr <= prev) {
|
|
60
|
+
ctx.addIssue({
|
|
61
|
+
code: z.ZodIssueCode.custom,
|
|
62
|
+
message: `up_to values must be strictly increasing across tiers (failed at index ${i})`
|
|
63
|
+
});
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const rateJsonUsageVolume = z.object({
|
|
69
|
+
model: z.literal("volume"),
|
|
70
|
+
tiers: tiersUnitPrice
|
|
71
|
+
}).strict().superRefine((val, ctx) => refineTierProgression(val.tiers, ctx));
|
|
72
|
+
const rateJsonUsageGraduated = z.object({
|
|
73
|
+
model: z.literal("graduated"),
|
|
74
|
+
tiers: tiersUnitPrice
|
|
75
|
+
}).strict().superRefine((val, ctx) => refineTierProgression(val.tiers, ctx));
|
|
76
|
+
const rateJsonUsageFlat = z.object({
|
|
77
|
+
model: z.literal("flat"),
|
|
78
|
+
tiers: tiersFlatAmount
|
|
79
|
+
}).strict().superRefine((val, ctx) => refineTierProgression(val.tiers, ctx));
|
|
80
|
+
const rateJsonUsageTiered = z.discriminatedUnion("model", [
|
|
81
|
+
rateJsonUsageVolume,
|
|
82
|
+
rateJsonUsageGraduated,
|
|
83
|
+
rateJsonUsageFlat
|
|
84
|
+
]);
|
|
85
|
+
const rateJsonUsage = z.union([rateJsonUsageSimple, rateJsonUsageTiered]);
|
|
86
|
+
function validateRateJson(type, rateJson) {
|
|
87
|
+
switch (type) {
|
|
88
|
+
case "one_time":
|
|
89
|
+
return rateJsonOneTime.parse(rateJson);
|
|
90
|
+
case "recurring":
|
|
91
|
+
return rateJsonRecurring.parse(rateJson);
|
|
92
|
+
case "usage":
|
|
93
|
+
return rateJsonUsage.parse(rateJson);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const invoiceAddressSchema = z.object({
|
|
97
|
+
line1: z.string().min(1),
|
|
98
|
+
line2: z.string().optional(),
|
|
99
|
+
city: z.string().min(1),
|
|
100
|
+
postal_code: z.string().min(1),
|
|
101
|
+
country: z.string().min(2).max(3)
|
|
102
|
+
// ISO 3166-1 alpha-2 or alpha-3
|
|
103
|
+
}).strict();
|
|
104
|
+
const scopedSchema = z.object({
|
|
105
|
+
tenantId: z.string().uuid(),
|
|
106
|
+
organizationId: z.string().uuid()
|
|
107
|
+
});
|
|
108
|
+
const listPaginationBase = {
|
|
109
|
+
page: z.coerce.number().int().min(1).default(1),
|
|
110
|
+
pageSize: z.coerce.number().int().min(1).max(100).default(50),
|
|
111
|
+
sortField: z.string().optional(),
|
|
112
|
+
sortDir: z.enum(["asc", "desc"]).optional()
|
|
113
|
+
};
|
|
114
|
+
const billingAccountCreateSchema = scopedSchema.extend({
|
|
115
|
+
customerId: z.string().min(1).max(255),
|
|
116
|
+
name: z.string().trim().min(1).max(255),
|
|
117
|
+
currencyCode: z.string().trim().toUpperCase().length(3),
|
|
118
|
+
billCycle: z.enum(BILL_CYCLES),
|
|
119
|
+
billCycleAnchor: billCycleAnchorSchema,
|
|
120
|
+
invoiceEmail: z.string().trim().email().max(320),
|
|
121
|
+
invoiceLanguage: z.string().trim().toLowerCase().min(2).max(5),
|
|
122
|
+
// Nullable + optional — consistent with the update schema, and the
|
|
123
|
+
// cpq-billing-connector's shell-account seed sends `taxId: null`
|
|
124
|
+
// for customers with no tax id.
|
|
125
|
+
taxId: z.string().trim().max(64).nullable().optional(),
|
|
126
|
+
invoiceAddress: invoiceAddressSchema,
|
|
127
|
+
nextBillDate: z.coerce.date(),
|
|
128
|
+
lastBillDate: z.coerce.date().optional(),
|
|
129
|
+
isActive: z.boolean().optional()
|
|
130
|
+
});
|
|
131
|
+
const billingAccountUpdateSchema = scopedSchema.extend({
|
|
132
|
+
id: z.string().uuid(),
|
|
133
|
+
name: z.string().trim().min(1).max(255).optional(),
|
|
134
|
+
billCycle: z.enum(BILL_CYCLES).optional(),
|
|
135
|
+
billCycleAnchor: billCycleAnchorSchema.optional(),
|
|
136
|
+
invoiceEmail: z.string().trim().email().max(320).optional(),
|
|
137
|
+
invoiceLanguage: z.string().trim().toLowerCase().min(2).max(5).optional(),
|
|
138
|
+
taxId: z.string().trim().max(64).nullable().optional(),
|
|
139
|
+
invoiceAddress: invoiceAddressSchema.optional(),
|
|
140
|
+
nextBillDate: z.coerce.date().optional(),
|
|
141
|
+
lastBillDate: z.coerce.date().nullable().optional(),
|
|
142
|
+
isActive: z.boolean().optional()
|
|
143
|
+
// `currencyCode` is intentionally NOT updatable — currency is frozen at
|
|
144
|
+
// account create time so historical invoices keep their currency context.
|
|
145
|
+
// `customerId` is also immutable; create a new account if the customer
|
|
146
|
+
// FK changes.
|
|
147
|
+
});
|
|
148
|
+
const billingAccountDeleteSchema = scopedSchema.extend({
|
|
149
|
+
id: z.string().uuid()
|
|
150
|
+
});
|
|
151
|
+
const billingAccountListQuerySchema = z.object({
|
|
152
|
+
...listPaginationBase,
|
|
153
|
+
id: z.string().uuid().optional(),
|
|
154
|
+
customerId: z.string().optional(),
|
|
155
|
+
currencyCode: z.string().optional(),
|
|
156
|
+
billCycle: z.enum(BILL_CYCLES).optional(),
|
|
157
|
+
isActive: z.coerce.boolean().optional(),
|
|
158
|
+
search: z.string().optional()
|
|
159
|
+
}).passthrough();
|
|
160
|
+
const ratePayloadByType = z.object({
|
|
161
|
+
type: z.enum(BILLING_ITEM_TYPES),
|
|
162
|
+
rateJson: z.unknown()
|
|
163
|
+
}).superRefine((val, ctx) => {
|
|
164
|
+
try {
|
|
165
|
+
validateRateJson(val.type, val.rateJson);
|
|
166
|
+
} catch (err) {
|
|
167
|
+
ctx.addIssue({
|
|
168
|
+
code: z.ZodIssueCode.custom,
|
|
169
|
+
path: ["rateJson"],
|
|
170
|
+
message: err instanceof Error ? err.message : "rate_json is invalid for this type"
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
const billingItemCreateSchema = scopedSchema.extend({
|
|
175
|
+
billAccountId: z.string().uuid(),
|
|
176
|
+
type: z.enum(BILLING_ITEM_TYPES),
|
|
177
|
+
billStartDate: z.coerce.date(),
|
|
178
|
+
billEndDate: z.coerce.date().nullable().optional(),
|
|
179
|
+
description: z.string().trim().min(1).max(500),
|
|
180
|
+
rateJson: z.unknown(),
|
|
181
|
+
// shape validated via the refine below
|
|
182
|
+
uomCode: z.string().trim().max(64).optional(),
|
|
183
|
+
subscriptionId: z.string().trim().max(255).optional(),
|
|
184
|
+
subscriptionItemId: z.string().trim().max(255).optional(),
|
|
185
|
+
// `source_ref` is the idempotency key. NULL → no dedup, always create.
|
|
186
|
+
sourceRef: z.string().trim().min(1).max(255).optional()
|
|
187
|
+
// currency_mismatch and billed_to_date are system-managed, never set by
|
|
188
|
+
// clients on create.
|
|
189
|
+
}).superRefine((val, ctx) => {
|
|
190
|
+
try {
|
|
191
|
+
validateRateJson(val.type, val.rateJson);
|
|
192
|
+
} catch (err) {
|
|
193
|
+
const message = err instanceof Error ? err.message : "rate_json is invalid for this type";
|
|
194
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["rateJson"], message });
|
|
195
|
+
}
|
|
196
|
+
if (val.type === "usage" && !val.uomCode) {
|
|
197
|
+
ctx.addIssue({
|
|
198
|
+
code: z.ZodIssueCode.custom,
|
|
199
|
+
path: ["uomCode"],
|
|
200
|
+
message: "uomCode is required for type=usage"
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
const billingItemBulkEntrySchema = z.object({
|
|
205
|
+
billAccountId: z.string().uuid(),
|
|
206
|
+
type: z.enum(BILLING_ITEM_TYPES),
|
|
207
|
+
billStartDate: z.coerce.date(),
|
|
208
|
+
billEndDate: z.coerce.date().nullable().optional(),
|
|
209
|
+
description: z.string().trim().min(1).max(500),
|
|
210
|
+
rateJson: z.unknown(),
|
|
211
|
+
uomCode: z.string().trim().max(64).optional(),
|
|
212
|
+
subscriptionId: z.string().trim().max(255).optional(),
|
|
213
|
+
subscriptionItemId: z.string().trim().max(255).optional(),
|
|
214
|
+
sourceRef: z.string().trim().min(1).max(255).optional()
|
|
215
|
+
}).superRefine((val, ctx) => {
|
|
216
|
+
try {
|
|
217
|
+
validateRateJson(val.type, val.rateJson);
|
|
218
|
+
} catch (err) {
|
|
219
|
+
const message = err instanceof Error ? err.message : "rate_json is invalid for this type";
|
|
220
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["rateJson"], message });
|
|
221
|
+
}
|
|
222
|
+
if (val.type === "usage" && !val.uomCode) {
|
|
223
|
+
ctx.addIssue({
|
|
224
|
+
code: z.ZodIssueCode.custom,
|
|
225
|
+
path: ["uomCode"],
|
|
226
|
+
message: "uomCode is required for type=usage"
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
const billingItemBulkCreateSchema = scopedSchema.extend({
|
|
231
|
+
// Cap at 500 per call — keeps a single bulk transaction bounded.
|
|
232
|
+
// A CPQ subscription with >500 charges should be split by the
|
|
233
|
+
// caller (the connector); 500 is already far past any realistic
|
|
234
|
+
// single-subscription charge count.
|
|
235
|
+
items: z.array(billingItemBulkEntrySchema).min(1).max(500)
|
|
236
|
+
});
|
|
237
|
+
const billingItemUpdateSchema = scopedSchema.extend({
|
|
238
|
+
id: z.string().uuid(),
|
|
239
|
+
// `type` is immutable — changing one_time → recurring would silently
|
|
240
|
+
// change billing semantics. Cancel the old item, create a new one.
|
|
241
|
+
billStartDate: z.coerce.date().optional(),
|
|
242
|
+
billEndDate: z.coerce.date().nullable().optional(),
|
|
243
|
+
description: z.string().trim().min(1).max(500).optional(),
|
|
244
|
+
rateJson: z.unknown().optional(),
|
|
245
|
+
uomCode: z.string().trim().max(64).nullable().optional(),
|
|
246
|
+
subscriptionId: z.string().trim().max(255).nullable().optional(),
|
|
247
|
+
subscriptionItemId: z.string().trim().max(255).nullable().optional(),
|
|
248
|
+
// `source_ref` immutable — it's the idempotency identity of the item.
|
|
249
|
+
isActive: z.boolean().optional()
|
|
250
|
+
});
|
|
251
|
+
const billingItemDeleteSchema = scopedSchema.extend({
|
|
252
|
+
id: z.string().uuid()
|
|
253
|
+
});
|
|
254
|
+
const billingItemListQuerySchema = z.object({
|
|
255
|
+
...listPaginationBase,
|
|
256
|
+
id: z.string().uuid().optional(),
|
|
257
|
+
search: z.string().optional(),
|
|
258
|
+
billAccountId: z.string().uuid().optional(),
|
|
259
|
+
type: z.enum(BILLING_ITEM_TYPES).optional(),
|
|
260
|
+
subscriptionId: z.string().optional(),
|
|
261
|
+
isActive: z.coerce.boolean().optional(),
|
|
262
|
+
activeAt: z.coerce.date().optional()
|
|
263
|
+
// bill_start_date <= X AND (bill_end_date IS NULL OR bill_end_date >= X)
|
|
264
|
+
}).passthrough();
|
|
265
|
+
const billingUsageCreateSchema = scopedSchema.extend({
|
|
266
|
+
billAccountId: z.string().uuid(),
|
|
267
|
+
uomCode: z.string().trim().min(1).max(64),
|
|
268
|
+
// `quantity` arrives as a number from JSON; MikroORM stores it as
|
|
269
|
+
// numeric(18,4). The service coerces to a string at persist time.
|
|
270
|
+
quantity: z.number().finite().nonnegative(),
|
|
271
|
+
periodStart: z.coerce.date(),
|
|
272
|
+
periodEnd: z.coerce.date(),
|
|
273
|
+
lineDescription: z.string().trim().min(1).max(500).optional(),
|
|
274
|
+
sourceRef: z.string().trim().min(1).max(255).optional()
|
|
275
|
+
}).superRefine((val, ctx) => {
|
|
276
|
+
if (val.periodEnd < val.periodStart) {
|
|
277
|
+
ctx.addIssue({
|
|
278
|
+
code: z.ZodIssueCode.custom,
|
|
279
|
+
path: ["periodEnd"],
|
|
280
|
+
message: "periodEnd must be on or after periodStart"
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
const billingUsageListQuerySchema = z.object({
|
|
285
|
+
...listPaginationBase,
|
|
286
|
+
billAccountId: z.string().uuid().optional(),
|
|
287
|
+
uomCode: z.string().optional(),
|
|
288
|
+
rated: z.coerce.boolean().optional(),
|
|
289
|
+
// true → already rated; false → unrated
|
|
290
|
+
periodEndFrom: z.coerce.date().optional(),
|
|
291
|
+
periodEndTo: z.coerce.date().optional()
|
|
292
|
+
}).passthrough();
|
|
293
|
+
void ratePayloadByType;
|
|
294
|
+
const BILL_RUN_MODES = ["real", "test", "dry"];
|
|
295
|
+
const billingRunTriggerSchema = scopedSchema.extend({
|
|
296
|
+
// `triggeredBy` is filled in by the route layer (always 'manual' for
|
|
297
|
+
// API triggers; the cron worker sets 'schedule'). The client cannot
|
|
298
|
+
// forge a 'schedule' trigger — the field is intentionally omitted
|
|
299
|
+
// from the input shape.
|
|
300
|
+
mode: z.enum(BILL_RUN_MODES).default("real"),
|
|
301
|
+
asOfDate: z.coerce.date().optional(),
|
|
302
|
+
scopedAccountIds: z.array(z.string().uuid()).optional(),
|
|
303
|
+
catchUp: z.boolean().optional()
|
|
304
|
+
});
|
|
305
|
+
const billingRunRetryFailedSchema = scopedSchema.extend({
|
|
306
|
+
billRunId: z.string().uuid(),
|
|
307
|
+
mode: z.enum(BILL_RUN_MODES).default("real")
|
|
308
|
+
});
|
|
309
|
+
const billingRunListQuerySchema = z.object({
|
|
310
|
+
...listPaginationBase,
|
|
311
|
+
id: z.string().uuid().optional(),
|
|
312
|
+
search: z.string().optional(),
|
|
313
|
+
status: z.enum(BILL_RUN_STATUSES).optional(),
|
|
314
|
+
triggeredBy: z.enum(BILL_RUN_TRIGGERS).optional(),
|
|
315
|
+
parentRunId: z.string().uuid().optional(),
|
|
316
|
+
asOfDateFrom: z.coerce.date().optional(),
|
|
317
|
+
asOfDateTo: z.coerce.date().optional()
|
|
318
|
+
}).passthrough();
|
|
319
|
+
const billingInvoicePostSchema = scopedSchema.extend({
|
|
320
|
+
invoiceId: z.string().uuid()
|
|
321
|
+
});
|
|
322
|
+
const lineEditableFields = z.object({
|
|
323
|
+
description: z.string().trim().min(1).max(500).optional(),
|
|
324
|
+
quantity: z.coerce.number().finite().nonnegative().optional(),
|
|
325
|
+
unitPriceNet: z.coerce.number().finite().optional(),
|
|
326
|
+
// `totalNetAmount` is operator-overridable for the "I know better
|
|
327
|
+
// than `unit_price × quantity`" cases (rare; mostly for negative
|
|
328
|
+
// credits or rounding fix-ups). When provided, it short-circuits
|
|
329
|
+
// the auto-compute path.
|
|
330
|
+
totalNetAmount: z.coerce.number().finite().optional()
|
|
331
|
+
});
|
|
332
|
+
const billingInvoiceEditLineSchema = scopedSchema.extend({
|
|
333
|
+
invoiceId: z.string().uuid(),
|
|
334
|
+
invoiceLineId: z.string().uuid(),
|
|
335
|
+
changes: lineEditableFields
|
|
336
|
+
});
|
|
337
|
+
const billingInvoiceAddLineSchema = scopedSchema.extend({
|
|
338
|
+
invoiceId: z.string().uuid(),
|
|
339
|
+
description: z.string().trim().min(1).max(500),
|
|
340
|
+
quantity: z.coerce.number().finite().nonnegative(),
|
|
341
|
+
unitPriceNet: z.coerce.number().finite(),
|
|
342
|
+
// Optional metadata for traceability — typically operators leave
|
|
343
|
+
// `billing_item_id` blank because ad-hoc lines aren't tied to a
|
|
344
|
+
// Billing Item.
|
|
345
|
+
billingItemId: z.string().uuid().optional(),
|
|
346
|
+
billingType: z.enum(BILLING_ITEM_TYPES).optional()
|
|
347
|
+
});
|
|
348
|
+
const billingInvoiceRemoveLineSchema = scopedSchema.extend({
|
|
349
|
+
invoiceId: z.string().uuid(),
|
|
350
|
+
invoiceLineId: z.string().uuid()
|
|
351
|
+
});
|
|
352
|
+
const billingWipeTestInvoicesSchema = scopedSchema.extend({
|
|
353
|
+
/** Optional — when set, wipes only test invoices from this run. */
|
|
354
|
+
billRunId: z.string().uuid().optional()
|
|
355
|
+
});
|
|
356
|
+
export {
|
|
357
|
+
BILLING_ITEM_TYPES,
|
|
358
|
+
BILL_CYCLES,
|
|
359
|
+
BILL_RUN_MODES,
|
|
360
|
+
BILL_RUN_OUTCOME_STATUSES,
|
|
361
|
+
BILL_RUN_STATUSES,
|
|
362
|
+
BILL_RUN_TRIGGERS,
|
|
363
|
+
DRAFT_INVOICE_EDIT_ACTIONS,
|
|
364
|
+
INVOICE_STATUSES,
|
|
365
|
+
billCycleAnchorSchema,
|
|
366
|
+
billingAccountCreateSchema,
|
|
367
|
+
billingAccountDeleteSchema,
|
|
368
|
+
billingAccountListQuerySchema,
|
|
369
|
+
billingAccountUpdateSchema,
|
|
370
|
+
billingInvoiceAddLineSchema,
|
|
371
|
+
billingInvoiceEditLineSchema,
|
|
372
|
+
billingInvoicePostSchema,
|
|
373
|
+
billingInvoiceRemoveLineSchema,
|
|
374
|
+
billingItemBulkCreateSchema,
|
|
375
|
+
billingItemCreateSchema,
|
|
376
|
+
billingItemDeleteSchema,
|
|
377
|
+
billingItemListQuerySchema,
|
|
378
|
+
billingItemUpdateSchema,
|
|
379
|
+
billingRunListQuerySchema,
|
|
380
|
+
billingRunRetryFailedSchema,
|
|
381
|
+
billingRunTriggerSchema,
|
|
382
|
+
billingUsageCreateSchema,
|
|
383
|
+
billingUsageListQuerySchema,
|
|
384
|
+
billingWipeTestInvoicesSchema,
|
|
385
|
+
invoiceAddressSchema,
|
|
386
|
+
rateJsonOneTime,
|
|
387
|
+
rateJsonRecurring,
|
|
388
|
+
rateJsonUsage,
|
|
389
|
+
rateJsonUsageFlat,
|
|
390
|
+
rateJsonUsageGraduated,
|
|
391
|
+
rateJsonUsageSimple,
|
|
392
|
+
rateJsonUsageTiered,
|
|
393
|
+
rateJsonUsageVolume,
|
|
394
|
+
validateRateJson
|
|
395
|
+
};
|
|
396
|
+
//# sourceMappingURL=validators.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/billing/data/validators.ts"],
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod'\n\n// \u2500\u2500\u2500 Enums \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport const BILLING_ITEM_TYPES = ['one_time', 'recurring', 'usage'] as const\nexport type BillingItemType = (typeof BILLING_ITEM_TYPES)[number]\n\nexport const BILL_CYCLES = ['weekly', 'monthly', 'quarterly', 'annually'] as const\nexport type BillCycle = (typeof BILL_CYCLES)[number]\n\nexport const BILL_RUN_TRIGGERS = ['schedule', 'manual'] as const\nexport type BillRunTrigger = (typeof BILL_RUN_TRIGGERS)[number]\n\nexport const BILL_RUN_STATUSES = ['running', 'completed', 'partial_failure', 'failed'] as const\nexport type BillRunStatus = (typeof BILL_RUN_STATUSES)[number]\n\nexport const BILL_RUN_OUTCOME_STATUSES = [\n 'success',\n 'success_with_warnings',\n 'skipped_existing_draft',\n 'failed',\n] as const\nexport type BillRunOutcomeStatus = (typeof BILL_RUN_OUTCOME_STATUSES)[number]\n\nexport const DRAFT_INVOICE_EDIT_ACTIONS = ['line_added', 'line_removed', 'line_edited'] as const\nexport type DraftInvoiceEditAction = (typeof DRAFT_INVOICE_EDIT_ACTIONS)[number]\n\nexport const INVOICE_STATUSES = ['draft', 'posted', 'paid', 'void'] as const\nexport type InvoiceStatus = (typeof INVOICE_STATUSES)[number]\n\n// `mon`\u2013`sun` for weekly cycles; 1\u201328 (as text) for the others.\n// Why text for numeric anchors: the column type stays uniform across cycles\n// and we never do arithmetic on the raw value (the engine parses it on use).\nconst WEEKLY_ANCHORS = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'] as const\n\nexport const billCycleAnchorSchema = z\n .string()\n .min(1)\n .refine(\n (val) => {\n if ((WEEKLY_ANCHORS as readonly string[]).includes(val.toLowerCase())) return true\n const n = Number.parseInt(val, 10)\n return Number.isInteger(n) && n >= 1 && n <= 28\n },\n {\n message:\n 'bill_cycle_anchor must be 1\u201328 (monthly/quarterly/annually) or mon\u2013sun (weekly)',\n },\n )\n\n// \u2500\u2500\u2500 rate_json \u2014 pricing definitions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// Validated at API ingress so the engine can trust the shape downstream.\n// Negative amounts are intentionally allowed only on `one_time` (refunds /\n// credits / proration credits). Recurring and usage unit prices MUST be\n// non-negative \u2014 discounts on those are modeled as separate `one_time`\n// credit items.\n\nconst numericNonNegative = z.number().finite().nonnegative()\nconst numericAny = z.number().finite()\n\nexport const rateJsonOneTime = z\n .object({ amount: numericAny })\n .strict()\n\nexport const rateJsonRecurring = z\n .object({ unit_price: numericNonNegative })\n .strict()\n\nexport const rateJsonUsageSimple = z\n .object({ unit_price: numericNonNegative })\n .strict()\n\nconst tierWithUnitPrice = z\n .object({\n up_to: z.union([z.number().int().positive(), z.null()]),\n unit_price: numericNonNegative,\n })\n .strict()\n\nconst tierWithFlatAmount = z\n .object({\n up_to: z.union([z.number().int().positive(), z.null()]),\n flat_amount: numericNonNegative,\n })\n .strict()\n\n// All tiers must use the same key shape (consistent with the model). Mixing\n// `unit_price` and `flat_amount` across tiers is rejected \u2014 see spec\n// validation rules.\nconst tiersUnitPrice = z\n .array(tierWithUnitPrice)\n .min(1, 'tiers must be a non-empty array')\nconst tiersFlatAmount = z\n .array(tierWithFlatAmount)\n .min(1, 'tiers must be a non-empty array')\n\nfunction refineTierProgression<T extends { up_to: number | null }>(\n tiers: T[],\n ctx: z.RefinementCtx,\n): void {\n const openTopCount = tiers.filter((t) => t.up_to === null).length\n if (openTopCount !== 1) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'tiers must contain exactly one open-ended top tier (up_to: null)',\n })\n return\n }\n if (tiers[tiers.length - 1].up_to !== null) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'the open-ended top tier (up_to: null) must be the last entry',\n })\n return\n }\n for (let i = 1; i < tiers.length - 1; i++) {\n const prev = tiers[i - 1].up_to\n const curr = tiers[i].up_to\n if (prev !== null && curr !== null && curr <= prev) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `up_to values must be strictly increasing across tiers (failed at index ${i})`,\n })\n return\n }\n }\n}\n\nexport const rateJsonUsageVolume = z\n .object({\n model: z.literal('volume'),\n tiers: tiersUnitPrice,\n })\n .strict()\n .superRefine((val, ctx) => refineTierProgression(val.tiers, ctx))\n\nexport const rateJsonUsageGraduated = z\n .object({\n model: z.literal('graduated'),\n tiers: tiersUnitPrice,\n })\n .strict()\n .superRefine((val, ctx) => refineTierProgression(val.tiers, ctx))\n\nexport const rateJsonUsageFlat = z\n .object({\n model: z.literal('flat'),\n tiers: tiersFlatAmount,\n })\n .strict()\n .superRefine((val, ctx) => refineTierProgression(val.tiers, ctx))\n\nexport const rateJsonUsageTiered = z.discriminatedUnion('model', [\n rateJsonUsageVolume,\n rateJsonUsageGraduated,\n rateJsonUsageFlat,\n])\n\nexport const rateJsonUsage = z.union([rateJsonUsageSimple, rateJsonUsageTiered])\n\n/**\n * Validate a `rate_json` payload against the rules for a given Billing Item\n * `type`. Returns the parsed value or throws a `ZodError` whose message\n * surfaces the specific shape violation.\n */\nexport function validateRateJson(\n type: BillingItemType,\n rateJson: unknown,\n):\n | z.infer<typeof rateJsonOneTime>\n | z.infer<typeof rateJsonRecurring>\n | z.infer<typeof rateJsonUsage> {\n switch (type) {\n case 'one_time':\n return rateJsonOneTime.parse(rateJson)\n case 'recurring':\n return rateJsonRecurring.parse(rateJson)\n case 'usage':\n return rateJsonUsage.parse(rateJson)\n }\n}\n\n// \u2500\u2500\u2500 Invoice address (BillingAccount.invoice_address) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport const invoiceAddressSchema = z\n .object({\n line1: z.string().min(1),\n line2: z.string().optional(),\n city: z.string().min(1),\n postal_code: z.string().min(1),\n country: z.string().min(2).max(3), // ISO 3166-1 alpha-2 or alpha-3\n })\n .strict()\n\nexport type InvoiceAddress = z.infer<typeof invoiceAddressSchema>\n\n// \u2500\u2500\u2500 Scope (injected by withScopedPayload at API ingress) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst scopedSchema = z.object({\n tenantId: z.string().uuid(),\n organizationId: z.string().uuid(),\n})\n\n// \u2500\u2500\u2500 List pagination (shared shape) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst listPaginationBase = {\n page: z.coerce.number().int().min(1).default(1),\n pageSize: z.coerce.number().int().min(1).max(100).default(50),\n sortField: z.string().optional(),\n sortDir: z.enum(['asc', 'desc']).optional(),\n}\n\n// \u2500\u2500\u2500 BillingAccount payloads \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport const billingAccountCreateSchema = scopedSchema.extend({\n customerId: z.string().min(1).max(255),\n name: z.string().trim().min(1).max(255),\n currencyCode: z.string().trim().toUpperCase().length(3),\n billCycle: z.enum(BILL_CYCLES),\n billCycleAnchor: billCycleAnchorSchema,\n invoiceEmail: z.string().trim().email().max(320),\n invoiceLanguage: z.string().trim().toLowerCase().min(2).max(5),\n // Nullable + optional \u2014 consistent with the update schema, and the\n // cpq-billing-connector's shell-account seed sends `taxId: null`\n // for customers with no tax id.\n taxId: z.string().trim().max(64).nullable().optional(),\n invoiceAddress: invoiceAddressSchema,\n nextBillDate: z.coerce.date(),\n lastBillDate: z.coerce.date().optional(),\n isActive: z.boolean().optional(),\n})\n\nexport type BillingAccountCreateInput = z.infer<typeof billingAccountCreateSchema>\n\nexport const billingAccountUpdateSchema = scopedSchema.extend({\n id: z.string().uuid(),\n name: z.string().trim().min(1).max(255).optional(),\n billCycle: z.enum(BILL_CYCLES).optional(),\n billCycleAnchor: billCycleAnchorSchema.optional(),\n invoiceEmail: z.string().trim().email().max(320).optional(),\n invoiceLanguage: z.string().trim().toLowerCase().min(2).max(5).optional(),\n taxId: z.string().trim().max(64).nullable().optional(),\n invoiceAddress: invoiceAddressSchema.optional(),\n nextBillDate: z.coerce.date().optional(),\n lastBillDate: z.coerce.date().nullable().optional(),\n isActive: z.boolean().optional(),\n // `currencyCode` is intentionally NOT updatable \u2014 currency is frozen at\n // account create time so historical invoices keep their currency context.\n // `customerId` is also immutable; create a new account if the customer\n // FK changes.\n})\n\nexport type BillingAccountUpdateInput = z.infer<typeof billingAccountUpdateSchema>\n\nexport const billingAccountDeleteSchema = scopedSchema.extend({\n id: z.string().uuid(),\n})\n\nexport type BillingAccountDeleteInput = z.infer<typeof billingAccountDeleteSchema>\n\nexport const billingAccountListQuerySchema = z\n .object({\n ...listPaginationBase,\n id: z.string().uuid().optional(),\n customerId: z.string().optional(),\n currencyCode: z.string().optional(),\n billCycle: z.enum(BILL_CYCLES).optional(),\n isActive: z.coerce.boolean().optional(),\n search: z.string().optional(),\n })\n .passthrough()\n\nexport type BillingAccountListQuery = z.infer<typeof billingAccountListQuerySchema>\n\n// \u2500\u2500\u2500 BillingItem payloads \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst ratePayloadByType = z\n .object({\n type: z.enum(BILLING_ITEM_TYPES),\n rateJson: z.unknown(),\n })\n .superRefine((val, ctx) => {\n try {\n validateRateJson(val.type, val.rateJson)\n } catch (err) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['rateJson'],\n message: err instanceof Error ? err.message : 'rate_json is invalid for this type',\n })\n }\n })\n\nexport const billingItemCreateSchema = scopedSchema\n .extend({\n billAccountId: z.string().uuid(),\n type: z.enum(BILLING_ITEM_TYPES),\n billStartDate: z.coerce.date(),\n billEndDate: z.coerce.date().nullable().optional(),\n description: z.string().trim().min(1).max(500),\n rateJson: z.unknown(), // shape validated via the refine below\n uomCode: z.string().trim().max(64).optional(),\n subscriptionId: z.string().trim().max(255).optional(),\n subscriptionItemId: z.string().trim().max(255).optional(),\n // `source_ref` is the idempotency key. NULL \u2192 no dedup, always create.\n sourceRef: z.string().trim().min(1).max(255).optional(),\n // currency_mismatch and billed_to_date are system-managed, never set by\n // clients on create.\n })\n .superRefine((val, ctx) => {\n try {\n validateRateJson(val.type, val.rateJson)\n } catch (err) {\n const message = err instanceof Error ? err.message : 'rate_json is invalid for this type'\n ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['rateJson'], message })\n }\n if (val.type === 'usage' && !val.uomCode) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['uomCode'],\n message: 'uomCode is required for type=usage',\n })\n }\n })\n\nexport type BillingItemCreateInput = z.infer<typeof billingItemCreateSchema>\n\n// \u2500\u2500\u2500 Bulk item create (Phase 4g) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// One scope envelope, N item payloads. The CPQ connector activating\n// a large subscription used to fire one `billing.items.create` per\n// charge \u2014 bulk-create collapses that into a single command with a\n// batched `source_ref` idempotency check + single flush.\n\nconst billingItemBulkEntrySchema = z\n .object({\n billAccountId: z.string().uuid(),\n type: z.enum(BILLING_ITEM_TYPES),\n billStartDate: z.coerce.date(),\n billEndDate: z.coerce.date().nullable().optional(),\n description: z.string().trim().min(1).max(500),\n rateJson: z.unknown(),\n uomCode: z.string().trim().max(64).optional(),\n subscriptionId: z.string().trim().max(255).optional(),\n subscriptionItemId: z.string().trim().max(255).optional(),\n sourceRef: z.string().trim().min(1).max(255).optional(),\n })\n .superRefine((val, ctx) => {\n try {\n validateRateJson(val.type, val.rateJson)\n } catch (err) {\n const message = err instanceof Error ? err.message : 'rate_json is invalid for this type'\n ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['rateJson'], message })\n }\n if (val.type === 'usage' && !val.uomCode) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['uomCode'],\n message: 'uomCode is required for type=usage',\n })\n }\n })\n\nexport type BillingItemBulkEntry = z.infer<typeof billingItemBulkEntrySchema>\n\nexport const billingItemBulkCreateSchema = scopedSchema.extend({\n // Cap at 500 per call \u2014 keeps a single bulk transaction bounded.\n // A CPQ subscription with >500 charges should be split by the\n // caller (the connector); 500 is already far past any realistic\n // single-subscription charge count.\n items: z.array(billingItemBulkEntrySchema).min(1).max(500),\n})\n\nexport type BillingItemBulkCreateInput = z.infer<typeof billingItemBulkCreateSchema>\n\nexport const billingItemUpdateSchema = scopedSchema.extend({\n id: z.string().uuid(),\n // `type` is immutable \u2014 changing one_time \u2192 recurring would silently\n // change billing semantics. Cancel the old item, create a new one.\n billStartDate: z.coerce.date().optional(),\n billEndDate: z.coerce.date().nullable().optional(),\n description: z.string().trim().min(1).max(500).optional(),\n rateJson: z.unknown().optional(),\n uomCode: z.string().trim().max(64).nullable().optional(),\n subscriptionId: z.string().trim().max(255).nullable().optional(),\n subscriptionItemId: z.string().trim().max(255).nullable().optional(),\n // `source_ref` immutable \u2014 it's the idempotency identity of the item.\n isActive: z.boolean().optional(),\n})\n\nexport type BillingItemUpdateInput = z.infer<typeof billingItemUpdateSchema>\n\nexport const billingItemDeleteSchema = scopedSchema.extend({\n id: z.string().uuid(),\n})\n\nexport type BillingItemDeleteInput = z.infer<typeof billingItemDeleteSchema>\n\nexport const billingItemListQuerySchema = z\n .object({\n ...listPaginationBase,\n id: z.string().uuid().optional(),\n search: z.string().optional(),\n billAccountId: z.string().uuid().optional(),\n type: z.enum(BILLING_ITEM_TYPES).optional(),\n subscriptionId: z.string().optional(),\n isActive: z.coerce.boolean().optional(),\n activeAt: z.coerce.date().optional(), // bill_start_date <= X AND (bill_end_date IS NULL OR bill_end_date >= X)\n })\n .passthrough()\n\nexport type BillingItemListQuery = z.infer<typeof billingItemListQuerySchema>\n\n// \u2500\u2500\u2500 BillingAccountUsage payloads \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport const billingUsageCreateSchema = scopedSchema.extend({\n billAccountId: z.string().uuid(),\n uomCode: z.string().trim().min(1).max(64),\n // `quantity` arrives as a number from JSON; MikroORM stores it as\n // numeric(18,4). The service coerces to a string at persist time.\n quantity: z.number().finite().nonnegative(),\n periodStart: z.coerce.date(),\n periodEnd: z.coerce.date(),\n lineDescription: z.string().trim().min(1).max(500).optional(),\n sourceRef: z.string().trim().min(1).max(255).optional(),\n}).superRefine((val, ctx) => {\n if (val.periodEnd < val.periodStart) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['periodEnd'],\n message: 'periodEnd must be on or after periodStart',\n })\n }\n})\n\nexport type BillingUsageCreateInput = z.infer<typeof billingUsageCreateSchema>\n\nexport const billingUsageListQuerySchema = z\n .object({\n ...listPaginationBase,\n billAccountId: z.string().uuid().optional(),\n uomCode: z.string().optional(),\n rated: z.coerce.boolean().optional(), // true \u2192 already rated; false \u2192 unrated\n periodEndFrom: z.coerce.date().optional(),\n periodEndTo: z.coerce.date().optional(),\n })\n .passthrough()\n\nexport type BillingUsageListQuery = z.infer<typeof billingUsageListQuerySchema>\n\n// Suppress unused-export TS warning \u2014 `ratePayloadByType` is reserved for\n// reuse by a future per-tenant rate-validation CLI tool.\nvoid ratePayloadByType\n\n// \u2500\u2500\u2500 Bill Run trigger payloads (Phase 2) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport const BILL_RUN_MODES = ['real', 'test', 'dry'] as const\nexport type BillRunMode = (typeof BILL_RUN_MODES)[number]\n\nexport const billingRunTriggerSchema = scopedSchema.extend({\n // `triggeredBy` is filled in by the route layer (always 'manual' for\n // API triggers; the cron worker sets 'schedule'). The client cannot\n // forge a 'schedule' trigger \u2014 the field is intentionally omitted\n // from the input shape.\n mode: z.enum(BILL_RUN_MODES).default('real'),\n asOfDate: z.coerce.date().optional(),\n scopedAccountIds: z.array(z.string().uuid()).optional(),\n catchUp: z.boolean().optional(),\n})\n\nexport type BillingRunTriggerInput = z.infer<typeof billingRunTriggerSchema>\n\nexport const billingRunRetryFailedSchema = scopedSchema.extend({\n billRunId: z.string().uuid(),\n mode: z.enum(BILL_RUN_MODES).default('real'),\n})\n\nexport type BillingRunRetryFailedInput = z.infer<typeof billingRunRetryFailedSchema>\n\nexport const billingRunListQuerySchema = z\n .object({\n ...listPaginationBase,\n id: z.string().uuid().optional(),\n search: z.string().optional(),\n status: z.enum(BILL_RUN_STATUSES).optional(),\n triggeredBy: z.enum(BILL_RUN_TRIGGERS).optional(),\n parentRunId: z.string().uuid().optional(),\n asOfDateFrom: z.coerce.date().optional(),\n asOfDateTo: z.coerce.date().optional(),\n })\n .passthrough()\n\nexport type BillingRunListQuery = z.infer<typeof billingRunListQuerySchema>\n\n// \u2500\u2500\u2500 Invoice post (Phase 4) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport const billingInvoicePostSchema = scopedSchema.extend({\n invoiceId: z.string().uuid(),\n})\n\nexport type BillingInvoicePostInput = z.infer<typeof billingInvoicePostSchema>\n\n// \u2500\u2500\u2500 Draft invoice edits (Phase 4b) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Fields the operator may change on a draft invoice line. Per spec:\n * \"operator CAN: add lines, remove lines, edit line description /\n * quantity / unit_price / amount\". `taxRate` is owned by core/sales\n * tax service and `currencyCode` is frozen at account create \u2014 both\n * intentionally absent from this schema.\n */\nconst lineEditableFields = z.object({\n description: z.string().trim().min(1).max(500).optional(),\n quantity: z.coerce.number().finite().nonnegative().optional(),\n unitPriceNet: z.coerce.number().finite().optional(),\n // `totalNetAmount` is operator-overridable for the \"I know better\n // than `unit_price \u00D7 quantity`\" cases (rare; mostly for negative\n // credits or rounding fix-ups). When provided, it short-circuits\n // the auto-compute path.\n totalNetAmount: z.coerce.number().finite().optional(),\n})\n\nexport const billingInvoiceEditLineSchema = scopedSchema.extend({\n invoiceId: z.string().uuid(),\n invoiceLineId: z.string().uuid(),\n changes: lineEditableFields,\n})\n\nexport type BillingInvoiceEditLineInput = z.infer<typeof billingInvoiceEditLineSchema>\n\nexport const billingInvoiceAddLineSchema = scopedSchema.extend({\n invoiceId: z.string().uuid(),\n description: z.string().trim().min(1).max(500),\n quantity: z.coerce.number().finite().nonnegative(),\n unitPriceNet: z.coerce.number().finite(),\n // Optional metadata for traceability \u2014 typically operators leave\n // `billing_item_id` blank because ad-hoc lines aren't tied to a\n // Billing Item.\n billingItemId: z.string().uuid().optional(),\n billingType: z.enum(BILLING_ITEM_TYPES).optional(),\n})\n\nexport type BillingInvoiceAddLineInput = z.infer<typeof billingInvoiceAddLineSchema>\n\nexport const billingInvoiceRemoveLineSchema = scopedSchema.extend({\n invoiceId: z.string().uuid(),\n invoiceLineId: z.string().uuid(),\n})\n\nexport type BillingInvoiceRemoveLineInput = z.infer<typeof billingInvoiceRemoveLineSchema>\n\n// \u2500\u2500\u2500 Test-invoices wipe (Phase 4b) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport const billingWipeTestInvoicesSchema = scopedSchema.extend({\n /** Optional \u2014 when set, wipes only test invoices from this run. */\n billRunId: z.string().uuid().optional(),\n})\n\nexport type BillingWipeTestInvoicesInput = z.infer<typeof billingWipeTestInvoicesSchema>\n\n\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/modules/billing/di.ts"],
|
|
4
|
+
"sourcesContent": ["import type { AppContainer } from '@open-mercato/shared/lib/di/container'\n\n/**\n * Billing module DI registrar.\n *\n * Phase 0 ships no services \u2014 entities, ACL, and tenant setup only. The\n * REST API surface (Phase 1) and Bill Run engine (Phase 2) bring services\n * here. Keeping the file in place so the auto-discovery generator picks\n * up `billing` as a DI-aware module without surprise on the first new\n * registration.\n */\nexport function register(_container: AppContainer): void {\n // intentionally empty \u2014 see file header\n}\n"],
|
|
5
|
+
"mappings": "AAWO,SAAS,SAAS,YAAgC;AAEzD;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createModuleEvents } from "@open-mercato/shared/modules/events";
|
|
2
|
+
const events = [
|
|
3
|
+
{
|
|
4
|
+
id: "billing.invoice.posted",
|
|
5
|
+
label: "Billing Invoice Posted",
|
|
6
|
+
entity: "invoice",
|
|
7
|
+
category: "lifecycle",
|
|
8
|
+
clientBroadcast: true
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
id: "billing.invoice.line_posted",
|
|
12
|
+
label: "Billing Invoice Line Posted",
|
|
13
|
+
entity: "invoice_line",
|
|
14
|
+
category: "lifecycle"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
id: "billing.run.completed",
|
|
18
|
+
label: "Bill Run Completed",
|
|
19
|
+
entity: "bill_run",
|
|
20
|
+
category: "lifecycle",
|
|
21
|
+
clientBroadcast: true
|
|
22
|
+
}
|
|
23
|
+
];
|
|
24
|
+
const eventsConfig = createModuleEvents({
|
|
25
|
+
moduleId: "billing",
|
|
26
|
+
events
|
|
27
|
+
});
|
|
28
|
+
const emitBillingEvent = eventsConfig.emit;
|
|
29
|
+
var events_default = eventsConfig;
|
|
30
|
+
export {
|
|
31
|
+
events_default as default,
|
|
32
|
+
emitBillingEvent,
|
|
33
|
+
eventsConfig
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/modules/billing/events.ts"],
|
|
4
|
+
"sourcesContent": ["import { createModuleEvents } from '@open-mercato/shared/modules/events'\n\n/**\n * Billing module events.\n *\n * Emission contract:\n * - `billing.invoice.posted` fires once per posted draft AFTER the post\n * transaction commits (sequence number assigned, status set to `posted`\n * in core/sales). Consumed by mailers / accounting bridges / analytics.\n * - `billing.invoice.line_posted` fires once per line on a posted invoice\n * so analytics can aggregate without scanning core/sales lines directly.\n * - `billing.run.completed` fires once per Bill Run after all per-account\n * transactions finished (status is one of `completed` / `partial_failure`\n * / `failed`). Useful for \"did the nightly run go OK?\" alerts.\n */\nconst events = [\n {\n id: 'billing.invoice.posted',\n label: 'Billing Invoice Posted',\n entity: 'invoice',\n category: 'lifecycle',\n clientBroadcast: true,\n },\n {\n id: 'billing.invoice.line_posted',\n label: 'Billing Invoice Line Posted',\n entity: 'invoice_line',\n category: 'lifecycle',\n },\n {\n id: 'billing.run.completed',\n label: 'Bill Run Completed',\n entity: 'bill_run',\n category: 'lifecycle',\n clientBroadcast: true,\n },\n] as const\n\nexport const eventsConfig = createModuleEvents({\n moduleId: 'billing',\n events,\n})\n\nexport const emitBillingEvent = eventsConfig.emit\nexport type BillingEventId = (typeof events)[number]['id']\n\nexport default eventsConfig\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,0BAA0B;AAenC,MAAM,SAAS;AAAA,EACb;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,iBAAiB;AAAA,EACnB;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,iBAAiB;AAAA,EACnB;AACF;AAEO,MAAM,eAAe,mBAAmB;AAAA,EAC7C,UAAU;AAAA,EACV;AACF,CAAC;AAEM,MAAM,mBAAmB,aAAa;AAG7C,IAAO,iBAAQ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|