@powerhousedao/contributor-billing 0.1.27 → 0.1.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/editors/invoice/exportSAFTPT.d.ts +184 -0
- package/dist/editors/invoice/exportSAFTPT.d.ts.map +1 -0
- package/dist/editors/invoice/exportSAFTPT.js +548 -0
- package/dist/editors/invoice/ingestPDF.js +1 -1
- package/dist/editors/invoice/invoiceToGnosis.js +2 -2
- package/dist/editors/invoice/legalEntity/bankSection.d.ts.map +1 -1
- package/dist/editors/invoice/legalEntity/bankSection.js +19 -10
- package/dist/editors/invoice/legalEntity/legalEntity.d.ts +4 -0
- package/dist/editors/invoice/legalEntity/legalEntity.d.ts.map +1 -1
- package/dist/editors/invoice/legalEntity/legalEntity.js +66 -2
- package/dist/editors/invoice/requestFinance.js +2 -2
- package/dist/editors/invoice/uploadPdfChunked.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import type { InvoiceState } from "../../document-models/invoice/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* SAF-T PT (Standard Audit File for Tax - Portugal) Export
|
|
4
|
+
* Format version: 1.04_01
|
|
5
|
+
* Reference: Portaria n.º 302/2016
|
|
6
|
+
*/
|
|
7
|
+
export interface SAFTPTExportOptions {
|
|
8
|
+
invoice: InvoiceState;
|
|
9
|
+
filename?: string;
|
|
10
|
+
/**
|
|
11
|
+
* Software certification details (required for certified billing software in Portugal)
|
|
12
|
+
* If not provided, placeholder values will be used
|
|
13
|
+
*/
|
|
14
|
+
softwareInfo?: {
|
|
15
|
+
productCompanyTaxID: string;
|
|
16
|
+
softwareCertificateNumber: string;
|
|
17
|
+
productID: string;
|
|
18
|
+
productVersion: string;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* ATCUD - Código Único de Documento
|
|
22
|
+
* Required for Portuguese invoices since 2022
|
|
23
|
+
* Format: VALIDATION_CODE-SEQUENCE_NUMBER
|
|
24
|
+
*/
|
|
25
|
+
atcud?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Hash and HashControl for digital signature
|
|
28
|
+
* Required for certified software
|
|
29
|
+
*/
|
|
30
|
+
hashInfo?: {
|
|
31
|
+
hash: string;
|
|
32
|
+
hashControl: string;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Source/Operator ID
|
|
36
|
+
*/
|
|
37
|
+
sourceId?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Economic Activity Code (CAE)
|
|
40
|
+
*/
|
|
41
|
+
eacCode?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Tax accounting basis
|
|
44
|
+
* F - Invoicing, C - Accounting, I - Integrated
|
|
45
|
+
*/
|
|
46
|
+
taxAccountingBasis?: "F" | "C" | "I" | "S" | "R" | "P";
|
|
47
|
+
/**
|
|
48
|
+
* Tax entity (usually "Global" or "Sede")
|
|
49
|
+
*/
|
|
50
|
+
taxEntity?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Fiscal year info - if not provided, derived from invoice date
|
|
53
|
+
*/
|
|
54
|
+
fiscalPeriod?: {
|
|
55
|
+
fiscalYear: number;
|
|
56
|
+
startDate: string;
|
|
57
|
+
endDate: string;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Header comment
|
|
61
|
+
*/
|
|
62
|
+
headerComment?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Customer ID for internal reference
|
|
65
|
+
*/
|
|
66
|
+
customerId?: string;
|
|
67
|
+
/**
|
|
68
|
+
* Tax exemption details (for 0% VAT)
|
|
69
|
+
*/
|
|
70
|
+
taxExemption?: {
|
|
71
|
+
reason: string;
|
|
72
|
+
code: string;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export declare class SAFTPTExporter {
|
|
76
|
+
private invoice;
|
|
77
|
+
private options;
|
|
78
|
+
constructor(options: SAFTPTExportOptions);
|
|
79
|
+
/**
|
|
80
|
+
* Convert the invoice state to SAF-T PT XML format
|
|
81
|
+
* @returns SAF-T PT XML string
|
|
82
|
+
*/
|
|
83
|
+
convertInvoiceToSAFTPT(): string;
|
|
84
|
+
/**
|
|
85
|
+
* Generate the Header section
|
|
86
|
+
*/
|
|
87
|
+
private generateHeader;
|
|
88
|
+
/**
|
|
89
|
+
* Generate company address block
|
|
90
|
+
*/
|
|
91
|
+
private generateCompanyAddress;
|
|
92
|
+
/**
|
|
93
|
+
* Generate the MasterFiles section
|
|
94
|
+
*/
|
|
95
|
+
private generateMasterFiles;
|
|
96
|
+
/**
|
|
97
|
+
* Generate customer entry
|
|
98
|
+
*/
|
|
99
|
+
private generateCustomer;
|
|
100
|
+
/**
|
|
101
|
+
* Generate products from line items
|
|
102
|
+
*/
|
|
103
|
+
private generateProducts;
|
|
104
|
+
/**
|
|
105
|
+
* Generate tax table with all Portuguese tax rates (PT, PT-MA, PT-AC regions)
|
|
106
|
+
* This includes the complete tax table as required by SAF-T PT specification
|
|
107
|
+
*/
|
|
108
|
+
private generateTaxTable;
|
|
109
|
+
/**
|
|
110
|
+
* Get Portuguese tax code based on rate
|
|
111
|
+
*/
|
|
112
|
+
private getTaxCode;
|
|
113
|
+
/**
|
|
114
|
+
* Generate the SourceDocuments section
|
|
115
|
+
*/
|
|
116
|
+
private generateSourceDocuments;
|
|
117
|
+
/**
|
|
118
|
+
* Generate single invoice entry
|
|
119
|
+
*/
|
|
120
|
+
private generateInvoice;
|
|
121
|
+
/**
|
|
122
|
+
* Generate invoice line items
|
|
123
|
+
*/
|
|
124
|
+
private generateInvoiceLines;
|
|
125
|
+
/**
|
|
126
|
+
* Generate a single invoice line
|
|
127
|
+
*/
|
|
128
|
+
private generateInvoiceLine;
|
|
129
|
+
/**
|
|
130
|
+
* Format invoice number for SAF-T PT format
|
|
131
|
+
* Converts "Invoice-123" to "FT 2025/123"
|
|
132
|
+
*/
|
|
133
|
+
private formatInvoiceNo;
|
|
134
|
+
/**
|
|
135
|
+
* Extract sequence number from invoice number
|
|
136
|
+
*/
|
|
137
|
+
private extractSequenceNumber;
|
|
138
|
+
/**
|
|
139
|
+
* Extract tax ID from legal entity
|
|
140
|
+
*/
|
|
141
|
+
private extractTaxId;
|
|
142
|
+
/**
|
|
143
|
+
* Format date as YYYY-MM-DD
|
|
144
|
+
*/
|
|
145
|
+
private formatDate;
|
|
146
|
+
/**
|
|
147
|
+
* Format datetime as YYYY-MM-DDTHH:MM:SS
|
|
148
|
+
*/
|
|
149
|
+
private formatDateTime;
|
|
150
|
+
/**
|
|
151
|
+
* Get last day of month
|
|
152
|
+
*/
|
|
153
|
+
private getLastDayOfMonth;
|
|
154
|
+
/**
|
|
155
|
+
* Escape special XML characters
|
|
156
|
+
*/
|
|
157
|
+
private escapeXml;
|
|
158
|
+
/**
|
|
159
|
+
* Export to file
|
|
160
|
+
*/
|
|
161
|
+
exportToFile(filename?: string): File;
|
|
162
|
+
/**
|
|
163
|
+
* Trigger download in browser
|
|
164
|
+
*/
|
|
165
|
+
downloadSAFTPT(filename?: string): void;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Export an invoice to SAF-T PT format
|
|
169
|
+
* @param options Export options
|
|
170
|
+
* @returns The generated XML file
|
|
171
|
+
*/
|
|
172
|
+
export declare function exportToSAFTPT(options: SAFTPTExportOptions): File;
|
|
173
|
+
/**
|
|
174
|
+
* Export and download an invoice as SAF-T PT
|
|
175
|
+
* @param options Export options
|
|
176
|
+
*/
|
|
177
|
+
export declare function downloadSAFTPT(options: SAFTPTExportOptions): void;
|
|
178
|
+
/**
|
|
179
|
+
* Convert invoice to SAF-T PT XML string
|
|
180
|
+
* @param options Export options
|
|
181
|
+
* @returns SAF-T PT XML string
|
|
182
|
+
*/
|
|
183
|
+
export declare function convertToSAFTPTXml(options: SAFTPTExportOptions): string;
|
|
184
|
+
//# sourceMappingURL=exportSAFTPT.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exportSAFTPT.d.ts","sourceRoot":"","sources":["../../../editors/invoice/exportSAFTPT.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,548 @@
|
|
|
1
|
+
// Helper function to format numbers with appropriate decimal places
|
|
2
|
+
function formatNumber(value, decimals = 2) {
|
|
3
|
+
return value.toFixed(decimals);
|
|
4
|
+
}
|
|
5
|
+
// Helper function to format numbers with high precision for unit prices
|
|
6
|
+
function formatUnitPrice(value) {
|
|
7
|
+
return value.toFixed(7);
|
|
8
|
+
}
|
|
9
|
+
// Portuguese month names
|
|
10
|
+
const PORTUGUESE_MONTHS = [
|
|
11
|
+
"Janeiro",
|
|
12
|
+
"Fevereiro",
|
|
13
|
+
"Março",
|
|
14
|
+
"Abril",
|
|
15
|
+
"Maio",
|
|
16
|
+
"Junho",
|
|
17
|
+
"Julho",
|
|
18
|
+
"Agosto",
|
|
19
|
+
"Setembro",
|
|
20
|
+
"Outubro",
|
|
21
|
+
"Novembro",
|
|
22
|
+
"Dezembro",
|
|
23
|
+
];
|
|
24
|
+
// Helper function to get Portuguese month name
|
|
25
|
+
function getPortugueseMonth(monthIndex) {
|
|
26
|
+
return PORTUGUESE_MONTHS[monthIndex] || "";
|
|
27
|
+
}
|
|
28
|
+
export class SAFTPTExporter {
|
|
29
|
+
invoice;
|
|
30
|
+
options;
|
|
31
|
+
constructor(options) {
|
|
32
|
+
this.invoice = options.invoice;
|
|
33
|
+
this.options = options;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Convert the invoice state to SAF-T PT XML format
|
|
37
|
+
* @returns SAF-T PT XML string
|
|
38
|
+
*/
|
|
39
|
+
convertInvoiceToSAFTPT() {
|
|
40
|
+
const xml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
41
|
+
<AuditFile xmlns="urn:OECD:StandardAuditFile-Tax:PT_1.04_01">
|
|
42
|
+
${this.generateHeader()}
|
|
43
|
+
${this.generateMasterFiles()}
|
|
44
|
+
${this.generateSourceDocuments()}
|
|
45
|
+
</AuditFile>`;
|
|
46
|
+
return xml;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Generate the Header section
|
|
50
|
+
*/
|
|
51
|
+
generateHeader() {
|
|
52
|
+
const issuer = this.invoice.issuer;
|
|
53
|
+
const taxId = this.extractTaxId(issuer);
|
|
54
|
+
const issueDate = new Date(this.invoice.dateIssued);
|
|
55
|
+
// Derive fiscal period from invoice date if not provided
|
|
56
|
+
const fiscalYear = this.options.fiscalPeriod?.fiscalYear || issueDate.getFullYear();
|
|
57
|
+
const month = issueDate.getMonth() + 1;
|
|
58
|
+
const startDate = this.options.fiscalPeriod?.startDate ||
|
|
59
|
+
`${fiscalYear}-${String(month).padStart(2, "0")}-01`;
|
|
60
|
+
const endDate = this.options.fiscalPeriod?.endDate ||
|
|
61
|
+
this.getLastDayOfMonth(fiscalYear, month);
|
|
62
|
+
const dateCreated = this.formatDate(new Date().toISOString());
|
|
63
|
+
// Default software info from TOConline (Portuguese SAF-T example)
|
|
64
|
+
const softwareInfo = this.options.softwareInfo || {
|
|
65
|
+
productCompanyTaxID: "503692310",
|
|
66
|
+
softwareCertificateNumber: "1662",
|
|
67
|
+
productID: "TOConline/Ordem dos Contabilistas Certificados",
|
|
68
|
+
productVersion: "3.0.4988",
|
|
69
|
+
};
|
|
70
|
+
// Generate HeaderComment with Portuguese month name if not provided
|
|
71
|
+
const portugueseMonth = getPortugueseMonth(issueDate.getMonth());
|
|
72
|
+
const headerComment = this.options.headerComment || `SAF-T ${portugueseMonth} ${fiscalYear}`;
|
|
73
|
+
return `<Header>
|
|
74
|
+
<AuditFileVersion>1.04_01</AuditFileVersion>
|
|
75
|
+
<CompanyID>${this.escapeXml(taxId)}</CompanyID>
|
|
76
|
+
<TaxRegistrationNumber>${this.escapeXml(taxId)}</TaxRegistrationNumber>
|
|
77
|
+
<TaxAccountingBasis>${this.options.taxAccountingBasis || "F"}</TaxAccountingBasis>
|
|
78
|
+
<CompanyName>${this.escapeXml(issuer.name || "")}</CompanyName>
|
|
79
|
+
<BusinessName>${this.escapeXml(issuer.name || "")}</BusinessName>
|
|
80
|
+
${this.generateCompanyAddress(issuer)}
|
|
81
|
+
<FiscalYear>${fiscalYear}</FiscalYear>
|
|
82
|
+
<StartDate>${startDate}</StartDate>
|
|
83
|
+
<EndDate>${endDate}</EndDate>
|
|
84
|
+
<CurrencyCode>${this.escapeXml(this.invoice.currency || "EUR")}</CurrencyCode>
|
|
85
|
+
<DateCreated>${dateCreated}</DateCreated>
|
|
86
|
+
<TaxEntity>${this.escapeXml(this.options.taxEntity || "Global")}</TaxEntity>
|
|
87
|
+
<ProductCompanyTaxID>${this.escapeXml(softwareInfo.productCompanyTaxID)}</ProductCompanyTaxID>
|
|
88
|
+
<SoftwareCertificateNumber>${this.escapeXml(softwareInfo.softwareCertificateNumber)}</SoftwareCertificateNumber>
|
|
89
|
+
<ProductID>${this.escapeXml(softwareInfo.productID)}</ProductID>
|
|
90
|
+
<ProductVersion>${this.escapeXml(softwareInfo.productVersion)}</ProductVersion>
|
|
91
|
+
<HeaderComment>${this.escapeXml(headerComment)}</HeaderComment>
|
|
92
|
+
${issuer.contactInfo?.email ? `<Email>${this.escapeXml(issuer.contactInfo.email)}</Email>` : ""}
|
|
93
|
+
</Header>`;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Generate company address block
|
|
97
|
+
*/
|
|
98
|
+
generateCompanyAddress(entity) {
|
|
99
|
+
const address = entity.address;
|
|
100
|
+
const addressDetail = [
|
|
101
|
+
address?.streetAddress,
|
|
102
|
+
address?.extendedAddress,
|
|
103
|
+
].filter(Boolean).join(", ");
|
|
104
|
+
return `<CompanyAddress>
|
|
105
|
+
<AddressDetail>${this.escapeXml(addressDetail || "Desconhecido")}</AddressDetail>
|
|
106
|
+
<City>${this.escapeXml(address?.city || "Desconhecido")}</City>
|
|
107
|
+
<PostalCode>${this.escapeXml(address?.postalCode || "Desconhecido")}</PostalCode>
|
|
108
|
+
<Country>${this.escapeXml(entity.country || "PT")}</Country>
|
|
109
|
+
</CompanyAddress>`;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Generate the MasterFiles section
|
|
113
|
+
*/
|
|
114
|
+
generateMasterFiles() {
|
|
115
|
+
return `<MasterFiles>
|
|
116
|
+
${this.generateCustomer()}
|
|
117
|
+
${this.generateProducts()}
|
|
118
|
+
${this.generateTaxTable()}
|
|
119
|
+
</MasterFiles>`;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Generate customer entry
|
|
123
|
+
*/
|
|
124
|
+
generateCustomer() {
|
|
125
|
+
const payer = this.invoice.payer;
|
|
126
|
+
const taxId = this.extractTaxId(payer);
|
|
127
|
+
const customerId = this.options.customerId || "1";
|
|
128
|
+
const addressDetail = [
|
|
129
|
+
payer.address?.streetAddress,
|
|
130
|
+
payer.address?.extendedAddress,
|
|
131
|
+
].filter(Boolean).join("\n") || "Desconhecido";
|
|
132
|
+
return `<Customer>
|
|
133
|
+
<CustomerID>${this.escapeXml(customerId)}</CustomerID>
|
|
134
|
+
<AccountID>Desconhecido</AccountID>
|
|
135
|
+
<CustomerTaxID>${this.escapeXml(taxId || "Consumidor Final")}</CustomerTaxID>
|
|
136
|
+
<CompanyName>${this.escapeXml(payer.name || "Consumidor Final")}</CompanyName>
|
|
137
|
+
<BillingAddress>
|
|
138
|
+
<AddressDetail>${this.escapeXml(addressDetail)}</AddressDetail>
|
|
139
|
+
<City>${this.escapeXml(payer.address?.city || "Desconhecido")}</City>
|
|
140
|
+
<PostalCode>${this.escapeXml(payer.address?.postalCode || "Desconhecido")}</PostalCode>
|
|
141
|
+
<Country>${this.escapeXml(payer.country || "PT")}</Country>
|
|
142
|
+
</BillingAddress>
|
|
143
|
+
<ShipToAddress>
|
|
144
|
+
<AddressDetail>${this.escapeXml(addressDetail)}</AddressDetail>
|
|
145
|
+
<City>${this.escapeXml(payer.address?.city || "Desconhecido")}</City>
|
|
146
|
+
<PostalCode>${this.escapeXml(payer.address?.postalCode || "Desconhecido")}</PostalCode>
|
|
147
|
+
<Country>${this.escapeXml(payer.country || "PT")}</Country>
|
|
148
|
+
</ShipToAddress>
|
|
149
|
+
<SelfBillingIndicator>0</SelfBillingIndicator>
|
|
150
|
+
</Customer>`;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Generate products from line items
|
|
154
|
+
*/
|
|
155
|
+
generateProducts() {
|
|
156
|
+
// Create unique product entries from line items
|
|
157
|
+
const productMap = new Map();
|
|
158
|
+
this.invoice.lineItems.forEach((item, index) => {
|
|
159
|
+
const code = String(index + 1).padStart(3, "0");
|
|
160
|
+
if (!productMap.has(item.description)) {
|
|
161
|
+
productMap.set(item.description, {
|
|
162
|
+
code,
|
|
163
|
+
description: item.description,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
// If no products, add a default service product
|
|
168
|
+
if (productMap.size === 0) {
|
|
169
|
+
productMap.set("Serviços", {
|
|
170
|
+
code: "001",
|
|
171
|
+
description: "Prestação de Serviços",
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
return Array.from(productMap.values())
|
|
175
|
+
.map((product) => `<Product>
|
|
176
|
+
<ProductType>S</ProductType>
|
|
177
|
+
<ProductCode>${this.escapeXml(product.code)}</ProductCode>
|
|
178
|
+
<ProductDescription>${this.escapeXml(product.description)}</ProductDescription>
|
|
179
|
+
<ProductNumberCode>${this.escapeXml(product.code)}</ProductNumberCode>
|
|
180
|
+
</Product>`)
|
|
181
|
+
.join("\n ");
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Generate tax table with all Portuguese tax rates (PT, PT-MA, PT-AC regions)
|
|
185
|
+
* This includes the complete tax table as required by SAF-T PT specification
|
|
186
|
+
*/
|
|
187
|
+
generateTaxTable() {
|
|
188
|
+
// Complete Portuguese tax table with all regions (Continental, Madeira, Azores)
|
|
189
|
+
return `<TaxTable>
|
|
190
|
+
<TaxTableEntry>
|
|
191
|
+
<TaxType>IVA</TaxType>
|
|
192
|
+
<TaxCountryRegion>PT</TaxCountryRegion>
|
|
193
|
+
<TaxCode>NOR</TaxCode>
|
|
194
|
+
<Description>Normal</Description>
|
|
195
|
+
<TaxPercentage>23</TaxPercentage>
|
|
196
|
+
</TaxTableEntry>
|
|
197
|
+
<TaxTableEntry>
|
|
198
|
+
<TaxType>IVA</TaxType>
|
|
199
|
+
<TaxCountryRegion>PT</TaxCountryRegion>
|
|
200
|
+
<TaxCode>INT</TaxCode>
|
|
201
|
+
<Description>Intermédia</Description>
|
|
202
|
+
<TaxPercentage>13</TaxPercentage>
|
|
203
|
+
</TaxTableEntry>
|
|
204
|
+
<TaxTableEntry>
|
|
205
|
+
<TaxType>IVA</TaxType>
|
|
206
|
+
<TaxCountryRegion>PT</TaxCountryRegion>
|
|
207
|
+
<TaxCode>RED</TaxCode>
|
|
208
|
+
<Description>Reduzida</Description>
|
|
209
|
+
<TaxPercentage>6</TaxPercentage>
|
|
210
|
+
</TaxTableEntry>
|
|
211
|
+
<TaxTableEntry>
|
|
212
|
+
<TaxType>IVA</TaxType>
|
|
213
|
+
<TaxCountryRegion>PT</TaxCountryRegion>
|
|
214
|
+
<TaxCode>ISE</TaxCode>
|
|
215
|
+
<Description>Isenta</Description>
|
|
216
|
+
<TaxPercentage>0</TaxPercentage>
|
|
217
|
+
</TaxTableEntry>
|
|
218
|
+
<TaxTableEntry>
|
|
219
|
+
<TaxType>IVA</TaxType>
|
|
220
|
+
<TaxCountryRegion>PT-MA</TaxCountryRegion>
|
|
221
|
+
<TaxCode>NOR</TaxCode>
|
|
222
|
+
<Description>Normal</Description>
|
|
223
|
+
<TaxPercentage>22</TaxPercentage>
|
|
224
|
+
</TaxTableEntry>
|
|
225
|
+
<TaxTableEntry>
|
|
226
|
+
<TaxType>IVA</TaxType>
|
|
227
|
+
<TaxCountryRegion>PT-MA</TaxCountryRegion>
|
|
228
|
+
<TaxCode>INT</TaxCode>
|
|
229
|
+
<Description>Intermédia</Description>
|
|
230
|
+
<TaxPercentage>12</TaxPercentage>
|
|
231
|
+
</TaxTableEntry>
|
|
232
|
+
<TaxTableEntry>
|
|
233
|
+
<TaxType>IVA</TaxType>
|
|
234
|
+
<TaxCountryRegion>PT-MA</TaxCountryRegion>
|
|
235
|
+
<TaxCode>ISE</TaxCode>
|
|
236
|
+
<Description>Isenta</Description>
|
|
237
|
+
<TaxPercentage>0</TaxPercentage>
|
|
238
|
+
</TaxTableEntry>
|
|
239
|
+
<TaxTableEntry>
|
|
240
|
+
<TaxType>IVA</TaxType>
|
|
241
|
+
<TaxCountryRegion>PT-AC</TaxCountryRegion>
|
|
242
|
+
<TaxCode>ISE</TaxCode>
|
|
243
|
+
<Description>Isenta</Description>
|
|
244
|
+
<TaxPercentage>0</TaxPercentage>
|
|
245
|
+
</TaxTableEntry>
|
|
246
|
+
<TaxTableEntry>
|
|
247
|
+
<TaxType>IVA</TaxType>
|
|
248
|
+
<TaxCountryRegion>PT-AC</TaxCountryRegion>
|
|
249
|
+
<TaxCode>INT</TaxCode>
|
|
250
|
+
<Description>Intermédia</Description>
|
|
251
|
+
<TaxPercentage>9</TaxPercentage>
|
|
252
|
+
</TaxTableEntry>
|
|
253
|
+
<TaxTableEntry>
|
|
254
|
+
<TaxType>IVA</TaxType>
|
|
255
|
+
<TaxCountryRegion>PT-AC</TaxCountryRegion>
|
|
256
|
+
<TaxCode>RED</TaxCode>
|
|
257
|
+
<Description>Reduzida</Description>
|
|
258
|
+
<TaxPercentage>4</TaxPercentage>
|
|
259
|
+
</TaxTableEntry>
|
|
260
|
+
<TaxTableEntry>
|
|
261
|
+
<TaxType>IVA</TaxType>
|
|
262
|
+
<TaxCountryRegion>PT-AC</TaxCountryRegion>
|
|
263
|
+
<TaxCode>NOR</TaxCode>
|
|
264
|
+
<Description>Normal</Description>
|
|
265
|
+
<TaxPercentage>16</TaxPercentage>
|
|
266
|
+
</TaxTableEntry>
|
|
267
|
+
<TaxTableEntry>
|
|
268
|
+
<TaxType>IVA</TaxType>
|
|
269
|
+
<TaxCountryRegion>PT-MA</TaxCountryRegion>
|
|
270
|
+
<TaxCode>RED</TaxCode>
|
|
271
|
+
<Description>Reduzida</Description>
|
|
272
|
+
<TaxPercentage>4</TaxPercentage>
|
|
273
|
+
</TaxTableEntry>
|
|
274
|
+
</TaxTable>`;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Get Portuguese tax code based on rate
|
|
278
|
+
*/
|
|
279
|
+
getTaxCode(rate) {
|
|
280
|
+
if (rate === 0)
|
|
281
|
+
return "ISE";
|
|
282
|
+
if (rate === 6 || rate === 4)
|
|
283
|
+
return "RED";
|
|
284
|
+
if (rate === 13 || rate === 12 || rate === 9)
|
|
285
|
+
return "INT";
|
|
286
|
+
if (rate === 23 || rate === 22 || rate === 16)
|
|
287
|
+
return "NOR";
|
|
288
|
+
return "ISE"; // Default to exempt for unknown rates
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Generate the SourceDocuments section
|
|
292
|
+
*/
|
|
293
|
+
generateSourceDocuments() {
|
|
294
|
+
const totalCredit = this.invoice.lineItems.reduce((sum, item) => sum + item.totalPriceTaxIncl, 0);
|
|
295
|
+
return `<SourceDocuments>
|
|
296
|
+
<SalesInvoices>
|
|
297
|
+
<NumberOfEntries>1</NumberOfEntries>
|
|
298
|
+
<TotalDebit>0.00</TotalDebit>
|
|
299
|
+
<TotalCredit>${formatNumber(totalCredit)}</TotalCredit>
|
|
300
|
+
${this.generateInvoice()}
|
|
301
|
+
</SalesInvoices>
|
|
302
|
+
<MovementOfGoods>
|
|
303
|
+
<NumberOfMovementLines>0</NumberOfMovementLines>
|
|
304
|
+
<TotalQuantityIssued>0</TotalQuantityIssued>
|
|
305
|
+
</MovementOfGoods>
|
|
306
|
+
<WorkingDocuments>
|
|
307
|
+
<NumberOfEntries>0</NumberOfEntries>
|
|
308
|
+
<TotalDebit>0.00</TotalDebit>
|
|
309
|
+
<TotalCredit>0.00</TotalCredit>
|
|
310
|
+
</WorkingDocuments>
|
|
311
|
+
<Payments>
|
|
312
|
+
<NumberOfEntries>0</NumberOfEntries>
|
|
313
|
+
<TotalDebit>0.00</TotalDebit>
|
|
314
|
+
<TotalCredit>0.00</TotalCredit>
|
|
315
|
+
</Payments>
|
|
316
|
+
</SourceDocuments>`;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Generate single invoice entry
|
|
320
|
+
*/
|
|
321
|
+
generateInvoice() {
|
|
322
|
+
const invoiceDate = this.formatDate(this.invoice.dateIssued);
|
|
323
|
+
const invoiceDateTime = this.formatDateTime(this.invoice.dateIssued);
|
|
324
|
+
const period = new Date(this.invoice.dateIssued).getMonth() + 1;
|
|
325
|
+
// Format invoice number for SAF-T (e.g., "FT 2025/1")
|
|
326
|
+
const invoiceNo = this.formatInvoiceNo(this.invoice.invoiceNo);
|
|
327
|
+
// ATCUD - use provided or generate based on example format (JJBDDFHD-sequence)
|
|
328
|
+
const sequenceNum = this.extractSequenceNumber(this.invoice.invoiceNo);
|
|
329
|
+
const atcud = this.options.atcud || `JJBDDFHD-${sequenceNum}`;
|
|
330
|
+
// Hash info - placeholder values (real hash requires certified software)
|
|
331
|
+
const hashInfo = this.options.hashInfo || {
|
|
332
|
+
hash: "Sn7zDVVOxNcAcW74Yd1b9YBHuwloo5y59NCW0MGBiBkuUz1fpLe8748ODBeFg5++Uzo2qNPfnzTOagpfe1IO3FZ54PJ65RquXuJ3TUc1rJMlEA0O89NGIVPbnbMQbk8CLFBkEolJoqfoqFHHc/GIedejFEyf+KrjhjsmxG/WvI4=",
|
|
333
|
+
hashControl: "1",
|
|
334
|
+
};
|
|
335
|
+
// Default source ID from example
|
|
336
|
+
const sourceId = this.options.sourceId || "919456";
|
|
337
|
+
const customerId = this.options.customerId || "1";
|
|
338
|
+
// Default EAC code from example (63110 = Data processing, hosting and related activities)
|
|
339
|
+
const eacCode = this.options.eacCode || "63110";
|
|
340
|
+
// Calculate totals
|
|
341
|
+
const netTotal = this.invoice.lineItems.reduce((sum, item) => sum + item.totalPriceTaxExcl, 0);
|
|
342
|
+
const grossTotal = this.invoice.lineItems.reduce((sum, item) => sum + item.totalPriceTaxIncl, 0);
|
|
343
|
+
const taxPayable = grossTotal - netTotal;
|
|
344
|
+
return `<Invoice>
|
|
345
|
+
<InvoiceNo>${this.escapeXml(invoiceNo)}</InvoiceNo>
|
|
346
|
+
<ATCUD>${this.escapeXml(atcud)}</ATCUD>
|
|
347
|
+
<DocumentStatus>
|
|
348
|
+
<InvoiceStatus>N</InvoiceStatus>
|
|
349
|
+
<InvoiceStatusDate>${invoiceDateTime}</InvoiceStatusDate>
|
|
350
|
+
<SourceID>${this.escapeXml(sourceId)}</SourceID>
|
|
351
|
+
<SourceBilling>P</SourceBilling>
|
|
352
|
+
</DocumentStatus>
|
|
353
|
+
<Hash>${this.escapeXml(hashInfo.hash)}</Hash>
|
|
354
|
+
<HashControl>${this.escapeXml(hashInfo.hashControl)}</HashControl>
|
|
355
|
+
<Period>${period}</Period>
|
|
356
|
+
<InvoiceDate>${invoiceDate}</InvoiceDate>
|
|
357
|
+
<InvoiceType>FT</InvoiceType>
|
|
358
|
+
<SpecialRegimes>
|
|
359
|
+
<SelfBillingIndicator>0</SelfBillingIndicator>
|
|
360
|
+
<CashVATSchemeIndicator>0</CashVATSchemeIndicator>
|
|
361
|
+
<ThirdPartiesBillingIndicator>0</ThirdPartiesBillingIndicator>
|
|
362
|
+
</SpecialRegimes>
|
|
363
|
+
<SourceID>${this.escapeXml(sourceId)}</SourceID>
|
|
364
|
+
<EACCode>${this.escapeXml(eacCode)}</EACCode>
|
|
365
|
+
<SystemEntryDate>${invoiceDateTime}</SystemEntryDate>
|
|
366
|
+
<CustomerID>${this.escapeXml(customerId)}</CustomerID>
|
|
367
|
+
${this.generateInvoiceLines()}
|
|
368
|
+
<DocumentTotals>
|
|
369
|
+
<TaxPayable>${formatNumber(taxPayable, 1)}</TaxPayable>
|
|
370
|
+
<NetTotal>${formatNumber(netTotal)}</NetTotal>
|
|
371
|
+
<GrossTotal>${formatNumber(grossTotal)}</GrossTotal>
|
|
372
|
+
</DocumentTotals>
|
|
373
|
+
</Invoice>`;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Generate invoice line items
|
|
377
|
+
*/
|
|
378
|
+
generateInvoiceLines() {
|
|
379
|
+
return this.invoice.lineItems
|
|
380
|
+
.map((item, index) => this.generateInvoiceLine(item, index + 1))
|
|
381
|
+
.join("\n ");
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Generate a single invoice line
|
|
385
|
+
*/
|
|
386
|
+
generateInvoiceLine(item, lineNumber) {
|
|
387
|
+
const taxPointDate = this.formatDate(this.invoice.dateIssued);
|
|
388
|
+
const taxCode = this.getTaxCode(item.taxPercent);
|
|
389
|
+
const productCode = String(lineNumber).padStart(3, "0");
|
|
390
|
+
// Tax exemption info (for 0% VAT) - using default from Portuguese SAF-T example
|
|
391
|
+
const taxExemption = item.taxPercent === 0 ? this.options.taxExemption || {
|
|
392
|
+
reason: "Outras situações de não liquidação do imposto (Exemplos: art",
|
|
393
|
+
code: "M99",
|
|
394
|
+
} : null;
|
|
395
|
+
return `<Line>
|
|
396
|
+
<LineNumber>${lineNumber}</LineNumber>
|
|
397
|
+
<ProductCode>${productCode}</ProductCode>
|
|
398
|
+
<ProductDescription>${this.escapeXml(item.description)}</ProductDescription>
|
|
399
|
+
<Quantity>${formatNumber(item.quantity)}</Quantity>
|
|
400
|
+
<UnitOfMeasure>UN</UnitOfMeasure>
|
|
401
|
+
<UnitPrice>${formatUnitPrice(item.unitPriceTaxExcl)}</UnitPrice>
|
|
402
|
+
<TaxPointDate>${taxPointDate}</TaxPointDate>
|
|
403
|
+
<Description>${this.escapeXml(item.description)}</Description>
|
|
404
|
+
<CreditAmount>${formatNumber(item.totalPriceTaxExcl)}</CreditAmount>
|
|
405
|
+
<Tax>
|
|
406
|
+
<TaxType>IVA</TaxType>
|
|
407
|
+
<TaxCountryRegion>PT</TaxCountryRegion>
|
|
408
|
+
<TaxCode>${taxCode}</TaxCode>
|
|
409
|
+
<TaxPercentage>${item.taxPercent}</TaxPercentage>
|
|
410
|
+
</Tax>
|
|
411
|
+
${taxExemption ? `<TaxExemptionReason>${this.escapeXml(taxExemption.reason)}</TaxExemptionReason>
|
|
412
|
+
<TaxExemptionCode>${this.escapeXml(taxExemption.code)}</TaxExemptionCode>` : ""}
|
|
413
|
+
</Line>`;
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Format invoice number for SAF-T PT format
|
|
417
|
+
* Converts "Invoice-123" to "FT 2025/123"
|
|
418
|
+
*/
|
|
419
|
+
formatInvoiceNo(invoiceNo) {
|
|
420
|
+
// Check if already in SAF-T format
|
|
421
|
+
if (/^[A-Z]{2}\s\d{4}\/\d+$/.test(invoiceNo)) {
|
|
422
|
+
return invoiceNo;
|
|
423
|
+
}
|
|
424
|
+
// Extract sequence number
|
|
425
|
+
const sequenceMatch = invoiceNo.match(/\d+/);
|
|
426
|
+
const sequence = sequenceMatch ? sequenceMatch[0] : "1";
|
|
427
|
+
const year = new Date(this.invoice.dateIssued).getFullYear();
|
|
428
|
+
return `FT ${year}/${sequence}`;
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Extract sequence number from invoice number
|
|
432
|
+
*/
|
|
433
|
+
extractSequenceNumber(invoiceNo) {
|
|
434
|
+
const match = invoiceNo.match(/\d+/);
|
|
435
|
+
return match ? match[0] : "1";
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Extract tax ID from legal entity
|
|
439
|
+
*/
|
|
440
|
+
extractTaxId(entity) {
|
|
441
|
+
if (!entity?.id)
|
|
442
|
+
return "";
|
|
443
|
+
const taxId = entity.id?.taxId;
|
|
444
|
+
const corpRegId = entity.id?.corpRegId;
|
|
445
|
+
// Remove country prefix if present (e.g., "PT515947504" -> "515947504")
|
|
446
|
+
const id = taxId || corpRegId || "";
|
|
447
|
+
return id.replace(/^[A-Z]{2}/, "");
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Format date as YYYY-MM-DD
|
|
451
|
+
*/
|
|
452
|
+
formatDate(dateString) {
|
|
453
|
+
if (!dateString)
|
|
454
|
+
return "";
|
|
455
|
+
try {
|
|
456
|
+
const date = new Date(dateString);
|
|
457
|
+
if (isNaN(date.getTime()))
|
|
458
|
+
return "";
|
|
459
|
+
return date.toISOString().split("T")[0];
|
|
460
|
+
}
|
|
461
|
+
catch {
|
|
462
|
+
return "";
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Format datetime as YYYY-MM-DDTHH:MM:SS
|
|
467
|
+
*/
|
|
468
|
+
formatDateTime(dateString) {
|
|
469
|
+
if (!dateString)
|
|
470
|
+
return "";
|
|
471
|
+
try {
|
|
472
|
+
const date = new Date(dateString);
|
|
473
|
+
if (isNaN(date.getTime()))
|
|
474
|
+
return "";
|
|
475
|
+
return date.toISOString().replace(/\.\d{3}Z$/, "");
|
|
476
|
+
}
|
|
477
|
+
catch {
|
|
478
|
+
return "";
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Get last day of month
|
|
483
|
+
*/
|
|
484
|
+
getLastDayOfMonth(year, month) {
|
|
485
|
+
const lastDay = new Date(year, month, 0).getDate();
|
|
486
|
+
return `${year}-${String(month).padStart(2, "0")}-${String(lastDay).padStart(2, "0")}`;
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Escape special XML characters
|
|
490
|
+
*/
|
|
491
|
+
escapeXml(str) {
|
|
492
|
+
return str
|
|
493
|
+
.replace(/&/g, "&")
|
|
494
|
+
.replace(/</g, "<")
|
|
495
|
+
.replace(/>/g, ">")
|
|
496
|
+
.replace(/"/g, """)
|
|
497
|
+
.replace(/'/g, "'");
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Export to file
|
|
501
|
+
*/
|
|
502
|
+
exportToFile(filename) {
|
|
503
|
+
const xml = this.convertInvoiceToSAFTPT();
|
|
504
|
+
const finalFilename = filename || this.options.filename || "saft-pt.xml";
|
|
505
|
+
const blob = new Blob([xml], { type: "application/xml" });
|
|
506
|
+
return new File([blob], finalFilename, { type: "application/xml" });
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Trigger download in browser
|
|
510
|
+
*/
|
|
511
|
+
downloadSAFTPT(filename) {
|
|
512
|
+
const xml = this.convertInvoiceToSAFTPT();
|
|
513
|
+
const finalFilename = filename || this.options.filename || "saft-pt.xml";
|
|
514
|
+
const blob = new Blob([xml], { type: "application/xml" });
|
|
515
|
+
const link = document.createElement("a");
|
|
516
|
+
link.href = URL.createObjectURL(blob);
|
|
517
|
+
link.download = finalFilename;
|
|
518
|
+
document.body.appendChild(link);
|
|
519
|
+
link.click();
|
|
520
|
+
document.body.removeChild(link);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Export an invoice to SAF-T PT format
|
|
525
|
+
* @param options Export options
|
|
526
|
+
* @returns The generated XML file
|
|
527
|
+
*/
|
|
528
|
+
export function exportToSAFTPT(options) {
|
|
529
|
+
const exporter = new SAFTPTExporter(options);
|
|
530
|
+
return exporter.exportToFile();
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Export and download an invoice as SAF-T PT
|
|
534
|
+
* @param options Export options
|
|
535
|
+
*/
|
|
536
|
+
export function downloadSAFTPT(options) {
|
|
537
|
+
const exporter = new SAFTPTExporter(options);
|
|
538
|
+
exporter.downloadSAFTPT();
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Convert invoice to SAF-T PT XML string
|
|
542
|
+
* @param options Export options
|
|
543
|
+
* @returns SAF-T PT XML string
|
|
544
|
+
*/
|
|
545
|
+
export function convertToSAFTPTXml(options) {
|
|
546
|
+
const exporter = new SAFTPTExporter(options);
|
|
547
|
+
return exporter.convertInvoiceToSAFTPT();
|
|
548
|
+
}
|
|
@@ -7,7 +7,7 @@ import { getCountryCodeFromName, mapChainNameToConfig } from "./utils/utils.js";
|
|
|
7
7
|
import { LoaderCircle } from "lucide-react";
|
|
8
8
|
let GRAPHQL_URL = "http://localhost:4001/graphql/invoice";
|
|
9
9
|
if (!window.document.baseURI.includes("localhost")) {
|
|
10
|
-
GRAPHQL_URL = "https://
|
|
10
|
+
GRAPHQL_URL = "https://switchboard.powerhouse.xyz/graphql/invoice";
|
|
11
11
|
}
|
|
12
12
|
export async function loadPDFFile({ file, dispatch, }) {
|
|
13
13
|
if (!file)
|
|
@@ -3,8 +3,8 @@ import React, { useState, useEffect } from "react";
|
|
|
3
3
|
import { actions } from "../../document-models/invoice/index.js";
|
|
4
4
|
import { generateId } from "document-model";
|
|
5
5
|
let GRAPHQL_URL = "http://localhost:4001/graphql/invoice";
|
|
6
|
-
if (!window.document.baseURI.includes(
|
|
7
|
-
GRAPHQL_URL =
|
|
6
|
+
if (!window.document.baseURI.includes('localhost')) {
|
|
7
|
+
GRAPHQL_URL = 'https://switchboard.powerhouse.xyz/graphql/invoice';
|
|
8
8
|
}
|
|
9
9
|
const InvoiceToGnosis = ({ docState, dispatch, }) => {
|
|
10
10
|
const [isLoading, setIsLoading] = useState(false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bankSection.d.ts","sourceRoot":"","sources":["../../../../editors/invoice/legalEntity/bankSection.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,qBAAqB,EAO3B,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAGjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"bankSection.d.ts","sourceRoot":"","sources":["../../../../editors/invoice/legalEntity/bankSection.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,qBAAqB,EAO3B,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAGjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAO3E,MAAM,MAAM,2BAA2B,GAAG,IAAI,CAC5C,qBAAqB,CAAC,KAAK,CAAC,EAC5B,UAAU,CACX,GAAG;IACF,QAAQ,CAAC,KAAK,EAAE,wBAAwB,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,IAAI,CAAC;IAC7D,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACrD,QAAQ,CAAC,cAAc,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAClD,QAAQ,CAAC,aAAa,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACjD,QAAQ,CAAC,uBAAuB,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC3D,QAAQ,CAAC,kBAAkB,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACtD,QAAQ,CAAC,uBAAuB,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC3D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,CAAC;AAmCF,eAAO,MAAM,sBAAsB,qIAglBlC,CAAC"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef, useCallback, useState, useEffect, useMemo, } from "react";
|
|
3
3
|
import { twMerge } from "tailwind-merge";
|
|
4
4
|
import { CountryForm } from "../components/countryForm.js";
|
|
5
5
|
import { InputField } from "../components/inputField.js";
|
|
6
6
|
import { Select } from "@powerhousedao/document-engineering";
|
|
7
7
|
import { isValidIBAN } from "../validation/validationRules.js";
|
|
8
|
+
import { STATE_PROVINCE_OPTIONS } from "./legalEntity.js";
|
|
8
9
|
const ACCOUNT_TYPES = ["CHECKING", "SAVINGS", "TRUST"];
|
|
9
10
|
function flattenBankInput(value) {
|
|
10
11
|
return {
|
|
@@ -129,11 +130,15 @@ export const LegalEntityBankSection = forwardRef(function LegalEntityBankSection
|
|
|
129
130
|
// input={localState.city ?? ""}
|
|
130
131
|
, {
|
|
131
132
|
// input={localState.city ?? ""}
|
|
132
|
-
value: localState.city ?? "", label: "City", placeholder: "City", onBlur: createBlurHandler("city"), handleInputChange: createInputHandler("city"), className: "h-10 w-full text-md mb-2" }), _jsx(
|
|
133
|
-
|
|
134
|
-
|
|
133
|
+
value: localState.city ?? "", label: "City", placeholder: "City", onBlur: createBlurHandler("city"), handleInputChange: createInputHandler("city"), className: "h-10 w-full text-md mb-2" }), _jsx("div", { className: "space-y-2", children: localState.country === "US" ? (_jsxs(_Fragment, { children: [_jsx("label", { className: "mb-2 block text-sm font-medium text-gray-700", children: "State/Province" }), _jsx(Select, { options: STATE_PROVINCE_OPTIONS, value: localState.stateProvince ?? "", onChange: (value) => {
|
|
134
|
+
createBlurHandler("stateProvince")({
|
|
135
|
+
target: { value: value },
|
|
136
|
+
});
|
|
137
|
+
}, className: "h-10 w-full text-md mb-2", searchable: true })] })) : (_jsx(InputField
|
|
135
138
|
// input={localState.stateProvince ?? ""}
|
|
136
|
-
|
|
139
|
+
, {
|
|
140
|
+
// input={localState.stateProvince ?? ""}
|
|
141
|
+
value: localState.stateProvince ?? "", label: "State/Province", placeholder: "State/Province", onBlur: createBlurHandler("stateProvince"), handleInputChange: createInputHandler("stateProvince"), className: "h-10 w-full text-md mb-2" })) })] }), _jsxs("div", { className: "grid grid-cols-2 gap-2", children: [_jsx(InputField
|
|
137
142
|
// input={localState.postalCode ?? ""}
|
|
138
143
|
, {
|
|
139
144
|
// input={localState.postalCode ?? ""}
|
|
@@ -182,11 +187,15 @@ export const LegalEntityBankSection = forwardRef(function LegalEntityBankSection
|
|
|
182
187
|
// input={localState.cityIntermediary ?? ""}
|
|
183
188
|
, {
|
|
184
189
|
// input={localState.cityIntermediary ?? ""}
|
|
185
|
-
value: localState.cityIntermediary ?? "", label: "City", placeholder: "City", onBlur: createBlurHandler("cityIntermediary"), handleInputChange: createInputHandler("cityIntermediary"), className: "h-10 w-full text-md mb-2" }), _jsx(
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
+
value: localState.cityIntermediary ?? "", label: "City", placeholder: "City", onBlur: createBlurHandler("cityIntermediary"), handleInputChange: createInputHandler("cityIntermediary"), className: "h-10 w-full text-md mb-2" }), _jsx("div", { className: "space-y-2", children: localState.countryIntermediary === "US" ? (_jsxs(_Fragment, { children: [_jsx("label", { className: "mb-2 block text-sm font-medium text-gray-700", children: "State/Province" }), _jsx(Select, { options: STATE_PROVINCE_OPTIONS, value: localState.stateProvinceIntermediary ?? "", onChange: (value) => {
|
|
191
|
+
createBlurHandler("stateProvinceIntermediary")({
|
|
192
|
+
target: { value: value },
|
|
193
|
+
});
|
|
194
|
+
}, className: "h-10 w-full text-md mb-2", searchable: true })] })) : (_jsx(InputField
|
|
195
|
+
// input={localState.stateProvince ?? ""}
|
|
196
|
+
, {
|
|
197
|
+
// input={localState.stateProvince ?? ""}
|
|
198
|
+
value: localState.stateProvinceIntermediary ?? "", label: "State/Province", placeholder: "State/Province", onBlur: createBlurHandler("stateProvinceIntermediary"), handleInputChange: createInputHandler("stateProvince"), className: "h-10 w-full text-md mb-2" })) })] }), _jsxs("div", { className: "grid grid-cols-2 gap-2", children: [_jsx(InputField
|
|
190
199
|
// input={localState.postalCodeIntermediary ?? ""}
|
|
191
200
|
, {
|
|
192
201
|
// input={localState.postalCodeIntermediary ?? ""}
|
|
@@ -4,6 +4,10 @@ import type { ValidationResult } from "../validation/validationManager.js";
|
|
|
4
4
|
export type EditLegalEntityWalletInput = EditIssuerWalletInput | EditPayerWalletInput;
|
|
5
5
|
export type EditLegalEntityBankInput = EditIssuerBankInput | EditPayerBankInput;
|
|
6
6
|
export type EditLegalEntityInput = EditIssuerInput | EditPayerInput;
|
|
7
|
+
export declare const STATE_PROVINCE_OPTIONS: {
|
|
8
|
+
label: string;
|
|
9
|
+
value: string;
|
|
10
|
+
}[];
|
|
7
11
|
export type LegalEntityMainSectionProps = Omit<ComponentPropsWithRef<"div">, "children"> & {
|
|
8
12
|
readonly value: EditLegalEntityInput;
|
|
9
13
|
readonly onChange: (value: EditLegalEntityInput) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"legalEntity.d.ts","sourceRoot":"","sources":["../../../../editors/invoice/legalEntity/legalEntity.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,mBAAmB,EACnB,eAAe,EACf,qBAAqB,EACrB,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,WAAW,EACZ,MAAM,2CAA2C,CAAC;AACnD,OAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,OAAO,CAAC;AAK1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"legalEntity.d.ts","sourceRoot":"","sources":["../../../../editors/invoice/legalEntity/legalEntity.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,71 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import React, {} from "react";
|
|
3
3
|
import { twMerge } from "tailwind-merge";
|
|
4
4
|
import { LegalEntityWalletSection } from "./walletSection.js";
|
|
5
5
|
import { LegalEntityBankSection } from "./bankSection.js";
|
|
6
6
|
import { CountryForm } from "../components/countryForm.js";
|
|
7
7
|
import { InputField } from "../components/inputField.js";
|
|
8
|
+
import { Select } from "@powerhousedao/document-engineering";
|
|
8
9
|
const FieldLabel = ({ children }) => (_jsx("label", { className: "block text-sm font-medium text-gray-700", children: children }));
|
|
10
|
+
export const STATE_PROVINCE_OPTIONS = [
|
|
11
|
+
{ label: "Alabama", value: "AL" },
|
|
12
|
+
{ label: "Alaska", value: "AK" },
|
|
13
|
+
{ label: "Arizona", value: "AZ" },
|
|
14
|
+
{ label: "Arkansas", value: "AR" },
|
|
15
|
+
{ label: "American Samoa", value: "AS" },
|
|
16
|
+
{ label: "California", value: "CA" },
|
|
17
|
+
{ label: "Colorado", value: "CO" },
|
|
18
|
+
{ label: "Connecticut", value: "CT" },
|
|
19
|
+
{ label: "Delaware", value: "DE" },
|
|
20
|
+
{ label: "District of Columbia", value: "DC" },
|
|
21
|
+
{ label: "Florida", value: "FL" },
|
|
22
|
+
{ label: "Georgia", value: "GA" },
|
|
23
|
+
{ label: "Guam", value: "GU" },
|
|
24
|
+
{ label: "Hawaii", value: "HI" },
|
|
25
|
+
{ label: "Idaho", value: "ID" },
|
|
26
|
+
{ label: "Illinois", value: "IL" },
|
|
27
|
+
{ label: "Indiana", value: "IN" },
|
|
28
|
+
{ label: "Iowa", value: "IA" },
|
|
29
|
+
{ label: "Kansas", value: "KS" },
|
|
30
|
+
{ label: "Kentucky", value: "KY" },
|
|
31
|
+
{ label: "Louisiana", value: "LA" },
|
|
32
|
+
{ label: "Maine", value: "ME" },
|
|
33
|
+
{ label: "Maryland", value: "MD" },
|
|
34
|
+
{ label: "Massachusetts", value: "MA" },
|
|
35
|
+
{ label: "Michigan", value: "MI" },
|
|
36
|
+
{ label: "Minnesota", value: "MN" },
|
|
37
|
+
{ label: "Mississippi", value: "MS" },
|
|
38
|
+
{ label: "Missouri", value: "MO" },
|
|
39
|
+
{ label: "Montana", value: "MT" },
|
|
40
|
+
{ label: "Nebraska", value: "NE" },
|
|
41
|
+
{ label: "Nevada", value: "NV" },
|
|
42
|
+
{ label: "New Hampshire", value: "NH" },
|
|
43
|
+
{ label: "New Jersey", value: "NJ" },
|
|
44
|
+
{ label: "New Mexico", value: "NM" },
|
|
45
|
+
{ label: "New York", value: "NY" },
|
|
46
|
+
{ label: "North Carolina", value: "NC" },
|
|
47
|
+
{ label: "North Dakota", value: "ND" },
|
|
48
|
+
{ label: "Northern Mariana Islands", value: "MP" },
|
|
49
|
+
{ label: "Ohio", value: "OH" },
|
|
50
|
+
{ label: "Oklahoma", value: "OK" },
|
|
51
|
+
{ label: "Oregon", value: "OR" },
|
|
52
|
+
{ label: "Pennsylvania", value: "PA" },
|
|
53
|
+
{ label: "Puerto Rico", value: "PR" },
|
|
54
|
+
{ label: "Rhode Island", value: "RI" },
|
|
55
|
+
{ label: "South Carolina", value: "SC" },
|
|
56
|
+
{ label: "South Dakota", value: "SD" },
|
|
57
|
+
{ label: "Tennessee", value: "TN" },
|
|
58
|
+
{ label: "Texas", value: "TX" },
|
|
59
|
+
{ label: "Trust Territories", value: "TT" },
|
|
60
|
+
{ label: "Utah", value: "UT" },
|
|
61
|
+
{ label: "Vermont", value: "VT" },
|
|
62
|
+
{ label: "Virgin Islands", value: "VI" },
|
|
63
|
+
{ label: "Virginia", value: "VA" },
|
|
64
|
+
{ label: "Washington", value: "WA" },
|
|
65
|
+
{ label: "West Virginia", value: "WV" },
|
|
66
|
+
{ label: "Wisconsin", value: "WI" },
|
|
67
|
+
{ label: "Wyoming", value: "WY" },
|
|
68
|
+
];
|
|
9
69
|
export const LegalEntityMainSection = (props) => {
|
|
10
70
|
const { value, onChange, disabled, mainCountryValidation, bankCountryValidation, streetaddressvalidation, cityvalidation, postalcodevalidation, payeremailvalidation, ...divProps } = props;
|
|
11
71
|
const handleInputChange = (field) => (e) => {
|
|
@@ -24,7 +84,11 @@ export const LegalEntityMainSection = (props) => {
|
|
|
24
84
|
onChange({ [field]: e.target.value });
|
|
25
85
|
}
|
|
26
86
|
};
|
|
27
|
-
return (_jsxs("div", { ...divProps, className: twMerge("rounded-lg border border-gray-200 bg-white p-6 mb-2", props.className), children: [_jsx("h3", { className: "mb-4 text-lg font-semibold text-gray-900", children: "Basic Information" }), _jsxs("div", { className: "space-y-6", children: [_jsx("div", { className: "space-y-2", children: _jsx(InputField, { value: value.name ?? "", label: "Name", placeholder: "Legal Entity Name", onBlur: handleTextareaBlur("name"), handleInputChange: handleTextareaChange("name"), className: "h-10 w-full text-md mb-2" }) }), _jsx("div", { className: "space-y-2", children: _jsx(InputField, { value: value.id ?? "", label: "Tax ID / Corp. Reg", placeholder: "332...", onBlur: handleTextareaBlur("id"), handleInputChange: handleTextareaChange("id"), className: "h-10 w-full text-md mb-2" }) }), _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "space-y-4", children: [_jsx(InputField, { value: value.streetAddress ?? "", label: "Address", placeholder: "Street Address", onBlur: handleTextareaBlur("streetAddress"), handleInputChange: handleTextareaChange("streetAddress"), className: "h-10 w-full text-md mb-2", validation: streetaddressvalidation }), _jsx(InputField, { value: value.extendedAddress ?? "", placeholder: "Extended Address", onBlur: handleTextareaBlur("extendedAddress"), handleInputChange: handleTextareaChange("extendedAddress"), className: "h-10 w-full text-md mb-2" })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsx("div", { className: "space-y-2", children: _jsx(InputField, { value: value.city ?? "", label: "City", placeholder: "City", onBlur: handleTextareaBlur("city"), handleInputChange: handleTextareaChange("city"), className: "h-10 w-full text-md mb-2", validation: cityvalidation }) }), _jsx("div", { className: "space-y-2", children:
|
|
87
|
+
return (_jsxs("div", { ...divProps, className: twMerge("rounded-lg border border-gray-200 bg-white p-6 mb-2", props.className), children: [_jsx("h3", { className: "mb-4 text-lg font-semibold text-gray-900", children: "Basic Information" }), _jsxs("div", { className: "space-y-6", children: [_jsx("div", { className: "space-y-2", children: _jsx(InputField, { value: value.name ?? "", label: "Name", placeholder: "Legal Entity Name", onBlur: handleTextareaBlur("name"), handleInputChange: handleTextareaChange("name"), className: "h-10 w-full text-md mb-2" }) }), _jsx("div", { className: "space-y-2", children: _jsx(InputField, { value: value.id ?? "", label: "Tax ID / Corp. Reg", placeholder: "332...", onBlur: handleTextareaBlur("id"), handleInputChange: handleTextareaChange("id"), className: "h-10 w-full text-md mb-2" }) }), _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "space-y-4", children: [_jsx(InputField, { value: value.streetAddress ?? "", label: "Address", placeholder: "Street Address", onBlur: handleTextareaBlur("streetAddress"), handleInputChange: handleTextareaChange("streetAddress"), className: "h-10 w-full text-md mb-2", validation: streetaddressvalidation }), _jsx(InputField, { value: value.extendedAddress ?? "", placeholder: "Extended Address", onBlur: handleTextareaBlur("extendedAddress"), handleInputChange: handleTextareaChange("extendedAddress"), className: "h-10 w-full text-md mb-2" })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsx("div", { className: "space-y-2", children: _jsx(InputField, { value: value.city ?? "", label: "City", placeholder: "City", onBlur: handleTextareaBlur("city"), handleInputChange: handleTextareaChange("city"), className: "h-10 w-full text-md mb-2", validation: cityvalidation }) }), _jsx("div", { className: "space-y-2", children: value.country === "US" ? (_jsxs(_Fragment, { children: [_jsx("label", { className: "mb-2 block text-sm font-medium text-gray-700", children: "State/Province" }), _jsx(Select, { options: STATE_PROVINCE_OPTIONS, value: value.stateProvince ?? "", onChange: (value) => {
|
|
88
|
+
handleBlur("stateProvince")({
|
|
89
|
+
target: { value: value },
|
|
90
|
+
});
|
|
91
|
+
}, className: "h-10 w-full text-md mb-2", searchable: true })] })) : (_jsx(InputField, { value: value.stateProvince ?? "", label: "State/Province", placeholder: "State/Province", onBlur: handleTextareaBlur("stateProvince"), handleInputChange: handleTextareaChange("stateProvince"), className: "h-10 w-full text-md mb-2" })) })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsx("div", { className: "space-y-2", children: _jsx(InputField, { value: value.postalCode ?? "", label: "Postal Code", placeholder: "Postal Code", onBlur: handleTextareaBlur("postalCode"), handleInputChange: handleTextareaChange("postalCode"), className: "h-10 w-full text-md mb-2", validation: postalcodevalidation }) }), _jsxs("div", { className: "space-y-2", children: [_jsx(FieldLabel, { children: "Country" }), _jsx(CountryForm, { country: value.country ?? "", handleInputChange: handleInputChange("country"), handleBlur: handleBlur("country"), className: "h-10 w-full text-md mb-2", validation: mainCountryValidation })] })] })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsx("div", { className: "space-y-2", children: _jsx(InputField, { value: value.email ?? "", label: "Email", placeholder: "Email", onBlur: handleTextareaBlur("email"), handleInputChange: handleTextareaChange("email"), className: "h-10 w-full text-md mb-2", validation: payeremailvalidation }) }), _jsx("div", { className: "space-y-2", children: _jsx(InputField, { value: value.tel ?? "", label: "Telephone", placeholder: "Telephone", onBlur: handleTextareaBlur("tel"), handleInputChange: handleTextareaChange("tel"), className: "h-10 w-full text-md mb-2" }) })] })] })] }));
|
|
28
92
|
};
|
|
29
93
|
// Helper to flatten LegalEntity to EditLegalEntityInput
|
|
30
94
|
function flattenLegalEntityToEditInput(legalEntity) {
|
|
@@ -3,8 +3,8 @@ import React, { useState } from "react";
|
|
|
3
3
|
import { actions } from "../../document-models/invoice/index.js";
|
|
4
4
|
import { generateId } from "document-model";
|
|
5
5
|
let GRAPHQL_URL = "http://localhost:4001/graphql/invoice";
|
|
6
|
-
if (!window.document.baseURI.includes(
|
|
7
|
-
GRAPHQL_URL =
|
|
6
|
+
if (!window.document.baseURI.includes('localhost')) {
|
|
7
|
+
GRAPHQL_URL = 'https://switchboard.powerhouse.xyz/graphql/invoice';
|
|
8
8
|
}
|
|
9
9
|
const RequestFinance = ({ docState, dispatch, }) => {
|
|
10
10
|
const [isLoading, setIsLoading] = useState(false);
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
let GRAPHQL_URL = 'http://localhost:4001/graphql/invoice';
|
|
9
9
|
if (!window.document.baseURI.includes('localhost')) {
|
|
10
|
-
GRAPHQL_URL =
|
|
10
|
+
GRAPHQL_URL = 'https://switchboard.powerhouse.xyz/graphql/invoice';
|
|
11
11
|
}
|
|
12
12
|
export async function uploadPdfChunked(pdfData, endpoint = GRAPHQL_URL, chunkSize = 500 * 1024, // 500KB chunks
|
|
13
13
|
onProgress) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@powerhousedao/contributor-billing",
|
|
3
3
|
"description": "Document models that help contributors of open organisations get paid anonymously for their work on a monthly basis.",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.29",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|