@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 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.31");
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@spaceinvoices/react-ui",
3
3
  "type": "module",
4
- "version": "0.4.31",
4
+ "version": "0.4.32",
5
5
  "private": false,
6
6
  "license": "MIT",
7
7
  "description": "Space Invoices UI components - copy-paste distribution with CLI support",
@@ -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: tax?.tax_id ?? undefined,
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
  }))
@@ -206,6 +206,7 @@ function buildInvoiceFormValues({
206
206
  gross_price: item.gross_price ?? undefined,
207
207
  taxes: item.taxes || [],
208
208
  discounts: normalizeLineItemDiscountsForForm(item.discounts),
209
+ metadata: item.metadata ?? undefined,
209
210
  }
210
211
  : {}),
211
212
  }))
@@ -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
- email: source.customer.email,
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
- const calculated = await documents.calculateDocumentPreview(
265
- calculatePayload,
266
- { type: targetType },
267
- { entity_id: activeEntity.id },
268
- );
269
- if (totalsDifferByCents(calculated.total_with_tax, (source as any).total_with_tax)) {
270
- (initialValues as any)._preserved_expected_total_with_tax = (source as any).total_with_tax;
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
  }