@dainamite/billing 0.20.0 → 0.22.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 +103 -0
- package/dist/modules/billing/acl.js +13 -1
- package/dist/modules/billing/acl.js.map +2 -2
- package/dist/modules/billing/api/accounts/[id]/summary/route.js +52 -0
- package/dist/modules/billing/api/accounts/[id]/summary/route.js.map +7 -0
- package/dist/modules/billing/api/accounts/route.js +47 -4
- package/dist/modules/billing/api/accounts/route.js.map +2 -2
- package/dist/modules/billing/api/export/account/[id]/route.js +11 -7
- package/dist/modules/billing/api/export/account/[id]/route.js.map +2 -2
- package/dist/modules/billing/api/invoices/[id]/memos/route.js +54 -0
- package/dist/modules/billing/api/invoices/[id]/memos/route.js.map +7 -0
- package/dist/modules/billing/api/invoices/[id]/pdf/route.js +70 -0
- package/dist/modules/billing/api/invoices/[id]/pdf/route.js.map +7 -0
- package/dist/modules/billing/api/invoices/[id]/route.js +44 -24
- package/dist/modules/billing/api/invoices/[id]/route.js.map +2 -2
- package/dist/modules/billing/api/invoices/[id]/send/route.js +107 -0
- package/dist/modules/billing/api/invoices/[id]/send/route.js.map +7 -0
- package/dist/modules/billing/api/invoices/add-line/route.js +2 -2
- package/dist/modules/billing/api/invoices/add-line/route.js.map +2 -2
- package/dist/modules/billing/api/invoices/delete-draft/route.js +33 -0
- package/dist/modules/billing/api/invoices/delete-draft/route.js.map +7 -0
- package/dist/modules/billing/api/invoices/edit-line/route.js +2 -2
- package/dist/modules/billing/api/invoices/edit-line/route.js.map +2 -2
- package/dist/modules/billing/api/invoices/post/route.js +2 -2
- package/dist/modules/billing/api/invoices/post/route.js.map +2 -2
- package/dist/modules/billing/api/invoices/remove-line/route.js +2 -2
- package/dist/modules/billing/api/invoices/remove-line/route.js.map +2 -2
- package/dist/modules/billing/api/invoices/route.js +45 -46
- package/dist/modules/billing/api/invoices/route.js.map +2 -2
- package/dist/modules/billing/api/items/bulk/route.js +1 -1
- package/dist/modules/billing/api/items/bulk/route.js.map +2 -2
- package/dist/modules/billing/api/items/change-price/route.js +44 -0
- package/dist/modules/billing/api/items/change-price/route.js.map +7 -0
- package/dist/modules/billing/api/items/route.js +19 -7
- package/dist/modules/billing/api/items/route.js.map +2 -2
- package/dist/modules/billing/api/payment-imports/[id]/route.js +49 -0
- package/dist/modules/billing/api/payment-imports/[id]/route.js.map +7 -0
- package/dist/modules/billing/api/payment-imports/route.js +57 -0
- package/dist/modules/billing/api/payment-imports/route.js.map +7 -0
- package/dist/modules/billing/api/payments/[id]/route.js +60 -0
- package/dist/modules/billing/api/payments/[id]/route.js.map +7 -0
- package/dist/modules/billing/api/payments/allocate/route.js +35 -0
- package/dist/modules/billing/api/payments/allocate/route.js.map +7 -0
- package/dist/modules/billing/api/payments/assign/route.js +36 -0
- package/dist/modules/billing/api/payments/assign/route.js.map +7 -0
- package/dist/modules/billing/api/payments/convert-to-topup/route.js +35 -0
- package/dist/modules/billing/api/payments/convert-to-topup/route.js.map +7 -0
- package/dist/modules/billing/api/payments/ignore/route.js +35 -0
- package/dist/modules/billing/api/payments/ignore/route.js.map +7 -0
- package/dist/modules/billing/api/payments/import/route.js +63 -0
- package/dist/modules/billing/api/payments/import/route.js.map +7 -0
- package/dist/modules/billing/api/payments/restore/route.js +35 -0
- package/dist/modules/billing/api/payments/restore/route.js.map +7 -0
- package/dist/modules/billing/api/payments/route.js +114 -0
- package/dist/modules/billing/api/payments/route.js.map +7 -0
- package/dist/modules/billing/api/payments/unallocate/route.js +35 -0
- package/dist/modules/billing/api/payments/unallocate/route.js.map +7 -0
- package/dist/modules/billing/api/payments/unassign/route.js +35 -0
- package/dist/modules/billing/api/payments/unassign/route.js.map +7 -0
- package/dist/modules/billing/api/run-outcomes/route.js +43 -6
- package/dist/modules/billing/api/run-outcomes/route.js.map +2 -2
- package/dist/modules/billing/api/runs/[id]/post-drafts/route.js +61 -0
- package/dist/modules/billing/api/runs/[id]/post-drafts/route.js.map +7 -0
- package/dist/modules/billing/api/runs/[id]/route.js +53 -0
- package/dist/modules/billing/api/runs/[id]/route.js.map +7 -0
- package/dist/modules/billing/api/runs/retry-failed/route.js +1 -1
- package/dist/modules/billing/api/runs/retry-failed/route.js.map +2 -2
- package/dist/modules/billing/api/runs/route.js +9 -3
- package/dist/modules/billing/api/runs/route.js.map +2 -2
- package/dist/modules/billing/api/settings/number-preview/route.js +42 -0
- package/dist/modules/billing/api/settings/number-preview/route.js.map +7 -0
- package/dist/modules/billing/api/settings/route.js +92 -0
- package/dist/modules/billing/api/settings/route.js.map +7 -0
- package/dist/modules/billing/api/statements/route.js +3 -0
- package/dist/modules/billing/api/statements/route.js.map +2 -2
- package/dist/modules/billing/api/test-invoices/wipe/route.js +2 -2
- package/dist/modules/billing/api/test-invoices/wipe/route.js.map +2 -2
- package/dist/modules/billing/backend/billing/accounts/[id]/page.js +121 -232
- package/dist/modules/billing/backend/billing/accounts/[id]/page.js.map +2 -2
- package/dist/modules/billing/backend/billing/accounts/create/page.js +6 -0
- package/dist/modules/billing/backend/billing/accounts/create/page.js.map +2 -2
- package/dist/modules/billing/backend/billing/accounts/page.js +63 -4
- package/dist/modules/billing/backend/billing/accounts/page.js.map +2 -2
- package/dist/modules/billing/backend/billing/invoices/[id]/page.js +297 -65
- package/dist/modules/billing/backend/billing/invoices/[id]/page.js.map +3 -3
- package/dist/modules/billing/backend/billing/invoices/page.js +6 -172
- package/dist/modules/billing/backend/billing/invoices/page.js.map +2 -2
- package/dist/modules/billing/backend/billing/items/[id]/page.js +51 -7
- package/dist/modules/billing/backend/billing/items/[id]/page.js.map +2 -2
- package/dist/modules/billing/backend/billing/items/create/page.js +9 -6
- package/dist/modules/billing/backend/billing/items/create/page.js.map +2 -2
- package/dist/modules/billing/backend/billing/items/page.js +8 -2
- package/dist/modules/billing/backend/billing/items/page.js.map +2 -2
- package/dist/modules/billing/backend/billing/payments/[id]/page.js +297 -0
- package/dist/modules/billing/backend/billing/payments/[id]/page.js.map +7 -0
- package/dist/modules/billing/backend/billing/payments/[id]/page.meta.js +21 -0
- package/dist/modules/billing/backend/billing/payments/[id]/page.meta.js.map +7 -0
- package/dist/modules/billing/backend/billing/payments/imports/[id]/page.js +74 -0
- package/dist/modules/billing/backend/billing/payments/imports/[id]/page.js.map +7 -0
- package/dist/modules/billing/backend/billing/payments/imports/[id]/page.meta.js +21 -0
- package/dist/modules/billing/backend/billing/payments/imports/[id]/page.meta.js.map +7 -0
- package/dist/modules/billing/backend/billing/payments/page.js +58 -0
- package/dist/modules/billing/backend/billing/payments/page.js.map +7 -0
- package/dist/modules/billing/backend/billing/payments/page.meta.js +18 -0
- package/dist/modules/billing/backend/billing/payments/page.meta.js.map +7 -0
- package/dist/modules/billing/backend/billing/runs/[id]/page.js +49 -14
- package/dist/modules/billing/backend/billing/runs/[id]/page.js.map +2 -2
- package/dist/modules/billing/backend/billing/runs/page.js +58 -7
- package/dist/modules/billing/backend/billing/runs/page.js.map +2 -2
- package/dist/modules/billing/backend/billing/statements/[id]/page.js +61 -6
- package/dist/modules/billing/backend/billing/statements/[id]/page.js.map +2 -2
- package/dist/modules/billing/backend/billing/statements/page.js +1 -1
- package/dist/modules/billing/backend/billing/statements/page.js.map +2 -2
- package/dist/modules/billing/backend/billing/topups/page.js +1 -1
- package/dist/modules/billing/backend/billing/topups/page.js.map +2 -2
- package/dist/modules/billing/backend/billing/transactions/page.js +1 -1
- package/dist/modules/billing/backend/billing/transactions/page.js.map +2 -2
- package/dist/modules/billing/backend/billing/usage/create/page.js +3 -2
- package/dist/modules/billing/backend/billing/usage/create/page.js.map +2 -2
- package/dist/modules/billing/backend/config/billing/page.js +472 -0
- package/dist/modules/billing/backend/config/billing/page.js.map +7 -0
- package/dist/modules/billing/backend/config/billing/page.meta.js +19 -0
- package/dist/modules/billing/backend/config/billing/page.meta.js.map +7 -0
- package/dist/modules/billing/cli.js +22 -1
- package/dist/modules/billing/cli.js.map +2 -2
- package/dist/modules/billing/commands/accounts.js +6 -0
- package/dist/modules/billing/commands/accounts.js.map +2 -2
- package/dist/modules/billing/commands/index.js +3 -0
- package/dist/modules/billing/commands/index.js.map +2 -2
- package/dist/modules/billing/commands/invoices.js +269 -167
- package/dist/modules/billing/commands/invoices.js.map +2 -2
- package/dist/modules/billing/commands/items.js +108 -0
- package/dist/modules/billing/commands/items.js.map +2 -2
- package/dist/modules/billing/commands/memos.js +179 -0
- package/dist/modules/billing/commands/memos.js.map +7 -0
- package/dist/modules/billing/commands/payments.js +379 -0
- package/dist/modules/billing/commands/payments.js.map +7 -0
- package/dist/modules/billing/commands/runs.js +151 -4
- package/dist/modules/billing/commands/runs.js.map +2 -2
- package/dist/modules/billing/commands/settings.js +59 -0
- package/dist/modules/billing/commands/settings.js.map +7 -0
- package/dist/modules/billing/commands/topups.js +9 -2
- package/dist/modules/billing/commands/topups.js.map +2 -2
- package/dist/modules/billing/commands/transactions.js +2 -2
- package/dist/modules/billing/commands/transactions.js.map +2 -2
- package/dist/modules/billing/components/AccountForm.js +149 -42
- package/dist/modules/billing/components/AccountForm.js.map +2 -2
- package/dist/modules/billing/components/AccountInvoicesSection.js +64 -0
- package/dist/modules/billing/components/AccountInvoicesSection.js.map +7 -0
- package/dist/modules/billing/components/AccountPaymentsSection.js +43 -0
- package/dist/modules/billing/components/AccountPaymentsSection.js.map +7 -0
- package/dist/modules/billing/components/AccountPicker.js +56 -0
- package/dist/modules/billing/components/AccountPicker.js.map +7 -0
- package/dist/modules/billing/components/AllocatePaymentDialog.js +134 -0
- package/dist/modules/billing/components/AllocatePaymentDialog.js.map +7 -0
- package/dist/modules/billing/components/BillingDataTable.js +21 -0
- package/dist/modules/billing/components/BillingDataTable.js.map +7 -0
- package/dist/modules/billing/components/BillingSettingsLink.js +19 -0
- package/dist/modules/billing/components/BillingSettingsLink.js.map +7 -0
- package/dist/modules/billing/components/ChangeItemPriceDialog.js +158 -0
- package/dist/modules/billing/components/ChangeItemPriceDialog.js.map +7 -0
- package/dist/modules/billing/components/CreateMemoDialog.js +200 -0
- package/dist/modules/billing/components/CreateMemoDialog.js.map +7 -0
- package/dist/modules/billing/components/CustomerLabel.js +33 -0
- package/dist/modules/billing/components/CustomerLabel.js.map +7 -0
- package/dist/modules/billing/components/InvoicesTable.js +270 -0
- package/dist/modules/billing/components/InvoicesTable.js.map +7 -0
- package/dist/modules/billing/components/ItemForm.js +176 -44
- package/dist/modules/billing/components/ItemForm.js.map +2 -2
- package/dist/modules/billing/components/ItemPriceField.js +46 -0
- package/dist/modules/billing/components/ItemPriceField.js.map +7 -0
- package/dist/modules/billing/components/LineFormDialog.js +25 -2
- package/dist/modules/billing/components/LineFormDialog.js.map +2 -2
- package/dist/modules/billing/components/ManualPaymentDialog.js +122 -0
- package/dist/modules/billing/components/ManualPaymentDialog.js.map +7 -0
- package/dist/modules/billing/components/MoneyInput.js +14 -0
- package/dist/modules/billing/components/MoneyInput.js.map +7 -0
- package/dist/modules/billing/components/PaymentUploadDialog.js +115 -0
- package/dist/modules/billing/components/PaymentUploadDialog.js.map +7 -0
- package/dist/modules/billing/components/PaymentsTable.js +171 -0
- package/dist/modules/billing/components/PaymentsTable.js.map +7 -0
- package/dist/modules/billing/components/PostRunDraftsButton.js +105 -0
- package/dist/modules/billing/components/PostRunDraftsButton.js.map +7 -0
- package/dist/modules/billing/components/PrepaidPanel.js +14 -4
- package/dist/modules/billing/components/PrepaidPanel.js.map +2 -2
- package/dist/modules/billing/components/RunCyclesSection.js +209 -0
- package/dist/modules/billing/components/RunCyclesSection.js.map +7 -0
- package/dist/modules/billing/components/TestRunActions.js +127 -0
- package/dist/modules/billing/components/TestRunActions.js.map +7 -0
- package/dist/modules/billing/components/account/AccountItemsTab.js +157 -0
- package/dist/modules/billing/components/account/AccountItemsTab.js.map +7 -0
- package/dist/modules/billing/components/account/AccountRunBillingDialog.js +122 -0
- package/dist/modules/billing/components/account/AccountRunBillingDialog.js.map +7 -0
- package/dist/modules/billing/components/account/AccountRunsTab.js +152 -0
- package/dist/modules/billing/components/account/AccountRunsTab.js.map +7 -0
- package/dist/modules/billing/components/account/AccountStatementsTab.js +98 -0
- package/dist/modules/billing/components/account/AccountStatementsTab.js.map +7 -0
- package/dist/modules/billing/components/account/AccountSummaryCards.js +125 -0
- package/dist/modules/billing/components/account/AccountSummaryCards.js.map +7 -0
- package/dist/modules/billing/components/account/AccountUsageTab.js +91 -0
- package/dist/modules/billing/components/account/AccountUsageTab.js.map +7 -0
- package/dist/modules/billing/components/account/AccountView.js +73 -0
- package/dist/modules/billing/components/account/AccountView.js.map +7 -0
- package/dist/modules/billing/components/account/accountRow.js +39 -0
- package/dist/modules/billing/components/account/accountRow.js.map +7 -0
- package/dist/modules/billing/components/customerNames.js +42 -0
- package/dist/modules/billing/components/customerNames.js.map +7 -0
- package/dist/modules/billing/data/entities.js +560 -4
- package/dist/modules/billing/data/entities.js.map +2 -2
- package/dist/modules/billing/data/entityIds.js +10 -1
- package/dist/modules/billing/data/entityIds.js.map +2 -2
- package/dist/modules/billing/data/validators.js +269 -15
- package/dist/modules/billing/data/validators.js.map +2 -2
- package/dist/modules/billing/events.js +50 -0
- package/dist/modules/billing/events.js.map +2 -2
- package/dist/modules/billing/i18n/de.json +880 -0
- package/dist/modules/billing/i18n/en.json +457 -21
- package/dist/modules/billing/i18n/es.json +880 -0
- package/dist/modules/billing/i18n/pl.json +458 -22
- package/dist/modules/billing/index.js +6 -2
- package/dist/modules/billing/index.js.map +2 -2
- package/dist/modules/billing/lib/accountFinancials.js +58 -0
- package/dist/modules/billing/lib/accountFinancials.js.map +7 -0
- package/dist/modules/billing/lib/accountLock.js +14 -0
- package/dist/modules/billing/lib/accountLock.js.map +7 -0
- package/dist/modules/billing/lib/accountStatus.js +9 -7
- package/dist/modules/billing/lib/accountStatus.js.map +2 -2
- package/dist/modules/billing/lib/accountSummary.js +106 -0
- package/dist/modules/billing/lib/accountSummary.js.map +7 -0
- package/dist/modules/billing/lib/allocation.js +356 -0
- package/dist/modules/billing/lib/allocation.js.map +7 -0
- package/dist/modules/billing/lib/allocationEvents.js +22 -0
- package/dist/modules/billing/lib/allocationEvents.js.map +7 -0
- package/dist/modules/billing/lib/billPeriod.js +15 -1
- package/dist/modules/billing/lib/billPeriod.js.map +2 -2
- package/dist/modules/billing/lib/billRunEngine.js +237 -102
- package/dist/modules/billing/lib/billRunEngine.js.map +2 -2
- package/dist/modules/billing/lib/billingSettings.js +116 -0
- package/dist/modules/billing/lib/billingSettings.js.map +7 -0
- package/dist/modules/billing/lib/commandRoute.js +81 -0
- package/dist/modules/billing/lib/commandRoute.js.map +7 -0
- package/dist/modules/billing/lib/customerLookup.js +97 -0
- package/dist/modules/billing/lib/customerLookup.js.map +7 -0
- package/dist/modules/billing/lib/dateOnly.js +13 -0
- package/dist/modules/billing/lib/dateOnly.js.map +7 -0
- package/dist/modules/billing/lib/documentParties.js +16 -0
- package/dist/modules/billing/lib/documentParties.js.map +7 -0
- package/dist/modules/billing/lib/documentTypes.js +27 -0
- package/dist/modules/billing/lib/documentTypes.js.map +7 -0
- package/dist/modules/billing/lib/dueDate.js +18 -0
- package/dist/modules/billing/lib/dueDate.js.map +7 -0
- package/dist/modules/billing/lib/iban.js +29 -0
- package/dist/modules/billing/lib/iban.js.map +7 -0
- package/dist/modules/billing/lib/invoiceDelivery.js +133 -0
- package/dist/modules/billing/lib/invoiceDelivery.js.map +7 -0
- package/dist/modules/billing/lib/invoiceLanguages.js +28 -0
- package/dist/modules/billing/lib/invoiceLanguages.js.map +7 -0
- package/dist/modules/billing/lib/invoiceWriter.js +107 -99
- package/dist/modules/billing/lib/invoiceWriter.js.map +2 -2
- package/dist/modules/billing/lib/itemBillingState.js +27 -0
- package/dist/modules/billing/lib/itemBillingState.js.map +7 -0
- package/dist/modules/billing/lib/itemPriceChange.js +18 -0
- package/dist/modules/billing/lib/itemPriceChange.js.map +7 -0
- package/dist/modules/billing/lib/itemSelector.js.map +2 -2
- package/dist/modules/billing/lib/lineAmounts.js +32 -0
- package/dist/modules/billing/lib/lineAmounts.js.map +7 -0
- package/dist/modules/billing/lib/memoGuards.js +25 -0
- package/dist/modules/billing/lib/memoGuards.js.map +7 -0
- package/dist/modules/billing/lib/navigation.js +48 -0
- package/dist/modules/billing/lib/navigation.js.map +7 -0
- package/dist/modules/billing/lib/numbering.js +120 -0
- package/dist/modules/billing/lib/numbering.js.map +7 -0
- package/dist/modules/billing/lib/overdue.js +36 -0
- package/dist/modules/billing/lib/overdue.js.map +7 -0
- package/dist/modules/billing/lib/paymentCsv.js +125 -0
- package/dist/modules/billing/lib/paymentCsv.js.map +7 -0
- package/dist/modules/billing/lib/paymentGateway.js +15 -0
- package/dist/modules/billing/lib/paymentGateway.js.map +7 -0
- package/dist/modules/billing/lib/paymentImport.js +164 -0
- package/dist/modules/billing/lib/paymentImport.js.map +7 -0
- package/dist/modules/billing/lib/paymentMatcher.js +36 -0
- package/dist/modules/billing/lib/paymentMatcher.js.map +7 -0
- package/dist/modules/billing/lib/pdf/attachmentStore.js +46 -0
- package/dist/modules/billing/lib/pdf/attachmentStore.js.map +7 -0
- package/dist/modules/billing/lib/pdf/fonts/embeddedFonts.js +7 -0
- package/dist/modules/billing/lib/pdf/fonts/embeddedFonts.js.map +7 -0
- package/dist/modules/billing/lib/pdf/invoiceModel.js +194 -0
- package/dist/modules/billing/lib/pdf/invoiceModel.js.map +7 -0
- package/dist/modules/billing/lib/pdf/invoicePdf.js +165 -0
- package/dist/modules/billing/lib/pdf/invoicePdf.js.map +7 -0
- package/dist/modules/billing/lib/pdf/invoiceTemplate.js +276 -0
- package/dist/modules/billing/lib/pdf/invoiceTemplate.js.map +7 -0
- package/dist/modules/billing/lib/prepaidConfig.js +17 -25
- package/dist/modules/billing/lib/prepaidConfig.js.map +2 -2
- package/dist/modules/billing/lib/prepaidConsume.js +26 -7
- package/dist/modules/billing/lib/prepaidConsume.js.map +2 -2
- package/dist/modules/billing/lib/prepaidPeriodClose.js +277 -158
- package/dist/modules/billing/lib/prepaidPeriodClose.js.map +2 -2
- package/dist/modules/billing/lib/prepaidTaxPoint.js +37 -0
- package/dist/modules/billing/lib/prepaidTaxPoint.js.map +7 -0
- package/dist/modules/billing/lib/seeds/demo.js +51 -3
- package/dist/modules/billing/lib/seeds/demo.js.map +2 -2
- package/dist/modules/billing/lib/seeds/paymentsSample.js +93 -0
- package/dist/modules/billing/lib/seeds/paymentsSample.js.map +7 -0
- package/dist/modules/billing/lib/seeds/sellerSettings.js +41 -0
- package/dist/modules/billing/lib/seeds/sellerSettings.js.map +7 -0
- package/dist/modules/billing/lib/servicePeriods.js +121 -0
- package/dist/modules/billing/lib/servicePeriods.js.map +7 -0
- package/dist/modules/billing/lib/testRunCleanup.js +24 -0
- package/dist/modules/billing/lib/testRunCleanup.js.map +7 -0
- package/dist/modules/billing/lib/topupCapture.js +2 -2
- package/dist/modules/billing/lib/topupCapture.js.map +2 -2
- package/dist/modules/billing/lib/topupReceipt.js +58 -79
- package/dist/modules/billing/lib/topupReceipt.js.map +2 -2
- package/dist/modules/billing/lib/usageRater.js.map +1 -1
- package/dist/modules/billing/lib/usageRunner.js +14 -6
- package/dist/modules/billing/lib/usageRunner.js.map +2 -2
- package/dist/modules/billing/lib/vat.js +39 -0
- package/dist/modules/billing/lib/vat.js.map +7 -0
- package/dist/modules/billing/migrations/Migration20261114000000_billing_customer_kind.js +15 -0
- package/dist/modules/billing/migrations/Migration20261114000000_billing_customer_kind.js.map +7 -0
- package/dist/modules/billing/migrations/Migration20261114100000_billing_cycle_semantics.js +25 -0
- package/dist/modules/billing/migrations/Migration20261114100000_billing_cycle_semantics.js.map +7 -0
- package/dist/modules/billing/migrations/Migration20261115000000_billing_invoice_ledger.js +115 -0
- package/dist/modules/billing/migrations/Migration20261115000000_billing_invoice_ledger.js.map +7 -0
- package/dist/modules/billing/migrations/Migration20261116000000_billing_invoice_documents.js +47 -0
- package/dist/modules/billing/migrations/Migration20261116000000_billing_invoice_documents.js.map +7 -0
- package/dist/modules/billing/migrations/Migration20261117000000_billing_payments.js +89 -0
- package/dist/modules/billing/migrations/Migration20261117000000_billing_payments.js.map +7 -0
- package/dist/modules/billing/migrations/Migration20261118000000_billing_memos.js +17 -0
- package/dist/modules/billing/migrations/Migration20261118000000_billing_memos.js.map +7 -0
- package/dist/modules/billing/migrations/Migration20261119000000_billing_operator_feedback.js +27 -0
- package/dist/modules/billing/migrations/Migration20261119000000_billing_operator_feedback.js.map +7 -0
- package/dist/modules/billing/migrations/Migration20261120000000_billing_allocation_scope_indexes.js +29 -0
- package/dist/modules/billing/migrations/Migration20261120000000_billing_allocation_scope_indexes.js.map +7 -0
- package/dist/modules/billing/setup.js +7 -184
- package/dist/modules/billing/setup.js.map +2 -2
- package/dist/modules/billing/subscribers/credit-memo-auto-send.js +16 -0
- package/dist/modules/billing/subscribers/credit-memo-auto-send.js.map +7 -0
- package/dist/modules/billing/subscribers/debit-memo-apply-credit.js +16 -0
- package/dist/modules/billing/subscribers/debit-memo-apply-credit.js.map +7 -0
- package/dist/modules/billing/subscribers/debit-memo-auto-send.js +16 -0
- package/dist/modules/billing/subscribers/debit-memo-auto-send.js.map +7 -0
- package/dist/modules/billing/subscribers/invoice-apply-credit.js +34 -0
- package/dist/modules/billing/subscribers/invoice-apply-credit.js.map +7 -0
- package/dist/modules/billing/subscribers/invoice-auto-send.js +30 -0
- package/dist/modules/billing/subscribers/invoice-auto-send.js.map +7 -0
- package/dist/modules/billing/subscribers/payment-captured-to-paid.js +69 -33
- package/dist/modules/billing/subscribers/payment-captured-to-paid.js.map +2 -2
- package/dist/modules/billing/subscribers/prepaid-topup-captured.js +4 -6
- package/dist/modules/billing/subscribers/prepaid-topup-captured.js.map +2 -2
- package/generated/entities/billing_account/index.ts +3 -0
- package/generated/entities/billing_allocation/index.ts +18 -0
- package/generated/entities/billing_document_sequence/index.ts +11 -0
- package/generated/entities/billing_invoice/index.ts +38 -0
- package/generated/entities/billing_invoice_line/index.ts +24 -0
- package/generated/entities/billing_item/index.ts +4 -0
- package/generated/entities/billing_payment/index.ts +25 -0
- package/generated/entities/billing_payment_import/index.ts +14 -0
- package/generated/entities/billing_run/index.ts +0 -1
- package/generated/entities/billing_run_outcome/index.ts +1 -0
- package/generated/entities/billing_settings/index.ts +26 -0
- package/generated/entities/billing_statement/index.ts +1 -0
- package/generated/entities.ids.generated.ts +7 -0
- package/package.json +5 -1
- package/src/modules/billing/__integration__/TC-BILL-004.spec.ts +171 -0
- package/src/modules/billing/__integration__/TC-BILL-005.spec.ts +134 -0
- package/src/modules/billing/__integration__/TC-BILL-006.spec.ts +101 -0
- package/src/modules/billing/__integration__/TC-BILL-007.spec.ts +140 -0
- package/src/modules/billing/__integration__/TC-BILL-008.spec.ts +108 -0
- package/src/modules/billing/__integration__/TC-BILL-009.spec.ts +113 -0
- package/src/modules/billing/__integration__/TC-BILL-010.spec.ts +118 -0
- package/src/modules/billing/__integration__/TC-BILL-011.spec.ts +142 -0
- package/src/modules/billing/__integration__/TC-BILL-012.spec.ts +115 -0
- package/src/modules/billing/__integration__/TC-BILL-013.spec.ts +118 -0
- package/src/modules/billing/__integration__/sellerSettings.ts +24 -0
- package/src/modules/billing/__tests__/commands/invoices.test.ts +436 -354
- package/src/modules/billing/__tests__/commands/itemsBulk.test.ts +33 -0
- package/src/modules/billing/__tests__/commands/memos.test.ts +205 -0
- package/src/modules/billing/__tests__/commands/payments.test.ts +241 -0
- package/src/modules/billing/__tests__/commands/runsDelete.test.ts +146 -0
- package/src/modules/billing/__tests__/commands/runsPostDrafts.test.ts +106 -0
- package/src/modules/billing/__tests__/commands/topups.test.ts +11 -0
- package/src/modules/billing/__tests__/entityRegistry.test.ts +8 -1
- package/src/modules/billing/__tests__/helpers/prepaidMockEm.ts +28 -11
- package/src/modules/billing/__tests__/i18n/dictionaries.test.ts +64 -0
- package/src/modules/billing/__tests__/lib/accountFinancials.test.ts +53 -0
- package/src/modules/billing/__tests__/lib/accountSummary.test.ts +97 -0
- package/src/modules/billing/__tests__/lib/allocation.test.ts +319 -0
- package/src/modules/billing/__tests__/lib/billRunEngine.test.ts +228 -17
- package/src/modules/billing/__tests__/lib/billingSettings.test.ts +109 -0
- package/src/modules/billing/__tests__/lib/customerLookup.test.ts +156 -0
- package/src/modules/billing/__tests__/lib/dueDate.test.ts +35 -0
- package/src/modules/billing/__tests__/lib/iban.test.ts +38 -0
- package/src/modules/billing/__tests__/lib/invoiceDelivery.test.ts +206 -0
- package/src/modules/billing/__tests__/lib/invoiceLanguages.test.ts +49 -0
- package/src/modules/billing/__tests__/lib/invoiceWriter.test.ts +212 -10
- package/src/modules/billing/__tests__/lib/itemBillingState.test.ts +42 -0
- package/src/modules/billing/__tests__/lib/itemPriceChange.test.ts +165 -0
- package/src/modules/billing/__tests__/lib/lineAmounts.test.ts +86 -0
- package/src/modules/billing/__tests__/lib/navigation.test.ts +71 -0
- package/src/modules/billing/__tests__/lib/numbering.test.ts +91 -0
- package/src/modules/billing/__tests__/lib/overdue.test.ts +36 -0
- package/src/modules/billing/__tests__/lib/paymentCsv.test.ts +148 -0
- package/src/modules/billing/__tests__/lib/paymentImport.test.ts +113 -0
- package/src/modules/billing/__tests__/lib/paymentsSample.test.ts +73 -0
- package/src/modules/billing/__tests__/lib/pdf/invoicePdf.test.ts +269 -0
- package/src/modules/billing/__tests__/lib/pdf/invoicePdfService.test.ts +147 -0
- package/src/modules/billing/__tests__/lib/prepaidPeriodClose.test.ts +374 -98
- package/src/modules/billing/__tests__/lib/prepaidTaxPoint.test.ts +118 -0
- package/src/modules/billing/__tests__/lib/seedsDemo.test.ts +53 -2
- package/src/modules/billing/__tests__/lib/sellerSettings.test.ts +28 -0
- package/src/modules/billing/__tests__/lib/servicePeriods.test.ts +190 -0
- package/src/modules/billing/__tests__/lib/topupCapture.test.ts +6 -28
- package/src/modules/billing/__tests__/lib/topupReceipt.test.ts +21 -52
- package/src/modules/billing/__tests__/lib/vat.test.ts +51 -0
- package/src/modules/billing/__tests__/package-isolation.test.ts +22 -8
- package/src/modules/billing/__tests__/setup.test.ts +13 -4
- package/src/modules/billing/__tests__/validators.test.ts +197 -3
- package/src/modules/billing/acl.ts +12 -0
- package/src/modules/billing/api/accounts/[id]/summary/route.ts +62 -0
- package/src/modules/billing/api/accounts/route.ts +59 -4
- package/src/modules/billing/api/export/account/[id]/route.ts +13 -11
- package/src/modules/billing/api/invoices/[id]/memos/route.ts +63 -0
- package/src/modules/billing/api/invoices/[id]/pdf/route.ts +80 -0
- package/src/modules/billing/api/invoices/[id]/route.ts +57 -70
- package/src/modules/billing/api/invoices/[id]/send/route.ts +127 -0
- package/src/modules/billing/api/invoices/add-line/route.ts +2 -2
- package/src/modules/billing/api/invoices/delete-draft/route.ts +33 -0
- package/src/modules/billing/api/invoices/edit-line/route.ts +2 -2
- package/src/modules/billing/api/invoices/post/route.ts +7 -6
- package/src/modules/billing/api/invoices/remove-line/route.ts +2 -2
- package/src/modules/billing/api/invoices/route.ts +81 -86
- package/src/modules/billing/api/items/bulk/route.ts +2 -1
- package/src/modules/billing/api/items/change-price/route.ts +54 -0
- package/src/modules/billing/api/items/route.ts +23 -7
- package/src/modules/billing/api/payment-imports/[id]/route.ts +49 -0
- package/src/modules/billing/api/payment-imports/route.ts +57 -0
- package/src/modules/billing/api/payments/[id]/route.ts +63 -0
- package/src/modules/billing/api/payments/allocate/route.ts +35 -0
- package/src/modules/billing/api/payments/assign/route.ts +36 -0
- package/src/modules/billing/api/payments/convert-to-topup/route.ts +35 -0
- package/src/modules/billing/api/payments/ignore/route.ts +35 -0
- package/src/modules/billing/api/payments/import/route.ts +72 -0
- package/src/modules/billing/api/payments/restore/route.ts +35 -0
- package/src/modules/billing/api/payments/route.ts +147 -0
- package/src/modules/billing/api/payments/unallocate/route.ts +35 -0
- package/src/modules/billing/api/payments/unassign/route.ts +35 -0
- package/src/modules/billing/api/run-outcomes/route.ts +49 -6
- package/src/modules/billing/api/runs/[id]/post-drafts/route.ts +71 -0
- package/src/modules/billing/api/runs/[id]/route.ts +59 -0
- package/src/modules/billing/api/runs/retry-failed/route.ts +2 -1
- package/src/modules/billing/api/runs/route.ts +15 -7
- package/src/modules/billing/api/settings/number-preview/route.ts +46 -0
- package/src/modules/billing/api/settings/route.ts +116 -0
- package/src/modules/billing/api/statements/route.ts +5 -0
- package/src/modules/billing/api/test-invoices/wipe/route.ts +2 -2
- package/src/modules/billing/backend/billing/accounts/[id]/page.tsx +151 -372
- package/src/modules/billing/backend/billing/accounts/create/page.tsx +6 -0
- package/src/modules/billing/backend/billing/accounts/page.tsx +70 -4
- package/src/modules/billing/backend/billing/invoices/[id]/page.tsx +444 -95
- package/src/modules/billing/backend/billing/invoices/page.tsx +8 -227
- package/src/modules/billing/backend/billing/items/[id]/page.tsx +75 -6
- package/src/modules/billing/backend/billing/items/create/page.tsx +13 -8
- package/src/modules/billing/backend/billing/items/page.tsx +18 -2
- package/src/modules/billing/backend/billing/payments/[id]/page.meta.ts +19 -0
- package/src/modules/billing/backend/billing/payments/[id]/page.tsx +415 -0
- package/src/modules/billing/backend/billing/payments/imports/[id]/page.meta.ts +19 -0
- package/src/modules/billing/backend/billing/payments/imports/[id]/page.tsx +106 -0
- package/src/modules/billing/backend/billing/payments/page.meta.ts +16 -0
- package/src/modules/billing/backend/billing/payments/page.tsx +56 -0
- package/src/modules/billing/backend/billing/runs/[id]/page.tsx +49 -18
- package/src/modules/billing/backend/billing/runs/page.tsx +59 -8
- package/src/modules/billing/backend/billing/statements/[id]/page.tsx +86 -5
- package/src/modules/billing/backend/billing/statements/page.tsx +1 -1
- package/src/modules/billing/backend/billing/topups/page.tsx +1 -1
- package/src/modules/billing/backend/billing/transactions/page.tsx +1 -1
- package/src/modules/billing/backend/billing/usage/create/page.tsx +3 -2
- package/src/modules/billing/backend/config/billing/page.meta.ts +21 -0
- package/src/modules/billing/backend/config/billing/page.tsx +549 -0
- package/src/modules/billing/cli.ts +31 -1
- package/src/modules/billing/commands/accounts.ts +6 -0
- package/src/modules/billing/commands/index.ts +3 -0
- package/src/modules/billing/commands/invoices.ts +364 -231
- package/src/modules/billing/commands/items.ts +143 -0
- package/src/modules/billing/commands/memos.ts +218 -0
- package/src/modules/billing/commands/payments.ts +428 -0
- package/src/modules/billing/commands/runs.ts +205 -3
- package/src/modules/billing/commands/settings.ts +77 -0
- package/src/modules/billing/commands/topups.ts +12 -3
- package/src/modules/billing/commands/transactions.ts +2 -2
- package/src/modules/billing/components/AccountForm.tsx +199 -53
- package/src/modules/billing/components/AccountInvoicesSection.tsx +75 -0
- package/src/modules/billing/components/AccountPaymentsSection.tsx +42 -0
- package/src/modules/billing/components/AccountPicker.tsx +70 -0
- package/src/modules/billing/components/AllocatePaymentDialog.tsx +167 -0
- package/src/modules/billing/components/BillingDataTable.tsx +34 -0
- package/src/modules/billing/components/BillingSettingsLink.tsx +25 -0
- package/src/modules/billing/components/ChangeItemPriceDialog.tsx +180 -0
- package/src/modules/billing/components/CreateMemoDialog.tsx +232 -0
- package/src/modules/billing/components/CustomerLabel.tsx +53 -0
- package/src/modules/billing/components/InvoicesTable.tsx +344 -0
- package/src/modules/billing/components/ItemForm.tsx +233 -44
- package/src/modules/billing/components/ItemPriceField.tsx +81 -0
- package/src/modules/billing/components/LineFormDialog.tsx +25 -1
- package/src/modules/billing/components/ManualPaymentDialog.tsx +140 -0
- package/src/modules/billing/components/MoneyInput.tsx +26 -0
- package/src/modules/billing/components/PaymentUploadDialog.tsx +148 -0
- package/src/modules/billing/components/PaymentsTable.tsx +213 -0
- package/src/modules/billing/components/PostRunDraftsButton.tsx +129 -0
- package/src/modules/billing/components/PrepaidPanel.tsx +19 -6
- package/src/modules/billing/components/RunCyclesSection.tsx +298 -0
- package/src/modules/billing/components/TestRunActions.tsx +152 -0
- package/src/modules/billing/components/account/AccountItemsTab.tsx +192 -0
- package/src/modules/billing/components/account/AccountRunBillingDialog.tsx +147 -0
- package/src/modules/billing/components/account/AccountRunsTab.tsx +201 -0
- package/src/modules/billing/components/account/AccountStatementsTab.tsx +120 -0
- package/src/modules/billing/components/account/AccountSummaryCards.tsx +153 -0
- package/src/modules/billing/components/account/AccountUsageTab.tsx +122 -0
- package/src/modules/billing/components/account/AccountView.tsx +101 -0
- package/src/modules/billing/components/account/accountRow.ts +70 -0
- package/src/modules/billing/components/customerNames.ts +62 -0
- package/src/modules/billing/data/entities.ts +656 -6
- package/src/modules/billing/data/entityIds.ts +9 -0
- package/src/modules/billing/data/validators.ts +388 -8
- package/src/modules/billing/events.ts +56 -3
- package/src/modules/billing/i18n/de.json +880 -0
- package/src/modules/billing/i18n/en.json +457 -21
- package/src/modules/billing/i18n/es.json +880 -0
- package/src/modules/billing/i18n/pl.json +458 -22
- package/src/modules/billing/index.ts +6 -2
- package/src/modules/billing/lib/accountFinancials.ts +84 -0
- package/src/modules/billing/lib/accountLock.ts +32 -0
- package/src/modules/billing/lib/accountStatus.ts +11 -9
- package/src/modules/billing/lib/accountSummary.ts +172 -0
- package/src/modules/billing/lib/allocation.ts +515 -0
- package/src/modules/billing/lib/allocationEvents.ts +26 -0
- package/src/modules/billing/lib/billPeriod.ts +19 -0
- package/src/modules/billing/lib/billRunEngine.ts +350 -150
- package/src/modules/billing/lib/billingSettings.ts +145 -0
- package/src/modules/billing/lib/commandRoute.ts +112 -0
- package/src/modules/billing/lib/customerLookup.ts +157 -0
- package/src/modules/billing/lib/dateOnly.ts +22 -0
- package/src/modules/billing/lib/documentParties.ts +23 -0
- package/src/modules/billing/lib/documentTypes.ts +37 -0
- package/src/modules/billing/lib/dueDate.ts +26 -0
- package/src/modules/billing/lib/iban.ts +36 -0
- package/src/modules/billing/lib/invoiceDelivery.ts +196 -0
- package/src/modules/billing/lib/invoiceLanguages.ts +57 -0
- package/src/modules/billing/lib/invoiceWriter.ts +162 -148
- package/src/modules/billing/lib/itemBillingState.ts +67 -0
- package/src/modules/billing/lib/itemPriceChange.ts +56 -0
- package/src/modules/billing/lib/itemSelector.ts +4 -1
- package/src/modules/billing/lib/lineAmounts.ts +61 -0
- package/src/modules/billing/lib/memoGuards.ts +41 -0
- package/src/modules/billing/lib/navigation.ts +64 -0
- package/src/modules/billing/lib/numbering.ts +174 -0
- package/src/modules/billing/lib/overdue.ts +60 -0
- package/src/modules/billing/lib/paymentCsv.ts +171 -0
- package/src/modules/billing/lib/paymentGateway.ts +52 -0
- package/src/modules/billing/lib/paymentImport.ts +228 -0
- package/src/modules/billing/lib/paymentMatcher.ts +88 -0
- package/src/modules/billing/lib/pdf/attachmentStore.ts +60 -0
- package/src/modules/billing/lib/pdf/fonts/NotoSans-Bold.ttf +0 -0
- package/src/modules/billing/lib/pdf/fonts/NotoSans-Regular.ttf +0 -0
- package/src/modules/billing/lib/pdf/fonts/OFL.txt +93 -0
- package/src/modules/billing/lib/pdf/fonts/embeddedFonts.ts +9 -0
- package/src/modules/billing/lib/pdf/invoiceModel.ts +329 -0
- package/src/modules/billing/lib/pdf/invoicePdf.ts +220 -0
- package/src/modules/billing/lib/pdf/invoiceTemplate.ts +338 -0
- package/src/modules/billing/lib/prepaidConfig.ts +27 -36
- package/src/modules/billing/lib/prepaidConsume.ts +29 -6
- package/src/modules/billing/lib/prepaidPeriodClose.ts +407 -239
- package/src/modules/billing/lib/prepaidTaxPoint.ts +76 -0
- package/src/modules/billing/lib/seeds/demo.ts +79 -6
- package/src/modules/billing/lib/seeds/paymentsSample.ts +136 -0
- package/src/modules/billing/lib/seeds/sellerSettings.ts +78 -0
- package/src/modules/billing/lib/servicePeriods.ts +226 -0
- package/src/modules/billing/lib/testRunCleanup.ts +42 -0
- package/src/modules/billing/lib/topupCapture.ts +3 -4
- package/src/modules/billing/lib/topupReceipt.ts +70 -103
- package/src/modules/billing/lib/usageRater.ts +1 -1
- package/src/modules/billing/lib/usageRunner.ts +17 -5
- package/src/modules/billing/lib/vat.ts +56 -0
- package/src/modules/billing/migrations/Migration20261114000000_billing_customer_kind.ts +25 -0
- package/src/modules/billing/migrations/Migration20261114100000_billing_cycle_semantics.ts +37 -0
- package/src/modules/billing/migrations/Migration20261115000000_billing_invoice_ledger.ts +132 -0
- package/src/modules/billing/migrations/Migration20261116000000_billing_invoice_documents.ts +58 -0
- package/src/modules/billing/migrations/Migration20261117000000_billing_payments.ts +97 -0
- package/src/modules/billing/migrations/Migration20261118000000_billing_memos.ts +21 -0
- package/src/modules/billing/migrations/Migration20261119000000_billing_operator_feedback.ts +39 -0
- package/src/modules/billing/migrations/Migration20261120000000_billing_allocation_scope_indexes.ts +35 -0
- package/src/modules/billing/setup.ts +11 -237
- package/src/modules/billing/subscribers/credit-memo-auto-send.ts +15 -0
- package/src/modules/billing/subscribers/debit-memo-apply-credit.ts +15 -0
- package/src/modules/billing/subscribers/debit-memo-auto-send.ts +15 -0
- package/src/modules/billing/subscribers/invoice-apply-credit.ts +39 -0
- package/src/modules/billing/subscribers/invoice-auto-send.ts +46 -0
- package/src/modules/billing/subscribers/payment-captured-to-paid.ts +84 -62
- package/src/modules/billing/subscribers/prepaid-topup-captured.ts +4 -8
- package/dist/modules/billing/lib/invoiceStatus.js +0 -38
- package/dist/modules/billing/lib/invoiceStatus.js.map +0 -7
- package/src/modules/billing/__tests__/lib/invoiceStatus.test.ts +0 -97
- package/src/modules/billing/lib/invoiceStatus.ts +0 -61
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../src/modules/billing/backend/config/billing/page.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Page, PageBody, PageHeader } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Textarea } from '@open-mercato/ui/primitives/textarea'\nimport { Switch } from '@open-mercato/ui/primitives/switch'\nimport { Tag } from '@open-mercato/ui/primitives/tag'\nimport { RadioGroup } from '@open-mercato/ui/primitives/radio'\nimport { RadioField } from '@open-mercato/ui/primitives/radio-field'\nimport { KbdShortcut } from '@open-mercato/ui/primitives/kbd'\nimport { LoadingMessage, ErrorMessage } from '@open-mercato/ui/backend/detail'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { apiCall, apiCallOrThrow, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { normalizeCrudServerError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { DOCUMENT_SERIES, type DocumentSeries } from '../../../lib/numbering'\n\n/**\n * Billing settings (Spec 0) \u2014 per organization:\n * - document number masks per series, with a live example of the next\n * number and the counter scope (never / yearly / monthly reset);\n * - prepaid defaults (moved from core `configs`);\n * - read-only: whether online top-ups are available (optional gateway);\n * - Spec B: seller block, payment instructions (bank / IBAN / BIC),\n * default payment terms and VAT rate, invoice footer and logo. Posting\n * is blocked until legal name, address, tax id and IBAN are filled \u2014 the\n * page shows what is missing.\n */\n\ntype Settings = {\n id: string\n lowBalanceThresholdDefault: number\n nearLimitBufferDefault: number\n statementEnabled: boolean\n topupTaxRate: number\n prepaidTaxPoint: 'topup' | 'consumption'\n topupProvider: string\n numberMasks: Record<DocumentSeries, string>\n legalName: string\n sellerAddress: SellerAddress | null\n taxId: string\n bankName: string\n iban: string\n bic: string\n invoiceFooter: string\n logoAttachmentId: string | null\n defaultPaymentTermsDays: number\n defaultTaxRate: number\n}\n\ntype SellerAddress = { line1: string; line2?: string; city: string; postal_code: string; country: string }\n\nconst EMPTY_ADDRESS: SellerAddress = { line1: '', line2: '', city: '', postal_code: '', country: 'PL' }\n\ntype SettingsResponse = {\n settings: Settings\n capabilities: { gatewayTopups: boolean }\n completeness?: { ready: boolean; missing: string[] }\n}\n\n/** Address is sent only when the required parts are filled; all blank clears it. */\nfunction addressPayload(address: SellerAddress | null): SellerAddress | null | undefined {\n if (!address) return null\n const trimmed = {\n line1: address.line1.trim(),\n line2: (address.line2 ?? '').trim(),\n city: address.city.trim(),\n postal_code: address.postal_code.trim(),\n country: address.country.trim().toUpperCase(),\n }\n if (!trimmed.line1 && !trimmed.city && !trimmed.postal_code) return null\n const { line2, ...rest } = trimmed\n return line2 ? { ...rest, line2 } : rest\n}\n\nconst ATTACHMENT_ENTITY_ID = 'billing:billing_settings'\n\ntype Preview = { valid: boolean; errors: string[]; example?: string; scopeKey?: string }\n\nfunction useMaskPreview(mask: string): Preview | null {\n const [preview, setPreview] = React.useState<Preview | null>(null)\n React.useEffect(() => {\n let cancelled = false\n const handle = setTimeout(() => {\n void apiCall<Preview>(`/api/billing/settings/number-preview?mask=${encodeURIComponent(mask)}`).then((call) => {\n if (!cancelled) setPreview(call.ok ? call.result ?? null : null)\n })\n }, 250)\n return () => {\n cancelled = true\n clearTimeout(handle)\n }\n }, [mask])\n return preview\n}\n\nfunction MaskField({\n series,\n value,\n initial,\n onChange,\n}: {\n series: DocumentSeries\n value: string\n initial: string\n onChange: (next: string) => void\n}) {\n const t = useT()\n const preview = useMaskPreview(value)\n const seriesLabel: Record<DocumentSeries, string> = {\n invoice: t('billing.settings.series.invoice', 'Invoices and debit memos'),\n credit_memo: t('billing.settings.series.credit_memo', 'Credit memos'),\n receipt: t('billing.settings.series.receipt', 'Top-up receipts'),\n }\n const scopeLabel = (scopeKey: string | undefined) =>\n !scopeKey\n ? t('billing.settings.mask.scope.none', 'Counter never resets')\n : scopeKey.length === 4\n ? t('billing.settings.mask.scope.year', 'Counter resets every year')\n : t('billing.settings.mask.scope.month', 'Counter resets every month')\n return (\n <label className=\"flex flex-col gap-1 text-sm\">\n <span className=\"text-muted-foreground\">{seriesLabel[series]}</span>\n <Input value={value} maxLength={64} onChange={(event) => onChange(event.currentTarget.value)} />\n {preview?.valid ? (\n <span className=\"text-xs text-muted-foreground\">\n {t('billing.settings.mask.example', 'Next number looks like')} <span className=\"font-mono\">{preview.example}</span>\n {' \u00B7 '}\n {scopeLabel(preview.scopeKey)}\n </span>\n ) : preview ? (\n <span className=\"text-xs text-destructive\">\n {preview.errors.map((code) => t(`billing.settings.mask.error.${code}`, code)).join(' ')}\n </span>\n ) : null}\n {value !== initial ? (\n <span className=\"text-xs text-muted-foreground\">\n {t(\n 'billing.settings.mask.change_warning',\n 'Changing the mask mid-period starts a new counter; a number that was already issued is rejected at post.',\n )}\n </span>\n ) : null}\n </label>\n )\n}\n\nexport default function BillingSettingsPage() {\n const t = useT()\n const [loaded, setLoaded] = React.useState<SettingsResponse | null>(null)\n const [values, setValues] = React.useState<Settings | null>(null)\n const [error, setError] = React.useState<string | null>(null)\n const [saving, setSaving] = React.useState(false)\n\n const load = React.useCallback(async () => {\n setError(null)\n try {\n const result = await readApiResultOrThrow<SettingsResponse>('/api/billing/settings')\n setLoaded(result)\n setValues(result.settings)\n } catch (err) {\n setError(normalizeCrudServerError(err).message || t('billing.settings.error.load', 'Could not load billing settings'))\n }\n }, [t])\n\n React.useEffect(() => {\n void load()\n }, [load])\n\n const set = <K extends keyof Settings>(key: K, value: Settings[K]) =>\n setValues((prev) => (prev ? { ...prev, [key]: value } : prev))\n\n const fieldLabel = React.useCallback(\n (field: string): string => {\n const labels: Record<string, string> = {\n legalName: t('billing.settings.seller.legal_name', 'Legal name'),\n sellerAddress: t('billing.settings.seller.address', 'Address'),\n taxId: t('billing.settings.seller.tax_id', 'Tax ID'),\n iban: 'IBAN',\n bic: 'BIC',\n bankName: t('billing.settings.payment.bank_name', 'Bank'),\n topupProvider: t('billing.settings.prepaid.topup_provider', 'Top-up payment provider'),\n topupTaxRate: t('billing.settings.prepaid.topup_tax_rate', 'VAT on top-up receipts (%)'),\n defaultPaymentTermsDays: t('billing.settings.payment.terms', 'Default payment terms (days)'),\n defaultTaxRate: t('billing.settings.payment.tax_rate', 'Default VAT rate (%)'),\n numberMasks: t('billing.settings.numbering.title', 'Document numbering'),\n }\n const root = field.split('.')[0]\n const rest = field.slice(root.length + 1)\n return `${labels[root] ?? root}${rest ? ` (${rest})` : ''}`\n },\n [t],\n )\n\n const handleSave = React.useCallback(async () => {\n if (!values) return\n setSaving(true)\n try {\n await apiCallOrThrow('/api/billing/settings', {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ ...values, sellerAddress: addressPayload(values.sellerAddress) }),\n })\n flash(t('billing.settings.saved', 'Billing settings saved'), 'success')\n await load()\n } catch (err) {\n // Name the failing fields \u2014 the API's top-level message is just\n // \"Invalid input\". Codes such as `billing.settings.error.iban_invalid`\n // and mask error codes are translated; anything else is shown as sent.\n const { message, fieldErrors } = normalizeCrudServerError(err)\n const details = Object.entries(fieldErrors ?? {})\n .map(([field, fieldMessage]) => {\n const text = String(fieldMessage)\n const translated = text.startsWith('billing.') ? t(text, text) : text\n return `${fieldLabel(field)}: ${translated}`\n })\n .join('; ')\n flash(\n details\n ? `${t('billing.settings.error.fields', 'Check these fields')} \u2014 ${details}`\n : message || t('billing.settings.error.save', 'Saving failed'),\n 'error',\n )\n } finally {\n setSaving(false)\n }\n }, [fieldLabel, load, t, values])\n\n const [uploading, setUploading] = React.useState(false)\n const handleLogoUpload = React.useCallback(\n async (file: File | null) => {\n if (!file || !values) return\n setUploading(true)\n try {\n const form = new FormData()\n form.set('entityId', ATTACHMENT_ENTITY_ID)\n form.set('recordId', loaded?.settings.id ?? 'settings')\n form.set('file', file)\n const call = await apiCall<{ item?: { id: string }; error?: string }>('/api/attachments', {\n method: 'POST',\n body: form,\n })\n if (!call.ok || !call.result?.item?.id) {\n throw new Error(call.result?.error || t('billing.settings.logo.upload_failed', 'Logo upload failed'))\n }\n set('logoAttachmentId', call.result.item.id)\n } catch (err) {\n flash(err instanceof Error ? err.message : t('billing.settings.logo.upload_failed', 'Logo upload failed'), 'error')\n } finally {\n setUploading(false)\n }\n },\n [loaded?.settings.id, t, values],\n )\n\n const address = values?.sellerAddress ?? EMPTY_ADDRESS\n const setAddress = (key: keyof SellerAddress, value: string) =>\n set('sellerAddress', { ...(values?.sellerAddress ?? EMPTY_ADDRESS), [key]: value })\n\n const missingLabels: Record<string, string> = {\n legalName: t('billing.settings.seller.legal_name', 'Legal name'),\n sellerAddress: t('billing.settings.seller.address', 'Address'),\n taxId: t('billing.settings.seller.tax_id', 'Tax ID'),\n iban: t('billing.settings.payment.iban', 'IBAN'),\n }\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n void handleSave()\n } else if (event.key === 'Escape' && loaded) {\n event.preventDefault()\n setValues(loaded.settings)\n }\n }\n\n return (\n <Page>\n <PageHeader title={t('billing.settings.title', 'Billing')} />\n <PageBody>\n {error ? (\n <ErrorMessage label={error} />\n ) : !values || !loaded ? (\n <LoadingMessage label={t('billing.settings.loading', 'Loading billing settings\u2026')} />\n ) : (\n <div className=\"flex flex-col gap-6\" onKeyDown={handleKeyDown}>\n {loaded.completeness && !loaded.completeness.ready ? (\n <div className=\"rounded-lg border border-status-warning-border bg-status-warning-bg p-4 text-sm\">\n <div className=\"font-medium\">\n {t('billing.settings.incomplete.title', 'Invoices cannot be posted yet')}\n </div>\n <div className=\"text-muted-foreground\">\n {t('billing.settings.incomplete.help', 'Fill in the seller details printed on every invoice:')}{' '}\n {loaded.completeness.missing.map((field) => missingLabels[field] ?? field).join(', ')}\n </div>\n </div>\n ) : null}\n\n <section className=\"rounded-lg border bg-card p-6 grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <h2 className=\"text-base font-semibold sm:col-span-2\">{t('billing.settings.seller.title', 'Seller')}</h2>\n <label className=\"flex flex-col gap-1 text-sm sm:col-span-2\">\n <span className=\"text-muted-foreground\">{t('billing.settings.seller.legal_name', 'Legal name')} *</span>\n <Input value={values.legalName} maxLength={255} onChange={(e) => set('legalName', e.currentTarget.value)} />\n </label>\n <label className=\"flex flex-col gap-1 text-sm sm:col-span-2\">\n <span className=\"text-muted-foreground\">{t('billing.settings.seller.line1', 'Address line 1')} *</span>\n <Input value={address.line1} onChange={(e) => setAddress('line1', e.currentTarget.value)} />\n </label>\n <label className=\"flex flex-col gap-1 text-sm sm:col-span-2\">\n <span className=\"text-muted-foreground\">{t('billing.settings.seller.line2', 'Address line 2')}</span>\n <Input value={address.line2 ?? ''} onChange={(e) => setAddress('line2', e.currentTarget.value)} />\n </label>\n <label className=\"flex flex-col gap-1 text-sm\">\n <span className=\"text-muted-foreground\">{t('billing.settings.seller.postal_code', 'Postal code')} *</span>\n <Input value={address.postal_code} onChange={(e) => setAddress('postal_code', e.currentTarget.value)} />\n </label>\n <label className=\"flex flex-col gap-1 text-sm\">\n <span className=\"text-muted-foreground\">{t('billing.settings.seller.city', 'City')} *</span>\n <Input value={address.city} onChange={(e) => setAddress('city', e.currentTarget.value)} />\n </label>\n <label className=\"flex flex-col gap-1 text-sm\">\n <span className=\"text-muted-foreground\">{t('billing.settings.seller.country', 'Country (ISO code)')} *</span>\n <Input value={address.country} maxLength={3} onChange={(e) => setAddress('country', e.currentTarget.value)} />\n </label>\n <label className=\"flex flex-col gap-1 text-sm\">\n <span className=\"text-muted-foreground\">{t('billing.settings.seller.tax_id', 'Tax ID')} *</span>\n <Input value={values.taxId} maxLength={64} onChange={(e) => set('taxId', e.currentTarget.value)} />\n </label>\n </section>\n\n <section className=\"rounded-lg border bg-card p-6 grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <h2 className=\"text-base font-semibold sm:col-span-2\">{t('billing.settings.payment.title', 'Payment and invoicing')}</h2>\n <label className=\"flex flex-col gap-1 text-sm sm:col-span-2\">\n <span className=\"text-muted-foreground\">{t('billing.settings.payment.bank_name', 'Bank name')}</span>\n <Input value={values.bankName} maxLength={255} onChange={(e) => set('bankName', e.currentTarget.value)} />\n </label>\n <label className=\"flex flex-col gap-1 text-sm\">\n <span className=\"text-muted-foreground\">{t('billing.settings.payment.iban', 'IBAN')} *</span>\n <Input value={values.iban} className=\"font-mono\" onChange={(e) => set('iban', e.currentTarget.value)} />\n </label>\n <label className=\"flex flex-col gap-1 text-sm\">\n <span className=\"text-muted-foreground\">{t('billing.settings.payment.bic', 'BIC / SWIFT')}</span>\n <Input value={values.bic} className=\"font-mono\" maxLength={11} onChange={(e) => set('bic', e.currentTarget.value)} />\n </label>\n <label className=\"flex flex-col gap-1 text-sm\">\n <span className=\"text-muted-foreground\">{t('billing.settings.payment.terms', 'Default payment terms (days)')}</span>\n <Input\n type=\"number\"\n min=\"0\"\n max=\"365\"\n step=\"1\"\n value={String(values.defaultPaymentTermsDays)}\n onChange={(e) => set('defaultPaymentTermsDays', Number.parseInt(e.currentTarget.value, 10) || 0)}\n />\n </label>\n <label className=\"flex flex-col gap-1 text-sm\">\n <span className=\"text-muted-foreground\">{t('billing.settings.payment.tax_rate', 'Default VAT rate (%)')}</span>\n <Input\n type=\"number\"\n min=\"0\"\n max=\"100\"\n step=\"0.01\"\n value={String(values.defaultTaxRate)}\n onChange={(e) => set('defaultTaxRate', Number(e.currentTarget.value) || 0)}\n />\n <span className=\"text-xs text-muted-foreground\">\n {t('billing.settings.payment.tax_rate.help', 'Applied to new billing items only; existing items keep their rate.')}\n </span>\n </label>\n <label className=\"flex flex-col gap-1 text-sm sm:col-span-2\">\n <span className=\"text-muted-foreground\">{t('billing.settings.document.footer', 'Invoice footer')}</span>\n <Textarea\n rows={2}\n maxLength={2000}\n value={values.invoiceFooter}\n onChange={(e) => set('invoiceFooter', e.currentTarget.value)}\n />\n <span className=\"text-xs text-muted-foreground\">\n {t('billing.settings.document.footer.help', 'Registration court, share capital and similar legal notes.')}\n </span>\n </label>\n <div className=\"flex flex-col gap-2 text-sm sm:col-span-2\">\n <span className=\"text-muted-foreground\">{t('billing.settings.document.logo', 'Logo (PNG or JPEG)')}</span>\n {values.logoAttachmentId ? (\n <div className=\"flex items-center gap-3\">\n <img\n src={`/api/attachments/file/${encodeURIComponent(values.logoAttachmentId)}`}\n alt={t('billing.settings.document.logo', 'Logo (PNG or JPEG)')}\n className=\"h-12 max-w-[200px] object-contain rounded border bg-background\"\n />\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => set('logoAttachmentId', null)}>\n {t('billing.settings.document.logo.remove', 'Remove')}\n </Button>\n </div>\n ) : (\n <span className=\"text-xs text-muted-foreground\">\n {t('billing.settings.document.logo.fallback', 'No logo \u2014 the organization logo is used when set.')}\n </span>\n )}\n <Input\n type=\"file\"\n accept=\"image/png,image/jpeg\"\n disabled={uploading}\n onChange={(e) => void handleLogoUpload(e.currentTarget.files?.[0] ?? null)}\n />\n </div>\n </section>\n\n <section className=\"rounded-lg border bg-card p-6 flex flex-col gap-4\">\n <div>\n <h2 className=\"text-base font-semibold\">{t('billing.settings.numbering.title', 'Document numbering')}</h2>\n <p className=\"text-sm text-muted-foreground\">\n {t(\n 'billing.settings.numbering.help',\n 'Use date tokens and exactly one counter token. The counter token decides when numbering restarts. Add :N to zero-pad the counter.',\n )}\n </p>\n {/* Tokens are rendered literally \u2014 never through i18n interpolation. */}\n <ul className=\"mt-2 grid grid-cols-1 sm:grid-cols-2 gap-1 text-xs\">\n {[\n ['{YYYY} {YY} {MM} {DD}', t('billing.settings.token.date', 'Issue date parts')],\n ['{SEQUENCE_NUM}', t('billing.settings.mask.scope.none', 'Counter never resets')],\n ['{SEQUENCE_NUM_YEAR}', t('billing.settings.mask.scope.year', 'Counter resets every year')],\n ['{SEQUENCE_NUM_MONTH}', t('billing.settings.mask.scope.month', 'Counter resets every month')],\n [':N ({SEQUENCE_NUM_MONTH:4} \u2192 0007)', t('billing.settings.token.pad', 'Zero-pad the counter to N digits')],\n ].map(([token, label]) => (\n <li key={token}>\n <span className=\"font-mono\">{token}</span> \u2014 {label}\n </li>\n ))}\n </ul>\n </div>\n {DOCUMENT_SERIES.map((series) => (\n <MaskField\n key={series}\n series={series}\n value={values.numberMasks[series]}\n initial={loaded.settings.numberMasks[series]}\n onChange={(next) => set('numberMasks', { ...values.numberMasks, [series]: next })}\n />\n ))}\n </section>\n\n <section className=\"rounded-lg border bg-card p-6 grid grid-cols-1 sm:grid-cols-2 gap-4\">\n <h2 className=\"text-base font-semibold sm:col-span-2\">{t('billing.settings.prepaid.title', 'Prepaid defaults')}</h2>\n <label className=\"flex flex-col gap-1 text-sm\">\n <span className=\"text-muted-foreground\">{t('billing.settings.prepaid.low_balance', 'Low-balance threshold')}</span>\n <Input\n type=\"number\"\n min=\"0\"\n step=\"0.01\"\n value={String(values.lowBalanceThresholdDefault)}\n onChange={(e) => set('lowBalanceThresholdDefault', Number(e.currentTarget.value) || 0)}\n />\n </label>\n <label className=\"flex flex-col gap-1 text-sm\">\n <span className=\"text-muted-foreground\">{t('billing.settings.prepaid.near_limit', 'Near credit-limit buffer')}</span>\n <Input\n type=\"number\"\n min=\"0\"\n step=\"0.01\"\n value={String(values.nearLimitBufferDefault)}\n onChange={(e) => set('nearLimitBufferDefault', Number(e.currentTarget.value) || 0)}\n />\n </label>\n <div className=\"flex flex-col gap-2 text-sm sm:col-span-2\">\n <span className=\"text-muted-foreground\">{t('billing.settings.prepaid.tax_point', 'When is VAT charged on prepaid accounts?')}</span>\n <RadioGroup\n value={values.prepaidTaxPoint ?? 'topup'}\n onValueChange={(next) => set('prepaidTaxPoint', next === 'consumption' ? 'consumption' : 'topup')}\n className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\"\n >\n <RadioField\n value=\"topup\"\n label={t('billing.settings.prepaid.tax_point.topup', 'At top-up')}\n description={t(\n 'billing.settings.prepaid.tax_point.topup_help',\n 'The top-up receipt includes VAT. Charges take the item amount from the balance as entered; item VAT rates do not apply.',\n )}\n />\n <RadioField\n value=\"consumption\"\n label={t('billing.settings.prepaid.tax_point.consumption', 'At billing')}\n description={t(\n 'billing.settings.prepaid.tax_point.consumption_help',\n 'Top-ups carry no VAT. Each charge takes its gross amount (at the item VAT rate) from the balance; statements show the VAT. Check with your accountant.',\n )}\n />\n </RadioGroup>\n {(values.prepaidTaxPoint ?? 'topup') !== (loaded.settings.prepaidTaxPoint ?? 'topup') ? (\n <div className=\"rounded-md border border-status-warning-border bg-status-warning-bg px-3 py-2 text-xs text-status-warning-text\">\n {t(\n 'billing.settings.prepaid.tax_point.change_warning',\n 'Applies to new top-ups and charges only. Balances topped up under the other setting keep their tax treatment; switching from top-up to billing taxes the remaining balance again when it is used.',\n )}\n </div>\n ) : null}\n </div>\n {(values.prepaidTaxPoint ?? 'topup') === 'topup' ? (\n <label className=\"flex flex-col gap-1 text-sm\">\n <span className=\"text-muted-foreground\">{t('billing.settings.prepaid.topup_tax_rate', 'VAT on top-up receipts (%)')}</span>\n <Input\n type=\"number\"\n min=\"0\"\n max=\"100\"\n step=\"0.01\"\n value={String(values.topupTaxRate)}\n onChange={(e) => set('topupTaxRate', Number(e.currentTarget.value) || 0)}\n />\n </label>\n ) : null}\n <label className=\"flex flex-col gap-1 text-sm\">\n <span className=\"text-muted-foreground\">{t('billing.settings.prepaid.topup_provider', 'Top-up payment provider')}</span>\n <Input value={values.topupProvider} onChange={(e) => set('topupProvider', e.currentTarget.value)} />\n </label>\n <div className=\"flex items-center justify-between gap-3 sm:col-span-2\">\n <span className=\"text-sm\">{t('billing.settings.prepaid.statements', 'Generate consumption statements at period close')}</span>\n <Switch checked={values.statementEnabled} onCheckedChange={(next) => set('statementEnabled', next)} />\n </div>\n <div className=\"flex items-center gap-2 text-sm sm:col-span-2\">\n <span className=\"text-muted-foreground\">{t('billing.settings.prepaid.gateway', 'Online top-ups')}</span>\n {loaded.capabilities.gatewayTopups ? (\n <Tag variant=\"success\">{t('billing.settings.prepaid.gateway.available', 'Available')}</Tag>\n ) : (\n <Tag variant=\"neutral\">\n {t('billing.settings.prepaid.gateway.unavailable', 'Unavailable \u2014 payment gateways module not installed')}\n </Tag>\n )}\n </div>\n </section>\n\n <div className=\"flex items-center justify-end gap-3\">\n <span className=\"text-xs text-muted-foreground\">\n <KbdShortcut keys={['Ctrl/\u2318', 'Enter']} /> {t('billing.settings.save_hint', 'to save')}\n </span>\n <Button type=\"button\" variant=\"outline\" onClick={() => setValues(loaded.settings)} disabled={saving}>\n {t('billing.common.cancel', 'Cancel')}\n </Button>\n <Button type=\"button\" onClick={() => void handleSave()} disabled={saving}>\n {saving ? t('billing.settings.saving', 'Saving\u2026') : t('billing.common.save', 'Save')}\n </Button>\n </div>\n </div>\n )}\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": ";AA2HM,cAGE,YAHF;AA1HN,YAAY,WAAW;AACvB,SAAS,YAAY;AACrB,SAAS,MAAM,UAAU,kBAAkB;AAC3C,SAAS,cAAc;AACvB,SAAS,aAAa;AACtB,SAAS,gBAAgB;AACzB,SAAS,cAAc;AACvB,SAAS,WAAW;AACpB,SAAS,kBAAkB;AAC3B,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,gBAAgB,oBAAoB;AAC7C,SAAS,aAAa;AACtB,SAAS,SAAS,gBAAgB,4BAA4B;AAC9D,SAAS,gCAAgC;AACzC,SAAS,uBAA4C;AAqCrD,MAAM,gBAA+B,EAAE,OAAO,IAAI,OAAO,IAAI,MAAM,IAAI,aAAa,IAAI,SAAS,KAAK;AAStG,SAAS,eAAe,SAAiE;AACvF,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,UAAU;AAAA,IACd,OAAO,QAAQ,MAAM,KAAK;AAAA,IAC1B,QAAQ,QAAQ,SAAS,IAAI,KAAK;AAAA,IAClC,MAAM,QAAQ,KAAK,KAAK;AAAA,IACxB,aAAa,QAAQ,YAAY,KAAK;AAAA,IACtC,SAAS,QAAQ,QAAQ,KAAK,EAAE,YAAY;AAAA,EAC9C;AACA,MAAI,CAAC,QAAQ,SAAS,CAAC,QAAQ,QAAQ,CAAC,QAAQ,YAAa,QAAO;AACpE,QAAM,EAAE,OAAO,GAAG,KAAK,IAAI;AAC3B,SAAO,QAAQ,EAAE,GAAG,MAAM,MAAM,IAAI;AACtC;AAEA,MAAM,uBAAuB;AAI7B,SAAS,eAAe,MAA8B;AACpD,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAyB,IAAI;AACjE,QAAM,UAAU,MAAM;AACpB,QAAI,YAAY;AAChB,UAAM,SAAS,WAAW,MAAM;AAC9B,WAAK,QAAiB,6CAA6C,mBAAmB,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,SAAS;AAC5G,YAAI,CAAC,UAAW,YAAW,KAAK,KAAK,KAAK,UAAU,OAAO,IAAI;AAAA,MACjE,CAAC;AAAA,IACH,GAAG,GAAG;AACN,WAAO,MAAM;AACX,kBAAY;AACZ,mBAAa,MAAM;AAAA,IACrB;AAAA,EACF,GAAG,CAAC,IAAI,CAAC;AACT,SAAO;AACT;AAEA,SAAS,UAAU;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,IAAI,KAAK;AACf,QAAM,UAAU,eAAe,KAAK;AACpC,QAAM,cAA8C;AAAA,IAClD,SAAS,EAAE,mCAAmC,0BAA0B;AAAA,IACxE,aAAa,EAAE,uCAAuC,cAAc;AAAA,IACpE,SAAS,EAAE,mCAAmC,iBAAiB;AAAA,EACjE;AACA,QAAM,aAAa,CAAC,aAClB,CAAC,WACG,EAAE,oCAAoC,sBAAsB,IAC5D,SAAS,WAAW,IAClB,EAAE,oCAAoC,2BAA2B,IACjE,EAAE,qCAAqC,4BAA4B;AAC3E,SACE,qBAAC,WAAM,WAAU,+BACf;AAAA,wBAAC,UAAK,WAAU,yBAAyB,sBAAY,MAAM,GAAE;AAAA,IAC7D,oBAAC,SAAM,OAAc,WAAW,IAAI,UAAU,CAAC,UAAU,SAAS,MAAM,cAAc,KAAK,GAAG;AAAA,IAC7F,SAAS,QACR,qBAAC,UAAK,WAAU,iCACb;AAAA,QAAE,iCAAiC,wBAAwB;AAAA,MAAE;AAAA,MAAC,oBAAC,UAAK,WAAU,aAAa,kBAAQ,SAAQ;AAAA,MAC3G;AAAA,MACA,WAAW,QAAQ,QAAQ;AAAA,OAC9B,IACE,UACF,oBAAC,UAAK,WAAU,4BACb,kBAAQ,OAAO,IAAI,CAAC,SAAS,EAAE,+BAA+B,IAAI,IAAI,IAAI,CAAC,EAAE,KAAK,GAAG,GACxF,IACE;AAAA,IACH,UAAU,UACT,oBAAC,UAAK,WAAU,iCACb;AAAA,MACC;AAAA,MACA;AAAA,IACF,GACF,IACE;AAAA,KACN;AAEJ;AAEe,SAAR,sBAAuC;AAC5C,QAAM,IAAI,KAAK;AACf,QAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAAkC,IAAI;AACxE,QAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAA0B,IAAI;AAChE,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAwB,IAAI;AAC5D,QAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAAS,KAAK;AAEhD,QAAM,OAAO,MAAM,YAAY,YAAY;AACzC,aAAS,IAAI;AACb,QAAI;AACF,YAAM,SAAS,MAAM,qBAAuC,uBAAuB;AACnF,gBAAU,MAAM;AAChB,gBAAU,OAAO,QAAQ;AAAA,IAC3B,SAAS,KAAK;AACZ,eAAS,yBAAyB,GAAG,EAAE,WAAW,EAAE,+BAA+B,iCAAiC,CAAC;AAAA,IACvH;AAAA,EACF,GAAG,CAAC,CAAC,CAAC;AAEN,QAAM,UAAU,MAAM;AACpB,SAAK,KAAK;AAAA,EACZ,GAAG,CAAC,IAAI,CAAC;AAET,QAAM,MAAM,CAA2B,KAAQ,UAC7C,UAAU,CAAC,SAAU,OAAO,EAAE,GAAG,MAAM,CAAC,GAAG,GAAG,MAAM,IAAI,IAAK;AAE/D,QAAM,aAAa,MAAM;AAAA,IACvB,CAAC,UAA0B;AACzB,YAAM,SAAiC;AAAA,QACrC,WAAW,EAAE,sCAAsC,YAAY;AAAA,QAC/D,eAAe,EAAE,mCAAmC,SAAS;AAAA,QAC7D,OAAO,EAAE,kCAAkC,QAAQ;AAAA,QACnD,MAAM;AAAA,QACN,KAAK;AAAA,QACL,UAAU,EAAE,sCAAsC,MAAM;AAAA,QACxD,eAAe,EAAE,2CAA2C,yBAAyB;AAAA,QACrF,cAAc,EAAE,2CAA2C,4BAA4B;AAAA,QACvF,yBAAyB,EAAE,kCAAkC,8BAA8B;AAAA,QAC3F,gBAAgB,EAAE,qCAAqC,sBAAsB;AAAA,QAC7E,aAAa,EAAE,oCAAoC,oBAAoB;AAAA,MACzE;AACA,YAAM,OAAO,MAAM,MAAM,GAAG,EAAE,CAAC;AAC/B,YAAM,OAAO,MAAM,MAAM,KAAK,SAAS,CAAC;AACxC,aAAO,GAAG,OAAO,IAAI,KAAK,IAAI,GAAG,OAAO,KAAK,IAAI,MAAM,EAAE;AAAA,IAC3D;AAAA,IACA,CAAC,CAAC;AAAA,EACJ;AAEA,QAAM,aAAa,MAAM,YAAY,YAAY;AAC/C,QAAI,CAAC,OAAQ;AACb,cAAU,IAAI;AACd,QAAI;AACF,YAAM,eAAe,yBAAyB;AAAA,QAC5C,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,GAAG,QAAQ,eAAe,eAAe,OAAO,aAAa,EAAE,CAAC;AAAA,MACzF,CAAC;AACD,YAAM,EAAE,0BAA0B,wBAAwB,GAAG,SAAS;AACtE,YAAM,KAAK;AAAA,IACb,SAAS,KAAK;AAIZ,YAAM,EAAE,SAAS,YAAY,IAAI,yBAAyB,GAAG;AAC7D,YAAM,UAAU,OAAO,QAAQ,eAAe,CAAC,CAAC,EAC7C,IAAI,CAAC,CAAC,OAAO,YAAY,MAAM;AAC9B,cAAM,OAAO,OAAO,YAAY;AAChC,cAAM,aAAa,KAAK,WAAW,UAAU,IAAI,EAAE,MAAM,IAAI,IAAI;AACjE,eAAO,GAAG,WAAW,KAAK,CAAC,KAAK,UAAU;AAAA,MAC5C,CAAC,EACA,KAAK,IAAI;AACZ;AAAA,QACE,UACI,GAAG,EAAE,iCAAiC,oBAAoB,CAAC,WAAM,OAAO,KACxE,WAAW,EAAE,+BAA+B,eAAe;AAAA,QAC/D;AAAA,MACF;AAAA,IACF,UAAE;AACA,gBAAU,KAAK;AAAA,IACjB;AAAA,EACF,GAAG,CAAC,YAAY,MAAM,GAAG,MAAM,CAAC;AAEhC,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAS,KAAK;AACtD,QAAM,mBAAmB,MAAM;AAAA,IAC7B,OAAO,SAAsB;AAC3B,UAAI,CAAC,QAAQ,CAAC,OAAQ;AACtB,mBAAa,IAAI;AACjB,UAAI;AACF,cAAM,OAAO,IAAI,SAAS;AAC1B,aAAK,IAAI,YAAY,oBAAoB;AACzC,aAAK,IAAI,YAAY,QAAQ,SAAS,MAAM,UAAU;AACtD,aAAK,IAAI,QAAQ,IAAI;AACrB,cAAM,OAAO,MAAM,QAAmD,oBAAoB;AAAA,UACxF,QAAQ;AAAA,UACR,MAAM;AAAA,QACR,CAAC;AACD,YAAI,CAAC,KAAK,MAAM,CAAC,KAAK,QAAQ,MAAM,IAAI;AACtC,gBAAM,IAAI,MAAM,KAAK,QAAQ,SAAS,EAAE,uCAAuC,oBAAoB,CAAC;AAAA,QACtG;AACA,YAAI,oBAAoB,KAAK,OAAO,KAAK,EAAE;AAAA,MAC7C,SAAS,KAAK;AACZ,cAAM,eAAe,QAAQ,IAAI,UAAU,EAAE,uCAAuC,oBAAoB,GAAG,OAAO;AAAA,MACpH,UAAE;AACA,qBAAa,KAAK;AAAA,MACpB;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,SAAS,IAAI,GAAG,MAAM;AAAA,EACjC;AAEA,QAAM,UAAU,QAAQ,iBAAiB;AACzC,QAAM,aAAa,CAAC,KAA0B,UAC5C,IAAI,iBAAiB,EAAE,GAAI,QAAQ,iBAAiB,eAAgB,CAAC,GAAG,GAAG,MAAM,CAAC;AAEpF,QAAM,gBAAwC;AAAA,IAC5C,WAAW,EAAE,sCAAsC,YAAY;AAAA,IAC/D,eAAe,EAAE,mCAAmC,SAAS;AAAA,IAC7D,OAAO,EAAE,kCAAkC,QAAQ;AAAA,IACnD,MAAM,EAAE,iCAAiC,MAAM;AAAA,EACjD;AAEA,QAAM,gBAAgB,CAAC,UAA+C;AACpE,SAAK,MAAM,WAAW,MAAM,YAAY,MAAM,QAAQ,SAAS;AAC7D,YAAM,eAAe;AACrB,WAAK,WAAW;AAAA,IAClB,WAAW,MAAM,QAAQ,YAAY,QAAQ;AAC3C,YAAM,eAAe;AACrB,gBAAU,OAAO,QAAQ;AAAA,IAC3B;AAAA,EACF;AAEA,SACE,qBAAC,QACC;AAAA,wBAAC,cAAW,OAAO,EAAE,0BAA0B,SAAS,GAAG;AAAA,IAC3D,oBAAC,YACE,kBACC,oBAAC,gBAAa,OAAO,OAAO,IAC1B,CAAC,UAAU,CAAC,SACd,oBAAC,kBAAe,OAAO,EAAE,4BAA4B,gCAA2B,GAAG,IAEnF,qBAAC,SAAI,WAAU,uBAAsB,WAAW,eAC7C;AAAA,aAAO,gBAAgB,CAAC,OAAO,aAAa,QAC3C,qBAAC,SAAI,WAAU,mFACb;AAAA,4BAAC,SAAI,WAAU,eACZ,YAAE,qCAAqC,+BAA+B,GACzE;AAAA,QACA,qBAAC,SAAI,WAAU,yBACZ;AAAA,YAAE,oCAAoC,sDAAsD;AAAA,UAAG;AAAA,UAC/F,OAAO,aAAa,QAAQ,IAAI,CAAC,UAAU,cAAc,KAAK,KAAK,KAAK,EAAE,KAAK,IAAI;AAAA,WACtF;AAAA,SACF,IACE;AAAA,MAEJ,qBAAC,aAAQ,WAAU,uEACjB;AAAA,4BAAC,QAAG,WAAU,yCAAyC,YAAE,iCAAiC,QAAQ,GAAE;AAAA,QACpG,qBAAC,WAAM,WAAU,6CACf;AAAA,+BAAC,UAAK,WAAU,yBAAyB;AAAA,cAAE,sCAAsC,YAAY;AAAA,YAAE;AAAA,aAAE;AAAA,UACjG,oBAAC,SAAM,OAAO,OAAO,WAAW,WAAW,KAAK,UAAU,CAAC,MAAM,IAAI,aAAa,EAAE,cAAc,KAAK,GAAG;AAAA,WAC5G;AAAA,QACA,qBAAC,WAAM,WAAU,6CACf;AAAA,+BAAC,UAAK,WAAU,yBAAyB;AAAA,cAAE,iCAAiC,gBAAgB;AAAA,YAAE;AAAA,aAAE;AAAA,UAChG,oBAAC,SAAM,OAAO,QAAQ,OAAO,UAAU,CAAC,MAAM,WAAW,SAAS,EAAE,cAAc,KAAK,GAAG;AAAA,WAC5F;AAAA,QACA,qBAAC,WAAM,WAAU,6CACf;AAAA,8BAAC,UAAK,WAAU,yBAAyB,YAAE,iCAAiC,gBAAgB,GAAE;AAAA,UAC9F,oBAAC,SAAM,OAAO,QAAQ,SAAS,IAAI,UAAU,CAAC,MAAM,WAAW,SAAS,EAAE,cAAc,KAAK,GAAG;AAAA,WAClG;AAAA,QACA,qBAAC,WAAM,WAAU,+BACf;AAAA,+BAAC,UAAK,WAAU,yBAAyB;AAAA,cAAE,uCAAuC,aAAa;AAAA,YAAE;AAAA,aAAE;AAAA,UACnG,oBAAC,SAAM,OAAO,QAAQ,aAAa,UAAU,CAAC,MAAM,WAAW,eAAe,EAAE,cAAc,KAAK,GAAG;AAAA,WACxG;AAAA,QACA,qBAAC,WAAM,WAAU,+BACf;AAAA,+BAAC,UAAK,WAAU,yBAAyB;AAAA,cAAE,gCAAgC,MAAM;AAAA,YAAE;AAAA,aAAE;AAAA,UACrF,oBAAC,SAAM,OAAO,QAAQ,MAAM,UAAU,CAAC,MAAM,WAAW,QAAQ,EAAE,cAAc,KAAK,GAAG;AAAA,WAC1F;AAAA,QACA,qBAAC,WAAM,WAAU,+BACf;AAAA,+BAAC,UAAK,WAAU,yBAAyB;AAAA,cAAE,mCAAmC,oBAAoB;AAAA,YAAE;AAAA,aAAE;AAAA,UACtG,oBAAC,SAAM,OAAO,QAAQ,SAAS,WAAW,GAAG,UAAU,CAAC,MAAM,WAAW,WAAW,EAAE,cAAc,KAAK,GAAG;AAAA,WAC9G;AAAA,QACA,qBAAC,WAAM,WAAU,+BACf;AAAA,+BAAC,UAAK,WAAU,yBAAyB;AAAA,cAAE,kCAAkC,QAAQ;AAAA,YAAE;AAAA,aAAE;AAAA,UACzF,oBAAC,SAAM,OAAO,OAAO,OAAO,WAAW,IAAI,UAAU,CAAC,MAAM,IAAI,SAAS,EAAE,cAAc,KAAK,GAAG;AAAA,WACnG;AAAA,SACF;AAAA,MAEA,qBAAC,aAAQ,WAAU,uEACjB;AAAA,4BAAC,QAAG,WAAU,yCAAyC,YAAE,kCAAkC,uBAAuB,GAAE;AAAA,QACpH,qBAAC,WAAM,WAAU,6CACf;AAAA,8BAAC,UAAK,WAAU,yBAAyB,YAAE,sCAAsC,WAAW,GAAE;AAAA,UAC9F,oBAAC,SAAM,OAAO,OAAO,UAAU,WAAW,KAAK,UAAU,CAAC,MAAM,IAAI,YAAY,EAAE,cAAc,KAAK,GAAG;AAAA,WAC1G;AAAA,QACA,qBAAC,WAAM,WAAU,+BACf;AAAA,+BAAC,UAAK,WAAU,yBAAyB;AAAA,cAAE,iCAAiC,MAAM;AAAA,YAAE;AAAA,aAAE;AAAA,UACtF,oBAAC,SAAM,OAAO,OAAO,MAAM,WAAU,aAAY,UAAU,CAAC,MAAM,IAAI,QAAQ,EAAE,cAAc,KAAK,GAAG;AAAA,WACxG;AAAA,QACA,qBAAC,WAAM,WAAU,+BACf;AAAA,8BAAC,UAAK,WAAU,yBAAyB,YAAE,gCAAgC,aAAa,GAAE;AAAA,UAC1F,oBAAC,SAAM,OAAO,OAAO,KAAK,WAAU,aAAY,WAAW,IAAI,UAAU,CAAC,MAAM,IAAI,OAAO,EAAE,cAAc,KAAK,GAAG;AAAA,WACrH;AAAA,QACA,qBAAC,WAAM,WAAU,+BACf;AAAA,8BAAC,UAAK,WAAU,yBAAyB,YAAE,kCAAkC,8BAA8B,GAAE;AAAA,UAC7G;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,KAAI;AAAA,cACJ,KAAI;AAAA,cACJ,MAAK;AAAA,cACL,OAAO,OAAO,OAAO,uBAAuB;AAAA,cAC5C,UAAU,CAAC,MAAM,IAAI,2BAA2B,OAAO,SAAS,EAAE,cAAc,OAAO,EAAE,KAAK,CAAC;AAAA;AAAA,UACjG;AAAA,WACF;AAAA,QACA,qBAAC,WAAM,WAAU,+BACf;AAAA,8BAAC,UAAK,WAAU,yBAAyB,YAAE,qCAAqC,sBAAsB,GAAE;AAAA,UACxG;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,KAAI;AAAA,cACJ,KAAI;AAAA,cACJ,MAAK;AAAA,cACL,OAAO,OAAO,OAAO,cAAc;AAAA,cACnC,UAAU,CAAC,MAAM,IAAI,kBAAkB,OAAO,EAAE,cAAc,KAAK,KAAK,CAAC;AAAA;AAAA,UAC3E;AAAA,UACA,oBAAC,UAAK,WAAU,iCACb,YAAE,0CAA0C,oEAAoE,GACnH;AAAA,WACF;AAAA,QACA,qBAAC,WAAM,WAAU,6CACf;AAAA,8BAAC,UAAK,WAAU,yBAAyB,YAAE,oCAAoC,gBAAgB,GAAE;AAAA,UACjG;AAAA,YAAC;AAAA;AAAA,cACC,MAAM;AAAA,cACN,WAAW;AAAA,cACX,OAAO,OAAO;AAAA,cACd,UAAU,CAAC,MAAM,IAAI,iBAAiB,EAAE,cAAc,KAAK;AAAA;AAAA,UAC7D;AAAA,UACA,oBAAC,UAAK,WAAU,iCACb,YAAE,yCAAyC,4DAA4D,GAC1G;AAAA,WACF;AAAA,QACA,qBAAC,SAAI,WAAU,6CACb;AAAA,8BAAC,UAAK,WAAU,yBAAyB,YAAE,kCAAkC,oBAAoB,GAAE;AAAA,UAClG,OAAO,mBACN,qBAAC,SAAI,WAAU,2BACb;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,KAAK,yBAAyB,mBAAmB,OAAO,gBAAgB,CAAC;AAAA,gBACzE,KAAK,EAAE,kCAAkC,oBAAoB;AAAA,gBAC7D,WAAU;AAAA;AAAA,YACZ;AAAA,YACA,oBAAC,UAAO,MAAK,UAAS,SAAQ,WAAU,MAAK,MAAK,SAAS,MAAM,IAAI,oBAAoB,IAAI,GAC1F,YAAE,yCAAyC,QAAQ,GACtD;AAAA,aACF,IAEA,oBAAC,UAAK,WAAU,iCACb,YAAE,2CAA2C,wDAAmD,GACnG;AAAA,UAEF;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,QAAO;AAAA,cACP,UAAU;AAAA,cACV,UAAU,CAAC,MAAM,KAAK,iBAAiB,EAAE,cAAc,QAAQ,CAAC,KAAK,IAAI;AAAA;AAAA,UAC3E;AAAA,WACF;AAAA,SACF;AAAA,MAEA,qBAAC,aAAQ,WAAU,qDACjB;AAAA,6BAAC,SACC;AAAA,8BAAC,QAAG,WAAU,2BAA2B,YAAE,oCAAoC,oBAAoB,GAAE;AAAA,UACrG,oBAAC,OAAE,WAAU,iCACV;AAAA,YACC;AAAA,YACA;AAAA,UACF,GACF;AAAA,UAEA,oBAAC,QAAG,WAAU,sDACX;AAAA,YACC,CAAC,yBAAyB,EAAE,+BAA+B,kBAAkB,CAAC;AAAA,YAC9E,CAAC,kBAAkB,EAAE,oCAAoC,sBAAsB,CAAC;AAAA,YAChF,CAAC,uBAAuB,EAAE,oCAAoC,2BAA2B,CAAC;AAAA,YAC1F,CAAC,wBAAwB,EAAE,qCAAqC,4BAA4B,CAAC;AAAA,YAC7F,CAAC,4CAAuC,EAAE,8BAA8B,kCAAkC,CAAC;AAAA,UAC7G,EAAE,IAAI,CAAC,CAAC,OAAO,KAAK,MAClB,qBAAC,QACC;AAAA,gCAAC,UAAK,WAAU,aAAa,iBAAM;AAAA,YAAO;AAAA,YAAI;AAAA,eADvC,KAET,CACD,GACH;AAAA,WACF;AAAA,QACC,gBAAgB,IAAI,CAAC,WACpB;AAAA,UAAC;AAAA;AAAA,YAEC;AAAA,YACA,OAAO,OAAO,YAAY,MAAM;AAAA,YAChC,SAAS,OAAO,SAAS,YAAY,MAAM;AAAA,YAC3C,UAAU,CAAC,SAAS,IAAI,eAAe,EAAE,GAAG,OAAO,aAAa,CAAC,MAAM,GAAG,KAAK,CAAC;AAAA;AAAA,UAJ3E;AAAA,QAKP,CACD;AAAA,SACH;AAAA,MAEA,qBAAC,aAAQ,WAAU,uEACjB;AAAA,4BAAC,QAAG,WAAU,yCAAyC,YAAE,kCAAkC,kBAAkB,GAAE;AAAA,QAC/G,qBAAC,WAAM,WAAU,+BACf;AAAA,8BAAC,UAAK,WAAU,yBAAyB,YAAE,wCAAwC,uBAAuB,GAAE;AAAA,UAC5G;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,KAAI;AAAA,cACJ,MAAK;AAAA,cACL,OAAO,OAAO,OAAO,0BAA0B;AAAA,cAC/C,UAAU,CAAC,MAAM,IAAI,8BAA8B,OAAO,EAAE,cAAc,KAAK,KAAK,CAAC;AAAA;AAAA,UACvF;AAAA,WACF;AAAA,QACA,qBAAC,WAAM,WAAU,+BACf;AAAA,8BAAC,UAAK,WAAU,yBAAyB,YAAE,uCAAuC,0BAA0B,GAAE;AAAA,UAC9G;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,KAAI;AAAA,cACJ,MAAK;AAAA,cACL,OAAO,OAAO,OAAO,sBAAsB;AAAA,cAC3C,UAAU,CAAC,MAAM,IAAI,0BAA0B,OAAO,EAAE,cAAc,KAAK,KAAK,CAAC;AAAA;AAAA,UACnF;AAAA,WACF;AAAA,QACA,qBAAC,SAAI,WAAU,6CACb;AAAA,8BAAC,UAAK,WAAU,yBAAyB,YAAE,sCAAsC,0CAA0C,GAAE;AAAA,UAC7H;AAAA,YAAC;AAAA;AAAA,cACC,OAAO,OAAO,mBAAmB;AAAA,cACjC,eAAe,CAAC,SAAS,IAAI,mBAAmB,SAAS,gBAAgB,gBAAgB,OAAO;AAAA,cAChG,WAAU;AAAA,cAEV;AAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAM;AAAA,oBACN,OAAO,EAAE,4CAA4C,WAAW;AAAA,oBAChE,aAAa;AAAA,sBACX;AAAA,sBACA;AAAA,oBACF;AAAA;AAAA,gBACF;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAM;AAAA,oBACN,OAAO,EAAE,kDAAkD,YAAY;AAAA,oBACvE,aAAa;AAAA,sBACX;AAAA,sBACA;AAAA,oBACF;AAAA;AAAA,gBACF;AAAA;AAAA;AAAA,UACF;AAAA,WACE,OAAO,mBAAmB,cAAc,OAAO,SAAS,mBAAmB,WAC3E,oBAAC,SAAI,WAAU,kHACZ;AAAA,YACC;AAAA,YACA;AAAA,UACF,GACF,IACE;AAAA,WACN;AAAA,SACE,OAAO,mBAAmB,aAAa,UACvC,qBAAC,WAAM,WAAU,+BACf;AAAA,8BAAC,UAAK,WAAU,yBAAyB,YAAE,2CAA2C,4BAA4B,GAAE;AAAA,UACpH;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,KAAI;AAAA,cACJ,KAAI;AAAA,cACJ,MAAK;AAAA,cACL,OAAO,OAAO,OAAO,YAAY;AAAA,cACjC,UAAU,CAAC,MAAM,IAAI,gBAAgB,OAAO,EAAE,cAAc,KAAK,KAAK,CAAC;AAAA;AAAA,UACzE;AAAA,WACF,IACE;AAAA,QACJ,qBAAC,WAAM,WAAU,+BACf;AAAA,8BAAC,UAAK,WAAU,yBAAyB,YAAE,2CAA2C,yBAAyB,GAAE;AAAA,UACjH,oBAAC,SAAM,OAAO,OAAO,eAAe,UAAU,CAAC,MAAM,IAAI,iBAAiB,EAAE,cAAc,KAAK,GAAG;AAAA,WACpG;AAAA,QACA,qBAAC,SAAI,WAAU,yDACb;AAAA,8BAAC,UAAK,WAAU,WAAW,YAAE,uCAAuC,iDAAiD,GAAE;AAAA,UACvH,oBAAC,UAAO,SAAS,OAAO,kBAAkB,iBAAiB,CAAC,SAAS,IAAI,oBAAoB,IAAI,GAAG;AAAA,WACtG;AAAA,QACA,qBAAC,SAAI,WAAU,iDACb;AAAA,8BAAC,UAAK,WAAU,yBAAyB,YAAE,oCAAoC,gBAAgB,GAAE;AAAA,UAChG,OAAO,aAAa,gBACnB,oBAAC,OAAI,SAAQ,WAAW,YAAE,8CAA8C,WAAW,GAAE,IAErF,oBAAC,OAAI,SAAQ,WACV,YAAE,gDAAgD,0DAAqD,GAC1G;AAAA,WAEJ;AAAA,SACF;AAAA,MAEA,qBAAC,SAAI,WAAU,uCACb;AAAA,6BAAC,UAAK,WAAU,iCACd;AAAA,8BAAC,eAAY,MAAM,CAAC,eAAU,OAAO,GAAG;AAAA,UAAE;AAAA,UAAE,EAAE,8BAA8B,SAAS;AAAA,WACvF;AAAA,QACA,oBAAC,UAAO,MAAK,UAAS,SAAQ,WAAU,SAAS,MAAM,UAAU,OAAO,QAAQ,GAAG,UAAU,QAC1F,YAAE,yBAAyB,QAAQ,GACtC;AAAA,QACA,oBAAC,UAAO,MAAK,UAAS,SAAS,MAAM,KAAK,WAAW,GAAG,UAAU,QAC/D,mBAAS,EAAE,2BAA2B,cAAS,IAAI,EAAE,uBAAuB,MAAM,GACrF;AAAA,SACF;AAAA,OACF,GAEJ;AAAA,KACF;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Receipt } from "lucide-react";
|
|
3
|
+
const billingSettingsIcon = React.createElement(Receipt, { size: 16 });
|
|
4
|
+
const metadata = {
|
|
5
|
+
requireAuth: true,
|
|
6
|
+
requireFeatures: ["billing.settings.view"],
|
|
7
|
+
pageTitle: "Billing",
|
|
8
|
+
pageTitleKey: "billing.settings.title",
|
|
9
|
+
pageGroup: "Module Configs",
|
|
10
|
+
pageGroupKey: "settings.sections.moduleConfigs",
|
|
11
|
+
pageOrder: 20,
|
|
12
|
+
icon: billingSettingsIcon,
|
|
13
|
+
pageContext: "settings",
|
|
14
|
+
breadcrumb: [{ label: "Billing", labelKey: "billing.settings.title" }]
|
|
15
|
+
};
|
|
16
|
+
export {
|
|
17
|
+
metadata
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=page.meta.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../src/modules/billing/backend/config/billing/page.meta.ts"],
|
|
4
|
+
"sourcesContent": ["import React from 'react'\nimport { Receipt } from 'lucide-react'\n\nconst billingSettingsIcon = React.createElement(Receipt, { size: 16 })\n\n// Spec 0 \u2014 billing settings (prepaid defaults + document number masks).\n// Lives in the settings area next to other module configs. No `navHidden`:\n// the nav builder drops navHidden routes from the Settings sidebar too\n// (Spec F, F6).\nexport const metadata = {\n requireAuth: true,\n requireFeatures: ['billing.settings.view'],\n pageTitle: 'Billing',\n pageTitleKey: 'billing.settings.title',\n pageGroup: 'Module Configs',\n pageGroupKey: 'settings.sections.moduleConfigs',\n pageOrder: 20,\n icon: billingSettingsIcon,\n pageContext: 'settings' as const,\n breadcrumb: [{ label: 'Billing', labelKey: 'billing.settings.title' }],\n} as const\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO,WAAW;AAClB,SAAS,eAAe;AAExB,MAAM,sBAAsB,MAAM,cAAc,SAAS,EAAE,MAAM,GAAG,CAAC;AAM9D,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,uBAAuB;AAAA,EACzC,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,MAAM;AAAA,EACN,aAAa;AAAA,EACb,YAAY,CAAC,EAAE,OAAO,WAAW,UAAU,yBAAyB,CAAC;AACvE;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -60,7 +60,28 @@ const seed = {
|
|
|
60
60
|
);
|
|
61
61
|
}
|
|
62
62
|
};
|
|
63
|
-
|
|
63
|
+
const paymentsSample = {
|
|
64
|
+
command: "payments-sample",
|
|
65
|
+
async run(rest) {
|
|
66
|
+
const args = parseArgs(rest);
|
|
67
|
+
const container = await createRequestContainer();
|
|
68
|
+
const em = container.resolve("em");
|
|
69
|
+
const scope = await resolveScope(em, args);
|
|
70
|
+
if (!scope) {
|
|
71
|
+
console.error("[billing payments-sample] No organization found. Pass --org <id>.");
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const { buildPaymentsSampleCsv, loadSampleSources } = await import("./lib/seeds/paymentsSample.js");
|
|
75
|
+
const { writeFile } = await import("node:fs/promises");
|
|
76
|
+
const sources = await loadSampleSources(em, scope);
|
|
77
|
+
const out = typeof args.out === "string" ? args.out : "payments-sample.csv";
|
|
78
|
+
const sample = buildPaymentsSampleCsv({ ...sources, date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10) });
|
|
79
|
+
await writeFile(out, sample.csv, "utf8");
|
|
80
|
+
console.log(`[billing payments-sample] wrote ${sample.rows} rows to ${out}`);
|
|
81
|
+
for (const note of sample.missing) console.log(` \xB7 skipped ${note}`);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
var cli_default = [seed, paymentsSample];
|
|
64
85
|
export {
|
|
65
86
|
cli_default as default
|
|
66
87
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/modules/billing/cli.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ModuleCli } from '@open-mercato/shared/modules/registry'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { seedBillingDemo } from './lib/seeds/demo'\n\n/**\n * `mercato billing seed [--reset] [--tenant <id>] [--org <id>]`\n *\n * Loads self-contained billing test data (demo accounts + recurring/usage\n * items + an unrated usage record) into a single tenant. With no `--tenant`/\n * `--org`, it resolves the first (primary) organization created by\n * `mercato init`. `--reset` clears the seed's own rows first.\n */\n\nfunction parseArgs(rest: string[]): Record<string, string | boolean> {\n const out: Record<string, string | boolean> = {}\n for (let i = 0; i < rest.length; i++) {\n const token = rest[i]\n if (!token || !token.startsWith('--')) continue\n const key = token.slice(2)\n const next = rest[i + 1]\n if (next === undefined || next.startsWith('--')) out[key] = true\n else {\n out[key] = next\n i++\n }\n }\n return out\n}\n\nasync function resolveScope(\n em: EntityManager,\n args: Record<string, string | boolean>,\n): Promise<{ tenantId: string; organizationId: string } | null> {\n const orgArg = typeof args.org === 'string' ? args.org : undefined\n const tenantArg = typeof args.tenant === 'string' ? args.tenant : undefined\n\n const { Organization } = await import('@open-mercato/core/modules/directory/data/entities')\n\n if (orgArg) {\n const org = await em.findOne(Organization, { id: orgArg } as never)\n if (!org) return null\n return { organizationId: org.id, tenantId: tenantArg ?? org.tenant.id }\n }\n\n const orgs = await em.find(\n Organization,\n { isActive: true } as never,\n { orderBy: { createdAt: 'asc' } as never, limit: 5 },\n )\n if (orgs.length === 0) return null\n const org = orgs[0]\n if (orgs.length > 1) {\n console.warn(\n `[billing seed] Multiple organizations found \u2014 defaulting to \"${org.name}\" (${org.id}). ` +\n `Pass --org <id> to target another.`,\n )\n }\n return { organizationId: org.id, tenantId: tenantArg ?? org.tenant.id }\n}\n\nconst seed: ModuleCli = {\n command: 'seed',\n async run(rest) {\n const args = parseArgs(rest)\n const reset = Boolean(args.reset)\n\n const container = await createRequestContainer()\n const em = container.resolve<EntityManager>('em')\n\n const scope = await resolveScope(em, args)\n if (!scope) {\n console.error(\n '[billing seed] No organization found. Run \"yarn initialize\" first, or pass --org <id>.',\n )\n return\n }\n\n const res = await seedBillingDemo(em, scope, { reset })\n console.log(\n `[billing seed] tenant=${scope.tenantId} org=${scope.organizationId}${reset ? ' (reset)' : ''}\\n` +\n ` \u2713 accounts +${res.accountsCreated}, items +${res.itemsCreated}, usage +${res.usageCreated} ` +\n `(existing rows left untouched)\\n` +\n ` \u2192 Bill Runs \u00B7 New run \u00B7 As-of = today \u00B7 Real \u2192 invoice for the previous month.`,\n )\n },\n}\n\nexport default [seed]\n"],
|
|
5
|
-
"mappings": "AACA,SAAS,8BAA8B;AAEvC,SAAS,uBAAuB;AAWhC,SAAS,UAAU,MAAkD;AACnE,QAAM,MAAwC,CAAC;AAC/C,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,QAAQ,KAAK,CAAC;AACpB,QAAI,CAAC,SAAS,CAAC,MAAM,WAAW,IAAI,EAAG;AACvC,UAAM,MAAM,MAAM,MAAM,CAAC;AACzB,UAAM,OAAO,KAAK,IAAI,CAAC;AACvB,QAAI,SAAS,UAAa,KAAK,WAAW,IAAI,EAAG,KAAI,GAAG,IAAI;AAAA,SACvD;AACH,UAAI,GAAG,IAAI;AACX;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAe,aACb,IACA,MAC8D;AAC9D,QAAM,SAAS,OAAO,KAAK,QAAQ,WAAW,KAAK,MAAM;AACzD,QAAM,YAAY,OAAO,KAAK,WAAW,WAAW,KAAK,SAAS;AAElE,QAAM,EAAE,aAAa,IAAI,MAAM,OAAO,oDAAoD;AAE1F,MAAI,QAAQ;AACV,UAAMA,OAAM,MAAM,GAAG,QAAQ,cAAc,EAAE,IAAI,OAAO,CAAU;AAClE,QAAI,CAACA,KAAK,QAAO;AACjB,WAAO,EAAE,gBAAgBA,KAAI,IAAI,UAAU,aAAaA,KAAI,OAAO,GAAG;AAAA,EACxE;AAEA,QAAM,OAAO,MAAM,GAAG;AAAA,IACpB;AAAA,IACA,EAAE,UAAU,KAAK;AAAA,IACjB,EAAE,SAAS,EAAE,WAAW,MAAM,GAAY,OAAO,EAAE;AAAA,EACrD;AACA,MAAI,KAAK,WAAW,EAAG,QAAO;AAC9B,QAAM,MAAM,KAAK,CAAC;AAClB,MAAI,KAAK,SAAS,GAAG;AACnB,YAAQ;AAAA,MACN,qEAAgE,IAAI,IAAI,MAAM,IAAI,EAAE;AAAA,IAEtF;AAAA,EACF;AACA,SAAO,EAAE,gBAAgB,IAAI,IAAI,UAAU,aAAa,IAAI,OAAO,GAAG;AACxE;AAEA,MAAM,OAAkB;AAAA,EACtB,SAAS;AAAA,EACT,MAAM,IAAI,MAAM;AACd,UAAM,OAAO,UAAU,IAAI;AAC3B,UAAM,QAAQ,QAAQ,KAAK,KAAK;AAEhC,UAAM,YAAY,MAAM,uBAAuB;AAC/C,UAAM,KAAK,UAAU,QAAuB,IAAI;AAEhD,UAAM,QAAQ,MAAM,aAAa,IAAI,IAAI;AACzC,QAAI,CAAC,OAAO;AACV,cAAQ;AAAA,QACN;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,MAAM,MAAM,gBAAgB,IAAI,OAAO,EAAE,MAAM,CAAC;AACtD,YAAQ;AAAA,MACN,yBAAyB,MAAM,QAAQ,QAAQ,MAAM,cAAc,GAAG,QAAQ,aAAa,EAAE;AAAA,qBAC1E,IAAI,eAAe,YAAY,IAAI,YAAY,YAAY,IAAI,YAAY;AAAA;AAAA,IAGhG;AAAA,EACF;AACF;AAEA,IAAO,cAAQ,CAAC,
|
|
4
|
+
"sourcesContent": ["import type { ModuleCli } from '@open-mercato/shared/modules/registry'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { seedBillingDemo } from './lib/seeds/demo'\n\n/**\n * `mercato billing seed [--reset] [--tenant <id>] [--org <id>]`\n *\n * Loads self-contained billing test data (demo accounts + recurring/usage\n * items + an unrated usage record) into a single tenant. With no `--tenant`/\n * `--org`, it resolves the first (primary) organization created by\n * `mercato init`. `--reset` clears the seed's own rows first.\n */\n\nfunction parseArgs(rest: string[]): Record<string, string | boolean> {\n const out: Record<string, string | boolean> = {}\n for (let i = 0; i < rest.length; i++) {\n const token = rest[i]\n if (!token || !token.startsWith('--')) continue\n const key = token.slice(2)\n const next = rest[i + 1]\n if (next === undefined || next.startsWith('--')) out[key] = true\n else {\n out[key] = next\n i++\n }\n }\n return out\n}\n\nasync function resolveScope(\n em: EntityManager,\n args: Record<string, string | boolean>,\n): Promise<{ tenantId: string; organizationId: string } | null> {\n const orgArg = typeof args.org === 'string' ? args.org : undefined\n const tenantArg = typeof args.tenant === 'string' ? args.tenant : undefined\n\n const { Organization } = await import('@open-mercato/core/modules/directory/data/entities')\n\n if (orgArg) {\n const org = await em.findOne(Organization, { id: orgArg } as never)\n if (!org) return null\n return { organizationId: org.id, tenantId: tenantArg ?? org.tenant.id }\n }\n\n const orgs = await em.find(\n Organization,\n { isActive: true } as never,\n { orderBy: { createdAt: 'asc' } as never, limit: 5 },\n )\n if (orgs.length === 0) return null\n const org = orgs[0]\n if (orgs.length > 1) {\n console.warn(\n `[billing seed] Multiple organizations found \u2014 defaulting to \"${org.name}\" (${org.id}). ` +\n `Pass --org <id> to target another.`,\n )\n }\n return { organizationId: org.id, tenantId: tenantArg ?? org.tenant.id }\n}\n\nconst seed: ModuleCli = {\n command: 'seed',\n async run(rest) {\n const args = parseArgs(rest)\n const reset = Boolean(args.reset)\n\n const container = await createRequestContainer()\n const em = container.resolve<EntityManager>('em')\n\n const scope = await resolveScope(em, args)\n if (!scope) {\n console.error(\n '[billing seed] No organization found. Run \"yarn initialize\" first, or pass --org <id>.',\n )\n return\n }\n\n const res = await seedBillingDemo(em, scope, { reset })\n console.log(\n `[billing seed] tenant=${scope.tenantId} org=${scope.organizationId}${reset ? ' (reset)' : ''}\\n` +\n ` \u2713 accounts +${res.accountsCreated}, items +${res.itemsCreated}, usage +${res.usageCreated} ` +\n `(existing rows left untouched)\\n` +\n ` \u2192 Bill Runs \u00B7 New run \u00B7 As-of = today \u00B7 Real \u2192 invoice for the previous month.`,\n )\n },\n}\n\n/**\n * `mercato billing payments-sample [--out <file>] [--tenant <id>] [--org <id>]`\n *\n * Spec C demo: writes a bank CSV built from the organization's posted,\n * unpaid invoices (and a top-up receipt, if any) that shows every matcher\n * outcome after one upload on Billing \u2192 Payments. Run a real bill run and\n * post a few invoices first.\n */\nconst paymentsSample: ModuleCli = {\n command: 'payments-sample',\n async run(rest) {\n const args = parseArgs(rest)\n const container = await createRequestContainer()\n const em = container.resolve<EntityManager>('em')\n const scope = await resolveScope(em, args)\n if (!scope) {\n console.error('[billing payments-sample] No organization found. Pass --org <id>.')\n return\n }\n const { buildPaymentsSampleCsv, loadSampleSources } = await import('./lib/seeds/paymentsSample')\n const { writeFile } = await import('node:fs/promises')\n const sources = await loadSampleSources(em, scope)\n const out = typeof args.out === 'string' ? args.out : 'payments-sample.csv'\n const sample = buildPaymentsSampleCsv({ ...sources, date: new Date().toISOString().slice(0, 10) })\n await writeFile(out, sample.csv, 'utf8')\n console.log(`[billing payments-sample] wrote ${sample.rows} rows to ${out}`)\n for (const note of sample.missing) console.log(` \u00B7 skipped ${note}`)\n },\n}\n\nexport default [seed, paymentsSample]\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["org"]
|
|
7
7
|
}
|
|
@@ -38,6 +38,7 @@ const createAccountCommand = {
|
|
|
38
38
|
organizationId: parsed.organizationId,
|
|
39
39
|
tenantId: parsed.tenantId,
|
|
40
40
|
customerId: parsed.customerId,
|
|
41
|
+
customerKind: parsed.customerKind,
|
|
41
42
|
name: parsed.name,
|
|
42
43
|
currencyCode: parsed.currencyCode,
|
|
43
44
|
billCycle: parsed.billCycle,
|
|
@@ -50,6 +51,9 @@ const createAccountCommand = {
|
|
|
50
51
|
lastBillDate: parsed.lastBillDate ?? null,
|
|
51
52
|
billingMode,
|
|
52
53
|
creditLimit: parsed.creditLimit !== void 0 ? formatMoney(parsed.creditLimit) : "0",
|
|
54
|
+
// Spec B: null = organization default terms.
|
|
55
|
+
paymentTermsDays: parsed.paymentTermsDays ?? null,
|
|
56
|
+
autoSendInvoice: parsed.autoSendInvoice ?? false,
|
|
53
57
|
isActive: parsed.isActive ?? true,
|
|
54
58
|
createdAt: now,
|
|
55
59
|
updatedAt: now
|
|
@@ -109,6 +113,8 @@ const updateAccountCommand = {
|
|
|
109
113
|
if (parsed.lastBillDate !== void 0) record.lastBillDate = parsed.lastBillDate;
|
|
110
114
|
if (parsed.isActive !== void 0) record.isActive = parsed.isActive;
|
|
111
115
|
if (parsed.creditLimit !== void 0) record.creditLimit = formatMoney(parsed.creditLimit);
|
|
116
|
+
if (parsed.paymentTermsDays !== void 0) record.paymentTermsDays = parsed.paymentTermsDays;
|
|
117
|
+
if (parsed.autoSendInvoice !== void 0) record.autoSendInvoice = parsed.autoSendInvoice;
|
|
112
118
|
record.updatedAt = /* @__PURE__ */ new Date();
|
|
113
119
|
if (parsed.lowBalanceThreshold !== void 0 && record.billingMode === "prepaid") {
|
|
114
120
|
const balanceRow = await em.findOne(BillingAccountBalance, {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/billing/commands/accounts.ts"],
|
|
4
|
-
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { CommandHandler, CommandRuntimeContext } from '@open-mercato/shared/lib/commands/types'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport {\n ensureOrganizationScope,\n ensureTenantScope,\n} from '@open-mercato/shared/lib/commands/scope'\nimport {\n emitCrudSideEffects,\n requireId,\n} from '@open-mercato/shared/lib/commands/helpers'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport { BillingAccount, BillingAccountBalance } from '../data/entities'\nimport { billingEntityIds } from '../data/entityIds'\nimport {\n billingAccountCreateSchema,\n billingAccountDeleteSchema,\n billingAccountUpdateSchema,\n type BillingAccountCreateInput,\n type BillingAccountDeleteInput,\n type BillingAccountUpdateInput,\n} from '../data/validators'\nimport { ensureBalanceRow } from '../lib/balanceLedger'\nimport { formatMoney } from '../lib/money'\n\n/**\n * BillingAccount writes \u2014 create / update / soft-delete.\n *\n * Phase 1 keeps the command surface lean \u2014 no undo / snapshot / audit\n * log. Phase 4 (admin UI + posting flow) revisits to add operator-driven\n * undo. The patterns to add:\n * - `prepare`: capture BEFORE snapshot for update / delete\n * - `captureAfter`: capture AFTER snapshot\n * - `buildLog`: emit a structured audit log entry\n * - `undo`: restore from snapshots + reverse side effects\n * See `node_modules/@open-mercato/core/src/modules/customers/commands/people.ts`\n * for the canonical full-feature shape.\n */\n\nconst accountIndexer = { entityType: billingEntityIds.account } as const\nconst accountEvents = { module: 'billing', entity: 'account', persistent: true } as const\n\nfunction getEm(ctx: CommandRuntimeContext): EntityManager {\n return (ctx.container.resolve('em') as EntityManager).fork()\n}\n\nfunction getDataEngine(ctx: CommandRuntimeContext): DataEngine {\n return ctx.container.resolve('dataEngine') as DataEngine\n}\n\n// \u2500\u2500\u2500 Create \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\nconst createAccountCommand: CommandHandler<BillingAccountCreateInput, { id: string }> = {\n id: 'billing.accounts.create',\n\n async execute(rawInput, ctx) {\n const parsed = billingAccountCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = getEm(ctx)\n const now = new Date()\n const billingMode = parsed.billingMode ?? 'postpaid'\n const entity = em.create(BillingAccount, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n customerId: parsed.customerId,\n name: parsed.name,\n currencyCode: parsed.currencyCode,\n billCycle: parsed.billCycle,\n billCycleAnchor: parsed.billCycleAnchor,\n invoiceEmail: parsed.invoiceEmail,\n invoiceLanguage: parsed.invoiceLanguage,\n taxId: parsed.taxId ?? null,\n invoiceAddress: parsed.invoiceAddress as Record<string, unknown>,\n nextBillDate: parsed.nextBillDate,\n lastBillDate: parsed.lastBillDate ?? null,\n billingMode,\n creditLimit:\n parsed.creditLimit !== undefined ? formatMoney(parsed.creditLimit) : '0',\n isActive: parsed.isActive ?? true,\n createdAt: now,\n updatedAt: now,\n })\n em.persist(entity)\n await em.flush()\n\n // SPEC-002: a prepaid account gets its 1:1 balance row (starting at 0)\n // at create time, so the consume path never races a missing row.\n if (billingMode === 'prepaid') {\n await ensureBalanceRow(em, {\n organizationId: entity.organizationId,\n tenantId: entity.tenantId,\n billAccountId: entity.id,\n currencyCode: entity.currencyCode,\n lowBalanceThreshold:\n parsed.lowBalanceThreshold !== undefined && parsed.lowBalanceThreshold !== null\n ? formatMoney(parsed.lowBalanceThreshold)\n : null,\n })\n }\n\n await emitCrudSideEffects({\n dataEngine: getDataEngine(ctx),\n action: 'created',\n entity,\n identifiers: {\n id: entity.id,\n tenantId: entity.tenantId,\n organizationId: entity.organizationId,\n },\n indexer: accountIndexer,\n events: accountEvents,\n })\n\n return { id: entity.id }\n },\n}\n\n// \u2500\u2500\u2500 Update \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\nconst updateAccountCommand: CommandHandler<BillingAccountUpdateInput, { id: string }> = {\n id: 'billing.accounts.update',\n\n async execute(rawInput, ctx) {\n const parsed = billingAccountUpdateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = getEm(ctx)\n const record = await em.findOne(BillingAccount, {\n id: parsed.id,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n deletedAt: null,\n })\n if (!record) {\n throw new CrudHttpError(404, { error: 'Billing account not found' })\n }\n\n if (parsed.name !== undefined) record.name = parsed.name\n if (parsed.billCycle !== undefined) record.billCycle = parsed.billCycle\n if (parsed.billCycleAnchor !== undefined) record.billCycleAnchor = parsed.billCycleAnchor\n if (parsed.invoiceEmail !== undefined) record.invoiceEmail = parsed.invoiceEmail\n if (parsed.invoiceLanguage !== undefined) record.invoiceLanguage = parsed.invoiceLanguage\n if (parsed.taxId !== undefined) record.taxId = parsed.taxId\n if (parsed.invoiceAddress !== undefined) {\n record.invoiceAddress = parsed.invoiceAddress as Record<string, unknown>\n }\n if (parsed.nextBillDate !== undefined) record.nextBillDate = parsed.nextBillDate\n if (parsed.lastBillDate !== undefined) record.lastBillDate = parsed.lastBillDate\n if (parsed.isActive !== undefined) record.isActive = parsed.isActive\n // SPEC-002: credit_limit is editable in both modes (billing_mode is not).\n if (parsed.creditLimit !== undefined) record.creditLimit = formatMoney(parsed.creditLimit)\n\n record.updatedAt = new Date()\n\n // SPEC-002: edit the prepaid balance row's low-balance threshold when\n // supplied (null clears it back to the tenant config default). No-op for\n // postpaid accounts (they have no balance row).\n if (parsed.lowBalanceThreshold !== undefined && record.billingMode === 'prepaid') {\n const balanceRow = await em.findOne(BillingAccountBalance, {\n tenantId: parsed.tenantId,\n billAccountId: record.id,\n })\n if (balanceRow) {\n balanceRow.lowBalanceThreshold =\n parsed.lowBalanceThreshold === null\n ? null\n : formatMoney(parsed.lowBalanceThreshold)\n balanceRow.updatedAt = new Date()\n }\n }\n\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: getDataEngine(ctx),\n action: 'updated',\n entity: record,\n identifiers: {\n id: record.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n },\n indexer: accountIndexer,\n events: accountEvents,\n })\n\n return { id: record.id }\n },\n}\n\n// \u2500\u2500\u2500 Delete (soft) \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\nconst deleteAccountCommand: CommandHandler<BillingAccountDeleteInput, { id: string }> = {\n id: 'billing.accounts.delete',\n\n async execute(rawInput, ctx) {\n const parsed = billingAccountDeleteSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const id = requireId(parsed)\n\n const em = getEm(ctx)\n const record = await em.findOne(BillingAccount, {\n id,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n deletedAt: null,\n })\n if (!record) {\n throw new CrudHttpError(404, { error: 'Billing account not found' })\n }\n\n record.deletedAt = new Date()\n record.updatedAt = record.deletedAt\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: getDataEngine(ctx),\n action: 'deleted',\n entity: record,\n identifiers: {\n id: record.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n },\n indexer: accountIndexer,\n events: accountEvents,\n })\n\n return { id: record.id }\n },\n}\n\nregisterCommand(createAccountCommand)\nregisterCommand(updateAccountCommand)\nregisterCommand(deleteAccountCommand)\n\nexport {\n createAccountCommand,\n updateAccountCommand,\n deleteAccountCommand,\n}\n"],
|
|
5
|
-
"mappings": "AAEA,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,qBAAqB;AAE9B,SAAS,gBAAgB,6BAA6B;AACtD,SAAS,wBAAwB;AACjC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AACP,SAAS,wBAAwB;AACjC,SAAS,mBAAmB;AAgB5B,MAAM,iBAAiB,EAAE,YAAY,iBAAiB,QAAQ;AAC9D,MAAM,gBAAgB,EAAE,QAAQ,WAAW,QAAQ,WAAW,YAAY,KAAK;AAE/E,SAAS,MAAM,KAA2C;AACxD,SAAQ,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC7D;AAEA,SAAS,cAAc,KAAwC;AAC7D,SAAO,IAAI,UAAU,QAAQ,YAAY;AAC3C;AAIA,MAAM,uBAAkF;AAAA,EACtF,IAAI;AAAA,EAEJ,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,SAAS,2BAA2B,MAAM,QAAQ;AACxD,sBAAkB,KAAK,OAAO,QAAQ;AACtC,4BAAwB,KAAK,OAAO,cAAc;AAElD,UAAM,KAAK,MAAM,GAAG;AACpB,UAAM,MAAM,oBAAI,KAAK;AACrB,UAAM,cAAc,OAAO,eAAe;AAC1C,UAAM,SAAS,GAAG,OAAO,gBAAgB;AAAA,MACvC,gBAAgB,OAAO;AAAA,MACvB,UAAU,OAAO;AAAA,MACjB,YAAY,OAAO;AAAA,MACnB,MAAM,OAAO;AAAA,MACb,cAAc,OAAO;AAAA,MACrB,WAAW,OAAO;AAAA,MAClB,iBAAiB,OAAO;AAAA,MACxB,cAAc,OAAO;AAAA,MACrB,iBAAiB,OAAO;AAAA,MACxB,OAAO,OAAO,SAAS;AAAA,MACvB,gBAAgB,OAAO;AAAA,MACvB,cAAc,OAAO;AAAA,MACrB,cAAc,OAAO,gBAAgB;AAAA,MACrC;AAAA,MACA,aACE,OAAO,gBAAgB,SAAY,YAAY,OAAO,WAAW,IAAI;AAAA,
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { CommandHandler, CommandRuntimeContext } from '@open-mercato/shared/lib/commands/types'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport {\n ensureOrganizationScope,\n ensureTenantScope,\n} from '@open-mercato/shared/lib/commands/scope'\nimport {\n emitCrudSideEffects,\n requireId,\n} from '@open-mercato/shared/lib/commands/helpers'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport { BillingAccount, BillingAccountBalance } from '../data/entities'\nimport { billingEntityIds } from '../data/entityIds'\nimport {\n billingAccountCreateSchema,\n billingAccountDeleteSchema,\n billingAccountUpdateSchema,\n type BillingAccountCreateInput,\n type BillingAccountDeleteInput,\n type BillingAccountUpdateInput,\n} from '../data/validators'\nimport { ensureBalanceRow } from '../lib/balanceLedger'\nimport { formatMoney } from '../lib/money'\n\n/**\n * BillingAccount writes \u2014 create / update / soft-delete.\n *\n * Phase 1 keeps the command surface lean \u2014 no undo / snapshot / audit\n * log. Phase 4 (admin UI + posting flow) revisits to add operator-driven\n * undo. The patterns to add:\n * - `prepare`: capture BEFORE snapshot for update / delete\n * - `captureAfter`: capture AFTER snapshot\n * - `buildLog`: emit a structured audit log entry\n * - `undo`: restore from snapshots + reverse side effects\n * See `node_modules/@open-mercato/core/src/modules/customers/commands/people.ts`\n * for the canonical full-feature shape.\n */\n\nconst accountIndexer = { entityType: billingEntityIds.account } as const\nconst accountEvents = { module: 'billing', entity: 'account', persistent: true } as const\n\nfunction getEm(ctx: CommandRuntimeContext): EntityManager {\n return (ctx.container.resolve('em') as EntityManager).fork()\n}\n\nfunction getDataEngine(ctx: CommandRuntimeContext): DataEngine {\n return ctx.container.resolve('dataEngine') as DataEngine\n}\n\n// \u2500\u2500\u2500 Create \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\nconst createAccountCommand: CommandHandler<BillingAccountCreateInput, { id: string }> = {\n id: 'billing.accounts.create',\n\n async execute(rawInput, ctx) {\n const parsed = billingAccountCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = getEm(ctx)\n const now = new Date()\n const billingMode = parsed.billingMode ?? 'postpaid'\n const entity = em.create(BillingAccount, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n customerId: parsed.customerId,\n customerKind: parsed.customerKind,\n name: parsed.name,\n currencyCode: parsed.currencyCode,\n billCycle: parsed.billCycle,\n billCycleAnchor: parsed.billCycleAnchor,\n invoiceEmail: parsed.invoiceEmail,\n invoiceLanguage: parsed.invoiceLanguage,\n taxId: parsed.taxId ?? null,\n invoiceAddress: parsed.invoiceAddress as Record<string, unknown>,\n nextBillDate: parsed.nextBillDate,\n lastBillDate: parsed.lastBillDate ?? null,\n billingMode,\n creditLimit:\n parsed.creditLimit !== undefined ? formatMoney(parsed.creditLimit) : '0',\n // Spec B: null = organization default terms.\n paymentTermsDays: parsed.paymentTermsDays ?? null,\n autoSendInvoice: parsed.autoSendInvoice ?? false,\n isActive: parsed.isActive ?? true,\n createdAt: now,\n updatedAt: now,\n })\n em.persist(entity)\n await em.flush()\n\n // SPEC-002: a prepaid account gets its 1:1 balance row (starting at 0)\n // at create time, so the consume path never races a missing row.\n if (billingMode === 'prepaid') {\n await ensureBalanceRow(em, {\n organizationId: entity.organizationId,\n tenantId: entity.tenantId,\n billAccountId: entity.id,\n currencyCode: entity.currencyCode,\n lowBalanceThreshold:\n parsed.lowBalanceThreshold !== undefined && parsed.lowBalanceThreshold !== null\n ? formatMoney(parsed.lowBalanceThreshold)\n : null,\n })\n }\n\n await emitCrudSideEffects({\n dataEngine: getDataEngine(ctx),\n action: 'created',\n entity,\n identifiers: {\n id: entity.id,\n tenantId: entity.tenantId,\n organizationId: entity.organizationId,\n },\n indexer: accountIndexer,\n events: accountEvents,\n })\n\n return { id: entity.id }\n },\n}\n\n// \u2500\u2500\u2500 Update \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\nconst updateAccountCommand: CommandHandler<BillingAccountUpdateInput, { id: string }> = {\n id: 'billing.accounts.update',\n\n async execute(rawInput, ctx) {\n const parsed = billingAccountUpdateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = getEm(ctx)\n const record = await em.findOne(BillingAccount, {\n id: parsed.id,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n deletedAt: null,\n })\n if (!record) {\n throw new CrudHttpError(404, { error: 'Billing account not found' })\n }\n\n if (parsed.name !== undefined) record.name = parsed.name\n if (parsed.billCycle !== undefined) record.billCycle = parsed.billCycle\n if (parsed.billCycleAnchor !== undefined) record.billCycleAnchor = parsed.billCycleAnchor\n if (parsed.invoiceEmail !== undefined) record.invoiceEmail = parsed.invoiceEmail\n if (parsed.invoiceLanguage !== undefined) record.invoiceLanguage = parsed.invoiceLanguage\n if (parsed.taxId !== undefined) record.taxId = parsed.taxId\n if (parsed.invoiceAddress !== undefined) {\n record.invoiceAddress = parsed.invoiceAddress as Record<string, unknown>\n }\n if (parsed.nextBillDate !== undefined) record.nextBillDate = parsed.nextBillDate\n if (parsed.lastBillDate !== undefined) record.lastBillDate = parsed.lastBillDate\n if (parsed.isActive !== undefined) record.isActive = parsed.isActive\n // SPEC-002: credit_limit is editable in both modes (billing_mode is not).\n if (parsed.creditLimit !== undefined) record.creditLimit = formatMoney(parsed.creditLimit)\n if (parsed.paymentTermsDays !== undefined) record.paymentTermsDays = parsed.paymentTermsDays\n if (parsed.autoSendInvoice !== undefined) record.autoSendInvoice = parsed.autoSendInvoice\n\n record.updatedAt = new Date()\n\n // SPEC-002: edit the prepaid balance row's low-balance threshold when\n // supplied (null clears it back to the tenant config default). No-op for\n // postpaid accounts (they have no balance row).\n if (parsed.lowBalanceThreshold !== undefined && record.billingMode === 'prepaid') {\n const balanceRow = await em.findOne(BillingAccountBalance, {\n tenantId: parsed.tenantId,\n billAccountId: record.id,\n })\n if (balanceRow) {\n balanceRow.lowBalanceThreshold =\n parsed.lowBalanceThreshold === null\n ? null\n : formatMoney(parsed.lowBalanceThreshold)\n balanceRow.updatedAt = new Date()\n }\n }\n\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: getDataEngine(ctx),\n action: 'updated',\n entity: record,\n identifiers: {\n id: record.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n },\n indexer: accountIndexer,\n events: accountEvents,\n })\n\n return { id: record.id }\n },\n}\n\n// \u2500\u2500\u2500 Delete (soft) \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\nconst deleteAccountCommand: CommandHandler<BillingAccountDeleteInput, { id: string }> = {\n id: 'billing.accounts.delete',\n\n async execute(rawInput, ctx) {\n const parsed = billingAccountDeleteSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const id = requireId(parsed)\n\n const em = getEm(ctx)\n const record = await em.findOne(BillingAccount, {\n id,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n deletedAt: null,\n })\n if (!record) {\n throw new CrudHttpError(404, { error: 'Billing account not found' })\n }\n\n record.deletedAt = new Date()\n record.updatedAt = record.deletedAt\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: getDataEngine(ctx),\n action: 'deleted',\n entity: record,\n identifiers: {\n id: record.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n },\n indexer: accountIndexer,\n events: accountEvents,\n })\n\n return { id: record.id }\n },\n}\n\nregisterCommand(createAccountCommand)\nregisterCommand(updateAccountCommand)\nregisterCommand(deleteAccountCommand)\n\nexport {\n createAccountCommand,\n updateAccountCommand,\n deleteAccountCommand,\n}\n"],
|
|
5
|
+
"mappings": "AAEA,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,qBAAqB;AAE9B,SAAS,gBAAgB,6BAA6B;AACtD,SAAS,wBAAwB;AACjC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AACP,SAAS,wBAAwB;AACjC,SAAS,mBAAmB;AAgB5B,MAAM,iBAAiB,EAAE,YAAY,iBAAiB,QAAQ;AAC9D,MAAM,gBAAgB,EAAE,QAAQ,WAAW,QAAQ,WAAW,YAAY,KAAK;AAE/E,SAAS,MAAM,KAA2C;AACxD,SAAQ,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC7D;AAEA,SAAS,cAAc,KAAwC;AAC7D,SAAO,IAAI,UAAU,QAAQ,YAAY;AAC3C;AAIA,MAAM,uBAAkF;AAAA,EACtF,IAAI;AAAA,EAEJ,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,SAAS,2BAA2B,MAAM,QAAQ;AACxD,sBAAkB,KAAK,OAAO,QAAQ;AACtC,4BAAwB,KAAK,OAAO,cAAc;AAElD,UAAM,KAAK,MAAM,GAAG;AACpB,UAAM,MAAM,oBAAI,KAAK;AACrB,UAAM,cAAc,OAAO,eAAe;AAC1C,UAAM,SAAS,GAAG,OAAO,gBAAgB;AAAA,MACvC,gBAAgB,OAAO;AAAA,MACvB,UAAU,OAAO;AAAA,MACjB,YAAY,OAAO;AAAA,MACnB,cAAc,OAAO;AAAA,MACrB,MAAM,OAAO;AAAA,MACb,cAAc,OAAO;AAAA,MACrB,WAAW,OAAO;AAAA,MAClB,iBAAiB,OAAO;AAAA,MACxB,cAAc,OAAO;AAAA,MACrB,iBAAiB,OAAO;AAAA,MACxB,OAAO,OAAO,SAAS;AAAA,MACvB,gBAAgB,OAAO;AAAA,MACvB,cAAc,OAAO;AAAA,MACrB,cAAc,OAAO,gBAAgB;AAAA,MACrC;AAAA,MACA,aACE,OAAO,gBAAgB,SAAY,YAAY,OAAO,WAAW,IAAI;AAAA;AAAA,MAEvE,kBAAkB,OAAO,oBAAoB;AAAA,MAC7C,iBAAiB,OAAO,mBAAmB;AAAA,MAC3C,UAAU,OAAO,YAAY;AAAA,MAC7B,WAAW;AAAA,MACX,WAAW;AAAA,IACb,CAAC;AACD,OAAG,QAAQ,MAAM;AACjB,UAAM,GAAG,MAAM;AAIf,QAAI,gBAAgB,WAAW;AAC7B,YAAM,iBAAiB,IAAI;AAAA,QACzB,gBAAgB,OAAO;AAAA,QACvB,UAAU,OAAO;AAAA,QACjB,eAAe,OAAO;AAAA,QACtB,cAAc,OAAO;AAAA,QACrB,qBACE,OAAO,wBAAwB,UAAa,OAAO,wBAAwB,OACvE,YAAY,OAAO,mBAAmB,IACtC;AAAA,MACR,CAAC;AAAA,IACH;AAEA,UAAM,oBAAoB;AAAA,MACxB,YAAY,cAAc,GAAG;AAAA,MAC7B,QAAQ;AAAA,MACR;AAAA,MACA,aAAa;AAAA,QACX,IAAI,OAAO;AAAA,QACX,UAAU,OAAO;AAAA,QACjB,gBAAgB,OAAO;AAAA,MACzB;AAAA,MACA,SAAS;AAAA,MACT,QAAQ;AAAA,IACV,CAAC;AAED,WAAO,EAAE,IAAI,OAAO,GAAG;AAAA,EACzB;AACF;AAIA,MAAM,uBAAkF;AAAA,EACtF,IAAI;AAAA,EAEJ,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,SAAS,2BAA2B,MAAM,QAAQ;AACxD,sBAAkB,KAAK,OAAO,QAAQ;AACtC,4BAAwB,KAAK,OAAO,cAAc;AAElD,UAAM,KAAK,MAAM,GAAG;AACpB,UAAM,SAAS,MAAM,GAAG,QAAQ,gBAAgB;AAAA,MAC9C,IAAI,OAAO;AAAA,MACX,UAAU,OAAO;AAAA,MACjB,gBAAgB,OAAO;AAAA,MACvB,WAAW;AAAA,IACb,CAAC;AACD,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,cAAc,KAAK,EAAE,OAAO,4BAA4B,CAAC;AAAA,IACrE;AAEA,QAAI,OAAO,SAAS,OAAW,QAAO,OAAO,OAAO;AACpD,QAAI,OAAO,cAAc,OAAW,QAAO,YAAY,OAAO;AAC9D,QAAI,OAAO,oBAAoB,OAAW,QAAO,kBAAkB,OAAO;AAC1E,QAAI,OAAO,iBAAiB,OAAW,QAAO,eAAe,OAAO;AACpE,QAAI,OAAO,oBAAoB,OAAW,QAAO,kBAAkB,OAAO;AAC1E,QAAI,OAAO,UAAU,OAAW,QAAO,QAAQ,OAAO;AACtD,QAAI,OAAO,mBAAmB,QAAW;AACvC,aAAO,iBAAiB,OAAO;AAAA,IACjC;AACA,QAAI,OAAO,iBAAiB,OAAW,QAAO,eAAe,OAAO;AACpE,QAAI,OAAO,iBAAiB,OAAW,QAAO,eAAe,OAAO;AACpE,QAAI,OAAO,aAAa,OAAW,QAAO,WAAW,OAAO;AAE5D,QAAI,OAAO,gBAAgB,OAAW,QAAO,cAAc,YAAY,OAAO,WAAW;AACzF,QAAI,OAAO,qBAAqB,OAAW,QAAO,mBAAmB,OAAO;AAC5E,QAAI,OAAO,oBAAoB,OAAW,QAAO,kBAAkB,OAAO;AAE1E,WAAO,YAAY,oBAAI,KAAK;AAK5B,QAAI,OAAO,wBAAwB,UAAa,OAAO,gBAAgB,WAAW;AAChF,YAAM,aAAa,MAAM,GAAG,QAAQ,uBAAuB;AAAA,QACzD,UAAU,OAAO;AAAA,QACjB,eAAe,OAAO;AAAA,MACxB,CAAC;AACD,UAAI,YAAY;AACd,mBAAW,sBACT,OAAO,wBAAwB,OAC3B,OACA,YAAY,OAAO,mBAAmB;AAC5C,mBAAW,YAAY,oBAAI,KAAK;AAAA,MAClC;AAAA,IACF;AAEA,UAAM,GAAG,MAAM;AAEf,UAAM,oBAAoB;AAAA,MACxB,YAAY,cAAc,GAAG;AAAA,MAC7B,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa;AAAA,QACX,IAAI,OAAO;AAAA,QACX,UAAU,OAAO;AAAA,QACjB,gBAAgB,OAAO;AAAA,MACzB;AAAA,MACA,SAAS;AAAA,MACT,QAAQ;AAAA,IACV,CAAC;AAED,WAAO,EAAE,IAAI,OAAO,GAAG;AAAA,EACzB;AACF;AAIA,MAAM,uBAAkF;AAAA,EACtF,IAAI;AAAA,EAEJ,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,SAAS,2BAA2B,MAAM,QAAQ;AACxD,sBAAkB,KAAK,OAAO,QAAQ;AACtC,4BAAwB,KAAK,OAAO,cAAc;AAClD,UAAM,KAAK,UAAU,MAAM;AAE3B,UAAM,KAAK,MAAM,GAAG;AACpB,UAAM,SAAS,MAAM,GAAG,QAAQ,gBAAgB;AAAA,MAC9C;AAAA,MACA,UAAU,OAAO;AAAA,MACjB,gBAAgB,OAAO;AAAA,MACvB,WAAW;AAAA,IACb,CAAC;AACD,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,cAAc,KAAK,EAAE,OAAO,4BAA4B,CAAC;AAAA,IACrE;AAEA,WAAO,YAAY,oBAAI,KAAK;AAC5B,WAAO,YAAY,OAAO;AAC1B,UAAM,GAAG,MAAM;AAEf,UAAM,oBAAoB;AAAA,MACxB,YAAY,cAAc,GAAG;AAAA,MAC7B,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa;AAAA,QACX,IAAI,OAAO;AAAA,QACX,UAAU,OAAO;AAAA,QACjB,gBAAgB,OAAO;AAAA,MACzB;AAAA,MACA,SAAS;AAAA,MACT,QAAQ;AAAA,IACV,CAAC;AAED,WAAO,EAAE,IAAI,OAAO,GAAG;AAAA,EACzB;AACF;AAEA,gBAAgB,oBAAoB;AACpC,gBAAgB,oBAAoB;AACpC,gBAAgB,oBAAoB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/billing/commands/index.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Billing module command registry.\n *\n * Each file below side-effect-registers its commands via\n * `registerCommand(...)` from `@open-mercato/shared/lib/commands`.\n * Importing this barrel forces the registrations to run. The CRUD\n * factory's `commandId` lookups then resolve at request time.\n */\nimport './accounts'\nimport './items'\nimport './usage'\nimport './runs'\nimport './invoices'\nimport './topups'\nimport './transactions'\nimport './statements'\n"],
|
|
5
|
-
"mappings": "AAQA,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;",
|
|
4
|
+
"sourcesContent": ["/**\n * Billing module command registry.\n *\n * Each file below side-effect-registers its commands via\n * `registerCommand(...)` from `@open-mercato/shared/lib/commands`.\n * Importing this barrel forces the registrations to run. The CRUD\n * factory's `commandId` lookups then resolve at request time.\n */\nimport './accounts'\nimport './items'\nimport './usage'\nimport './runs'\nimport './invoices'\nimport './topups'\nimport './transactions'\nimport './statements'\nimport './settings'\nimport './payments'\nimport './memos'\n"],
|
|
5
|
+
"mappings": "AAQA,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|