@spaceinvoices/react-ui 0.4.31 → 0.4.32
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/cli/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/components/advance-invoices/create/create-advance-invoice-form.tsx +1 -0
- package/src/components/credit-notes/create/create-credit-note-form.tsx +1 -0
- package/src/components/delivery-notes/create/create-delivery-note-form.tsx +1 -0
- package/src/components/documents/create/custom-create-template.ts +42 -5
- package/src/components/estimates/create/create-estimate-form.tsx +1 -0
- package/src/components/invoices/create/create-invoice-form.tsx +1 -0
- package/src/hooks/use-duplicate-document.ts +20 -9
package/cli/dist/index.js
CHANGED
|
@@ -933,7 +933,7 @@ async function list(options = {}) {
|
|
|
933
933
|
|
|
934
934
|
// cli/src/index.ts
|
|
935
935
|
var program = new Command();
|
|
936
|
-
program.name("spaceinvoices-ui").description("CLI for adding Space Invoices React UI components to your project").version("0.4.
|
|
936
|
+
program.name("spaceinvoices-ui").description("CLI for adding Space Invoices React UI components to your project").version("0.4.32");
|
|
937
937
|
program.option("--local <path>", "Use local registry from specified path (for development)");
|
|
938
938
|
program.command("init").description("Initialize Space Invoices UI in your project").option("-y, --yes", "Skip prompts and use defaults").option("-f, --force", "Overwrite existing configuration").option("--cwd <path>", "Working directory (defaults to current directory)").action(async (options) => {
|
|
939
939
|
const globalOpts = program.opts();
|
package/package.json
CHANGED
|
@@ -312,6 +312,7 @@ export default function CreateAdvanceInvoiceForm({
|
|
|
312
312
|
classification: item.classification ?? undefined,
|
|
313
313
|
taxes: item.taxes || [],
|
|
314
314
|
discounts: normalizeLineItemDiscountsForForm(item.discounts),
|
|
315
|
+
metadata: item.metadata ?? undefined,
|
|
315
316
|
}
|
|
316
317
|
: {}),
|
|
317
318
|
}))
|
|
@@ -256,6 +256,7 @@ export default function CreateCreditNoteForm({
|
|
|
256
256
|
classification: item.classification ?? undefined,
|
|
257
257
|
taxes: item.taxes || [],
|
|
258
258
|
discounts: normalizeLineItemDiscountsForForm(item.discounts),
|
|
259
|
+
metadata: item.metadata ?? undefined,
|
|
259
260
|
}
|
|
260
261
|
: {}),
|
|
261
262
|
}))
|
|
@@ -148,6 +148,7 @@ export default function CreateDeliveryNoteForm({
|
|
|
148
148
|
classification: item.classification ?? undefined,
|
|
149
149
|
taxes: item.taxes || [],
|
|
150
150
|
discounts: normalizeLineItemDiscountsForForm(item.discounts),
|
|
151
|
+
metadata: item.metadata ?? undefined,
|
|
151
152
|
}
|
|
152
153
|
: {}),
|
|
153
154
|
}))
|
|
@@ -28,6 +28,35 @@ function sanitizeDiscounts(discounts: any[] | undefined): any[] {
|
|
|
28
28
|
}));
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
function getTaxIdentityKey(tax: any): string {
|
|
32
|
+
return JSON.stringify({
|
|
33
|
+
rate: tax?.rate ?? null,
|
|
34
|
+
reverse_charge: tax?.reverse_charge ?? false,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function collectResolvedItemTaxIds(items: any[] | undefined): Map<string, Set<string>> {
|
|
39
|
+
const taxIdsByKey = new Map<string, Set<string>>();
|
|
40
|
+
|
|
41
|
+
for (const item of items ?? []) {
|
|
42
|
+
if (item?.type === "separator") continue;
|
|
43
|
+
|
|
44
|
+
for (const tax of item?.taxes ?? []) {
|
|
45
|
+
if (!tax?.tax_id) continue;
|
|
46
|
+
|
|
47
|
+
const key = getTaxIdentityKey(tax);
|
|
48
|
+
const existing = taxIdsByKey.get(key);
|
|
49
|
+
if (existing) {
|
|
50
|
+
existing.add(tax.tax_id);
|
|
51
|
+
} else {
|
|
52
|
+
taxIdsByKey.set(key, new Set([tax.tax_id]));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return taxIdsByKey;
|
|
58
|
+
}
|
|
59
|
+
|
|
31
60
|
export function toCustomCreateItem(item: any): any {
|
|
32
61
|
if (item?.type === "separator") {
|
|
33
62
|
return {
|
|
@@ -55,9 +84,17 @@ export function toCustomCreateItem(item: any): any {
|
|
|
55
84
|
};
|
|
56
85
|
}
|
|
57
86
|
|
|
58
|
-
export function sanitizeSummaryTaxes(taxes: any[] | undefined): any[] {
|
|
87
|
+
export function sanitizeSummaryTaxes(taxes: any[] | undefined, items?: any[]): any[] {
|
|
88
|
+
const resolvedItemTaxIds = collectResolvedItemTaxIds(items);
|
|
89
|
+
|
|
59
90
|
return (taxes ?? []).map((tax) => ({
|
|
60
|
-
tax_id:
|
|
91
|
+
tax_id:
|
|
92
|
+
tax?.tax_id ??
|
|
93
|
+
(() => {
|
|
94
|
+
const candidates = resolvedItemTaxIds.get(getTaxIdentityKey(tax));
|
|
95
|
+
if (!candidates || candidates.size !== 1) return undefined;
|
|
96
|
+
return Array.from(candidates)[0];
|
|
97
|
+
})(),
|
|
61
98
|
rate: tax?.rate ?? null,
|
|
62
99
|
base: tax?.base ?? 0,
|
|
63
100
|
amount: tax?.amount ?? 0,
|
|
@@ -73,11 +110,11 @@ function getSummaryTaxKey(tax: any): string {
|
|
|
73
110
|
});
|
|
74
111
|
}
|
|
75
112
|
|
|
76
|
-
export function sumSummaryTaxes(documents: Array<{ taxes?: any[] }>): any[] {
|
|
113
|
+
export function sumSummaryTaxes(documents: Array<{ taxes?: any[]; items?: any[] }>): any[] {
|
|
77
114
|
const aggregated = new Map<string, any>();
|
|
78
115
|
|
|
79
116
|
for (const document of documents) {
|
|
80
|
-
for (const tax of sanitizeSummaryTaxes(document.taxes)) {
|
|
117
|
+
for (const tax of sanitizeSummaryTaxes(document.taxes, document.items)) {
|
|
81
118
|
const key = getSummaryTaxKey(tax);
|
|
82
119
|
const existing = aggregated.get(key);
|
|
83
120
|
if (existing) {
|
|
@@ -98,7 +135,7 @@ export function buildCustomCreateTemplateFromDocument(document: any): CustomCrea
|
|
|
98
135
|
total: document?.total ?? 0,
|
|
99
136
|
total_with_tax: document?.total_with_tax ?? 0,
|
|
100
137
|
total_discount: document?.total_discount ?? 0,
|
|
101
|
-
taxes: sanitizeSummaryTaxes(document?.taxes),
|
|
138
|
+
taxes: sanitizeSummaryTaxes(document?.taxes, document?.items),
|
|
102
139
|
};
|
|
103
140
|
}
|
|
104
141
|
|
|
@@ -184,6 +184,7 @@ export default function CreateEstimateForm({
|
|
|
184
184
|
gross_price: item.gross_price ?? undefined,
|
|
185
185
|
taxes: item.taxes || [],
|
|
186
186
|
discounts: normalizeLineItemDiscountsForForm(item.discounts),
|
|
187
|
+
metadata: item.metadata ?? undefined,
|
|
187
188
|
}
|
|
188
189
|
: {}),
|
|
189
190
|
}))
|
|
@@ -101,14 +101,21 @@ function transformDocumentForDuplication(source: Document, targetType: DocumentT
|
|
|
101
101
|
const customerData = source.customer
|
|
102
102
|
? {
|
|
103
103
|
name: source.customer.name,
|
|
104
|
+
email: source.customer.email,
|
|
104
105
|
address: source.customer.address,
|
|
105
106
|
address_2: source.customer.address_2,
|
|
106
|
-
city: source.customer.city,
|
|
107
107
|
post_code: source.customer.post_code,
|
|
108
|
+
city: source.customer.city,
|
|
109
|
+
state: source.customer.state,
|
|
108
110
|
country: source.customer.country,
|
|
109
111
|
country_code: source.customer.country_code,
|
|
110
112
|
tax_number: source.customer.tax_number,
|
|
111
|
-
|
|
113
|
+
tax_number_2: source.customer.tax_number_2,
|
|
114
|
+
company_number: source.customer.company_number,
|
|
115
|
+
phone: source.customer.phone,
|
|
116
|
+
peppol_id: source.customer.peppol_id,
|
|
117
|
+
is_end_consumer: source.customer.is_end_consumer,
|
|
118
|
+
bank_account: source.customer.bank_account,
|
|
112
119
|
}
|
|
113
120
|
: undefined;
|
|
114
121
|
|
|
@@ -261,13 +268,17 @@ export function useDuplicateDocument({
|
|
|
261
268
|
if (shouldCheckForPreservedTotal(source)) {
|
|
262
269
|
const calculatePayload = buildCalculatePayload(initialValues);
|
|
263
270
|
if (calculatePayload) {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
(
|
|
271
|
+
try {
|
|
272
|
+
const calculated = await documents.calculateDocumentPreview(
|
|
273
|
+
calculatePayload,
|
|
274
|
+
{ type: targetType },
|
|
275
|
+
{ entity_id: activeEntity.id },
|
|
276
|
+
);
|
|
277
|
+
if (totalsDifferByCents(calculated.total_with_tax, (source as any).total_with_tax)) {
|
|
278
|
+
(initialValues as any)._preserved_expected_total_with_tax = (source as any).total_with_tax;
|
|
279
|
+
}
|
|
280
|
+
} catch {
|
|
281
|
+
// Keep duplicate prefill data even if preview validation is temporarily unavailable.
|
|
271
282
|
}
|
|
272
283
|
}
|
|
273
284
|
}
|