@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,200 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@open-mercato/ui/primitives/dialog";
|
|
5
|
+
import { Button } from "@open-mercato/ui/primitives/button";
|
|
6
|
+
import { Input } from "@open-mercato/ui/primitives/input";
|
|
7
|
+
import { Textarea } from "@open-mercato/ui/primitives/textarea";
|
|
8
|
+
import { Checkbox } from "@open-mercato/ui/primitives/checkbox";
|
|
9
|
+
import { Kbd, KbdShortcut } from "@open-mercato/ui/primitives/kbd";
|
|
10
|
+
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
11
|
+
import { apiCallOrThrow } from "@open-mercato/ui/backend/utils/apiCall";
|
|
12
|
+
import { normalizeCrudServerError } from "@open-mercato/ui/backend/utils/serverErrors";
|
|
13
|
+
import { flash } from "@open-mercato/ui/backend/FlashMessages";
|
|
14
|
+
import { formatMoney } from "./InvoicesTable.js";
|
|
15
|
+
function round2(value) {
|
|
16
|
+
return Math.round((value + Number.EPSILON) * 100) / 100;
|
|
17
|
+
}
|
|
18
|
+
function CreateMemoDialog({
|
|
19
|
+
open,
|
|
20
|
+
type,
|
|
21
|
+
invoiceId,
|
|
22
|
+
invoiceNumber,
|
|
23
|
+
currencyCode,
|
|
24
|
+
lines,
|
|
25
|
+
onClose,
|
|
26
|
+
onCreated
|
|
27
|
+
}) {
|
|
28
|
+
const t = useT();
|
|
29
|
+
const [reason, setReason] = React.useState("");
|
|
30
|
+
const [state, setState] = React.useState({});
|
|
31
|
+
const [saving, setSaving] = React.useState(false);
|
|
32
|
+
const fullCredit = React.useCallback(() => {
|
|
33
|
+
setState(
|
|
34
|
+
Object.fromEntries(
|
|
35
|
+
lines.map((line) => [
|
|
36
|
+
line.id,
|
|
37
|
+
{ selected: true, quantity: String(Number(line.quantity)), unitPriceNet: String(Math.abs(Number(line.unit_price_net))) }
|
|
38
|
+
])
|
|
39
|
+
)
|
|
40
|
+
);
|
|
41
|
+
}, [lines]);
|
|
42
|
+
React.useEffect(() => {
|
|
43
|
+
if (!open) return;
|
|
44
|
+
setReason("");
|
|
45
|
+
if (type === "credit_memo") fullCredit();
|
|
46
|
+
else setState({});
|
|
47
|
+
}, [fullCredit, open, type]);
|
|
48
|
+
const selected = lines.filter((line) => state[line.id]?.selected);
|
|
49
|
+
const projected = selected.reduce(
|
|
50
|
+
(acc, line) => {
|
|
51
|
+
const s = state[line.id];
|
|
52
|
+
const net = round2((Number.parseFloat(s.quantity) || 0) * (Number.parseFloat(s.unitPriceNet) || 0));
|
|
53
|
+
const tax = round2(net * ((Number(line.tax_rate) || 0) / 100));
|
|
54
|
+
return { net: acc.net + net, tax: acc.tax + tax };
|
|
55
|
+
},
|
|
56
|
+
{ net: 0, tax: 0 }
|
|
57
|
+
);
|
|
58
|
+
const update = (id, patch) => setState((prev) => ({ ...prev, [id]: { ...prev[id], ...patch } }));
|
|
59
|
+
const submit = React.useCallback(async () => {
|
|
60
|
+
if (saving) return;
|
|
61
|
+
if (!reason.trim()) {
|
|
62
|
+
flash(t("billing.memo.error.reason_required", "A reason is required"), "error");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (type === "credit_memo" && selected.length === 0) {
|
|
66
|
+
flash(t("billing.memo.error.no_lines", "Select at least one line to credit"), "error");
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
setSaving(true);
|
|
70
|
+
try {
|
|
71
|
+
const body = type === "credit_memo" ? {
|
|
72
|
+
type,
|
|
73
|
+
reason: reason.trim(),
|
|
74
|
+
lines: selected.map((line) => ({
|
|
75
|
+
correctsLineId: line.id,
|
|
76
|
+
description: line.description ?? "",
|
|
77
|
+
quantity: Number.parseFloat(state[line.id].quantity),
|
|
78
|
+
unitPriceNet: Number.parseFloat(state[line.id].unitPriceNet)
|
|
79
|
+
}))
|
|
80
|
+
} : { type, reason: reason.trim() };
|
|
81
|
+
const call = await apiCallOrThrow(`/api/billing/invoices/${encodeURIComponent(invoiceId)}/memos`, {
|
|
82
|
+
method: "POST",
|
|
83
|
+
headers: { "Content-Type": "application/json" },
|
|
84
|
+
body: JSON.stringify(body)
|
|
85
|
+
});
|
|
86
|
+
flash(t("billing.memo.created", "Draft memo created"), "success");
|
|
87
|
+
onClose();
|
|
88
|
+
if (call.result?.memoId) onCreated(call.result.memoId);
|
|
89
|
+
} catch (err) {
|
|
90
|
+
const code = err?.body?.code;
|
|
91
|
+
flash(
|
|
92
|
+
code === "billing.memo.exceeds_invoice" ? t("billing.memo.error.exceeds", "The credit is more than what is left to credit on this invoice") : normalizeCrudServerError(err).message || t("billing.memo.error.create", "Could not create the memo"),
|
|
93
|
+
"error"
|
|
94
|
+
);
|
|
95
|
+
} finally {
|
|
96
|
+
setSaving(false);
|
|
97
|
+
}
|
|
98
|
+
}, [invoiceId, onClose, onCreated, reason, saving, selected, state, t, type]);
|
|
99
|
+
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (next) => !next ? onClose() : void 0, children: /* @__PURE__ */ jsxs(
|
|
100
|
+
DialogContent,
|
|
101
|
+
{
|
|
102
|
+
className: "max-w-3xl",
|
|
103
|
+
onKeyDown: (event) => {
|
|
104
|
+
if ((event.metaKey || event.ctrlKey) && event.key === "Enter") {
|
|
105
|
+
event.preventDefault();
|
|
106
|
+
void submit();
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
children: [
|
|
110
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
111
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: type === "credit_memo" ? t("billing.memo.create_credit.title", "Create credit memo") : t("billing.memo.create_debit.title", "Create debit memo") }),
|
|
112
|
+
/* @__PURE__ */ jsxs(DialogDescription, { children: [
|
|
113
|
+
t("billing.memo.corrects", "Corrects"),
|
|
114
|
+
" ",
|
|
115
|
+
invoiceNumber,
|
|
116
|
+
" \xB7",
|
|
117
|
+
" ",
|
|
118
|
+
t("billing.memo.hint", "Corrects this document only. Update the billing item to change future invoices.")
|
|
119
|
+
] })
|
|
120
|
+
] }),
|
|
121
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 py-2 text-sm", children: [
|
|
122
|
+
type === "credit_memo" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
123
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
124
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: t("billing.memo.lines", "Lines to credit") }),
|
|
125
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: fullCredit, children: t("billing.memo.full_credit", "Full credit") })
|
|
126
|
+
] }),
|
|
127
|
+
/* @__PURE__ */ jsx("div", { className: "max-h-72 overflow-auto rounded-md border", children: lines.map((line) => {
|
|
128
|
+
const s = state[line.id] ?? { selected: false, quantity: "", unitPriceNet: "" };
|
|
129
|
+
return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[24px_1fr_90px_110px_60px] items-center gap-2 border-b px-2 py-1 last:border-b-0", children: [
|
|
130
|
+
/* @__PURE__ */ jsx(Checkbox, { checked: s.selected, onCheckedChange: (next) => update(line.id, { selected: next === true }) }),
|
|
131
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: line.description }),
|
|
132
|
+
/* @__PURE__ */ jsx(
|
|
133
|
+
Input,
|
|
134
|
+
{
|
|
135
|
+
type: "number",
|
|
136
|
+
min: "0",
|
|
137
|
+
step: "0.0001",
|
|
138
|
+
value: s.quantity,
|
|
139
|
+
disabled: !s.selected,
|
|
140
|
+
onChange: (e) => update(line.id, { quantity: e.currentTarget.value })
|
|
141
|
+
}
|
|
142
|
+
),
|
|
143
|
+
/* @__PURE__ */ jsx(
|
|
144
|
+
Input,
|
|
145
|
+
{
|
|
146
|
+
type: "number",
|
|
147
|
+
min: "0",
|
|
148
|
+
step: "0.01",
|
|
149
|
+
value: s.unitPriceNet,
|
|
150
|
+
disabled: !s.selected,
|
|
151
|
+
onChange: (e) => update(line.id, { unitPriceNet: e.currentTarget.value })
|
|
152
|
+
}
|
|
153
|
+
),
|
|
154
|
+
/* @__PURE__ */ jsxs("span", { className: "text-right text-xs text-muted-foreground", children: [
|
|
155
|
+
Number(line.tax_rate ?? 0),
|
|
156
|
+
" %"
|
|
157
|
+
] })
|
|
158
|
+
] }, line.id);
|
|
159
|
+
}) }),
|
|
160
|
+
/* @__PURE__ */ jsxs("div", { className: "text-right text-muted-foreground", children: [
|
|
161
|
+
t("billing.memo.projected", "Credit"),
|
|
162
|
+
": ",
|
|
163
|
+
formatMoney(String(projected.net), currencyCode),
|
|
164
|
+
" +",
|
|
165
|
+
" ",
|
|
166
|
+
t("billing.invoices.lines.columns.tax_amount", "VAT"),
|
|
167
|
+
" ",
|
|
168
|
+
formatMoney(String(projected.tax), currencyCode),
|
|
169
|
+
" =",
|
|
170
|
+
" ",
|
|
171
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: formatMoney(String(projected.net + projected.tax), currencyCode) })
|
|
172
|
+
] })
|
|
173
|
+
] }) : null,
|
|
174
|
+
/* @__PURE__ */ jsxs("label", { className: "flex flex-col gap-1", children: [
|
|
175
|
+
/* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
|
|
176
|
+
t("billing.memo.reason", "Reason (printed on the document)"),
|
|
177
|
+
" *"
|
|
178
|
+
] }),
|
|
179
|
+
/* @__PURE__ */ jsx(Textarea, { rows: 2, maxLength: 1e3, value: reason, onChange: (e) => setReason(e.currentTarget.value) })
|
|
180
|
+
] })
|
|
181
|
+
] }),
|
|
182
|
+
/* @__PURE__ */ jsx(DialogFooter, { children: /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center justify-between gap-3", children: [
|
|
183
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
|
|
184
|
+
/* @__PURE__ */ jsx(KbdShortcut, { keys: ["Ctrl/\u2318", "Enter"] }),
|
|
185
|
+
" \xB7 ",
|
|
186
|
+
/* @__PURE__ */ jsx(Kbd, { children: "Esc" })
|
|
187
|
+
] }),
|
|
188
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
189
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", onClick: onClose, children: t("billing.common.cancel", "Cancel") }),
|
|
190
|
+
/* @__PURE__ */ jsx(Button, { type: "button", onClick: () => void submit(), disabled: saving, children: t("billing.memo.create", "Create draft") })
|
|
191
|
+
] })
|
|
192
|
+
] }) })
|
|
193
|
+
]
|
|
194
|
+
}
|
|
195
|
+
) });
|
|
196
|
+
}
|
|
197
|
+
export {
|
|
198
|
+
CreateMemoDialog
|
|
199
|
+
};
|
|
200
|
+
//# sourceMappingURL=CreateMemoDialog.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/billing/components/CreateMemoDialog.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@open-mercato/ui/primitives/dialog'\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 { Checkbox } from '@open-mercato/ui/primitives/checkbox'\nimport { Kbd, KbdShortcut } from '@open-mercato/ui/primitives/kbd'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { normalizeCrudServerError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { formatMoney } from './InvoicesTable'\n\n/**\n * Create a credit or debit memo for a posted invoice (Spec D, D-D9).\n *\n * - credit memo: the original lines with a checkbox and editable quantity /\n * unit net (VAT rate stays the original's), a \"Full credit\" shortcut,\n * the required reason and the projected totals;\n * - debit memo: the reason only \u2014 lines are added on the draft.\n *\n * Creates a DRAFT memo and hands its id back (the page navigates to it).\n * Cmd/Ctrl+Enter submits, Escape cancels.\n */\n\nexport type MemoSourceLine = {\n id: string\n description: string | null\n quantity: string\n unit_price_net: string\n tax_rate: string | number | null\n}\n\ntype LineState = { selected: boolean; quantity: string; unitPriceNet: string }\n\nfunction round2(value: number): number {\n return Math.round((value + Number.EPSILON) * 100) / 100\n}\n\nexport function CreateMemoDialog({\n open,\n type,\n invoiceId,\n invoiceNumber,\n currencyCode,\n lines,\n onClose,\n onCreated,\n}: {\n open: boolean\n type: 'credit_memo' | 'debit_memo'\n invoiceId: string\n invoiceNumber: string\n currencyCode: string\n lines: MemoSourceLine[]\n onClose: () => void\n onCreated: (memoId: string) => void\n}) {\n const t = useT()\n const [reason, setReason] = React.useState('')\n const [state, setState] = React.useState<Record<string, LineState>>({})\n const [saving, setSaving] = React.useState(false)\n\n const fullCredit = React.useCallback(() => {\n setState(\n Object.fromEntries(\n lines.map((line) => [\n line.id,\n { selected: true, quantity: String(Number(line.quantity)), unitPriceNet: String(Math.abs(Number(line.unit_price_net))) },\n ]),\n ),\n )\n }, [lines])\n\n React.useEffect(() => {\n if (!open) return\n setReason('')\n if (type === 'credit_memo') fullCredit()\n else setState({})\n }, [fullCredit, open, type])\n\n const selected = lines.filter((line) => state[line.id]?.selected)\n const projected = selected.reduce(\n (acc, line) => {\n const s = state[line.id]\n const net = round2((Number.parseFloat(s.quantity) || 0) * (Number.parseFloat(s.unitPriceNet) || 0))\n const tax = round2(net * ((Number(line.tax_rate) || 0) / 100))\n return { net: acc.net + net, tax: acc.tax + tax }\n },\n { net: 0, tax: 0 },\n )\n\n const update = (id: string, patch: Partial<LineState>) =>\n setState((prev) => ({ ...prev, [id]: { ...prev[id], ...patch } }))\n\n const submit = React.useCallback(async () => {\n if (saving) return\n if (!reason.trim()) {\n flash(t('billing.memo.error.reason_required', 'A reason is required'), 'error')\n return\n }\n if (type === 'credit_memo' && selected.length === 0) {\n flash(t('billing.memo.error.no_lines', 'Select at least one line to credit'), 'error')\n return\n }\n setSaving(true)\n try {\n const body =\n type === 'credit_memo'\n ? {\n type,\n reason: reason.trim(),\n lines: selected.map((line) => ({\n correctsLineId: line.id,\n description: line.description ?? '',\n quantity: Number.parseFloat(state[line.id].quantity),\n unitPriceNet: Number.parseFloat(state[line.id].unitPriceNet),\n })),\n }\n : { type, reason: reason.trim() }\n const call = await apiCallOrThrow<{ memoId: string }>(`/api/billing/invoices/${encodeURIComponent(invoiceId)}/memos`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n })\n flash(t('billing.memo.created', 'Draft memo created'), 'success')\n onClose()\n if (call.result?.memoId) onCreated(call.result.memoId)\n } catch (err) {\n const code = (err as { body?: { code?: string } } | null)?.body?.code\n flash(\n code === 'billing.memo.exceeds_invoice'\n ? t('billing.memo.error.exceeds', 'The credit is more than what is left to credit on this invoice')\n : normalizeCrudServerError(err).message || t('billing.memo.error.create', 'Could not create the memo'),\n 'error',\n )\n } finally {\n setSaving(false)\n }\n }, [invoiceId, onClose, onCreated, reason, saving, selected, state, t, type])\n\n return (\n <Dialog open={open} onOpenChange={(next) => (!next ? onClose() : undefined)}>\n <DialogContent\n className=\"max-w-3xl\"\n onKeyDown={(event) => {\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n void submit()\n }\n }}\n >\n <DialogHeader>\n <DialogTitle>\n {type === 'credit_memo'\n ? t('billing.memo.create_credit.title', 'Create credit memo')\n : t('billing.memo.create_debit.title', 'Create debit memo')}\n </DialogTitle>\n <DialogDescription>\n {t('billing.memo.corrects', 'Corrects')} {invoiceNumber} \u00B7{' '}\n {t('billing.memo.hint', 'Corrects this document only. Update the billing item to change future invoices.')}\n </DialogDescription>\n </DialogHeader>\n <div className=\"flex flex-col gap-3 py-2 text-sm\">\n {type === 'credit_memo' ? (\n <>\n <div className=\"flex items-center justify-between\">\n <span className=\"font-medium\">{t('billing.memo.lines', 'Lines to credit')}</span>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={fullCredit}>\n {t('billing.memo.full_credit', 'Full credit')}\n </Button>\n </div>\n <div className=\"max-h-72 overflow-auto rounded-md border\">\n {lines.map((line) => {\n const s = state[line.id] ?? { selected: false, quantity: '', unitPriceNet: '' }\n return (\n <div key={line.id} className=\"grid grid-cols-[24px_1fr_90px_110px_60px] items-center gap-2 border-b px-2 py-1 last:border-b-0\">\n <Checkbox checked={s.selected} onCheckedChange={(next) => update(line.id, { selected: next === true })} />\n <span className=\"truncate\">{line.description}</span>\n <Input\n type=\"number\"\n min=\"0\"\n step=\"0.0001\"\n value={s.quantity}\n disabled={!s.selected}\n onChange={(e) => update(line.id, { quantity: e.currentTarget.value })}\n />\n <Input\n type=\"number\"\n min=\"0\"\n step=\"0.01\"\n value={s.unitPriceNet}\n disabled={!s.selected}\n onChange={(e) => update(line.id, { unitPriceNet: e.currentTarget.value })}\n />\n <span className=\"text-right text-xs text-muted-foreground\">{Number(line.tax_rate ?? 0)} %</span>\n </div>\n )\n })}\n </div>\n <div className=\"text-right text-muted-foreground\">\n {t('billing.memo.projected', 'Credit')}: {formatMoney(String(projected.net), currencyCode)} +{' '}\n {t('billing.invoices.lines.columns.tax_amount', 'VAT')} {formatMoney(String(projected.tax), currencyCode)} ={' '}\n <span className=\"font-medium text-foreground\">{formatMoney(String(projected.net + projected.tax), currencyCode)}</span>\n </div>\n </>\n ) : null}\n <label className=\"flex flex-col gap-1\">\n <span className=\"text-muted-foreground\">{t('billing.memo.reason', 'Reason (printed on the document)')} *</span>\n <Textarea rows={2} maxLength={1000} value={reason} onChange={(e) => setReason(e.currentTarget.value)} />\n </label>\n </div>\n <DialogFooter>\n <div className=\"flex w-full items-center justify-between gap-3\">\n <span className=\"text-xs text-muted-foreground\">\n <KbdShortcut keys={['Ctrl/\u2318', 'Enter']} /> \u00B7 <Kbd>Esc</Kbd>\n </span>\n <div className=\"flex items-center gap-2\">\n <Button type=\"button\" variant=\"outline\" onClick={onClose}>\n {t('billing.common.cancel', 'Cancel')}\n </Button>\n <Button type=\"button\" onClick={() => void submit()} disabled={saving}>\n {t('billing.memo.create', 'Create draft')}\n </Button>\n </div>\n </div>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import Link from "next/link";
|
|
4
|
+
import { Building2, User } from "lucide-react";
|
|
5
|
+
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
6
|
+
import { customerDetailHref } from "../lib/customerLookup.js";
|
|
7
|
+
function CustomerLabel({
|
|
8
|
+
customerId,
|
|
9
|
+
customerKind,
|
|
10
|
+
name,
|
|
11
|
+
linkToCustomer = false
|
|
12
|
+
}) {
|
|
13
|
+
const t = useT();
|
|
14
|
+
const kindLabel = customerKind === "person" ? t("billing.accounts.kind.person", "Person") : t("billing.accounts.kind.company", "Company");
|
|
15
|
+
const Icon = customerKind === "person" ? User : Building2;
|
|
16
|
+
const text = name ? /* @__PURE__ */ jsx("span", { children: name }) : /* @__PURE__ */ jsx("span", { className: "font-mono text-xs", children: customerId });
|
|
17
|
+
return /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5", title: kindLabel, children: [
|
|
18
|
+
/* @__PURE__ */ jsx(Icon, { size: 14, "aria-label": kindLabel, className: "shrink-0 text-muted-foreground" }),
|
|
19
|
+
linkToCustomer ? /* @__PURE__ */ jsx(
|
|
20
|
+
Link,
|
|
21
|
+
{
|
|
22
|
+
href: customerDetailHref(customerKind, customerId),
|
|
23
|
+
className: "underline-offset-2 hover:underline",
|
|
24
|
+
onClick: (event) => event.stopPropagation(),
|
|
25
|
+
children: text
|
|
26
|
+
}
|
|
27
|
+
) : text
|
|
28
|
+
] });
|
|
29
|
+
}
|
|
30
|
+
export {
|
|
31
|
+
CustomerLabel
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=CustomerLabel.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/billing/components/CustomerLabel.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { Building2, User } from 'lucide-react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { CustomerKind } from '../data/validators'\nimport { customerDetailHref } from '../lib/customerLookup'\n\n/**\n * Customer reference for billing views (Spec E): kind icon + resolved\n * display name, falling back to the raw id when the customers lookup is\n * unavailable. `linkToCustomer` turns the name into a link to the customer\n * record in the customers module.\n */\nexport function CustomerLabel({\n customerId,\n customerKind,\n name,\n linkToCustomer = false,\n}: {\n customerId: string\n customerKind: CustomerKind\n name?: string | null\n linkToCustomer?: boolean\n}) {\n const t = useT()\n const kindLabel =\n customerKind === 'person'\n ? t('billing.accounts.kind.person', 'Person')\n : t('billing.accounts.kind.company', 'Company')\n const Icon = customerKind === 'person' ? User : Building2\n const text = name ? (\n <span>{name}</span>\n ) : (\n <span className=\"font-mono text-xs\">{customerId}</span>\n )\n return (\n <span className=\"inline-flex items-center gap-1.5\" title={kindLabel}>\n <Icon size={14} aria-label={kindLabel} className=\"shrink-0 text-muted-foreground\" />\n {linkToCustomer ? (\n <Link\n href={customerDetailHref(customerKind, customerId)}\n className=\"underline-offset-2 hover:underline\"\n onClick={(event) => event.stopPropagation()}\n >\n {text}\n </Link>\n ) : (\n text\n )}\n </span>\n )\n}\n"],
|
|
5
|
+
"mappings": ";AAgCI,cAKA,YALA;AA9BJ,OAAO,UAAU;AACjB,SAAS,WAAW,YAAY;AAChC,SAAS,YAAY;AAErB,SAAS,0BAA0B;AAQ5B,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AACnB,GAKG;AACD,QAAM,IAAI,KAAK;AACf,QAAM,YACJ,iBAAiB,WACb,EAAE,gCAAgC,QAAQ,IAC1C,EAAE,iCAAiC,SAAS;AAClD,QAAM,OAAO,iBAAiB,WAAW,OAAO;AAChD,QAAM,OAAO,OACX,oBAAC,UAAM,gBAAK,IAEZ,oBAAC,UAAK,WAAU,qBAAqB,sBAAW;AAElD,SACE,qBAAC,UAAK,WAAU,oCAAmC,OAAO,WACxD;AAAA,wBAAC,QAAK,MAAM,IAAI,cAAY,WAAW,WAAU,kCAAiC;AAAA,IACjF,iBACC;AAAA,MAAC;AAAA;AAAA,QACC,MAAM,mBAAmB,cAAc,UAAU;AAAA,QACjD,WAAU;AAAA,QACV,SAAS,CAAC,UAAU,MAAM,gBAAgB;AAAA,QAEzC;AAAA;AAAA,IACH,IAEA;AAAA,KAEJ;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { useRouter } from "next/navigation";
|
|
5
|
+
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
6
|
+
import { BillingDataTable as DataTable } from "./BillingDataTable.js";
|
|
7
|
+
import { RowActions } from "@open-mercato/ui/backend/RowActions";
|
|
8
|
+
import { Tag } from "@open-mercato/ui/primitives/tag";
|
|
9
|
+
import { readApiResultOrThrow } from "@open-mercato/ui/backend/utils/apiCall";
|
|
10
|
+
import { invoiceDetailHref, invoicePdfHref } from "../lib/navigation.js";
|
|
11
|
+
import { displaySign } from "../lib/documentTypes.js";
|
|
12
|
+
function formatDate(value) {
|
|
13
|
+
if (!value) return "\u2014";
|
|
14
|
+
const parsed = new Date(value);
|
|
15
|
+
return Number.isNaN(parsed.getTime()) ? value : parsed.toLocaleDateString();
|
|
16
|
+
}
|
|
17
|
+
function formatMoney(value, currency) {
|
|
18
|
+
const n = Number.parseFloat(value);
|
|
19
|
+
if (!Number.isFinite(n)) return value;
|
|
20
|
+
try {
|
|
21
|
+
return new Intl.NumberFormat(void 0, { style: "currency", currency }).format(n);
|
|
22
|
+
} catch {
|
|
23
|
+
return `${value} ${currency}`;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function invoiceStatusVariant(status) {
|
|
27
|
+
switch (status) {
|
|
28
|
+
case "paid":
|
|
29
|
+
case "credited":
|
|
30
|
+
return "success";
|
|
31
|
+
case "posted":
|
|
32
|
+
case "partially_paid":
|
|
33
|
+
return "warning";
|
|
34
|
+
case "draft":
|
|
35
|
+
default:
|
|
36
|
+
return "default";
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function InvoicesTable({ title, billAccountId, tableId, pageSize = 25, actions }) {
|
|
40
|
+
const t = useT();
|
|
41
|
+
const router = useRouter();
|
|
42
|
+
const [rows, setRows] = React.useState([]);
|
|
43
|
+
const [page, setPage] = React.useState(1);
|
|
44
|
+
const [filters, setFilters] = React.useState({});
|
|
45
|
+
const [search, setSearch] = React.useState("");
|
|
46
|
+
const [total, setTotal] = React.useState(0);
|
|
47
|
+
const [totalPages, setTotalPages] = React.useState(1);
|
|
48
|
+
const [loading, setLoading] = React.useState(true);
|
|
49
|
+
const [error, setError] = React.useState(null);
|
|
50
|
+
const statusLabel = React.useCallback(
|
|
51
|
+
(status) => ({
|
|
52
|
+
draft: t("billing.invoices.status.draft", "Draft"),
|
|
53
|
+
posted: t("billing.invoices.status.posted", "Posted"),
|
|
54
|
+
partially_paid: t("billing.invoices.status.partially_paid", "Partially paid"),
|
|
55
|
+
paid: t("billing.invoices.status.paid", "Paid"),
|
|
56
|
+
credited: t("billing.invoices.status.credited", "Credited")
|
|
57
|
+
})[status] ?? status,
|
|
58
|
+
[t]
|
|
59
|
+
);
|
|
60
|
+
const filterDefs = React.useMemo(
|
|
61
|
+
() => [
|
|
62
|
+
{
|
|
63
|
+
id: "status",
|
|
64
|
+
label: t("billing.invoices.filters.status", "Status"),
|
|
65
|
+
type: "select",
|
|
66
|
+
options: ["draft", "posted", "partially_paid", "paid", "credited"].map((value) => ({
|
|
67
|
+
value,
|
|
68
|
+
label: statusLabel(value)
|
|
69
|
+
}))
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
id: "overdue",
|
|
73
|
+
label: t("billing.invoices.filters.overdue", "Overdue"),
|
|
74
|
+
type: "select",
|
|
75
|
+
options: [
|
|
76
|
+
{ value: "true", label: t("billing.invoices.filters.overdue.only", "Only overdue") },
|
|
77
|
+
{ value: "false", label: t("billing.invoices.filters.overdue.exclude", "Not overdue") }
|
|
78
|
+
]
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: "documentType",
|
|
82
|
+
label: t("billing.invoices.filters.document_type", "Document type"),
|
|
83
|
+
type: "select",
|
|
84
|
+
options: [
|
|
85
|
+
{ value: "invoice", label: t("billing.invoices.document_type.invoice", "Invoice") },
|
|
86
|
+
{ value: "credit_memo", label: t("billing.invoices.document_type.credit_memo", "Credit memo") },
|
|
87
|
+
{ value: "debit_memo", label: t("billing.invoices.document_type.debit_memo", "Debit memo") },
|
|
88
|
+
{ value: "receipt", label: t("billing.invoices.document_type.receipt", "Top-up receipt") }
|
|
89
|
+
]
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
id: "testRun",
|
|
93
|
+
label: t("billing.invoices.filters.test_run", "Test runs"),
|
|
94
|
+
type: "select",
|
|
95
|
+
options: [
|
|
96
|
+
{ value: "true", label: t("billing.invoices.filters.test_run.only", "Only test") },
|
|
97
|
+
{ value: "false", label: t("billing.invoices.filters.test_run.exclude", "Exclude test") }
|
|
98
|
+
]
|
|
99
|
+
}
|
|
100
|
+
],
|
|
101
|
+
[statusLabel, t]
|
|
102
|
+
);
|
|
103
|
+
const loadRows = React.useCallback(async () => {
|
|
104
|
+
setLoading(true);
|
|
105
|
+
setError(null);
|
|
106
|
+
try {
|
|
107
|
+
const params = new URLSearchParams({ page: String(page), pageSize: String(Math.min(pageSize, 100)) });
|
|
108
|
+
if (billAccountId) params.set("billAccountId", billAccountId);
|
|
109
|
+
if (search.trim()) params.set("search", search.trim());
|
|
110
|
+
for (const key of ["status", "documentType"]) {
|
|
111
|
+
const value = filters[key];
|
|
112
|
+
if (typeof value === "string" && value) params.set(key, value);
|
|
113
|
+
}
|
|
114
|
+
for (const key of ["testRun", "overdue"]) {
|
|
115
|
+
const value = filters[key];
|
|
116
|
+
if (value === "true" || value === "false") params.set(key, value);
|
|
117
|
+
}
|
|
118
|
+
const result = await readApiResultOrThrow(`/api/billing/invoices?${params.toString()}`);
|
|
119
|
+
setRows(result.items ?? []);
|
|
120
|
+
setTotal(result.total ?? 0);
|
|
121
|
+
setTotalPages(result.totalPages ?? 1);
|
|
122
|
+
} catch (err) {
|
|
123
|
+
setError(err instanceof Error ? err.message : t("billing.invoices.error.load", "Could not load invoices"));
|
|
124
|
+
} finally {
|
|
125
|
+
setLoading(false);
|
|
126
|
+
}
|
|
127
|
+
}, [billAccountId, filters, page, pageSize, search, t]);
|
|
128
|
+
React.useEffect(() => {
|
|
129
|
+
void loadRows();
|
|
130
|
+
}, [loadRows]);
|
|
131
|
+
const columns = React.useMemo(() => {
|
|
132
|
+
const cols = [
|
|
133
|
+
{
|
|
134
|
+
accessorKey: "number",
|
|
135
|
+
header: t("billing.invoices.columns.number", "Number"),
|
|
136
|
+
cell: ({ row }) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
137
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-primary", children: row.original.number }),
|
|
138
|
+
row.original.test_run ? /* @__PURE__ */ jsx(Tag, { variant: "warning", children: "TEST" }) : null
|
|
139
|
+
] })
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
accessorKey: "document_type",
|
|
143
|
+
header: t("billing.invoices.columns.type", "Type"),
|
|
144
|
+
cell: ({ row }) => ({
|
|
145
|
+
invoice: t("billing.invoices.document_type.invoice", "Invoice"),
|
|
146
|
+
credit_memo: t("billing.invoices.document_type.credit_memo", "Credit memo"),
|
|
147
|
+
debit_memo: t("billing.invoices.document_type.debit_memo", "Debit memo"),
|
|
148
|
+
receipt: t("billing.invoices.document_type.receipt", "Top-up receipt")
|
|
149
|
+
})[row.original.document_type] ?? row.original.document_type
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
accessorKey: "status",
|
|
153
|
+
header: t("billing.invoices.columns.status", "Status"),
|
|
154
|
+
cell: ({ row }) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
155
|
+
/* @__PURE__ */ jsx(Tag, { variant: invoiceStatusVariant(row.original.status), children: statusLabel(row.original.status) }),
|
|
156
|
+
row.original.days_overdue > 0 ? /* @__PURE__ */ jsx(Tag, { variant: "error", children: t("billing.invoices.overdue", "Overdue") }) : null
|
|
157
|
+
] })
|
|
158
|
+
}
|
|
159
|
+
];
|
|
160
|
+
if (!billAccountId) {
|
|
161
|
+
cols.push({
|
|
162
|
+
accessorKey: "bill_account_name",
|
|
163
|
+
header: t("billing.invoices.columns.account", "Account"),
|
|
164
|
+
cell: ({ row }) => row.original.bill_account_name ?? "\u2014",
|
|
165
|
+
meta: { truncate: true, maxWidth: "220px" }
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
cols.push(
|
|
169
|
+
{
|
|
170
|
+
id: "period",
|
|
171
|
+
header: t("billing.invoices.columns.period", "Period"),
|
|
172
|
+
cell: ({ row }) => {
|
|
173
|
+
const start = row.original.period_start?.slice(0, 10);
|
|
174
|
+
const end = row.original.period_end?.slice(0, 10);
|
|
175
|
+
if (!start || !end) return "\u2014";
|
|
176
|
+
return /* @__PURE__ */ jsxs("span", { className: "text-xs", children: [
|
|
177
|
+
start,
|
|
178
|
+
" \u2192 ",
|
|
179
|
+
end
|
|
180
|
+
] });
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
id: "total",
|
|
185
|
+
header: t("billing.invoices.columns.total", "Total"),
|
|
186
|
+
// Credit memos are stored positive (D-D5) and shown negative.
|
|
187
|
+
cell: ({ row }) => formatMoney(
|
|
188
|
+
String(displaySign(row.original.document_type) * Number.parseFloat(row.original.total_gross)),
|
|
189
|
+
row.original.currency_code
|
|
190
|
+
)
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
accessorKey: "outstanding",
|
|
194
|
+
header: t("billing.invoices.columns.outstanding", "Outstanding"),
|
|
195
|
+
cell: ({ row }) => formatMoney(row.original.outstanding, row.original.currency_code)
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
accessorKey: "issue_date",
|
|
199
|
+
header: t("billing.invoices.columns.issued", "Issued"),
|
|
200
|
+
cell: ({ row }) => formatDate(row.original.issue_date)
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
accessorKey: "due_date",
|
|
204
|
+
header: t("billing.invoices.columns.due", "Due"),
|
|
205
|
+
cell: ({ row }) => formatDate(row.original.due_date)
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
accessorKey: "days_overdue",
|
|
209
|
+
header: t("billing.invoices.columns.days_overdue", "Days overdue"),
|
|
210
|
+
cell: ({ row }) => row.original.days_overdue > 0 ? /* @__PURE__ */ jsx("span", { className: "font-medium text-status-error-text tabular-nums", children: row.original.days_overdue }) : /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "\u2014" })
|
|
211
|
+
}
|
|
212
|
+
);
|
|
213
|
+
return cols;
|
|
214
|
+
}, [billAccountId, statusLabel, t]);
|
|
215
|
+
return /* @__PURE__ */ jsx(
|
|
216
|
+
DataTable,
|
|
217
|
+
{
|
|
218
|
+
title,
|
|
219
|
+
actions,
|
|
220
|
+
refreshButton: { label: t("billing.common.refresh", "Refresh"), onRefresh: loadRows, isRefreshing: loading },
|
|
221
|
+
columnChooser: { auto: true },
|
|
222
|
+
perspective: { tableId },
|
|
223
|
+
columns,
|
|
224
|
+
data: rows,
|
|
225
|
+
error,
|
|
226
|
+
emptyState: t("billing.invoices.empty", "No invoices yet."),
|
|
227
|
+
onRowClick: (row) => router.push(invoiceDetailHref(row.id, { fromAccountId: billAccountId })),
|
|
228
|
+
rowActions: (row) => /* @__PURE__ */ jsx(
|
|
229
|
+
RowActions,
|
|
230
|
+
{
|
|
231
|
+
items: [
|
|
232
|
+
{
|
|
233
|
+
id: "open",
|
|
234
|
+
label: t("billing.invoices.actions.open", "Open"),
|
|
235
|
+
href: invoiceDetailHref(row.id, { fromAccountId: billAccountId })
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
id: "pdf",
|
|
239
|
+
label: row.status === "draft" ? t("billing.invoices.actions.pdf_preview", "Preview PDF") : t("billing.invoices.actions.pdf", "Download PDF"),
|
|
240
|
+
href: invoicePdfHref(row.id)
|
|
241
|
+
}
|
|
242
|
+
]
|
|
243
|
+
}
|
|
244
|
+
),
|
|
245
|
+
isLoading: loading,
|
|
246
|
+
pagination: { page, pageSize, total, totalPages, onPageChange: setPage },
|
|
247
|
+
filters: filterDefs,
|
|
248
|
+
filterValues: filters,
|
|
249
|
+
onFiltersApply: (next) => {
|
|
250
|
+
setPage(1);
|
|
251
|
+
setFilters(next);
|
|
252
|
+
},
|
|
253
|
+
onFiltersClear: () => {
|
|
254
|
+
setPage(1);
|
|
255
|
+
setFilters({});
|
|
256
|
+
},
|
|
257
|
+
searchValue: search,
|
|
258
|
+
onSearchChange: (next) => {
|
|
259
|
+
setPage(1);
|
|
260
|
+
setSearch(next);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
export {
|
|
266
|
+
InvoicesTable,
|
|
267
|
+
formatMoney,
|
|
268
|
+
invoiceStatusVariant
|
|
269
|
+
};
|
|
270
|
+
//# sourceMappingURL=InvoicesTable.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/billing/components/InvoicesTable.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport type { LegacyColumnDef as ColumnDef } from '@tanstack/react-table/legacy'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { BillingDataTable as DataTable } from './BillingDataTable'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Tag } from '@open-mercato/ui/primitives/tag'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { invoiceDetailHref, invoicePdfHref } from '../lib/navigation'\nimport { displaySign } from '../lib/documentTypes'\n\n/**\n * Billing documents table (Spec B) \u2014 shared by the global Invoices list and\n * the Invoices section of a billing account (and, later, Spec E's tab).\n *\n * - `billAccountId` pins the list to one account (no account column; rows\n * open the invoice with a return link to the account).\n * - Filters: status, overdue (computed server-side, B-D6), document type,\n * test runs. Columns include due date, outstanding and days overdue.\n * - Row action: download the PDF (frozen when posted, preview for drafts).\n *\n * Server-paginated via `GET /api/billing/invoices` (pageSize \u2264 100).\n */\n\nexport type BillingInvoiceRow = {\n id: string\n number: string\n document_type: 'invoice' | 'credit_memo' | 'debit_memo' | 'receipt'\n status: 'draft' | 'posted' | 'partially_paid' | 'paid' | 'credited'\n test_run: boolean\n bill_account_id: string\n bill_account_name: string | null\n bill_run_id: string | null\n bill_date: string | null\n period_start: string | null\n period_end: string | null\n currency_code: string\n issue_date: string | null\n due_date: string | null\n subtotal_net: string\n total_gross: string\n paid_total: string\n outstanding: string\n days_overdue: number\n created_at: string\n updated_at: string\n}\n\ntype ListResponse = {\n items: BillingInvoiceRow[]\n total: number\n totalPages: number\n}\n\nexport type InvoicesTableProps = {\n title: string\n /** Pin the table to one account (account Invoices section). */\n billAccountId?: string\n /** Stable perspective / extension id. */\n tableId: string\n pageSize?: number\n /** Extra header actions (e.g. the billing settings shortcut). */\n actions?: React.ReactNode\n}\n\nfunction formatDate(value: string | null | undefined): string {\n if (!value) return '\u2014'\n const parsed = new Date(value)\n return Number.isNaN(parsed.getTime()) ? value : parsed.toLocaleDateString()\n}\n\nexport function formatMoney(value: string, currency: string): string {\n const n = Number.parseFloat(value)\n if (!Number.isFinite(n)) return value\n try {\n return new Intl.NumberFormat(undefined, { style: 'currency', currency }).format(n)\n } catch {\n return `${value} ${currency}`\n }\n}\n\nexport function invoiceStatusVariant(status: BillingInvoiceRow['status']): 'default' | 'success' | 'warning' | 'error' {\n switch (status) {\n case 'paid':\n case 'credited':\n return 'success'\n case 'posted':\n case 'partially_paid':\n return 'warning'\n case 'draft':\n default:\n return 'default'\n }\n}\n\nexport function InvoicesTable({ title, billAccountId, tableId, pageSize = 25, actions }: InvoicesTableProps) {\n const t = useT()\n const router = useRouter()\n const [rows, setRows] = React.useState<BillingInvoiceRow[]>([])\n const [page, setPage] = React.useState(1)\n const [filters, setFilters] = React.useState<FilterValues>({})\n const [search, setSearch] = React.useState('')\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n\n const statusLabel = React.useCallback(\n (status: BillingInvoiceRow['status']) =>\n ({\n draft: t('billing.invoices.status.draft', 'Draft'),\n posted: t('billing.invoices.status.posted', 'Posted'),\n partially_paid: t('billing.invoices.status.partially_paid', 'Partially paid'),\n paid: t('billing.invoices.status.paid', 'Paid'),\n credited: t('billing.invoices.status.credited', 'Credited'),\n })[status] ?? status,\n [t],\n )\n\n const filterDefs = React.useMemo<FilterDef[]>(\n () => [\n {\n id: 'status',\n label: t('billing.invoices.filters.status', 'Status'),\n type: 'select',\n options: (['draft', 'posted', 'partially_paid', 'paid', 'credited'] as const).map((value) => ({\n value,\n label: statusLabel(value),\n })),\n },\n {\n id: 'overdue',\n label: t('billing.invoices.filters.overdue', 'Overdue'),\n type: 'select',\n options: [\n { value: 'true', label: t('billing.invoices.filters.overdue.only', 'Only overdue') },\n { value: 'false', label: t('billing.invoices.filters.overdue.exclude', 'Not overdue') },\n ],\n },\n {\n id: 'documentType',\n label: t('billing.invoices.filters.document_type', 'Document type'),\n type: 'select',\n options: [\n { value: 'invoice', label: t('billing.invoices.document_type.invoice', 'Invoice') },\n { value: 'credit_memo', label: t('billing.invoices.document_type.credit_memo', 'Credit memo') },\n { value: 'debit_memo', label: t('billing.invoices.document_type.debit_memo', 'Debit memo') },\n { value: 'receipt', label: t('billing.invoices.document_type.receipt', 'Top-up receipt') },\n ],\n },\n {\n id: 'testRun',\n label: t('billing.invoices.filters.test_run', 'Test runs'),\n type: 'select',\n options: [\n { value: 'true', label: t('billing.invoices.filters.test_run.only', 'Only test') },\n { value: 'false', label: t('billing.invoices.filters.test_run.exclude', 'Exclude test') },\n ],\n },\n ],\n [statusLabel, t],\n )\n\n const loadRows = React.useCallback(async () => {\n setLoading(true)\n setError(null)\n try {\n const params = new URLSearchParams({ page: String(page), pageSize: String(Math.min(pageSize, 100)) })\n if (billAccountId) params.set('billAccountId', billAccountId)\n if (search.trim()) params.set('search', search.trim())\n for (const key of ['status', 'documentType'] as const) {\n const value = filters[key]\n if (typeof value === 'string' && value) params.set(key, value)\n }\n for (const key of ['testRun', 'overdue'] as const) {\n const value = filters[key]\n if (value === 'true' || value === 'false') params.set(key, value)\n }\n const result = await readApiResultOrThrow<ListResponse>(`/api/billing/invoices?${params.toString()}`)\n setRows(result.items ?? [])\n setTotal(result.total ?? 0)\n setTotalPages(result.totalPages ?? 1)\n } catch (err) {\n setError(err instanceof Error ? err.message : t('billing.invoices.error.load', 'Could not load invoices'))\n } finally {\n setLoading(false)\n }\n }, [billAccountId, filters, page, pageSize, search, t])\n\n React.useEffect(() => {\n void loadRows()\n }, [loadRows])\n\n const columns = React.useMemo<ColumnDef<BillingInvoiceRow>[]>(() => {\n const cols: ColumnDef<BillingInvoiceRow>[] = [\n {\n accessorKey: 'number',\n header: t('billing.invoices.columns.number', 'Number'),\n cell: ({ row }) => (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium text-primary\">{row.original.number}</span>\n {row.original.test_run ? <Tag variant=\"warning\">TEST</Tag> : null}\n </div>\n ),\n },\n {\n accessorKey: 'document_type',\n header: t('billing.invoices.columns.type', 'Type'),\n cell: ({ row }) =>\n ({\n invoice: t('billing.invoices.document_type.invoice', 'Invoice'),\n credit_memo: t('billing.invoices.document_type.credit_memo', 'Credit memo'),\n debit_memo: t('billing.invoices.document_type.debit_memo', 'Debit memo'),\n receipt: t('billing.invoices.document_type.receipt', 'Top-up receipt'),\n })[row.original.document_type] ?? row.original.document_type,\n },\n {\n accessorKey: 'status',\n header: t('billing.invoices.columns.status', 'Status'),\n cell: ({ row }) => (\n <div className=\"flex items-center gap-1\">\n <Tag variant={invoiceStatusVariant(row.original.status)}>{statusLabel(row.original.status)}</Tag>\n {row.original.days_overdue > 0 ? (\n <Tag variant=\"error\">{t('billing.invoices.overdue', 'Overdue')}</Tag>\n ) : null}\n </div>\n ),\n },\n ]\n if (!billAccountId) {\n cols.push({\n accessorKey: 'bill_account_name',\n header: t('billing.invoices.columns.account', 'Account'),\n cell: ({ row }) => row.original.bill_account_name ?? '\u2014',\n meta: { truncate: true, maxWidth: '220px' },\n })\n }\n cols.push(\n {\n id: 'period',\n header: t('billing.invoices.columns.period', 'Period'),\n cell: ({ row }) => {\n const start = row.original.period_start?.slice(0, 10)\n const end = row.original.period_end?.slice(0, 10)\n if (!start || !end) return '\u2014'\n return (\n <span className=\"text-xs\">\n {start} \u2192 {end}\n </span>\n )\n },\n },\n {\n id: 'total',\n header: t('billing.invoices.columns.total', 'Total'),\n // Credit memos are stored positive (D-D5) and shown negative.\n cell: ({ row }) =>\n formatMoney(\n String(displaySign(row.original.document_type) * Number.parseFloat(row.original.total_gross)),\n row.original.currency_code,\n ),\n },\n {\n accessorKey: 'outstanding',\n header: t('billing.invoices.columns.outstanding', 'Outstanding'),\n cell: ({ row }) => formatMoney(row.original.outstanding, row.original.currency_code),\n },\n {\n accessorKey: 'issue_date',\n header: t('billing.invoices.columns.issued', 'Issued'),\n cell: ({ row }) => formatDate(row.original.issue_date),\n },\n {\n accessorKey: 'due_date',\n header: t('billing.invoices.columns.due', 'Due'),\n cell: ({ row }) => formatDate(row.original.due_date),\n },\n {\n accessorKey: 'days_overdue',\n header: t('billing.invoices.columns.days_overdue', 'Days overdue'),\n cell: ({ row }) =>\n row.original.days_overdue > 0 ? (\n <span className=\"font-medium text-status-error-text tabular-nums\">{row.original.days_overdue}</span>\n ) : (\n <span className=\"text-muted-foreground\">\u2014</span>\n ),\n },\n )\n return cols\n }, [billAccountId, statusLabel, t])\n\n return (\n <DataTable\n title={title}\n actions={actions}\n refreshButton={{ label: t('billing.common.refresh', 'Refresh'), onRefresh: loadRows, isRefreshing: loading }}\n columnChooser={{ auto: true }}\n perspective={{ tableId }}\n columns={columns}\n data={rows}\n error={error}\n emptyState={t('billing.invoices.empty', 'No invoices yet.')}\n onRowClick={(row) => router.push(invoiceDetailHref(row.id, { fromAccountId: billAccountId }))}\n rowActions={(row) => (\n <RowActions\n items={[\n {\n id: 'open',\n label: t('billing.invoices.actions.open', 'Open'),\n href: invoiceDetailHref(row.id, { fromAccountId: billAccountId }),\n },\n {\n id: 'pdf',\n label:\n row.status === 'draft'\n ? t('billing.invoices.actions.pdf_preview', 'Preview PDF')\n : t('billing.invoices.actions.pdf', 'Download PDF'),\n href: invoicePdfHref(row.id),\n },\n ]}\n />\n )}\n isLoading={loading}\n pagination={{ page, pageSize, total, totalPages, onPageChange: setPage }}\n filters={filterDefs}\n filterValues={filters}\n onFiltersApply={(next) => {\n setPage(1)\n setFilters(next)\n }}\n onFiltersClear={() => {\n setPage(1)\n setFilters({})\n }}\n searchValue={search}\n onSearchChange={(next) => {\n setPage(1)\n setSearch(next)\n }}\n />\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|