@powerhousedao/contributor-billing 0.0.1
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/LICENSE +661 -0
- package/README.md +22 -0
- package/dist/document-models/index.d.ts +2 -0
- package/dist/document-models/index.d.ts.map +1 -0
- package/dist/document-models/index.js +1 -0
- package/dist/document-models/invoice/gen/actions.d.ts +8 -0
- package/dist/document-models/invoice/gen/actions.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/actions.js +3 -0
- package/dist/document-models/invoice/gen/creators.d.ts +4 -0
- package/dist/document-models/invoice/gen/creators.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/creators.js +3 -0
- package/dist/document-models/invoice/gen/document-model.d.ts +3 -0
- package/dist/document-models/invoice/gen/document-model.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/document-model.js +227 -0
- package/dist/document-models/invoice/gen/general/actions.d.ts +10 -0
- package/dist/document-models/invoice/gen/general/actions.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/general/actions.js +1 -0
- package/dist/document-models/invoice/gen/general/creators.d.ts +9 -0
- package/dist/document-models/invoice/gen/general/creators.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/general/creators.js +8 -0
- package/dist/document-models/invoice/gen/general/error.d.ts +2 -0
- package/dist/document-models/invoice/gen/general/error.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/general/error.js +1 -0
- package/dist/document-models/invoice/gen/general/object.d.ts +12 -0
- package/dist/document-models/invoice/gen/general/object.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/general/object.js +22 -0
- package/dist/document-models/invoice/gen/general/operations.d.ts +12 -0
- package/dist/document-models/invoice/gen/general/operations.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/general/operations.js +1 -0
- package/dist/document-models/invoice/gen/index.d.ts +6 -0
- package/dist/document-models/invoice/gen/index.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/index.js +5 -0
- package/dist/document-models/invoice/gen/items/actions.d.ts +8 -0
- package/dist/document-models/invoice/gen/items/actions.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/items/actions.js +1 -0
- package/dist/document-models/invoice/gen/items/creators.d.ts +7 -0
- package/dist/document-models/invoice/gen/items/creators.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/items/creators.js +6 -0
- package/dist/document-models/invoice/gen/items/error.d.ts +2 -0
- package/dist/document-models/invoice/gen/items/error.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/items/error.js +1 -0
- package/dist/document-models/invoice/gen/items/object.d.ts +10 -0
- package/dist/document-models/invoice/gen/items/object.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/items/object.js +16 -0
- package/dist/document-models/invoice/gen/items/operations.d.ts +10 -0
- package/dist/document-models/invoice/gen/items/operations.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/items/operations.js +1 -0
- package/dist/document-models/invoice/gen/object.d.ts +20 -0
- package/dist/document-models/invoice/gen/object.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/object.js +29 -0
- package/dist/document-models/invoice/gen/parties/actions.d.ts +10 -0
- package/dist/document-models/invoice/gen/parties/actions.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/parties/actions.js +1 -0
- package/dist/document-models/invoice/gen/parties/creators.d.ts +9 -0
- package/dist/document-models/invoice/gen/parties/creators.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/parties/creators.js +8 -0
- package/dist/document-models/invoice/gen/parties/error.d.ts +2 -0
- package/dist/document-models/invoice/gen/parties/error.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/parties/error.js +1 -0
- package/dist/document-models/invoice/gen/parties/object.d.ts +12 -0
- package/dist/document-models/invoice/gen/parties/object.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/parties/object.js +22 -0
- package/dist/document-models/invoice/gen/parties/operations.d.ts +12 -0
- package/dist/document-models/invoice/gen/parties/operations.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/parties/operations.js +1 -0
- package/dist/document-models/invoice/gen/reducer.d.ts +3 -0
- package/dist/document-models/invoice/gen/reducer.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/reducer.js +79 -0
- package/dist/document-models/invoice/gen/schema/index.d.ts +3 -0
- package/dist/document-models/invoice/gen/schema/index.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/schema/index.js +2 -0
- package/dist/document-models/invoice/gen/schema/types.d.ts +390 -0
- package/dist/document-models/invoice/gen/schema/types.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/schema/types.js +1 -0
- package/dist/document-models/invoice/gen/schema/zod.d.ts +56 -0
- package/dist/document-models/invoice/gen/schema/zod.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/schema/zod.js +362 -0
- package/dist/document-models/invoice/gen/types.d.ts +10 -0
- package/dist/document-models/invoice/gen/types.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/types.js +1 -0
- package/dist/document-models/invoice/gen/utils.d.ts +7 -0
- package/dist/document-models/invoice/gen/utils.d.ts.map +1 -0
- package/dist/document-models/invoice/gen/utils.js +166 -0
- package/dist/document-models/invoice/index.d.ts +41 -0
- package/dist/document-models/invoice/index.d.ts.map +1 -0
- package/dist/document-models/invoice/index.js +21 -0
- package/dist/document-models/invoice/src/reducers/general.d.ts +8 -0
- package/dist/document-models/invoice/src/reducers/general.d.ts.map +1 -0
- package/dist/document-models/invoice/src/reducers/general.js +79 -0
- package/dist/document-models/invoice/src/reducers/items.d.ts +8 -0
- package/dist/document-models/invoice/src/reducers/items.d.ts.map +1 -0
- package/dist/document-models/invoice/src/reducers/items.js +108 -0
- package/dist/document-models/invoice/src/reducers/parties.d.ts +8 -0
- package/dist/document-models/invoice/src/reducers/parties.d.ts.map +1 -0
- package/dist/document-models/invoice/src/reducers/parties.js +266 -0
- package/dist/document-models/invoice/src/tests/document-model.test.d.ts +6 -0
- package/dist/document-models/invoice/src/tests/document-model.test.d.ts.map +1 -0
- package/dist/document-models/invoice/src/tests/document-model.test.js +17 -0
- package/dist/document-models/invoice/src/tests/general.test.d.ts +6 -0
- package/dist/document-models/invoice/src/tests/general.test.d.ts.map +1 -0
- package/dist/document-models/invoice/src/tests/general.test.js +75 -0
- package/dist/document-models/invoice/src/tests/items.test.d.ts +6 -0
- package/dist/document-models/invoice/src/tests/items.test.d.ts.map +1 -0
- package/dist/document-models/invoice/src/tests/items.test.js +45 -0
- package/dist/document-models/invoice/src/tests/parties.test.d.ts +6 -0
- package/dist/document-models/invoice/src/tests/parties.test.d.ts.map +1 -0
- package/dist/document-models/invoice/src/tests/parties.test.js +75 -0
- package/dist/document-models/invoice/src/utils.d.ts +2 -0
- package/dist/document-models/invoice/src/utils.d.ts.map +1 -0
- package/dist/document-models/invoice/src/utils.js +1 -0
- package/dist/editors/contributor-billing/components/CreateDocument.d.ts +8 -0
- package/dist/editors/contributor-billing/components/CreateDocument.d.ts.map +1 -0
- package/dist/editors/contributor-billing/components/CreateDocument.js +14 -0
- package/dist/editors/contributor-billing/components/DocumentDispatch.d.ts +12 -0
- package/dist/editors/contributor-billing/components/DocumentDispatch.d.ts.map +1 -0
- package/dist/editors/contributor-billing/components/DocumentDispatch.js +20 -0
- package/dist/editors/contributor-billing/components/DriveExplorer.d.ts +17 -0
- package/dist/editors/contributor-billing/components/DriveExplorer.d.ts.map +1 -0
- package/dist/editors/contributor-billing/components/DriveExplorer.js +112 -0
- package/dist/editors/contributor-billing/components/EditorContainer.d.ts +14 -0
- package/dist/editors/contributor-billing/components/EditorContainer.d.ts.map +1 -0
- package/dist/editors/contributor-billing/components/EditorContainer.js +28 -0
- package/dist/editors/contributor-billing/components/FileItemsGrid.d.ts +12 -0
- package/dist/editors/contributor-billing/components/FileItemsGrid.d.ts.map +1 -0
- package/dist/editors/contributor-billing/components/FileItemsGrid.js +7 -0
- package/dist/editors/contributor-billing/components/FolderItemsGrid.d.ts +17 -0
- package/dist/editors/contributor-billing/components/FolderItemsGrid.d.ts.map +1 -0
- package/dist/editors/contributor-billing/components/FolderItemsGrid.js +14 -0
- package/dist/editors/contributor-billing/components/FolderTree.d.ts +9 -0
- package/dist/editors/contributor-billing/components/FolderTree.d.ts.map +1 -0
- package/dist/editors/contributor-billing/components/FolderTree.js +31 -0
- package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.d.ts +16 -0
- package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.d.ts.map +1 -0
- package/dist/editors/contributor-billing/components/InvoiceTable/HeaderControls.js +16 -0
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.d.ts +21 -0
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.d.ts.map +1 -0
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTable.js +45 -0
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableRow.d.ts +12 -0
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableRow.d.ts.map +1 -0
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableRow.js +12 -0
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableSection.d.ts +7 -0
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableSection.d.ts.map +1 -0
- package/dist/editors/contributor-billing/components/InvoiceTable/InvoiceTableSection.js +7 -0
- package/dist/editors/contributor-billing/components/InvoiceTable/RowActionMenu.d.ts +8 -0
- package/dist/editors/contributor-billing/components/InvoiceTable/RowActionMenu.d.ts.map +1 -0
- package/dist/editors/contributor-billing/components/InvoiceTable/RowActionMenu.js +2 -0
- package/dist/editors/contributor-billing/editor.d.ts +6 -0
- package/dist/editors/contributor-billing/editor.d.ts.map +1 -0
- package/dist/editors/contributor-billing/editor.js +48 -0
- package/dist/editors/contributor-billing/hooks/useDispatchMap.d.ts +9 -0
- package/dist/editors/contributor-billing/hooks/useDispatchMap.d.ts.map +1 -0
- package/dist/editors/contributor-billing/hooks/useDispatchMap.js +21 -0
- package/dist/editors/contributor-billing/hooks/useDrop.d.ts +22 -0
- package/dist/editors/contributor-billing/hooks/useDrop.d.ts.map +1 -0
- package/dist/editors/contributor-billing/hooks/useDrop.js +57 -0
- package/dist/editors/contributor-billing/hooks/useSelectedFolderChildren.d.ts +8 -0
- package/dist/editors/contributor-billing/hooks/useSelectedFolderChildren.d.ts.map +1 -0
- package/dist/editors/contributor-billing/hooks/useSelectedFolderChildren.js +19 -0
- package/dist/editors/contributor-billing/hooks/useTransformedNodes.d.ts +4 -0
- package/dist/editors/contributor-billing/hooks/useTransformedNodes.d.ts.map +1 -0
- package/dist/editors/contributor-billing/hooks/useTransformedNodes.js +32 -0
- package/dist/editors/contributor-billing/index.d.ts +5 -0
- package/dist/editors/contributor-billing/index.d.ts.map +1 -0
- package/dist/editors/contributor-billing/index.js +12 -0
- package/dist/editors/index.d.ts +3 -0
- package/dist/editors/index.d.ts.map +1 -0
- package/dist/editors/index.js +2 -0
- package/dist/editors/invoice/InvoicePDF.d.ts +8 -0
- package/dist/editors/invoice/InvoicePDF.d.ts.map +1 -0
- package/dist/editors/invoice/InvoicePDF.js +359 -0
- package/dist/editors/invoice/assets/custom.d.ts +4 -0
- package/dist/editors/invoice/assets/powerhouseLogo.png +0 -0
- package/dist/editors/invoice/components/countryForm.d.ts +12 -0
- package/dist/editors/invoice/components/countryForm.d.ts.map +1 -0
- package/dist/editors/invoice/components/countryForm.js +28 -0
- package/dist/editors/invoice/components/currencyForm.d.ts +13 -0
- package/dist/editors/invoice/components/currencyForm.d.ts.map +1 -0
- package/dist/editors/invoice/components/currencyForm.js +26 -0
- package/dist/editors/invoice/components/datePicker.d.ts +11 -0
- package/dist/editors/invoice/components/datePicker.d.ts.map +1 -0
- package/dist/editors/invoice/components/datePicker.js +8 -0
- package/dist/editors/invoice/components/inputField.d.ts +14 -0
- package/dist/editors/invoice/components/inputField.d.ts.map +1 -0
- package/dist/editors/invoice/components/inputField.js +25 -0
- package/dist/editors/invoice/components/numberForm.d.ts +11 -0
- package/dist/editors/invoice/components/numberForm.d.ts.map +1 -0
- package/dist/editors/invoice/components/numberForm.js +7 -0
- package/dist/editors/invoice/components/selectField.d.ts +8 -0
- package/dist/editors/invoice/components/selectField.d.ts.map +1 -0
- package/dist/editors/invoice/components/selectField.js +323 -0
- package/dist/editors/invoice/editor.d.ts +5 -0
- package/dist/editors/invoice/editor.d.ts.map +1 -0
- package/dist/editors/invoice/editor.js +377 -0
- package/dist/editors/invoice/exportUBL.d.ts +85 -0
- package/dist/editors/invoice/exportUBL.d.ts.map +1 -0
- package/dist/editors/invoice/exportUBL.js +382 -0
- package/dist/editors/invoice/index.d.ts +5 -0
- package/dist/editors/invoice/index.d.ts.map +1 -0
- package/dist/editors/invoice/index.js +12 -0
- package/dist/editors/invoice/ingestPDF.d.ts +12 -0
- package/dist/editors/invoice/ingestPDF.d.ts.map +1 -0
- package/dist/editors/invoice/ingestPDF.js +193 -0
- package/dist/editors/invoice/ingestUBL.d.ts +21 -0
- package/dist/editors/invoice/ingestUBL.d.ts.map +1 -0
- package/dist/editors/invoice/ingestUBL.js +169 -0
- package/dist/editors/invoice/invoiceToGnosis.d.ts +7 -0
- package/dist/editors/invoice/invoiceToGnosis.d.ts.map +1 -0
- package/dist/editors/invoice/invoiceToGnosis.js +139 -0
- package/dist/editors/invoice/legalEntity/bankSection.d.ts +14 -0
- package/dist/editors/invoice/legalEntity/bankSection.d.ts.map +1 -0
- package/dist/editors/invoice/legalEntity/bankSection.js +156 -0
- package/dist/editors/invoice/legalEntity/common.d.ts +6 -0
- package/dist/editors/invoice/legalEntity/common.d.ts.map +1 -0
- package/dist/editors/invoice/legalEntity/common.js +6 -0
- package/dist/editors/invoice/legalEntity/legalEntity.d.ts +40 -0
- package/dist/editors/invoice/legalEntity/legalEntity.d.ts.map +1 -0
- package/dist/editors/invoice/legalEntity/legalEntity.js +63 -0
- package/dist/editors/invoice/legalEntity/walletSection.d.ts +13 -0
- package/dist/editors/invoice/legalEntity/walletSection.d.ts.map +1 -0
- package/dist/editors/invoice/legalEntity/walletSection.js +55 -0
- package/dist/editors/invoice/lineItems.d.ts +23 -0
- package/dist/editors/invoice/lineItems.d.ts.map +1 -0
- package/dist/editors/invoice/lineItems.js +157 -0
- package/dist/editors/invoice/requestFinance.d.ts +7 -0
- package/dist/editors/invoice/requestFinance.d.ts.map +1 -0
- package/dist/editors/invoice/requestFinance.js +155 -0
- package/dist/editors/invoice/uploadPdfChunked.d.ts +10 -0
- package/dist/editors/invoice/uploadPdfChunked.d.ts.map +1 -0
- package/dist/editors/invoice/uploadPdfChunked.js +79 -0
- package/dist/editors/invoice/utils/utils.d.ts +2 -0
- package/dist/editors/invoice/utils/utils.d.ts.map +1 -0
- package/dist/editors/invoice/utils/utils.js +54 -0
- package/dist/editors/invoice/validation/validationManager.d.ts +28 -0
- package/dist/editors/invoice/validation/validationManager.d.ts.map +1 -0
- package/dist/editors/invoice/validation/validationManager.js +65 -0
- package/dist/editors/invoice/validation/validationRules.d.ts +14 -0
- package/dist/editors/invoice/validation/validationRules.d.ts.map +1 -0
- package/dist/editors/invoice/validation/validationRules.js +334 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/powerhouse.manifest.json +31 -0
- package/dist/processors/index.d.ts +2 -0
- package/dist/processors/index.d.ts.map +1 -0
- package/dist/processors/index.js +1 -0
- package/dist/scripts/invoice/exampleBatchTxn.d.ts +2 -0
- package/dist/scripts/invoice/exampleBatchTxn.d.ts.map +1 -0
- package/dist/scripts/invoice/exampleBatchTxn.js +44 -0
- package/dist/scripts/invoice/gnosisTransactionBuilder.d.ts +28 -0
- package/dist/scripts/invoice/gnosisTransactionBuilder.d.ts.map +1 -0
- package/dist/scripts/invoice/gnosisTransactionBuilder.js +74 -0
- package/dist/scripts/invoice/pdfToDocumentAi.d.ts +5 -0
- package/dist/scripts/invoice/pdfToDocumentAi.d.ts.map +1 -0
- package/dist/scripts/invoice/pdfToDocumentAi.js +659 -0
- package/dist/scripts/invoice/requestFinance.d.ts +2 -0
- package/dist/scripts/invoice/requestFinance.d.ts.map +1 -0
- package/dist/scripts/invoice/requestFinance.js +38 -0
- package/dist/style.css +6463 -0
- package/dist/subgraphs/index.d.ts +2 -0
- package/dist/subgraphs/index.d.ts.map +1 -0
- package/dist/subgraphs/index.js +1 -0
- package/dist/subgraphs/invoice/customResolvers.d.ts +50 -0
- package/dist/subgraphs/invoice/customResolvers.d.ts.map +1 -0
- package/dist/subgraphs/invoice/customResolvers.js +327 -0
- package/dist/subgraphs/invoice/index.d.ts +10 -0
- package/dist/subgraphs/invoice/index.d.ts.map +1 -0
- package/dist/subgraphs/invoice/index.js +30 -0
- package/dist/subgraphs/invoice/resolvers.d.ts +3 -0
- package/dist/subgraphs/invoice/resolvers.d.ts.map +1 -0
- package/dist/subgraphs/invoice/resolvers.js +184 -0
- package/dist/subgraphs/invoice/schema.d.ts +3 -0
- package/dist/subgraphs/invoice/schema.d.ts.map +1 -0
- package/dist/subgraphs/invoice/schema.js +460 -0
- package/dist/tailwind.config.d.ts +13 -0
- package/dist/tailwind.config.d.ts.map +1 -0
- package/dist/tailwind.config.js +15 -0
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/dist/vitest.config.js +8 -0
- package/editors/invoice/assets/custom.d.ts +4 -0
- package/editors/invoice/assets/powerhouseLogo.png +0 -0
- package/package.json +117 -0
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
// Helper function to format numbers with appropriate decimal places
|
|
2
|
+
function formatNumber(value) {
|
|
3
|
+
// Check if the value has decimal places
|
|
4
|
+
const hasDecimals = value % 1 !== 0;
|
|
5
|
+
// If no decimals or only trailing zeros after 2 decimal places, show 2 decimal places
|
|
6
|
+
if (!hasDecimals || value.toFixed(5).endsWith("000")) {
|
|
7
|
+
return value.toFixed(2);
|
|
8
|
+
}
|
|
9
|
+
// Otherwise, show actual decimal places up to 5
|
|
10
|
+
const stringValue = value.toString();
|
|
11
|
+
const decimalPart = stringValue.split(".")[1] || "";
|
|
12
|
+
// Determine how many decimal places to show (up to 5)
|
|
13
|
+
const decimalPlaces = Math.min(Math.max(2, decimalPart.length), 5);
|
|
14
|
+
return value.toFixed(decimalPlaces);
|
|
15
|
+
}
|
|
16
|
+
export class UBLExporter {
|
|
17
|
+
invoice;
|
|
18
|
+
pdfBlob;
|
|
19
|
+
constructor(invoice, pdfBlob) {
|
|
20
|
+
this.invoice = invoice;
|
|
21
|
+
this.pdfBlob = pdfBlob;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Convert the invoice state to UBL XML format
|
|
25
|
+
* @returns UBL XML string
|
|
26
|
+
*/
|
|
27
|
+
async convertInvoiceToUBL() {
|
|
28
|
+
const issueDate = this.formatDate(this.invoice.dateIssued);
|
|
29
|
+
const dueDate = this.formatDate(this.invoice.dateDue);
|
|
30
|
+
const deliveryDate = this.formatDate(this.invoice.dateDelivered);
|
|
31
|
+
// Generate PDF attachment section first
|
|
32
|
+
const pdfAttachmentSection = await this.generatePDFAttachment();
|
|
33
|
+
let xml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
34
|
+
<Invoice xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
|
|
35
|
+
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
|
|
36
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
37
|
+
xsi:schemaLocation="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 UBL-Invoice-2.1.xsd"
|
|
38
|
+
xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
|
|
39
|
+
<cbc:UBLVersionID>2.1</cbc:UBLVersionID>
|
|
40
|
+
<cbc:ID>${this.escapeXml(this.invoice.invoiceNo || "")}</cbc:ID>
|
|
41
|
+
<cbc:IssueDate>${issueDate}</cbc:IssueDate>
|
|
42
|
+
${dueDate ? `<cbc:DueDate>${dueDate}</cbc:DueDate>` : ""}
|
|
43
|
+
<cbc:InvoiceTypeCode listID="UNCL1001" listAgencyID="6">380</cbc:InvoiceTypeCode>
|
|
44
|
+
<cbc:DocumentCurrencyCode listID="ISO4217" listAgencyID="6">${this.escapeXml(this.invoice.currency || "")}</cbc:DocumentCurrencyCode>
|
|
45
|
+
${this.invoice.payer?.name ? `<cbc:BuyerReference>${this.escapeXml(this.invoice.payer.name)}</cbc:BuyerReference>` : ""}
|
|
46
|
+
${pdfAttachmentSection}
|
|
47
|
+
${this.generateSupplierParty(this.invoice.issuer)}
|
|
48
|
+
${this.generateCustomerParty(this.invoice.payer)}
|
|
49
|
+
${this.generatePaymentMeans()}
|
|
50
|
+
${this.generatePaymentTerms()}
|
|
51
|
+
${this.generateTaxSummary()}
|
|
52
|
+
${this.generateLegalMonetaryTotal()}
|
|
53
|
+
${this.generateInvoiceLines()}
|
|
54
|
+
</Invoice>`;
|
|
55
|
+
return xml;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Export the invoice to a UBL file
|
|
59
|
+
* @param options Export options
|
|
60
|
+
* @returns Promise resolving to the generated file
|
|
61
|
+
*/
|
|
62
|
+
async exportToFile({ filename = "invoice.xml", } = {}) {
|
|
63
|
+
const ublXml = await this.convertInvoiceToUBL();
|
|
64
|
+
const blob = new Blob([ublXml], { type: "application/xml" });
|
|
65
|
+
return new File([blob], filename, { type: "application/xml" });
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Trigger download of the UBL file in the browser
|
|
69
|
+
*/
|
|
70
|
+
async downloadUBL(filename = "invoice.xml") {
|
|
71
|
+
const ublXml = await this.convertInvoiceToUBL();
|
|
72
|
+
const blob = new Blob([ublXml], { type: "application/xml" });
|
|
73
|
+
// Create download link and trigger click
|
|
74
|
+
const link = document.createElement("a");
|
|
75
|
+
link.href = URL.createObjectURL(blob);
|
|
76
|
+
link.download = filename;
|
|
77
|
+
document.body.appendChild(link);
|
|
78
|
+
link.click();
|
|
79
|
+
document.body.removeChild(link);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Format date as YYYY-MM-DD for UBL format
|
|
83
|
+
*/
|
|
84
|
+
formatDate(dateString) {
|
|
85
|
+
if (!dateString)
|
|
86
|
+
return "";
|
|
87
|
+
try {
|
|
88
|
+
const date = new Date(dateString);
|
|
89
|
+
if (isNaN(date.getTime()))
|
|
90
|
+
return "";
|
|
91
|
+
return date.toISOString().split("T")[0];
|
|
92
|
+
}
|
|
93
|
+
catch (e) {
|
|
94
|
+
return "";
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Escape special XML characters
|
|
99
|
+
*/
|
|
100
|
+
escapeXml(str) {
|
|
101
|
+
return str
|
|
102
|
+
.replace(/&/g, "&")
|
|
103
|
+
.replace(/</g, "<")
|
|
104
|
+
.replace(/>/g, ">")
|
|
105
|
+
.replace(/"/g, """)
|
|
106
|
+
.replace(/'/g, "'");
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Generate the AccountingSupplierParty section
|
|
110
|
+
*/
|
|
111
|
+
generateSupplierParty(issuer) {
|
|
112
|
+
if (!issuer)
|
|
113
|
+
return "";
|
|
114
|
+
const taxId = issuer.id?.taxId;
|
|
115
|
+
const corpRegId = issuer.id?.corpRegId;
|
|
116
|
+
const companyId = taxId || corpRegId;
|
|
117
|
+
return `<cac:AccountingSupplierParty>
|
|
118
|
+
<cac:Party>
|
|
119
|
+
${companyId ? `<cbc:EndpointID schemeID="0106">${this.escapeXml(companyId)}</cbc:EndpointID>` : ""}
|
|
120
|
+
${issuer.name ? `<cac:PartyName>
|
|
121
|
+
<cbc:Name>${this.escapeXml(issuer.name)}</cbc:Name>
|
|
122
|
+
</cac:PartyName>` : ""}
|
|
123
|
+
<cac:PostalAddress>
|
|
124
|
+
${issuer.address?.streetAddress ? `<cbc:StreetName>${this.escapeXml(issuer.address?.streetAddress)}</cbc:StreetName>` : ""}
|
|
125
|
+
${issuer.address?.city ? `<cbc:CityName>${this.escapeXml(issuer.address?.city)}</cbc:CityName>` : ""}
|
|
126
|
+
${issuer.address?.postalCode ? `<cbc:PostalZone>${this.escapeXml(issuer.address?.postalCode)}</cbc:PostalZone>` : ""}
|
|
127
|
+
${issuer.country ? `<cac:Country>
|
|
128
|
+
<cbc:IdentificationCode listID="ISO3166-1:Alpha2" listAgencyID="6">${this.escapeXml(issuer.country)}</cbc:IdentificationCode>
|
|
129
|
+
</cac:Country>` : ""}
|
|
130
|
+
</cac:PostalAddress>
|
|
131
|
+
${taxId && issuer.country ? `<cac:PartyTaxScheme>
|
|
132
|
+
<cbc:CompanyID schemeID="${issuer.country}:VAT">${this.escapeXml(taxId)}</cbc:CompanyID>
|
|
133
|
+
<cac:TaxScheme>
|
|
134
|
+
<cbc:ID schemeID="UN/ECE 5153">VAT</cbc:ID>
|
|
135
|
+
</cac:TaxScheme>
|
|
136
|
+
</cac:PartyTaxScheme>` : ""}
|
|
137
|
+
<cac:PartyLegalEntity>
|
|
138
|
+
<cbc:RegistrationName>${this.escapeXml(issuer.name || "")}</cbc:RegistrationName>
|
|
139
|
+
${companyId ? `<cbc:CompanyID schemeID="0106">${this.escapeXml(companyId)}</cbc:CompanyID>` : ""}
|
|
140
|
+
</cac:PartyLegalEntity>
|
|
141
|
+
${issuer.contactInfo?.email ? `<cac:Contact>
|
|
142
|
+
<cbc:ElectronicMail>${this.escapeXml(issuer.contactInfo.email)}</cbc:ElectronicMail>
|
|
143
|
+
</cac:Contact>` : ""}
|
|
144
|
+
</cac:Party>
|
|
145
|
+
</cac:AccountingSupplierParty>`;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Generate the AccountingCustomerParty section
|
|
149
|
+
*/
|
|
150
|
+
generateCustomerParty(payer) {
|
|
151
|
+
if (!payer)
|
|
152
|
+
return "";
|
|
153
|
+
return `<cac:AccountingCustomerParty>
|
|
154
|
+
<cac:Party>
|
|
155
|
+
${payer.name ? `<cac:PartyName>
|
|
156
|
+
<cbc:Name>${this.escapeXml(payer.name)}</cbc:Name>
|
|
157
|
+
</cac:PartyName>` : ""}
|
|
158
|
+
<cac:PostalAddress>
|
|
159
|
+
${payer.address?.streetAddress ? `<cbc:StreetName>${this.escapeXml(payer.address?.streetAddress)}</cbc:StreetName>` : ""}
|
|
160
|
+
${payer.address?.city ? `<cbc:CityName>${this.escapeXml(payer.address?.city)}</cbc:CityName>` : ""}
|
|
161
|
+
${payer.address?.postalCode ? `<cbc:PostalZone>${this.escapeXml(payer.address?.postalCode)}</cbc:PostalZone>` : ""}
|
|
162
|
+
${payer.country ? `<cac:Country>
|
|
163
|
+
<cbc:IdentificationCode listID="ISO3166-1:Alpha2" listAgencyID="6">${this.escapeXml(payer.country)}</cbc:IdentificationCode>
|
|
164
|
+
</cac:Country>` : ""}
|
|
165
|
+
</cac:PostalAddress>
|
|
166
|
+
<cac:PartyLegalEntity>
|
|
167
|
+
<cbc:RegistrationName>${this.escapeXml(payer.name || "")}</cbc:RegistrationName>
|
|
168
|
+
</cac:PartyLegalEntity>
|
|
169
|
+
${payer.contactInfo?.email ? `<cac:Contact>
|
|
170
|
+
</cac:Contact>` : ""}
|
|
171
|
+
</cac:Party>
|
|
172
|
+
</cac:AccountingCustomerParty>`;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Generate payment terms section
|
|
176
|
+
*/
|
|
177
|
+
generatePaymentTerms() {
|
|
178
|
+
const dueDate = this.formatDate(this.invoice.dateDue);
|
|
179
|
+
const amount = this.invoice.lineItems.reduce((sum, item) => sum + item.totalPriceTaxIncl, 0);
|
|
180
|
+
const currency = this.invoice.currency;
|
|
181
|
+
const paymentRef = `RF47${this.invoice.invoiceNo?.replace(/[^a-zA-Z0-9]/g, "")}`;
|
|
182
|
+
if (!dueDate || !currency)
|
|
183
|
+
return "";
|
|
184
|
+
const note = `We kindly request you to pay the above amount of ${currency}${amount} before ${dueDate} to our bank account with the description ${paymentRef}. For questions you can contact us by email.`;
|
|
185
|
+
return `<cac:PaymentTerms>
|
|
186
|
+
<cbc:Note>${this.escapeXml(note)}</cbc:Note>
|
|
187
|
+
</cac:PaymentTerms>`;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Generate the PaymentMeans section with bank details
|
|
191
|
+
*/
|
|
192
|
+
generatePaymentMeans() {
|
|
193
|
+
const bank = this.invoice.issuer?.paymentRouting?.bank;
|
|
194
|
+
if (!bank?.accountNum)
|
|
195
|
+
return "";
|
|
196
|
+
const dueDate = this.formatDate(this.invoice.dateDue);
|
|
197
|
+
// Generate a payment reference based on invoice number
|
|
198
|
+
const paymentRef = `RF47${this.invoice.invoiceNo?.replace(/[^a-zA-Z0-9]/g, "")}`;
|
|
199
|
+
return `<cac:PaymentMeans>
|
|
200
|
+
<cbc:PaymentMeansCode listID="UNCL4461" listAgencyID="6">30</cbc:PaymentMeansCode>
|
|
201
|
+
${dueDate ? `<cbc:PaymentDueDate>${dueDate}</cbc:PaymentDueDate>` : ""}
|
|
202
|
+
${paymentRef ? `<cbc:PaymentID>${this.escapeXml(paymentRef)}</cbc:PaymentID>` : ""}
|
|
203
|
+
<cac:PayeeFinancialAccount>
|
|
204
|
+
<cbc:ID schemeID="IBAN">${this.escapeXml(bank.accountNum)}</cbc:ID>
|
|
205
|
+
${bank.BIC || bank.SWIFT ? `<cac:FinancialInstitutionBranch>
|
|
206
|
+
<cac:FinancialInstitution>
|
|
207
|
+
<cbc:ID schemeID="BIC">${this.escapeXml(bank.BIC || bank.SWIFT || "")}</cbc:ID>
|
|
208
|
+
</cac:FinancialInstitution>
|
|
209
|
+
</cac:FinancialInstitutionBranch>` : ""}
|
|
210
|
+
</cac:PayeeFinancialAccount>
|
|
211
|
+
</cac:PaymentMeans>`;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Generate tax summary section
|
|
215
|
+
*/
|
|
216
|
+
generateTaxSummary() {
|
|
217
|
+
if (!this.invoice.currency)
|
|
218
|
+
return "";
|
|
219
|
+
const currency = this.invoice.currency;
|
|
220
|
+
const taxGroups = new Map();
|
|
221
|
+
// Group tax amounts by tax rate
|
|
222
|
+
for (const item of this.invoice.lineItems) {
|
|
223
|
+
const taxRate = item.taxPercent;
|
|
224
|
+
const taxAmount = item.totalPriceTaxIncl - item.totalPriceTaxExcl;
|
|
225
|
+
if (taxGroups.has(taxRate)) {
|
|
226
|
+
taxGroups.set(taxRate, (taxGroups.get(taxRate) || 0) + taxAmount);
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
taxGroups.set(taxRate, taxAmount);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (taxGroups.size === 0)
|
|
233
|
+
return "";
|
|
234
|
+
const taxTotalAmount = Array.from(taxGroups.values()).reduce((sum, amount) => sum + amount, 0);
|
|
235
|
+
// Add tax totals
|
|
236
|
+
let xml = `<cac:TaxTotal>
|
|
237
|
+
<cbc:TaxAmount currencyID="${this.escapeXml(currency)}">${formatNumber(taxTotalAmount)}</cbc:TaxAmount>`;
|
|
238
|
+
// Add tax subtotals for each tax rate
|
|
239
|
+
const taxSubtotals = {};
|
|
240
|
+
for (const item of this.invoice.lineItems) {
|
|
241
|
+
const taxRate = item.taxPercent.toString();
|
|
242
|
+
const taxableAmount = item.totalPriceTaxExcl;
|
|
243
|
+
const taxAmount = item.totalPriceTaxIncl - item.totalPriceTaxExcl;
|
|
244
|
+
if (taxSubtotals[taxRate]) {
|
|
245
|
+
taxSubtotals[taxRate].taxableAmount += taxableAmount;
|
|
246
|
+
taxSubtotals[taxRate].taxAmount += taxAmount;
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
taxSubtotals[taxRate] = { taxableAmount, taxAmount };
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
// Add tax subtotals for each tax rate
|
|
253
|
+
for (const [taxRate, { taxableAmount, taxAmount }] of Object.entries(taxSubtotals)) {
|
|
254
|
+
xml += `
|
|
255
|
+
<cac:TaxSubtotal>
|
|
256
|
+
<cbc:TaxableAmount currencyID="${this.escapeXml(currency)}">${formatNumber(taxableAmount)}</cbc:TaxableAmount>
|
|
257
|
+
<cbc:TaxAmount currencyID="${this.escapeXml(currency)}">${formatNumber(taxAmount)}</cbc:TaxAmount>
|
|
258
|
+
<cac:TaxCategory>
|
|
259
|
+
<cbc:ID schemeID="UNCL5305">S</cbc:ID>
|
|
260
|
+
<cbc:Percent>${taxRate}</cbc:Percent>
|
|
261
|
+
<cac:TaxScheme>
|
|
262
|
+
<cbc:ID schemeID="UN/ECE 5153">VAT</cbc:ID>
|
|
263
|
+
</cac:TaxScheme>
|
|
264
|
+
</cac:TaxCategory>
|
|
265
|
+
</cac:TaxSubtotal>`;
|
|
266
|
+
}
|
|
267
|
+
xml += `
|
|
268
|
+
</cac:TaxTotal>`;
|
|
269
|
+
return xml;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Generate the LegalMonetaryTotal section
|
|
273
|
+
*/
|
|
274
|
+
generateLegalMonetaryTotal() {
|
|
275
|
+
if (!this.invoice.currency)
|
|
276
|
+
return "";
|
|
277
|
+
const currency = this.invoice.currency;
|
|
278
|
+
// Calculate totals
|
|
279
|
+
const lineExtensionAmount = this.invoice.lineItems.reduce((sum, item) => sum + item.totalPriceTaxExcl, 0);
|
|
280
|
+
const taxExclusiveAmount = lineExtensionAmount;
|
|
281
|
+
const taxInclusiveAmount = this.invoice.lineItems.reduce((sum, item) => sum + item.totalPriceTaxIncl, 0);
|
|
282
|
+
const allowanceTotalAmount = 0; // Add if we implement allowances
|
|
283
|
+
const payableAmount = taxInclusiveAmount;
|
|
284
|
+
return `<cac:LegalMonetaryTotal>
|
|
285
|
+
<cbc:LineExtensionAmount currencyID="${this.escapeXml(currency)}">${formatNumber(lineExtensionAmount)}</cbc:LineExtensionAmount>
|
|
286
|
+
<cbc:TaxExclusiveAmount currencyID="${this.escapeXml(currency)}">${formatNumber(taxExclusiveAmount)}</cbc:TaxExclusiveAmount>
|
|
287
|
+
<cbc:TaxInclusiveAmount currencyID="${this.escapeXml(currency)}">${formatNumber(taxInclusiveAmount)}</cbc:TaxInclusiveAmount>
|
|
288
|
+
<cbc:AllowanceTotalAmount currencyID="${this.escapeXml(currency)}">${formatNumber(allowanceTotalAmount)}</cbc:AllowanceTotalAmount>
|
|
289
|
+
<cbc:PayableAmount currencyID="${this.escapeXml(currency)}">${formatNumber(payableAmount)}</cbc:PayableAmount>
|
|
290
|
+
</cac:LegalMonetaryTotal>`;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Generate InvoiceLine sections for each line item
|
|
294
|
+
*/
|
|
295
|
+
generateInvoiceLines() {
|
|
296
|
+
if (!this.invoice.lineItems.length || !this.invoice.currency)
|
|
297
|
+
return "";
|
|
298
|
+
const currency = this.invoice.currency;
|
|
299
|
+
return this.invoice.lineItems
|
|
300
|
+
.map((item, index) => {
|
|
301
|
+
const lineId = item.id || (index + 1).toString();
|
|
302
|
+
return `<cac:InvoiceLine>
|
|
303
|
+
<cbc:ID>${this.escapeXml(lineId)}</cbc:ID>
|
|
304
|
+
<cbc:InvoicedQuantity unitCode="ZZ" unitCodeListID="UNECERec20">${formatNumber(item.quantity)}</cbc:InvoicedQuantity>
|
|
305
|
+
<cbc:LineExtensionAmount currencyID="${currency}">${formatNumber(item.totalPriceTaxExcl)}</cbc:LineExtensionAmount>
|
|
306
|
+
<cac:Item>
|
|
307
|
+
<cbc:Description>${this.escapeXml(item.description || "")}</cbc:Description>
|
|
308
|
+
<cbc:Name>${this.escapeXml(item.description || "")}</cbc:Name>
|
|
309
|
+
<cac:ClassifiedTaxCategory>
|
|
310
|
+
<cbc:ID schemeID="UNCL5305">S</cbc:ID>
|
|
311
|
+
<cbc:Percent>${item.taxPercent || 0}</cbc:Percent>
|
|
312
|
+
<cac:TaxScheme>
|
|
313
|
+
<cbc:ID schemeID="UN/ECE 5153">VAT</cbc:ID>
|
|
314
|
+
</cac:TaxScheme>
|
|
315
|
+
</cac:ClassifiedTaxCategory>
|
|
316
|
+
</cac:Item>
|
|
317
|
+
<cac:Price>
|
|
318
|
+
<cbc:PriceAmount currencyID="${currency}">${formatNumber(item.unitPriceTaxExcl)}</cbc:PriceAmount>
|
|
319
|
+
</cac:Price>
|
|
320
|
+
</cac:InvoiceLine>`;
|
|
321
|
+
})
|
|
322
|
+
.join("\n");
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Generate PDF attachment section if a PDF blob is available
|
|
326
|
+
*/
|
|
327
|
+
async generatePDFAttachment() {
|
|
328
|
+
if (!this.pdfBlob)
|
|
329
|
+
return "";
|
|
330
|
+
try {
|
|
331
|
+
// Convert PDF blob to base64
|
|
332
|
+
const base64Data = await this.blobToBase64(this.pdfBlob);
|
|
333
|
+
const filename = `${this.invoice.invoiceNo || "invoice"}.pdf`;
|
|
334
|
+
return `<cac:AdditionalDocumentReference>
|
|
335
|
+
<cbc:ID>${filename}</cbc:ID>
|
|
336
|
+
<cbc:DocumentType>PrimaryImage</cbc:DocumentType>
|
|
337
|
+
<cac:Attachment>
|
|
338
|
+
<cbc:EmbeddedDocumentBinaryObject mimeCode="application/pdf" filename="${filename}">
|
|
339
|
+
${base64Data}
|
|
340
|
+
</cbc:EmbeddedDocumentBinaryObject>
|
|
341
|
+
</cac:Attachment>
|
|
342
|
+
</cac:AdditionalDocumentReference>`;
|
|
343
|
+
}
|
|
344
|
+
catch (error) {
|
|
345
|
+
console.error("Error embedding PDF in UBL:", error);
|
|
346
|
+
return "";
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Convert a Blob to base64 string
|
|
351
|
+
*/
|
|
352
|
+
blobToBase64(blob) {
|
|
353
|
+
return new Promise((resolve, reject) => {
|
|
354
|
+
const reader = new FileReader();
|
|
355
|
+
reader.onloadend = () => {
|
|
356
|
+
const base64data = reader.result;
|
|
357
|
+
// Remove data URL prefix if present
|
|
358
|
+
const base64Content = base64data.split(",")[1] || base64data;
|
|
359
|
+
resolve(base64Content);
|
|
360
|
+
};
|
|
361
|
+
reader.onerror = reject;
|
|
362
|
+
reader.readAsDataURL(blob);
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Export an invoice to UBL format
|
|
368
|
+
* @param options Export options
|
|
369
|
+
* @returns Promise resolving to the generated file
|
|
370
|
+
*/
|
|
371
|
+
export async function exportToUBL({ invoice, filename = "invoice.xml", pdfBlob, }) {
|
|
372
|
+
const exporter = new UBLExporter(invoice, pdfBlob);
|
|
373
|
+
return exporter.exportToFile({ filename });
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Export and download an invoice as UBL
|
|
377
|
+
* @param options Export options
|
|
378
|
+
*/
|
|
379
|
+
export async function downloadUBL({ invoice, filename = "invoice.xml", pdfBlob, }) {
|
|
380
|
+
const exporter = new UBLExporter(invoice, pdfBlob);
|
|
381
|
+
return exporter.downloadUBL(filename);
|
|
382
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../editors/invoice/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAC;AAE9E,eAAO,MAAM,MAAM,EAAE,YAAY,CAAC,eAAe,CAShD,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import Editor from "./editor.js";
|
|
2
|
+
export const module = {
|
|
3
|
+
Component: Editor,
|
|
4
|
+
documentTypes: ["powerhouse/invoice"],
|
|
5
|
+
config: {
|
|
6
|
+
id: "powerhouse-invoice-editor",
|
|
7
|
+
disableExternalControls: true,
|
|
8
|
+
documentToolbarEnabled: true,
|
|
9
|
+
showSwitchboardLink: true,
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
export default module;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { InvoiceAction } from "../../document-models/invoice/index.js";
|
|
2
|
+
export declare function loadPDFFile({ file, dispatch, }: {
|
|
3
|
+
file: File;
|
|
4
|
+
dispatch: (action: InvoiceAction) => void;
|
|
5
|
+
}): Promise<File>;
|
|
6
|
+
interface PDFUploaderProps {
|
|
7
|
+
dispatch: (action: InvoiceAction) => void;
|
|
8
|
+
changeDropdownOpen: (open: boolean) => void;
|
|
9
|
+
}
|
|
10
|
+
export default function PDFUploader({ dispatch, changeDropdownOpen, }: PDFUploaderProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=ingestPDF.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingestPDF.d.ts","sourceRoot":"","sources":["../../../editors/invoice/ingestPDF.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAW,MAAM,wCAAwC,CAAC;AAYhF,wBAAsB,WAAW,CAAC,EAChC,IAAI,EACJ,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;CAC3C,iBAUA;AAED,UAAU,gBAAgB;IACxB,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IAC1C,kBAAkB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CAC7C;AAED,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAClC,QAAQ,EACR,kBAAkB,GACnB,EAAE,gBAAgB,2CAoRlB"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { actions } from "../../document-models/invoice/index.js";
|
|
4
|
+
import { toast } from "@powerhousedao/design-system";
|
|
5
|
+
import { uploadPdfChunked } from "./uploadPdfChunked.js";
|
|
6
|
+
import { getCountryCodeFromName } from "./utils/utils.js";
|
|
7
|
+
let GRAPHQL_URL = 'http://localhost:4001/graphql/invoice';
|
|
8
|
+
if (window.document.baseURI !== 'http://localhost:3000/') {
|
|
9
|
+
GRAPHQL_URL = 'https://switchboard-dev.powerhouse.xyz/graphql/invoice';
|
|
10
|
+
}
|
|
11
|
+
export async function loadPDFFile({ file, dispatch, }) {
|
|
12
|
+
if (!file)
|
|
13
|
+
throw new Error("No file provided");
|
|
14
|
+
if (file.type !== "application/pdf") {
|
|
15
|
+
throw new Error("Please upload a PDF file");
|
|
16
|
+
}
|
|
17
|
+
console.log("Loading PDF file:", file.name);
|
|
18
|
+
return file;
|
|
19
|
+
}
|
|
20
|
+
export default function PDFUploader({ dispatch, changeDropdownOpen, }) {
|
|
21
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
22
|
+
const [error, setError] = useState(null);
|
|
23
|
+
const [uploadProgress, setUploadProgress] = useState(0);
|
|
24
|
+
const handleFileChange = async (event) => {
|
|
25
|
+
const file = event.target.files?.[0];
|
|
26
|
+
if (!file) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
setError(null);
|
|
30
|
+
setIsLoading(true);
|
|
31
|
+
setUploadProgress(0);
|
|
32
|
+
try {
|
|
33
|
+
const reader = new FileReader();
|
|
34
|
+
reader.onload = async () => {
|
|
35
|
+
const base64Data = reader.result?.toString().split(",")[1];
|
|
36
|
+
if (!base64Data) {
|
|
37
|
+
throw new Error("Failed to read file");
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const result = await uploadPdfChunked(base64Data, GRAPHQL_URL, 50 * 1024, (progress) => setUploadProgress(progress));
|
|
41
|
+
if (result.success) {
|
|
42
|
+
const invoiceData = result.data.invoiceData;
|
|
43
|
+
// Dispatch the parsed invoice data
|
|
44
|
+
dispatch(actions.editInvoice({
|
|
45
|
+
invoiceNo: invoiceData.invoiceNo || "",
|
|
46
|
+
dateIssued: invoiceData.dateIssued ||
|
|
47
|
+
new Date().toISOString().split("T")[0],
|
|
48
|
+
dateDue: invoiceData.dateDue || new Date().toISOString().split("T")[0],
|
|
49
|
+
currency: invoiceData.currency || "USD",
|
|
50
|
+
}));
|
|
51
|
+
// If we have line items, dispatch them
|
|
52
|
+
if (invoiceData.lineItems && invoiceData.lineItems.length > 0) {
|
|
53
|
+
invoiceData.lineItems.forEach((item) => {
|
|
54
|
+
dispatch(actions.addLineItem({
|
|
55
|
+
id: item.id,
|
|
56
|
+
description: item.description,
|
|
57
|
+
taxPercent: item.taxPercent,
|
|
58
|
+
quantity: item.quantity,
|
|
59
|
+
currency: item.currency,
|
|
60
|
+
unitPriceTaxExcl: item.unitPriceTaxExcl,
|
|
61
|
+
unitPriceTaxIncl: item.unitPriceTaxIncl,
|
|
62
|
+
totalPriceTaxExcl: item.totalPriceTaxExcl,
|
|
63
|
+
totalPriceTaxIncl: item.totalPriceTaxIncl,
|
|
64
|
+
}));
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
// If we have issuer data, dispatch it
|
|
68
|
+
if (invoiceData.issuer) {
|
|
69
|
+
dispatch(actions.editIssuer({
|
|
70
|
+
name: invoiceData.issuer.name || "",
|
|
71
|
+
country: getCountryCodeFromName(invoiceData.issuer.country) || "",
|
|
72
|
+
streetAddress: invoiceData.issuer.address?.streetAddress || "",
|
|
73
|
+
extendedAddress: invoiceData.issuer.address?.extendedAddress || "",
|
|
74
|
+
city: invoiceData.issuer.address?.city || "",
|
|
75
|
+
postalCode: invoiceData.issuer.address?.postalCode || "",
|
|
76
|
+
stateProvince: invoiceData.issuer.address?.stateProvince || "",
|
|
77
|
+
tel: invoiceData.issuer.contactInfo?.tel || "",
|
|
78
|
+
email: invoiceData.issuer.contactInfo?.email || "",
|
|
79
|
+
id: invoiceData.issuer.id?.taxId || "",
|
|
80
|
+
}));
|
|
81
|
+
// Add bank information dispatch
|
|
82
|
+
if (invoiceData.issuer.paymentRouting?.bank) {
|
|
83
|
+
const bank = invoiceData.issuer.paymentRouting.bank;
|
|
84
|
+
console.log("Dispatching bank details:", bank); // Debug log
|
|
85
|
+
dispatch(actions.editIssuerBank({
|
|
86
|
+
name: bank.name || "",
|
|
87
|
+
accountNum: bank.accountNum || "",
|
|
88
|
+
ABA: bank.ABA || "",
|
|
89
|
+
BIC: bank.BIC || "",
|
|
90
|
+
SWIFT: bank.SWIFT || "",
|
|
91
|
+
accountType: bank.accountType || "CHECKING",
|
|
92
|
+
beneficiary: bank.beneficiary || "",
|
|
93
|
+
memo: bank.memo || "",
|
|
94
|
+
streetAddress: bank.address?.streetAddress || "",
|
|
95
|
+
city: bank.address?.city || "",
|
|
96
|
+
stateProvince: bank.address?.stateProvince || "",
|
|
97
|
+
postalCode: bank.address?.postalCode || "",
|
|
98
|
+
country: getCountryCodeFromName(bank.address?.country) || "",
|
|
99
|
+
extendedAddress: bank.address?.extendedAddress || "",
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
// Add crypto wallet information dispatch
|
|
103
|
+
if (invoiceData.issuer.paymentRouting?.wallet) {
|
|
104
|
+
dispatch(actions.editIssuerWallet({
|
|
105
|
+
address: invoiceData.issuer.paymentRouting.wallet.address || "",
|
|
106
|
+
chainId: invoiceData.issuer.paymentRouting.wallet.chainId || "",
|
|
107
|
+
chainName: invoiceData.issuer.paymentRouting.wallet.chainName || "",
|
|
108
|
+
rpc: invoiceData.issuer.paymentRouting.wallet.rpc || "",
|
|
109
|
+
}));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// If we have payer data, dispatch it
|
|
113
|
+
if (invoiceData.payer) {
|
|
114
|
+
dispatch(actions.editPayer({
|
|
115
|
+
name: invoiceData.payer.name || "",
|
|
116
|
+
country: getCountryCodeFromName(invoiceData.payer.country) || "",
|
|
117
|
+
streetAddress: invoiceData.payer.address?.streetAddress || "",
|
|
118
|
+
extendedAddress: invoiceData.payer.address?.extendedAddress || "",
|
|
119
|
+
city: invoiceData.payer.address?.city || "",
|
|
120
|
+
postalCode: invoiceData.payer.address?.postalCode || "",
|
|
121
|
+
stateProvince: invoiceData.payer.address?.stateProvince || "",
|
|
122
|
+
tel: invoiceData.payer.contactInfo?.tel || "",
|
|
123
|
+
email: invoiceData.payer.contactInfo?.email || "",
|
|
124
|
+
id: invoiceData.payer.id?.taxId || "",
|
|
125
|
+
}));
|
|
126
|
+
// Add payer bank information if present
|
|
127
|
+
if (invoiceData.payer.paymentRouting?.bank) {
|
|
128
|
+
dispatch(actions.editPayerBank({
|
|
129
|
+
name: invoiceData.payer.paymentRouting.bank.name || "",
|
|
130
|
+
accountNum: invoiceData.payer.paymentRouting.bank.accountNum || "",
|
|
131
|
+
ABA: invoiceData.payer.paymentRouting.bank.ABA || "",
|
|
132
|
+
BIC: invoiceData.payer.paymentRouting.bank.BIC || "",
|
|
133
|
+
SWIFT: invoiceData.payer.paymentRouting.bank.SWIFT || "",
|
|
134
|
+
accountType: invoiceData.payer.paymentRouting.bank.accountType ||
|
|
135
|
+
"CHECKING",
|
|
136
|
+
beneficiary: invoiceData.payer.paymentRouting.bank.beneficiary || "",
|
|
137
|
+
memo: invoiceData.payer.paymentRouting.bank.memo || "",
|
|
138
|
+
}));
|
|
139
|
+
}
|
|
140
|
+
// Add payer crypto wallet information if present
|
|
141
|
+
if (invoiceData.payer.paymentRouting?.wallet) {
|
|
142
|
+
dispatch(actions.editPayerWallet({
|
|
143
|
+
address: invoiceData.payer.paymentRouting.wallet.address || "",
|
|
144
|
+
chainId: invoiceData.payer.paymentRouting.wallet.chainId || "",
|
|
145
|
+
chainName: invoiceData.payer.paymentRouting.wallet.chainName || "",
|
|
146
|
+
rpc: invoiceData.payer.paymentRouting.wallet.rpc || "",
|
|
147
|
+
}));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
setIsLoading(false);
|
|
151
|
+
toast("Invoice uploaded successfully", {
|
|
152
|
+
type: "success",
|
|
153
|
+
});
|
|
154
|
+
// Add debug logging here
|
|
155
|
+
console.log("Final document state:", JSON.stringify({
|
|
156
|
+
issuer: invoiceData.issuer,
|
|
157
|
+
payer: invoiceData.payer,
|
|
158
|
+
lineItems: invoiceData.lineItems,
|
|
159
|
+
paymentRouting: invoiceData.issuer?.paymentRouting,
|
|
160
|
+
bankDetails: invoiceData.issuer?.paymentRouting?.bank,
|
|
161
|
+
}, null, 2));
|
|
162
|
+
changeDropdownOpen(false);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
throw new Error(result.error || "Failed to process PDF");
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
console.error("Error processing PDF:", error);
|
|
170
|
+
setError(error instanceof Error
|
|
171
|
+
? error.message
|
|
172
|
+
: "An error occurred while processing the PDF");
|
|
173
|
+
}
|
|
174
|
+
finally {
|
|
175
|
+
setIsLoading(false);
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
reader.onerror = () => {
|
|
179
|
+
setError("Failed to read file");
|
|
180
|
+
setIsLoading(false);
|
|
181
|
+
};
|
|
182
|
+
reader.readAsDataURL(file);
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
console.error("Error handling file:", error);
|
|
186
|
+
setError(error instanceof Error
|
|
187
|
+
? error.message
|
|
188
|
+
: "An error occurred while handling the file");
|
|
189
|
+
setIsLoading(false);
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
return (_jsx("div", { className: "flex flex-col gap-4", children: _jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("label", { htmlFor: "pdf-upload", className: "block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 cursor-pointer", children: [isLoading ? "Uploading..." : "Upload PDF", _jsx("input", { id: "pdf-upload", type: "file", accept: "application/pdf", onChange: handleFileChange, className: "hidden", disabled: isLoading })] }), isLoading && uploadProgress > 0 && (_jsxs("div", { className: "mt-2", children: [_jsxs("p", { className: "text-sm text-gray-600", children: ["Uploading: ", uploadProgress.toFixed(1), "%"] }), _jsx("div", { className: "w-full bg-gray-200 rounded-full h-2.5 mt-1", children: _jsx("div", { className: "bg-blue-600 h-2.5 rounded-full", style: { width: `${uploadProgress}%` } }) })] })), error && _jsx("p", { className: "text-red-500 text-sm", children: error })] }) }));
|
|
193
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { InvoiceAction } from "../../document-models/invoice/index.js";
|
|
2
|
+
interface LoadUBLFileProps {
|
|
3
|
+
file: File;
|
|
4
|
+
dispatch: (action: InvoiceAction) => void;
|
|
5
|
+
}
|
|
6
|
+
interface UBLConverterConfig {
|
|
7
|
+
dispatch: (action: InvoiceAction) => void;
|
|
8
|
+
}
|
|
9
|
+
export declare class UBLConverter {
|
|
10
|
+
private dispatch;
|
|
11
|
+
constructor(config: UBLConverterConfig);
|
|
12
|
+
convertUBLToInvoice(ublXml: string): void;
|
|
13
|
+
getElementText(node: Element, selector: string, schemeID?: string): string | null;
|
|
14
|
+
private getElementTextList;
|
|
15
|
+
private processGeneralData;
|
|
16
|
+
private processParties;
|
|
17
|
+
private processLineItems;
|
|
18
|
+
}
|
|
19
|
+
export declare function loadUBLFile({ file, dispatch, }: LoadUBLFileProps): Promise<void>;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=ingestUBL.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingestUBL.d.ts","sourceRoot":"","sources":["../../../editors/invoice/ingestUBL.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,aAAa,EAGd,MAAM,wCAAwC,CAAC;AAEhD,UAAU,gBAAgB;IACxB,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;CAC3C;AAED,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;CAC3C;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAkC;gBAEtC,MAAM,EAAE,kBAAkB;IAItC,mBAAmB,CAAC,MAAM,EAAE,MAAM;IAqBlC,cAAc,CACZ,IAAI,EAAE,OAAO,EACb,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,GAAG,IAAI;IAUhB,OAAO,CAAC,kBAAkB;IAK1B,OAAO,CAAC,kBAAkB;IA2B1B,OAAO,CAAC,cAAc;IA8NtB,OAAO,CAAC,gBAAgB;CA4DzB;AAED,wBAAsB,WAAW,CAAC,EAChC,IAAI,EACJ,QAAQ,GACT,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBlC"}
|