@spaceinvoices/react-ui 0.4.4 → 0.4.5

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.
Files changed (147) hide show
  1. package/cli/dist/index.js +1 -1
  2. package/package.json +1 -1
  3. package/src/components/advance-invoices/create/create-advance-invoice-form.tsx +61 -11
  4. package/src/components/advance-invoices/create/locales/de.ts +15 -0
  5. package/src/components/advance-invoices/create/locales/es.ts +15 -0
  6. package/src/components/advance-invoices/create/locales/fr.ts +15 -0
  7. package/src/components/advance-invoices/create/locales/hr.ts +15 -0
  8. package/src/components/advance-invoices/create/locales/it.ts +15 -0
  9. package/src/components/advance-invoices/create/locales/nl.ts +15 -0
  10. package/src/components/advance-invoices/create/locales/pl.ts +15 -0
  11. package/src/components/advance-invoices/create/locales/pt.ts +15 -0
  12. package/src/components/advance-invoices/create/locales/sl.ts +15 -0
  13. package/src/components/advance-invoices/list/list-row-actions.tsx +48 -1
  14. package/src/components/advance-invoices/list/list-table.tsx +21 -1
  15. package/src/components/advance-invoices/list/locales/de.ts +4 -0
  16. package/src/components/advance-invoices/list/locales/en.ts +3 -0
  17. package/src/components/advance-invoices/list/locales/es.ts +4 -0
  18. package/src/components/advance-invoices/list/locales/fr.ts +4 -0
  19. package/src/components/advance-invoices/list/locales/hr.ts +3 -0
  20. package/src/components/advance-invoices/list/locales/it.ts +4 -0
  21. package/src/components/advance-invoices/list/locales/nl.ts +4 -0
  22. package/src/components/advance-invoices/list/locales/pl.ts +3 -0
  23. package/src/components/advance-invoices/list/locales/pt.ts +4 -0
  24. package/src/components/advance-invoices/list/locales/sl.ts +3 -0
  25. package/src/components/credit-notes/create/create-credit-note-form.tsx +71 -8
  26. package/src/components/credit-notes/create/locales/de.ts +16 -0
  27. package/src/components/credit-notes/create/locales/es.ts +16 -0
  28. package/src/components/credit-notes/create/locales/fr.ts +16 -0
  29. package/src/components/credit-notes/create/locales/hr.ts +16 -0
  30. package/src/components/credit-notes/create/locales/it.ts +16 -0
  31. package/src/components/credit-notes/create/locales/nl.ts +16 -0
  32. package/src/components/credit-notes/create/locales/pl.ts +16 -0
  33. package/src/components/credit-notes/create/locales/pt.ts +16 -0
  34. package/src/components/credit-notes/create/locales/sl.ts +17 -1
  35. package/src/components/credit-notes/list/list-row-actions.tsx +44 -1
  36. package/src/components/credit-notes/list/list-table.tsx +16 -2
  37. package/src/components/credit-notes/list/locales/de.ts +2 -0
  38. package/src/components/credit-notes/list/locales/en.ts +2 -0
  39. package/src/components/credit-notes/list/locales/es.ts +2 -0
  40. package/src/components/credit-notes/list/locales/fr.ts +2 -0
  41. package/src/components/credit-notes/list/locales/hr.ts +2 -0
  42. package/src/components/credit-notes/list/locales/it.ts +2 -0
  43. package/src/components/credit-notes/list/locales/nl.ts +2 -0
  44. package/src/components/credit-notes/list/locales/pl.ts +2 -0
  45. package/src/components/credit-notes/list/locales/pt.ts +2 -0
  46. package/src/components/credit-notes/list/locales/sl.ts +2 -0
  47. package/src/components/dashboard/collection-rate-card/use-collection-rate.ts +48 -9
  48. package/src/components/dashboard/revenue-trend-chart/use-revenue-trend.ts +77 -48
  49. package/src/components/dashboard/shared/use-revenue-data.ts +77 -9
  50. package/src/components/delivery-notes/create/create-delivery-note-form.tsx +67 -7
  51. package/src/components/delivery-notes/create/locales/de.ts +16 -0
  52. package/src/components/delivery-notes/create/locales/es.ts +16 -0
  53. package/src/components/delivery-notes/create/locales/fr.ts +16 -0
  54. package/src/components/delivery-notes/create/locales/hr.ts +16 -0
  55. package/src/components/delivery-notes/create/locales/it.ts +16 -0
  56. package/src/components/delivery-notes/create/locales/nl.ts +16 -0
  57. package/src/components/delivery-notes/create/locales/pl.ts +16 -0
  58. package/src/components/delivery-notes/create/locales/pt.ts +16 -0
  59. package/src/components/delivery-notes/create/locales/sl.ts +17 -1
  60. package/src/components/delivery-notes/list/list-table.tsx +17 -8
  61. package/src/components/delivery-notes/list/locales/de.ts +32 -1
  62. package/src/components/delivery-notes/list/locales/en.ts +31 -0
  63. package/src/components/delivery-notes/list/locales/es.ts +32 -1
  64. package/src/components/delivery-notes/list/locales/fr.ts +32 -1
  65. package/src/components/delivery-notes/list/locales/hr.ts +32 -1
  66. package/src/components/delivery-notes/list/locales/it.ts +32 -1
  67. package/src/components/delivery-notes/list/locales/nl.ts +32 -1
  68. package/src/components/delivery-notes/list/locales/pl.ts +32 -1
  69. package/src/components/delivery-notes/list/locales/pt.ts +32 -1
  70. package/src/components/delivery-notes/list/locales/sl.ts +32 -1
  71. package/src/components/documents/create/document-add-item-form.tsx +70 -0
  72. package/src/components/documents/create/document-details-section.tsx +122 -2
  73. package/src/components/documents/create/document-items-section.tsx +21 -4
  74. package/src/components/documents/create/live-preview.tsx +24 -4
  75. package/src/components/documents/create/mark-as-paid-section.tsx +29 -20
  76. package/src/components/documents/create/prepare-document-submission.ts +19 -7
  77. package/src/components/documents/shared/document-preview-display.tsx +3 -4
  78. package/src/components/documents/view/document-actions-bar.tsx +7 -27
  79. package/src/components/documents/view/document-details-card.tsx +26 -9
  80. package/src/components/documents/view/locales/de.ts +2 -0
  81. package/src/components/documents/view/locales/es.ts +2 -0
  82. package/src/components/documents/view/locales/fr.ts +2 -0
  83. package/src/components/documents/view/locales/hr.ts +2 -0
  84. package/src/components/documents/view/locales/it.ts +2 -0
  85. package/src/components/documents/view/locales/nl.ts +2 -0
  86. package/src/components/documents/view/locales/pl.ts +2 -0
  87. package/src/components/documents/view/locales/pt.ts +2 -0
  88. package/src/components/documents/view/locales/sl.ts +3 -1
  89. package/src/components/documents/view/use-document-download.ts +6 -3
  90. package/src/components/entities/create-entity-form.tsx +2 -1
  91. package/src/components/entities/entity-settings-form/input-with-preview.tsx +30 -2
  92. package/src/components/entities/entity-settings-form/locales/de.ts +1 -0
  93. package/src/components/entities/entity-settings-form/locales/es.ts +1 -0
  94. package/src/components/entities/entity-settings-form/locales/fr.ts +1 -0
  95. package/src/components/entities/entity-settings-form/locales/hr.ts +1 -0
  96. package/src/components/entities/entity-settings-form/locales/it.ts +1 -0
  97. package/src/components/entities/entity-settings-form/locales/nl.ts +1 -0
  98. package/src/components/entities/entity-settings-form/locales/pl.ts +1 -0
  99. package/src/components/entities/entity-settings-form/locales/pt.ts +1 -0
  100. package/src/components/entities/entity-settings-form/locales/sl.ts +1 -0
  101. package/src/components/entities/settings/company-settings-form.tsx +173 -20
  102. package/src/components/estimates/create/create-estimate-form.tsx +64 -6
  103. package/src/components/estimates/create/locales/de.ts +16 -0
  104. package/src/components/estimates/create/locales/es.ts +16 -0
  105. package/src/components/estimates/create/locales/fr.ts +16 -0
  106. package/src/components/estimates/create/locales/hr.ts +16 -0
  107. package/src/components/estimates/create/locales/it.ts +16 -0
  108. package/src/components/estimates/create/locales/nl.ts +16 -0
  109. package/src/components/estimates/create/locales/pl.ts +16 -0
  110. package/src/components/estimates/create/locales/pt.ts +16 -0
  111. package/src/components/estimates/create/locales/sl.ts +17 -1
  112. package/src/components/estimates/list/list-table.tsx +11 -2
  113. package/src/components/estimates/list/locales/de.ts +1 -0
  114. package/src/components/estimates/list/locales/en.ts +1 -0
  115. package/src/components/estimates/list/locales/es.ts +1 -0
  116. package/src/components/estimates/list/locales/fr.ts +1 -0
  117. package/src/components/estimates/list/locales/hr.ts +1 -0
  118. package/src/components/estimates/list/locales/it.ts +1 -0
  119. package/src/components/estimates/list/locales/nl.ts +1 -0
  120. package/src/components/estimates/list/locales/pl.ts +1 -0
  121. package/src/components/estimates/list/locales/pt.ts +1 -0
  122. package/src/components/estimates/list/locales/sl.ts +1 -0
  123. package/src/components/export/document-export-form.tsx +46 -12
  124. package/src/components/invoices/create/create-invoice-form.tsx +58 -10
  125. package/src/components/invoices/create/locales/de.ts +15 -0
  126. package/src/components/invoices/create/locales/es.ts +15 -0
  127. package/src/components/invoices/create/locales/fr.ts +15 -0
  128. package/src/components/invoices/create/locales/hr.ts +15 -0
  129. package/src/components/invoices/create/locales/it.ts +15 -0
  130. package/src/components/invoices/create/locales/nl.ts +15 -0
  131. package/src/components/invoices/create/locales/pl.ts +15 -0
  132. package/src/components/invoices/create/locales/pt.ts +15 -0
  133. package/src/components/invoices/create/locales/sl.ts +16 -1
  134. package/src/components/invoices/view/fiscalization-status-card.tsx +10 -8
  135. package/src/components/table/search-input.tsx +17 -0
  136. package/src/generated/schemas/advanceinvoice.ts +4 -2
  137. package/src/generated/schemas/creditnote.ts +2 -1
  138. package/src/generated/schemas/deliverynote.ts +2 -1
  139. package/src/generated/schemas/estimate.ts +4 -2
  140. package/src/generated/schemas/invoice.ts +2 -1
  141. package/src/generated/schemas/renderadvanceinvoicepreview_body.ts +17 -23
  142. package/src/generated/schemas/rendercreditnotepreview_body.ts +17 -23
  143. package/src/generated/schemas/renderdeliverynotepreview_body.ts +17 -23
  144. package/src/generated/schemas/renderestimatepreview_body.ts +17 -23
  145. package/src/generated/schemas/renderinvoicepreview_body.ts +19 -23
  146. package/src/hooks/use-duplicate-document.ts +16 -9
  147. package/src/hooks/use-vies-check.ts +3 -0
package/cli/dist/index.js CHANGED
@@ -870,7 +870,7 @@ async function list(options = {}) {
870
870
 
871
871
  // cli/src/index.ts
872
872
  var program = new Command();
873
- program.name("spaceinvoices-ui").description("CLI for adding Space Invoices React UI components to your project").version("0.4.4");
873
+ program.name("spaceinvoices-ui").description("CLI for adding Space Invoices React UI components to your project").version("0.4.5");
874
874
  program.option("--local <path>", "Use local registry from specified path (for development)");
875
875
  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) => {
876
876
  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.4",
4
+ "version": "0.4.5",
5
5
  "private": false,
6
6
  "license": "MIT",
7
7
  "description": "Space Invoices UI components - copy-paste distribution with CLI support",
@@ -19,7 +19,11 @@ import { createTranslation } from "@/ui/lib/translation";
19
19
  import { cn } from "@/ui/lib/utils";
20
20
  import { useEntities } from "@/ui/providers/entities-context";
21
21
  import { useFormFooterRegistration } from "@/ui/providers/form-footer-context";
22
- import { DocumentDetailsSection, DocumentNoteField } from "../../documents/create/document-details-section";
22
+ import {
23
+ DocumentDetailsSection,
24
+ DocumentNoteField,
25
+ DocumentTaxClauseField,
26
+ } from "../../documents/create/document-details-section";
23
27
  import { DocumentItemsSection, type PriceModesMap } from "../../documents/create/document-items-section";
24
28
  import { DocumentRecipientSection } from "../../documents/create/document-recipient-section";
25
29
  import { MarkAsPaidSection } from "../../documents/create/mark-as-paid-section";
@@ -143,7 +147,7 @@ export default function CreateAdvanceInvoiceForm({
143
147
  const [selectedFinaDeviceId, setSelectedFinaDeviceId] = useState<string | undefined>();
144
148
 
145
149
  // UI-only state (not part of API schema)
146
- const [markAsPaid, setMarkAsPaid] = useState(false);
150
+ const [markAsPaid, setMarkAsPaid] = useState(true);
147
151
  const [paymentTypes, setPaymentTypes] = useState<string[]>(["bank_transfer"]);
148
152
  const [isDraftPending, setIsDraftPending] = useState(false);
149
153
 
@@ -288,13 +292,18 @@ export default function CreateAdvanceInvoiceForm({
288
292
  // Cast customer to form schema type (API type may have additional fields)
289
293
  customer: (initialValues?.customer as CreateAdvanceInvoiceFormValues["customer"]) ?? undefined,
290
294
  items: initialValues?.items?.length
291
- ? initialValues.items.map((item) => ({
295
+ ? initialValues.items.map((item: any) => ({
296
+ type: item.type,
292
297
  name: item.name || "",
293
298
  description: item.description || "",
294
- quantity: item.quantity ?? 1,
295
- // Use gross_price if set, otherwise use price
296
- price: item.gross_price ?? item.price,
297
- taxes: item.taxes || [],
299
+ ...(item.type !== "separator"
300
+ ? {
301
+ quantity: item.quantity ?? 1,
302
+ // Use gross_price if set, otherwise use price
303
+ price: item.gross_price ?? item.price,
304
+ taxes: item.taxes || [],
305
+ }
306
+ : {}),
298
307
  }))
299
308
  : [
300
309
  {
@@ -307,6 +316,7 @@ export default function CreateAdvanceInvoiceForm({
307
316
  ],
308
317
  currency_code: initialValues?.currency_code || activeEntity?.currency_code || "EUR",
309
318
  note: initialValues?.note ?? defaultNote,
319
+ tax_clause: "",
310
320
  },
311
321
  });
312
322
 
@@ -468,7 +478,13 @@ export default function CreateAdvanceInvoiceForm({
468
478
  // ============================================================================
469
479
  // VIES Check - determine if reverse charge applies
470
480
  // ============================================================================
471
- const { reverseChargeApplies, warning: viesWarning } = useViesCheck({
481
+ const {
482
+ reverseChargeApplies,
483
+ transactionType,
484
+ customerCountryCode: viesCustomerCountryCode,
485
+ isFetching: isViesFetching,
486
+ warning: viesWarning,
487
+ } = useViesCheck({
472
488
  issuerCountryCode: activeEntity?.country_code,
473
489
  isTaxSubject: activeEntity?.is_tax_subject ?? true,
474
490
  customerCountry: formValues.customer?.country,
@@ -477,6 +493,23 @@ export default function CreateAdvanceInvoiceForm({
477
493
  enabled: !!activeEntity,
478
494
  });
479
495
 
496
+ // FINA non-domestic guard: hide FINA selectors for non-domestic transactions
497
+ const isFinaNonDomestic = isFinaEnabled && viesCustomerCountryCode != null && viesCustomerCountryCode !== "HR";
498
+
499
+ // Auto-populate tax_clause from entity settings when transaction type changes
500
+ const effectiveTransactionType = transactionType ?? "domestic";
501
+ const prevTransactionTypeRef = useRef<string | undefined>(undefined);
502
+ useEffect(() => {
503
+ if (effectiveTransactionType === prevTransactionTypeRef.current) return;
504
+ prevTransactionTypeRef.current = effectiveTransactionType;
505
+
506
+ const taxClauseDefaults = (activeEntity?.settings as any)?.tax_clause_defaults;
507
+ if (!taxClauseDefaults) return;
508
+
509
+ const clause = taxClauseDefaults[effectiveTransactionType] ?? "";
510
+ form.setValue("tax_clause", clause);
511
+ }, [effectiveTransactionType, activeEntity, form]);
512
+
480
513
  // Customer form management
481
514
  const {
482
515
  originalCustomer,
@@ -547,7 +580,7 @@ export default function CreateAdvanceInvoiceForm({
547
580
 
548
581
  // Build FINA options (skip for drafts; FINA can't be skipped)
549
582
  const finaOptions =
550
- !isDraft && isFinaEnabled && selectedFinaPremiseId && selectedFinaDeviceId
583
+ !isDraft && isFinaEnabled && !isFinaNonDomestic && selectedFinaPremiseId && selectedFinaDeviceId
551
584
  ? { premise_id: selectedFinaPremiseId, device_id: selectedFinaDeviceId, payment_type: paymentTypes[0] }
552
585
  : undefined;
553
586
 
@@ -573,6 +606,7 @@ export default function CreateAdvanceInvoiceForm({
573
606
  isEslogAvailable,
574
607
  isFursEnabled,
575
608
  isFinaEnabled,
609
+ isFinaNonDomestic,
576
610
  markAsPaid,
577
611
  originalCustomer,
578
612
  paymentTypes,
@@ -602,7 +636,7 @@ export default function CreateAdvanceInvoiceForm({
602
636
  useFormFooterRegistration({
603
637
  formId: "create-advance-invoice-form",
604
638
  isPending,
605
- isDirty: form.formState.isDirty,
639
+ isDirty: form.formState.isDirty || !!initialValues,
606
640
  label: t("Save"),
607
641
  secondaryAction: {
608
642
  label: t("Save as Draft"),
@@ -761,7 +795,7 @@ export default function CreateAdvanceInvoiceForm({
761
795
  : undefined
762
796
  }
763
797
  finaInline={
764
- isFinaEnabled && hasFinaPremises
798
+ isFinaEnabled && hasFinaPremises && !isFinaNonDomestic
765
799
  ? {
766
800
  premises: activeFinaPremises.map((p: any) => ({ id: p.id, premise_id: p.premise_id })),
767
801
  devices: activeFinaDevices.map((d: any) => ({ id: d.id, device_id: d.device_id })),
@@ -781,6 +815,7 @@ export default function CreateAdvanceInvoiceForm({
781
815
  onPaymentTypesChange={setPaymentTypes}
782
816
  t={t}
783
817
  alwaysShowPaymentType={!!isFinaActive}
818
+ forced
784
819
  />
785
820
  </DocumentDetailsSection>
786
821
  </div>
@@ -814,6 +849,21 @@ export default function CreateAdvanceInvoiceForm({
814
849
  customer: formValues.customer as any,
815
850
  }}
816
851
  />
852
+
853
+ <DocumentTaxClauseField
854
+ control={form.control}
855
+ t={t}
856
+ entity={activeEntity}
857
+ document={{
858
+ number: formValues.number,
859
+ date: formValues.date,
860
+ currency_code: formValues.currency_code,
861
+ customer: formValues.customer as any,
862
+ }}
863
+ transactionType={transactionType}
864
+ isTransactionTypeFetching={isViesFetching}
865
+ isFinaNonDomestic={isFinaNonDomestic}
866
+ />
817
867
  </form>
818
868
  </Form>
819
869
  );
@@ -30,4 +30,19 @@ export default {
30
30
  Device: "Gerät",
31
31
  "FINA fiscalized invoices always use the current date":
32
32
  "FINA-fiskalisierte Dokumente verwenden immer das aktuelle Datum",
33
+ // Separator items
34
+ "Add separator": "Trennzeile hinzufügen",
35
+ "Section header": "Abschnittsüberschrift",
36
+ "Section title...": "Abschnittstitel...",
37
+ // Transaction type
38
+ "Transaction type": "Transaktionstyp",
39
+ Domestic: "Inland",
40
+ "EU B2B": "EU B2B",
41
+ "EU B2C": "EU B2C",
42
+ Export: "Export",
43
+ "Determining transaction type...": "Transaktionstyp wird ermittelt...",
44
+ "This invoice will not be fiscalized (non-domestic transaction)":
45
+ "Diese Rechnung wird nicht fiskalisiert (nicht-inländische Transaktion)",
46
+ "Tax Clause": "Steuerklausel",
47
+ "Add tax clause...": "Steuerklausel hinzufügen...",
33
48
  } as const;
@@ -30,4 +30,19 @@ export default {
30
30
  Device: "Dispositivo",
31
31
  "FINA fiscalized invoices always use the current date":
32
32
  "Los documentos fiscalizados con FINA siempre usan la fecha actual",
33
+ // Separator items
34
+ "Add separator": "Añadir separador",
35
+ "Section header": "Encabezado de sección",
36
+ "Section title...": "Título de sección...",
37
+ // Transaction type
38
+ "Transaction type": "Tipo de transacción",
39
+ Domestic: "Nacional",
40
+ "EU B2B": "EU B2B",
41
+ "EU B2C": "EU B2C",
42
+ Export: "Exportación",
43
+ "Determining transaction type...": "Determinando tipo de transacción...",
44
+ "This invoice will not be fiscalized (non-domestic transaction)":
45
+ "Esta factura no será fiscalizada (transacción no nacional)",
46
+ "Tax Clause": "Cláusula fiscal",
47
+ "Add tax clause...": "Agregar cláusula fiscal...",
33
48
  } as const;
@@ -29,4 +29,19 @@ export default {
29
29
  Device: "Appareil",
30
30
  "FINA fiscalized invoices always use the current date":
31
31
  "Les documents fiscalisés FINA utilisent toujours la date actuelle",
32
+ // Separator items
33
+ "Add separator": "Ajouter un séparateur",
34
+ "Section header": "En-tête de section",
35
+ "Section title...": "Titre de section...",
36
+ // Transaction type
37
+ "Transaction type": "Type de transaction",
38
+ Domestic: "Nationale",
39
+ "EU B2B": "EU B2B",
40
+ "EU B2C": "EU B2C",
41
+ Export: "Exportation",
42
+ "Determining transaction type...": "Détermination du type de transaction...",
43
+ "This invoice will not be fiscalized (non-domestic transaction)":
44
+ "Cette facture ne sera pas fiscalisée (transaction non nationale)",
45
+ "Tax Clause": "Clause fiscale",
46
+ "Add tax clause...": "Ajouter une clause fiscale...",
32
47
  } as const;
@@ -27,4 +27,19 @@ export default {
27
27
  Premise: "Prostor",
28
28
  Device: "Uredaj",
29
29
  "FINA fiscalized invoices always use the current date": "FINA fiskalizirani dokumenti uvijek koriste trenutni datum",
30
+ // Separator items
31
+ "Add separator": "Dodaj separator",
32
+ "Section header": "Naslov odjeljka",
33
+ "Section title...": "Naslov odjeljka...",
34
+ // Transaction type
35
+ "Transaction type": "Vrsta transakcije",
36
+ Domestic: "Domaća",
37
+ "EU B2B": "EU B2B",
38
+ "EU B2C": "EU B2C",
39
+ Export: "Izvoz",
40
+ "Determining transaction type...": "Određivanje vrste transakcije...",
41
+ "This invoice will not be fiscalized (non-domestic transaction)":
42
+ "Ovaj račun neće biti fiskaliziran (nedomaća transakcija)",
43
+ "Tax Clause": "Porezna klauzula",
44
+ "Add tax clause...": "Dodajte poreznu klauzulu...",
30
45
  } as const;
@@ -30,4 +30,19 @@ export default {
30
30
  Device: "Dispositivo",
31
31
  "FINA fiscalized invoices always use the current date":
32
32
  "I documenti fiscalizzati FINA utilizzano sempre la data corrente",
33
+ // Separator items
34
+ "Add separator": "Aggiungi separatore",
35
+ "Section header": "Intestazione sezione",
36
+ "Section title...": "Titolo sezione...",
37
+ // Transaction type
38
+ "Transaction type": "Tipo di transazione",
39
+ Domestic: "Nazionale",
40
+ "EU B2B": "EU B2B",
41
+ "EU B2C": "EU B2C",
42
+ Export: "Esportazione",
43
+ "Determining transaction type...": "Determinazione tipo di transazione...",
44
+ "This invoice will not be fiscalized (non-domestic transaction)":
45
+ "Questa fattura non sarà fiscalizzata (transazione non nazionale)",
46
+ "Tax Clause": "Clausola fiscale",
47
+ "Add tax clause...": "Aggiungi clausola fiscale...",
33
48
  } as const;
@@ -29,4 +29,19 @@ export default {
29
29
  Device: "Apparaat",
30
30
  "FINA fiscalized invoices always use the current date":
31
31
  "FINA-gefiscaliseerde documenten gebruiken altijd de huidige datum",
32
+ // Separator items
33
+ "Add separator": "Scheidingslijn toevoegen",
34
+ "Section header": "Sectiekop",
35
+ "Section title...": "Sectietitel...",
36
+ // Transaction type
37
+ "Transaction type": "Transactietype",
38
+ Domestic: "Binnenland",
39
+ "EU B2B": "EU B2B",
40
+ "EU B2C": "EU B2C",
41
+ Export: "Export",
42
+ "Determining transaction type...": "Transactietype bepalen...",
43
+ "This invoice will not be fiscalized (non-domestic transaction)":
44
+ "Deze factuur wordt niet gefiscaliseerd (niet-binnenlandse transactie)",
45
+ "Tax Clause": "Belastingclausule",
46
+ "Add tax clause...": "Belastingclausule toevoegen...",
32
47
  } as const;
@@ -28,4 +28,19 @@ export default {
28
28
  Premise: "Lokal",
29
29
  Device: "Urządzenie",
30
30
  "FINA fiscalized invoices always use the current date": "Dokumenty fiskalizowane FINA zawsze używają bieżącej daty",
31
+ // Separator items
32
+ "Add separator": "Dodaj separator",
33
+ "Section header": "Nagłówek sekcji",
34
+ "Section title...": "Tytuł sekcji...",
35
+ // Transaction type
36
+ "Transaction type": "Typ transakcji",
37
+ Domestic: "Krajowa",
38
+ "EU B2B": "EU B2B",
39
+ "EU B2C": "EU B2C",
40
+ Export: "Eksport",
41
+ "Determining transaction type...": "Określanie typu transakcji...",
42
+ "This invoice will not be fiscalized (non-domestic transaction)":
43
+ "Ta faktura nie będzie fiskalizowana (transakcja niekrajowa)",
44
+ "Tax Clause": "Klauzula podatkowa",
45
+ "Add tax clause...": "Dodaj klauzulę podatkową...",
31
46
  } as const;
@@ -29,4 +29,19 @@ export default {
29
29
  Premise: "Estabelecimento",
30
30
  Device: "Dispositivo",
31
31
  "FINA fiscalized invoices always use the current date": "Os documentos fiscalizados FINA usam sempre a data atual",
32
+ // Separator items
33
+ "Add separator": "Adicionar separador",
34
+ "Section header": "Cabeçalho da secção",
35
+ "Section title...": "Título da secção...",
36
+ // Transaction type
37
+ "Transaction type": "Tipo de transação",
38
+ Domestic: "Nacional",
39
+ "EU B2B": "EU B2B",
40
+ "EU B2C": "EU B2C",
41
+ Export: "Exportação",
42
+ "Determining transaction type...": "Determinando tipo de transação...",
43
+ "This invoice will not be fiscalized (non-domestic transaction)":
44
+ "Esta fatura não será fiscalizada (transação não nacional)",
45
+ "Tax Clause": "Cláusula fiscal",
46
+ "Add tax clause...": "Adicionar cláusula fiscal...",
32
47
  } as const;
@@ -25,4 +25,19 @@ export default {
25
25
  Premise: "Poslovni prostor",
26
26
  Device: "Naprava",
27
27
  "FINA fiscalized invoices always use the current date": "FINA fiskalizirani dokumenti vedno uporabijo trenutni datum",
28
+ // Separator items
29
+ "Add separator": "Dodaj ločilnik",
30
+ "Section header": "Naslov razdelka",
31
+ "Section title...": "Naslov razdelka...",
32
+ // Transaction type
33
+ "Transaction type": "Vrsta transakcije",
34
+ Domestic: "Domača",
35
+ "EU B2B": "EU B2B",
36
+ "EU B2C": "EU B2C",
37
+ Export: "Izvoz",
38
+ "Determining transaction type...": "Določanje vrste transakcije...",
39
+ "This invoice will not be fiscalized (non-domestic transaction)":
40
+ "Ta račun ne bo fiskaliziran (nedomača transakcija)",
41
+ "Tax Clause": "Davčna klavzula",
42
+ "Add tax clause...": "Dodajte davčno klavzulo...",
28
43
  } as const;
@@ -1,6 +1,6 @@
1
1
  import type { AdvanceInvoice } from "@spaceinvoices/js-sdk";
2
2
 
3
- import { Copy, Download, Eye, Link2Off, Loader2, MoreHorizontal, Plus } from "lucide-react";
3
+ import { Ban, Copy, Download, Eye, Link2Off, Loader2, MoreHorizontal, Plus } from "lucide-react";
4
4
  import { Button } from "@/ui/components/ui/button";
5
5
  import {
6
6
  DropdownMenu,
@@ -11,6 +11,7 @@ import {
11
11
  DropdownMenuSeparator,
12
12
  DropdownMenuTrigger,
13
13
  } from "@/ui/components/ui/dropdown-menu";
14
+ import { Tooltip, TooltipContent, TooltipTrigger } from "@/ui/components/ui/tooltip";
14
15
  import type { ComponentTranslationProps } from "@/ui/lib/translation";
15
16
  import { createTranslation } from "@/ui/lib/translation";
16
17
  import { useAdvanceInvoiceDownload } from "./use-advance-invoice-download";
@@ -25,6 +26,8 @@ type AdvanceInvoiceListRowActionsProps = {
25
26
  onDownloadError?: (error: string) => void;
26
27
  onUnshare?: (advanceInvoice: AdvanceInvoice) => Promise<void>;
27
28
  isUnsharing?: boolean;
29
+ onVoid?: (advanceInvoice: AdvanceInvoice) => void;
30
+ isVoiding?: boolean;
28
31
  } & ComponentTranslationProps;
29
32
 
30
33
  export default function AdvanceInvoiceListRowActions({
@@ -37,6 +40,8 @@ export default function AdvanceInvoiceListRowActions({
37
40
  onDownloadError,
38
41
  onUnshare,
39
42
  isUnsharing,
43
+ onVoid,
44
+ isVoiding,
40
45
  ...i18nProps
41
46
  }: AdvanceInvoiceListRowActionsProps) {
42
47
  const t = createTranslation(i18nProps);
@@ -110,6 +115,48 @@ export default function AdvanceInvoiceListRowActions({
110
115
  </DropdownMenuGroup>
111
116
  </>
112
117
  )}
118
+ {onVoid &&
119
+ !(advanceInvoice as any).voided_at &&
120
+ !(advanceInvoice as any).is_draft &&
121
+ (() => {
122
+ const isLinked = (advanceInvoice as any).document_relations?.some(
123
+ (rel: any) => rel.relation_type === "advance_applied" || rel.relation_type === "applied_to",
124
+ );
125
+ const voidDisabled = isVoiding || isLinked;
126
+ const voidItem = (
127
+ <DropdownMenuItem
128
+ className={
129
+ voidDisabled
130
+ ? "text-destructive opacity-50"
131
+ : "cursor-pointer text-destructive focus:text-destructive"
132
+ }
133
+ onClick={() => !voidDisabled && onVoid(advanceInvoice)}
134
+ disabled={voidDisabled}
135
+ >
136
+ {isVoiding ? <Loader2 className="h-4 w-4 animate-spin" /> : <Ban className="h-4 w-4" />}
137
+ {t("Void")}
138
+ </DropdownMenuItem>
139
+ );
140
+ return (
141
+ <>
142
+ <DropdownMenuSeparator />
143
+ <DropdownMenuGroup>
144
+ {isLinked ? (
145
+ <Tooltip>
146
+ <TooltipTrigger asChild>
147
+ <div>{voidItem}</div>
148
+ </TooltipTrigger>
149
+ <TooltipContent side="left">
150
+ {t("Cannot void an advance invoice linked to an invoice")}
151
+ </TooltipContent>
152
+ </Tooltip>
153
+ ) : (
154
+ voidItem
155
+ )}
156
+ </DropdownMenuGroup>
157
+ </>
158
+ );
159
+ })()}
113
160
  </DropdownMenuContent>
114
161
  </DropdownMenu>
115
162
  );
@@ -56,9 +56,12 @@ type AdvanceInvoiceListTableProps = {
56
56
  onDownloadSuccess?: (fileName: string) => void;
57
57
  onDownloadError?: (error: string) => void;
58
58
  onExportSelected?: (documentIds: string[]) => void;
59
+ onCopyToInvoice?: (documentIds: string[]) => void;
59
60
  onRetryFiscalization?: (documentIds: string[]) => void;
60
61
  fiscalizationFeatures?: ("furs" | "fina")[];
61
62
  onCreateNew?: () => void;
63
+ onVoid?: (advanceInvoice: AdvanceInvoice) => void;
64
+ isVoiding?: boolean;
62
65
  } & ListTableProps<AdvanceInvoice>;
63
66
 
64
67
  export default function AdvanceInvoiceListTable({
@@ -73,9 +76,12 @@ export default function AdvanceInvoiceListTable({
73
76
  onDownloadSuccess,
74
77
  onDownloadError,
75
78
  onExportSelected,
79
+ onCopyToInvoice,
76
80
  onRetryFiscalization,
77
81
  fiscalizationFeatures,
78
82
  onCreateNew,
83
+ onVoid,
84
+ isVoiding,
79
85
  ...i18nProps
80
86
  }: AdvanceInvoiceListTableProps) {
81
87
  const t = createTranslation({
@@ -97,6 +103,7 @@ export default function AdvanceInvoiceListTable({
97
103
  prev_cursor: params.prev_cursor,
98
104
  search: params.search,
99
105
  query: params.query,
106
+ include: "document_relations",
100
107
  });
101
108
  return response as unknown as TableQueryResponse<AdvanceInvoice>;
102
109
  }, entityId);
@@ -118,6 +125,12 @@ export default function AdvanceInvoiceListTable({
118
125
  }
119
126
  }, [selectedIds, onExportSelected]);
120
127
 
128
+ const handleCopyToInvoice = useCallback(() => {
129
+ if (selectedIds.size > 0 && onCopyToInvoice) {
130
+ onCopyToInvoice(Array.from(selectedIds));
131
+ }
132
+ }, [selectedIds, onCopyToInvoice]);
133
+
121
134
  const handleDeselectAll = useCallback(() => {
122
135
  setSelectedIds(new Set());
123
136
  }, []);
@@ -140,6 +153,7 @@ export default function AdvanceInvoiceListTable({
140
153
  <SelectionToolbar
141
154
  selectedCount={count}
142
155
  onExportPdfs={onExportSelected ? handleExportPdfs : undefined}
156
+ onCopyToInvoice={onCopyToInvoice ? handleCopyToInvoice : undefined}
143
157
  onRetryFiscalization={showRetry ? () => onRetryFiscalization(failedDocs.map((d) => d.id)) : undefined}
144
158
  retryFiscalizationDisabled={someFailed && !allFailed}
145
159
  retryFiscalizationTooltip={
@@ -152,8 +166,10 @@ export default function AdvanceInvoiceListTable({
152
166
  },
153
167
  [
154
168
  handleExportPdfs,
169
+ handleCopyToInvoice,
155
170
  handleDeselectAll,
156
171
  onExportSelected,
172
+ onCopyToInvoice,
157
173
  onRetryFiscalization,
158
174
  fiscalizationFeatures,
159
175
  selectedIds,
@@ -240,6 +256,8 @@ export default function AdvanceInvoiceListTable({
240
256
  onDownloadStart={onDownloadStart}
241
257
  onDownloadSuccess={onDownloadSuccess}
242
258
  onDownloadError={onDownloadError}
259
+ onVoid={onVoid}
260
+ isVoiding={isVoiding}
243
261
  t={t}
244
262
  locale={i18nProps.locale}
245
263
  />
@@ -255,6 +273,8 @@ export default function AdvanceInvoiceListTable({
255
273
  onDownloadStart,
256
274
  onDownloadSuccess,
257
275
  onDownloadError,
276
+ onVoid,
277
+ isVoiding,
258
278
  i18nProps.locale,
259
279
  fiscalizationFeatures,
260
280
  ],
@@ -274,7 +294,7 @@ export default function AdvanceInvoiceListTable({
274
294
  filterConfig={filterConfig}
275
295
  t={t}
276
296
  locale={i18nProps.locale}
277
- selectable={!!(onExportSelected || onRetryFiscalization)}
297
+ selectable={!!(onExportSelected || onCopyToInvoice || onRetryFiscalization)}
278
298
  selectedIds={selectedIds}
279
299
  onSelectionChange={setSelectedIds}
280
300
  selectionToolbar={selectionToolbar}
@@ -47,4 +47,8 @@ export default {
47
47
  "FINA fiscalization failed": "FINA fiscalization failed",
48
48
  "Retry Fiscalization": "Retry Fiscalization",
49
49
  "Some selected documents don't have failed fiscalization": "Some selected documents don't have failed fiscalization",
50
+ "Copy to Invoice": "In Rechnung kopieren",
51
+ Void: "Stornieren",
52
+ "Cannot void an advance invoice linked to an invoice":
53
+ "Stornierung einer mit einer Rechnung verknüpften Anzahlungsrechnung nicht möglich",
50
54
  } as const;
@@ -13,4 +13,7 @@ export default {
13
13
  "FINA fiscalization failed": "FINA fiscalization failed",
14
14
  "Retry Fiscalization": "Retry Fiscalization",
15
15
  "Some selected documents don't have failed fiscalization": "Some selected documents don't have failed fiscalization",
16
+ "Copy to Invoice": "Copy to Invoice",
17
+ Void: "Void",
18
+ "Cannot void an advance invoice linked to an invoice": "Cannot void an advance invoice linked to an invoice",
16
19
  } as const;
@@ -47,4 +47,8 @@ export default {
47
47
  "FINA fiscalization failed": "FINA fiscalization failed",
48
48
  "Retry Fiscalization": "Retry Fiscalization",
49
49
  "Some selected documents don't have failed fiscalization": "Some selected documents don't have failed fiscalization",
50
+ "Copy to Invoice": "Copiar a factura",
51
+ Void: "Anular",
52
+ "Cannot void an advance invoice linked to an invoice":
53
+ "No se puede anular una factura anticipada vinculada a una factura",
50
54
  } as const;
@@ -47,4 +47,8 @@ export default {
47
47
  "FINA fiscalization failed": "FINA fiscalization failed",
48
48
  "Retry Fiscalization": "Retry Fiscalization",
49
49
  "Some selected documents don't have failed fiscalization": "Some selected documents don't have failed fiscalization",
50
+ "Copy to Invoice": "Copier vers facture",
51
+ Void: "Annuler",
52
+ "Cannot void an advance invoice linked to an invoice":
53
+ "Impossible d'annuler une facture d'acompte liée à une facture",
50
54
  } as const;
@@ -47,4 +47,7 @@ export default {
47
47
  "FINA fiscalization failed": "FINA fiskalizacija nije uspjela",
48
48
  "Retry Fiscalization": "Ponovi fiskalizaciju",
49
49
  "Some selected documents don't have failed fiscalization": "Neki odabrani dokumenti nemaju neuspjelu fiskalizaciju",
50
+ "Copy to Invoice": "Kopiraj u račun",
51
+ Void: "Storniraj",
52
+ "Cannot void an advance invoice linked to an invoice": "Nije moguće poništiti avansni račun povezan s računom",
50
53
  } as const;
@@ -47,4 +47,8 @@ export default {
47
47
  "FINA fiscalization failed": "FINA fiscalization failed",
48
48
  "Retry Fiscalization": "Retry Fiscalization",
49
49
  "Some selected documents don't have failed fiscalization": "Some selected documents don't have failed fiscalization",
50
+ "Copy to Invoice": "Copia in fattura",
51
+ Void: "Annulla",
52
+ "Cannot void an advance invoice linked to an invoice":
53
+ "Impossibile annullare una fattura anticipata collegata a una fattura",
50
54
  } as const;
@@ -47,4 +47,8 @@ export default {
47
47
  "FINA fiscalization failed": "FINA fiscalization failed",
48
48
  "Retry Fiscalization": "Retry Fiscalization",
49
49
  "Some selected documents don't have failed fiscalization": "Some selected documents don't have failed fiscalization",
50
+ "Copy to Invoice": "Kopieer naar factuur",
51
+ Void: "Nietig verklaren",
52
+ "Cannot void an advance invoice linked to an invoice":
53
+ "Kan een voorschotfactuur gekoppeld aan een factuur niet ongeldig maken",
50
54
  } as const;
@@ -47,4 +47,7 @@ export default {
47
47
  "FINA fiscalization failed": "FINA fiscalization failed",
48
48
  "Retry Fiscalization": "Retry Fiscalization",
49
49
  "Some selected documents don't have failed fiscalization": "Some selected documents don't have failed fiscalization",
50
+ "Copy to Invoice": "Kopiuj do faktury",
51
+ Void: "Anuluj",
52
+ "Cannot void an advance invoice linked to an invoice": "Nie można anulować faktury zaliczkowej powiązanej z fakturą",
50
53
  } as const;
@@ -47,4 +47,8 @@ export default {
47
47
  "FINA fiscalization failed": "FINA fiscalization failed",
48
48
  "Retry Fiscalization": "Retry Fiscalization",
49
49
  "Some selected documents don't have failed fiscalization": "Some selected documents don't have failed fiscalization",
50
+ "Copy to Invoice": "Copiar para fatura",
51
+ Void: "Anular",
52
+ "Cannot void an advance invoice linked to an invoice":
53
+ "Não é possível anular uma fatura antecipada vinculada a uma fatura",
50
54
  } as const;
@@ -47,4 +47,7 @@ export default {
47
47
  "FINA fiscalization failed": "FINA fiskalizacija ni uspela",
48
48
  "Retry Fiscalization": "Ponovi fiskalizacijo",
49
49
  "Some selected documents don't have failed fiscalization": "Nekateri izbrani dokumenti nimajo neuspele fiskalizacije",
50
+ "Copy to Invoice": "Kopiraj v račun",
51
+ Void: "Storniraj",
52
+ "Cannot void an advance invoice linked to an invoice": "Ni mogoče razveljaviti predračuna, ki je povezan z računom",
50
53
  } as const;