@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.
- package/cli/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/components/advance-invoices/create/create-advance-invoice-form.tsx +61 -11
- package/src/components/advance-invoices/create/locales/de.ts +15 -0
- package/src/components/advance-invoices/create/locales/es.ts +15 -0
- package/src/components/advance-invoices/create/locales/fr.ts +15 -0
- package/src/components/advance-invoices/create/locales/hr.ts +15 -0
- package/src/components/advance-invoices/create/locales/it.ts +15 -0
- package/src/components/advance-invoices/create/locales/nl.ts +15 -0
- package/src/components/advance-invoices/create/locales/pl.ts +15 -0
- package/src/components/advance-invoices/create/locales/pt.ts +15 -0
- package/src/components/advance-invoices/create/locales/sl.ts +15 -0
- package/src/components/advance-invoices/list/list-row-actions.tsx +48 -1
- package/src/components/advance-invoices/list/list-table.tsx +21 -1
- package/src/components/advance-invoices/list/locales/de.ts +4 -0
- package/src/components/advance-invoices/list/locales/en.ts +3 -0
- package/src/components/advance-invoices/list/locales/es.ts +4 -0
- package/src/components/advance-invoices/list/locales/fr.ts +4 -0
- package/src/components/advance-invoices/list/locales/hr.ts +3 -0
- package/src/components/advance-invoices/list/locales/it.ts +4 -0
- package/src/components/advance-invoices/list/locales/nl.ts +4 -0
- package/src/components/advance-invoices/list/locales/pl.ts +3 -0
- package/src/components/advance-invoices/list/locales/pt.ts +4 -0
- package/src/components/advance-invoices/list/locales/sl.ts +3 -0
- package/src/components/credit-notes/create/create-credit-note-form.tsx +71 -8
- package/src/components/credit-notes/create/locales/de.ts +16 -0
- package/src/components/credit-notes/create/locales/es.ts +16 -0
- package/src/components/credit-notes/create/locales/fr.ts +16 -0
- package/src/components/credit-notes/create/locales/hr.ts +16 -0
- package/src/components/credit-notes/create/locales/it.ts +16 -0
- package/src/components/credit-notes/create/locales/nl.ts +16 -0
- package/src/components/credit-notes/create/locales/pl.ts +16 -0
- package/src/components/credit-notes/create/locales/pt.ts +16 -0
- package/src/components/credit-notes/create/locales/sl.ts +17 -1
- package/src/components/credit-notes/list/list-row-actions.tsx +44 -1
- package/src/components/credit-notes/list/list-table.tsx +16 -2
- package/src/components/credit-notes/list/locales/de.ts +2 -0
- package/src/components/credit-notes/list/locales/en.ts +2 -0
- package/src/components/credit-notes/list/locales/es.ts +2 -0
- package/src/components/credit-notes/list/locales/fr.ts +2 -0
- package/src/components/credit-notes/list/locales/hr.ts +2 -0
- package/src/components/credit-notes/list/locales/it.ts +2 -0
- package/src/components/credit-notes/list/locales/nl.ts +2 -0
- package/src/components/credit-notes/list/locales/pl.ts +2 -0
- package/src/components/credit-notes/list/locales/pt.ts +2 -0
- package/src/components/credit-notes/list/locales/sl.ts +2 -0
- package/src/components/dashboard/collection-rate-card/use-collection-rate.ts +48 -9
- package/src/components/dashboard/revenue-trend-chart/use-revenue-trend.ts +77 -48
- package/src/components/dashboard/shared/use-revenue-data.ts +77 -9
- package/src/components/delivery-notes/create/create-delivery-note-form.tsx +67 -7
- package/src/components/delivery-notes/create/locales/de.ts +16 -0
- package/src/components/delivery-notes/create/locales/es.ts +16 -0
- package/src/components/delivery-notes/create/locales/fr.ts +16 -0
- package/src/components/delivery-notes/create/locales/hr.ts +16 -0
- package/src/components/delivery-notes/create/locales/it.ts +16 -0
- package/src/components/delivery-notes/create/locales/nl.ts +16 -0
- package/src/components/delivery-notes/create/locales/pl.ts +16 -0
- package/src/components/delivery-notes/create/locales/pt.ts +16 -0
- package/src/components/delivery-notes/create/locales/sl.ts +17 -1
- package/src/components/delivery-notes/list/list-table.tsx +17 -8
- package/src/components/delivery-notes/list/locales/de.ts +32 -1
- package/src/components/delivery-notes/list/locales/en.ts +31 -0
- package/src/components/delivery-notes/list/locales/es.ts +32 -1
- package/src/components/delivery-notes/list/locales/fr.ts +32 -1
- package/src/components/delivery-notes/list/locales/hr.ts +32 -1
- package/src/components/delivery-notes/list/locales/it.ts +32 -1
- package/src/components/delivery-notes/list/locales/nl.ts +32 -1
- package/src/components/delivery-notes/list/locales/pl.ts +32 -1
- package/src/components/delivery-notes/list/locales/pt.ts +32 -1
- package/src/components/delivery-notes/list/locales/sl.ts +32 -1
- package/src/components/documents/create/document-add-item-form.tsx +70 -0
- package/src/components/documents/create/document-details-section.tsx +122 -2
- package/src/components/documents/create/document-items-section.tsx +21 -4
- package/src/components/documents/create/live-preview.tsx +24 -4
- package/src/components/documents/create/mark-as-paid-section.tsx +29 -20
- package/src/components/documents/create/prepare-document-submission.ts +19 -7
- package/src/components/documents/shared/document-preview-display.tsx +3 -4
- package/src/components/documents/view/document-actions-bar.tsx +7 -27
- package/src/components/documents/view/document-details-card.tsx +26 -9
- package/src/components/documents/view/locales/de.ts +2 -0
- package/src/components/documents/view/locales/es.ts +2 -0
- package/src/components/documents/view/locales/fr.ts +2 -0
- package/src/components/documents/view/locales/hr.ts +2 -0
- package/src/components/documents/view/locales/it.ts +2 -0
- package/src/components/documents/view/locales/nl.ts +2 -0
- package/src/components/documents/view/locales/pl.ts +2 -0
- package/src/components/documents/view/locales/pt.ts +2 -0
- package/src/components/documents/view/locales/sl.ts +3 -1
- package/src/components/documents/view/use-document-download.ts +6 -3
- package/src/components/entities/create-entity-form.tsx +2 -1
- package/src/components/entities/entity-settings-form/input-with-preview.tsx +30 -2
- package/src/components/entities/entity-settings-form/locales/de.ts +1 -0
- package/src/components/entities/entity-settings-form/locales/es.ts +1 -0
- package/src/components/entities/entity-settings-form/locales/fr.ts +1 -0
- package/src/components/entities/entity-settings-form/locales/hr.ts +1 -0
- package/src/components/entities/entity-settings-form/locales/it.ts +1 -0
- package/src/components/entities/entity-settings-form/locales/nl.ts +1 -0
- package/src/components/entities/entity-settings-form/locales/pl.ts +1 -0
- package/src/components/entities/entity-settings-form/locales/pt.ts +1 -0
- package/src/components/entities/entity-settings-form/locales/sl.ts +1 -0
- package/src/components/entities/settings/company-settings-form.tsx +173 -20
- package/src/components/estimates/create/create-estimate-form.tsx +64 -6
- package/src/components/estimates/create/locales/de.ts +16 -0
- package/src/components/estimates/create/locales/es.ts +16 -0
- package/src/components/estimates/create/locales/fr.ts +16 -0
- package/src/components/estimates/create/locales/hr.ts +16 -0
- package/src/components/estimates/create/locales/it.ts +16 -0
- package/src/components/estimates/create/locales/nl.ts +16 -0
- package/src/components/estimates/create/locales/pl.ts +16 -0
- package/src/components/estimates/create/locales/pt.ts +16 -0
- package/src/components/estimates/create/locales/sl.ts +17 -1
- package/src/components/estimates/list/list-table.tsx +11 -2
- package/src/components/estimates/list/locales/de.ts +1 -0
- package/src/components/estimates/list/locales/en.ts +1 -0
- package/src/components/estimates/list/locales/es.ts +1 -0
- package/src/components/estimates/list/locales/fr.ts +1 -0
- package/src/components/estimates/list/locales/hr.ts +1 -0
- package/src/components/estimates/list/locales/it.ts +1 -0
- package/src/components/estimates/list/locales/nl.ts +1 -0
- package/src/components/estimates/list/locales/pl.ts +1 -0
- package/src/components/estimates/list/locales/pt.ts +1 -0
- package/src/components/estimates/list/locales/sl.ts +1 -0
- package/src/components/export/document-export-form.tsx +46 -12
- package/src/components/invoices/create/create-invoice-form.tsx +58 -10
- package/src/components/invoices/create/locales/de.ts +15 -0
- package/src/components/invoices/create/locales/es.ts +15 -0
- package/src/components/invoices/create/locales/fr.ts +15 -0
- package/src/components/invoices/create/locales/hr.ts +15 -0
- package/src/components/invoices/create/locales/it.ts +15 -0
- package/src/components/invoices/create/locales/nl.ts +15 -0
- package/src/components/invoices/create/locales/pl.ts +15 -0
- package/src/components/invoices/create/locales/pt.ts +15 -0
- package/src/components/invoices/create/locales/sl.ts +16 -1
- package/src/components/invoices/view/fiscalization-status-card.tsx +10 -8
- package/src/components/table/search-input.tsx +17 -0
- package/src/generated/schemas/advanceinvoice.ts +4 -2
- package/src/generated/schemas/creditnote.ts +2 -1
- package/src/generated/schemas/deliverynote.ts +2 -1
- package/src/generated/schemas/estimate.ts +4 -2
- package/src/generated/schemas/invoice.ts +2 -1
- package/src/generated/schemas/renderadvanceinvoicepreview_body.ts +17 -23
- package/src/generated/schemas/rendercreditnotepreview_body.ts +17 -23
- package/src/generated/schemas/renderdeliverynotepreview_body.ts +17 -23
- package/src/generated/schemas/renderestimatepreview_body.ts +17 -23
- package/src/generated/schemas/renderinvoicepreview_body.ts +19 -23
- package/src/hooks/use-duplicate-document.ts +16 -9
- package/src/hooks/use-vies-check.ts +3 -0
|
@@ -54,4 +54,20 @@ export default {
|
|
|
54
54
|
"Net price": "Prezzo netto",
|
|
55
55
|
"Gross price (tax included)": "Prezzo lordo (imposte incluse)",
|
|
56
56
|
"Net price (before tax)": "Prezzo netto (prima delle imposte)",
|
|
57
|
+
// Separator items
|
|
58
|
+
"Add separator": "Aggiungi separatore",
|
|
59
|
+
"Section header": "Intestazione sezione",
|
|
60
|
+
"Section title...": "Titolo sezione...",
|
|
61
|
+
// Transaction type
|
|
62
|
+
"Transaction type": "Tipo di transazione",
|
|
63
|
+
Domestic: "Nazionale",
|
|
64
|
+
"EU B2B": "EU B2B",
|
|
65
|
+
"EU B2C": "EU B2C",
|
|
66
|
+
Export: "Esportazione",
|
|
67
|
+
"Determining transaction type...": "Determinazione tipo di transazione...",
|
|
68
|
+
"This invoice will not be fiscalized (non-domestic transaction)":
|
|
69
|
+
"Questa fattura non sarà fiscalizzata (transazione non nazionale)",
|
|
70
|
+
"Tax Clause": "Clausola fiscale",
|
|
71
|
+
"Add tax clause...": "Aggiungi clausola fiscale...",
|
|
72
|
+
"Reverse charge - tax exempt EU B2B sale": "Inversione contabile - vendita B2B UE esente da imposta",
|
|
57
73
|
} as const;
|
|
@@ -55,4 +55,20 @@ export default {
|
|
|
55
55
|
"Net price": "Nettoprijs",
|
|
56
56
|
"Gross price (tax included)": "Brutoprijs (inclusief belasting)",
|
|
57
57
|
"Net price (before tax)": "Nettoprijs (exclusief belasting)",
|
|
58
|
+
// Separator items
|
|
59
|
+
"Add separator": "Scheidingslijn toevoegen",
|
|
60
|
+
"Section header": "Sectiekop",
|
|
61
|
+
"Section title...": "Sectietitel...",
|
|
62
|
+
// Transaction type
|
|
63
|
+
"Transaction type": "Transactietype",
|
|
64
|
+
Domestic: "Binnenland",
|
|
65
|
+
"EU B2B": "EU B2B",
|
|
66
|
+
"EU B2C": "EU B2C",
|
|
67
|
+
Export: "Export",
|
|
68
|
+
"Determining transaction type...": "Transactietype bepalen...",
|
|
69
|
+
"This invoice will not be fiscalized (non-domestic transaction)":
|
|
70
|
+
"Deze factuur wordt niet gefiscaliseerd (niet-binnenlandse transactie)",
|
|
71
|
+
"Tax Clause": "Belastingclausule",
|
|
72
|
+
"Add tax clause...": "Belastingclausule toevoegen...",
|
|
73
|
+
"Reverse charge - tax exempt EU B2B sale": "Verlegging - belastingvrijgestelde EU B2B verkoop",
|
|
58
74
|
} as const;
|
|
@@ -54,4 +54,20 @@ export default {
|
|
|
54
54
|
"Net price": "Cena netto",
|
|
55
55
|
"Gross price (tax included)": "Cena brutto (z podatkiem)",
|
|
56
56
|
"Net price (before tax)": "Cena netto (przed podatkiem)",
|
|
57
|
+
// Separator items
|
|
58
|
+
"Add separator": "Dodaj separator",
|
|
59
|
+
"Section header": "Nagłówek sekcji",
|
|
60
|
+
"Section title...": "Tytuł sekcji...",
|
|
61
|
+
// Transaction type
|
|
62
|
+
"Transaction type": "Typ transakcji",
|
|
63
|
+
Domestic: "Krajowa",
|
|
64
|
+
"EU B2B": "EU B2B",
|
|
65
|
+
"EU B2C": "EU B2C",
|
|
66
|
+
Export: "Eksport",
|
|
67
|
+
"Determining transaction type...": "Określanie typu transakcji...",
|
|
68
|
+
"This invoice will not be fiscalized (non-domestic transaction)":
|
|
69
|
+
"Ta faktura nie będzie fiskalizowana (transakcja niekrajowa)",
|
|
70
|
+
"Tax Clause": "Klauzula podatkowa",
|
|
71
|
+
"Add tax clause...": "Dodaj klauzulę podatkową...",
|
|
72
|
+
"Reverse charge - tax exempt EU B2B sale": "Odwrotne obciążenie - zwolniona z podatku sprzedaż EU B2B",
|
|
57
73
|
} as const;
|
|
@@ -55,4 +55,20 @@ export default {
|
|
|
55
55
|
"Net price": "Preço líquido",
|
|
56
56
|
"Gross price (tax included)": "Preço bruto (impostos incluídos)",
|
|
57
57
|
"Net price (before tax)": "Preço líquido (antes de impostos)",
|
|
58
|
+
// Separator items
|
|
59
|
+
"Add separator": "Adicionar separador",
|
|
60
|
+
"Section header": "Cabeçalho da secção",
|
|
61
|
+
"Section title...": "Título da secção...",
|
|
62
|
+
// Transaction type
|
|
63
|
+
"Transaction type": "Tipo de transação",
|
|
64
|
+
Domestic: "Nacional",
|
|
65
|
+
"EU B2B": "EU B2B",
|
|
66
|
+
"EU B2C": "EU B2C",
|
|
67
|
+
Export: "Exportação",
|
|
68
|
+
"Determining transaction type...": "Determinando tipo de transação...",
|
|
69
|
+
"This invoice will not be fiscalized (non-domestic transaction)":
|
|
70
|
+
"Esta fatura não será fiscalizada (transação não nacional)",
|
|
71
|
+
"Tax Clause": "Cláusula fiscal",
|
|
72
|
+
"Add tax clause...": "Adicionar cláusula fiscal...",
|
|
73
|
+
"Reverse charge - tax exempt EU B2B sale": "Autoliquidação - venda B2B UE isenta de imposto",
|
|
58
74
|
} as const;
|
|
@@ -23,7 +23,7 @@ export default {
|
|
|
23
23
|
"Tax Number": "Davčna številka",
|
|
24
24
|
Items: "Postavke",
|
|
25
25
|
"Add item": "Dodaj postavko",
|
|
26
|
-
Tax: "
|
|
26
|
+
Tax: "DDV",
|
|
27
27
|
"Tax rate": "Davčna stopnja",
|
|
28
28
|
"Add tax": "Dodaj davek",
|
|
29
29
|
"Select tax...": "Izberi davek...",
|
|
@@ -60,4 +60,20 @@ export default {
|
|
|
60
60
|
"Net price": "Neto cena",
|
|
61
61
|
"Gross price (tax included)": "Bruto cena (z davkom)",
|
|
62
62
|
"Net price (before tax)": "Neto cena (brez davka)",
|
|
63
|
+
// Separator items
|
|
64
|
+
"Add separator": "Dodaj ločilnik",
|
|
65
|
+
"Section header": "Naslov razdelka",
|
|
66
|
+
"Section title...": "Naslov razdelka...",
|
|
67
|
+
// Transaction type
|
|
68
|
+
"Transaction type": "Vrsta transakcije",
|
|
69
|
+
Domestic: "Domača",
|
|
70
|
+
"EU B2B": "EU B2B",
|
|
71
|
+
"EU B2C": "EU B2C",
|
|
72
|
+
Export: "Izvoz",
|
|
73
|
+
"Determining transaction type...": "Določanje vrste transakcije...",
|
|
74
|
+
"This invoice will not be fiscalized (non-domestic transaction)":
|
|
75
|
+
"Ta račun ne bo fiskaliziran (nedomača transakcija)",
|
|
76
|
+
"Tax Clause": "Davčna klavzula",
|
|
77
|
+
"Add tax clause...": "Dodajte davčno klavzulo...",
|
|
78
|
+
"Reverse charge - tax exempt EU B2B sale": "Obrnjena davčna obveznost - davka oproščena EU B2B prodaja",
|
|
63
79
|
} as const;
|
|
@@ -52,6 +52,7 @@ type EstimateListTableProps = {
|
|
|
52
52
|
onDownloadSuccess?: (fileName: string) => void;
|
|
53
53
|
onDownloadError?: (error: string) => void;
|
|
54
54
|
onExportSelected?: (documentIds: string[]) => void;
|
|
55
|
+
onCopyToInvoice?: (documentIds: string[]) => void;
|
|
55
56
|
onCreateNew?: () => void;
|
|
56
57
|
} & ListTableProps<Estimate>;
|
|
57
58
|
|
|
@@ -66,6 +67,7 @@ export default function EstimateListTable({
|
|
|
66
67
|
onDownloadSuccess,
|
|
67
68
|
onDownloadError,
|
|
68
69
|
onExportSelected,
|
|
70
|
+
onCopyToInvoice,
|
|
69
71
|
onCreateNew,
|
|
70
72
|
...i18nProps
|
|
71
73
|
}: EstimateListTableProps) {
|
|
@@ -110,6 +112,12 @@ export default function EstimateListTable({
|
|
|
110
112
|
}
|
|
111
113
|
}, [selectedIds, onExportSelected]);
|
|
112
114
|
|
|
115
|
+
const handleCopyToInvoice = useCallback(() => {
|
|
116
|
+
if (selectedIds.size > 0 && onCopyToInvoice) {
|
|
117
|
+
onCopyToInvoice(Array.from(selectedIds));
|
|
118
|
+
}
|
|
119
|
+
}, [selectedIds, onCopyToInvoice]);
|
|
120
|
+
|
|
113
121
|
const handleDeselectAll = useCallback(() => {
|
|
114
122
|
setSelectedIds(new Set());
|
|
115
123
|
}, []);
|
|
@@ -119,11 +127,12 @@ export default function EstimateListTable({
|
|
|
119
127
|
<SelectionToolbar
|
|
120
128
|
selectedCount={count}
|
|
121
129
|
onExportPdfs={onExportSelected ? handleExportPdfs : undefined}
|
|
130
|
+
onCopyToInvoice={onCopyToInvoice ? handleCopyToInvoice : undefined}
|
|
122
131
|
onDeselectAll={handleDeselectAll}
|
|
123
132
|
t={t}
|
|
124
133
|
/>
|
|
125
134
|
),
|
|
126
|
-
[handleExportPdfs, handleDeselectAll, onExportSelected, t],
|
|
135
|
+
[handleExportPdfs, handleCopyToInvoice, handleDeselectAll, onExportSelected, onCopyToInvoice, t],
|
|
127
136
|
);
|
|
128
137
|
|
|
129
138
|
const columns: Column<Estimate>[] = useMemo(
|
|
@@ -209,7 +218,7 @@ export default function EstimateListTable({
|
|
|
209
218
|
filterConfig={filterConfig}
|
|
210
219
|
t={t}
|
|
211
220
|
locale={i18nProps.locale}
|
|
212
|
-
selectable={!!onExportSelected}
|
|
221
|
+
selectable={!!(onExportSelected || onCopyToInvoice)}
|
|
213
222
|
selectedIds={selectedIds}
|
|
214
223
|
onSelectionChange={setSelectedIds}
|
|
215
224
|
selectionToolbar={selectionToolbar}
|
|
@@ -3,13 +3,16 @@ type TFunction = (key: string, options?: Record<string, unknown>) => string;
|
|
|
3
3
|
import { Calendar, Download, Loader2 } from "lucide-react";
|
|
4
4
|
import { useRef, useState } from "react";
|
|
5
5
|
import { Button } from "../ui/button";
|
|
6
|
+
import { Checkbox } from "../ui/checkbox";
|
|
6
7
|
import { Input } from "../ui/input";
|
|
7
8
|
import { Label } from "../ui/label";
|
|
8
9
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/select";
|
|
9
10
|
|
|
10
|
-
export type DocumentType = "invoice" | "estimate" | "credit_note";
|
|
11
|
+
export type DocumentType = "invoice" | "estimate" | "credit_note" | "advance_invoice" | "delivery_note";
|
|
11
12
|
export type ExportFormat = "xlsx" | "csv" | "pdf_zip";
|
|
12
13
|
|
|
14
|
+
const ALL_DOCUMENT_TYPES: DocumentType[] = ["invoice", "estimate", "credit_note", "advance_invoice", "delivery_note"];
|
|
15
|
+
|
|
13
16
|
// Maximum date range for export (1 year in milliseconds)
|
|
14
17
|
const MAX_DATE_RANGE_MS = 365 * 24 * 60 * 60 * 1000;
|
|
15
18
|
|
|
@@ -65,6 +68,7 @@ export function DocumentExportForm({
|
|
|
65
68
|
}: DocumentExportFormProps) {
|
|
66
69
|
const defaultDates = getPreviousMonthRange();
|
|
67
70
|
const [documentType, setDocumentType] = useState<DocumentType>("invoice");
|
|
71
|
+
const [selectedTypes, setSelectedTypes] = useState<DocumentType[]>(["invoice"]);
|
|
68
72
|
const [exportFormat, setExportFormat] = useState<ExportFormat>("xlsx");
|
|
69
73
|
const [dateFrom, setDateFrom] = useState(defaultDates.from);
|
|
70
74
|
const [dateTo, setDateTo] = useState(defaultDates.to);
|
|
@@ -73,6 +77,17 @@ export function DocumentExportForm({
|
|
|
73
77
|
|
|
74
78
|
const toastIdRef = useRef<string | number | null>(null);
|
|
75
79
|
|
|
80
|
+
const toggleType = (type: DocumentType) => {
|
|
81
|
+
setSelectedTypes((prev) => {
|
|
82
|
+
if (prev.includes(type)) {
|
|
83
|
+
// Don't allow deselecting the last type
|
|
84
|
+
if (prev.length === 1) return prev;
|
|
85
|
+
return prev.filter((t) => t !== type);
|
|
86
|
+
}
|
|
87
|
+
return [...prev, type];
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
|
|
76
91
|
const validateDateRange = (from: string, to: string) => {
|
|
77
92
|
const isValid = isDateRangeValid(from, to);
|
|
78
93
|
setDateRangeError(!isValid);
|
|
@@ -100,7 +115,7 @@ export function DocumentExportForm({
|
|
|
100
115
|
"Content-Type": "application/json",
|
|
101
116
|
},
|
|
102
117
|
body: JSON.stringify({
|
|
103
|
-
|
|
118
|
+
types: selectedTypes,
|
|
104
119
|
date_from: dateFrom || undefined,
|
|
105
120
|
date_to: dateTo || undefined,
|
|
106
121
|
}),
|
|
@@ -187,16 +202,35 @@ export function DocumentExportForm({
|
|
|
187
202
|
<div className="grid grid-cols-2 gap-4">
|
|
188
203
|
<div className="space-y-2">
|
|
189
204
|
<Label htmlFor="document-type">{t("export-page.document-type")}</Label>
|
|
190
|
-
|
|
191
|
-
<
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
205
|
+
{exportFormat === "pdf_zip" ? (
|
|
206
|
+
<fieldset className="space-y-2 rounded-md border p-3">
|
|
207
|
+
{ALL_DOCUMENT_TYPES.map((type) => (
|
|
208
|
+
<div key={type} className="flex items-center gap-2">
|
|
209
|
+
<Checkbox
|
|
210
|
+
id={`type-${type}`}
|
|
211
|
+
checked={selectedTypes.includes(type)}
|
|
212
|
+
onCheckedChange={() => toggleType(type)}
|
|
213
|
+
/>
|
|
214
|
+
<Label htmlFor={`type-${type}`} className="cursor-pointer font-normal">
|
|
215
|
+
{t(`export-page.types.${type}`)}
|
|
216
|
+
</Label>
|
|
217
|
+
</div>
|
|
218
|
+
))}
|
|
219
|
+
</fieldset>
|
|
220
|
+
) : (
|
|
221
|
+
<Select value={documentType} onValueChange={(v) => setDocumentType(v as DocumentType)}>
|
|
222
|
+
<SelectTrigger id="document-type">
|
|
223
|
+
<SelectValue />
|
|
224
|
+
</SelectTrigger>
|
|
225
|
+
<SelectContent>
|
|
226
|
+
<SelectItem value="invoice">{t("export-page.types.invoice")}</SelectItem>
|
|
227
|
+
<SelectItem value="estimate">{t("export-page.types.estimate")}</SelectItem>
|
|
228
|
+
<SelectItem value="credit_note">{t("export-page.types.credit_note")}</SelectItem>
|
|
229
|
+
<SelectItem value="advance_invoice">{t("export-page.types.advance_invoice")}</SelectItem>
|
|
230
|
+
<SelectItem value="delivery_note">{t("export-page.types.delivery_note")}</SelectItem>
|
|
231
|
+
</SelectContent>
|
|
232
|
+
</Select>
|
|
233
|
+
)}
|
|
200
234
|
</div>
|
|
201
235
|
|
|
202
236
|
<div className="space-y-2">
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
DocumentDetailsSection,
|
|
25
25
|
DocumentNoteField,
|
|
26
26
|
DocumentPaymentTermsField,
|
|
27
|
+
DocumentTaxClauseField,
|
|
27
28
|
} from "../../documents/create/document-details-section";
|
|
28
29
|
import { DocumentItemsSection, type PriceModesMap } from "../../documents/create/document-items-section";
|
|
29
30
|
import { DocumentRecipientSection } from "../../documents/create/document-recipient-section";
|
|
@@ -321,13 +322,18 @@ export default function CreateInvoiceForm({
|
|
|
321
322
|
// Cast customer to form schema type (API type may have additional fields)
|
|
322
323
|
customer: (initialValues?.customer as CreateInvoiceFormValues["customer"]) ?? undefined,
|
|
323
324
|
items: initialValues?.items?.length
|
|
324
|
-
? initialValues.items.map((item) => ({
|
|
325
|
+
? initialValues.items.map((item: any) => ({
|
|
326
|
+
type: item.type,
|
|
325
327
|
name: item.name || "",
|
|
326
328
|
description: item.description || "",
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
329
|
+
...(item.type !== "separator"
|
|
330
|
+
? {
|
|
331
|
+
quantity: item.quantity ?? 1,
|
|
332
|
+
// Use gross_price if set, otherwise use price
|
|
333
|
+
price: item.gross_price ?? item.price,
|
|
334
|
+
taxes: item.taxes || [],
|
|
335
|
+
}
|
|
336
|
+
: {}),
|
|
331
337
|
}))
|
|
332
338
|
: [
|
|
333
339
|
{
|
|
@@ -340,6 +346,7 @@ export default function CreateInvoiceForm({
|
|
|
340
346
|
],
|
|
341
347
|
currency_code: initialValues?.currency_code || activeEntity?.currency_code || "EUR",
|
|
342
348
|
note: initialValues?.note ?? defaultInvoiceNote,
|
|
349
|
+
tax_clause: (initialValues as any)?.tax_clause ?? "",
|
|
343
350
|
payment_terms: initialValues?.payment_terms ?? defaultPaymentTerms,
|
|
344
351
|
date_due:
|
|
345
352
|
initialValues?.date_due ||
|
|
@@ -529,7 +536,13 @@ export default function CreateInvoiceForm({
|
|
|
529
536
|
// ============================================================================
|
|
530
537
|
// VIES Check - determine if reverse charge applies
|
|
531
538
|
// ============================================================================
|
|
532
|
-
const {
|
|
539
|
+
const {
|
|
540
|
+
reverseChargeApplies,
|
|
541
|
+
transactionType,
|
|
542
|
+
customerCountryCode: viesCustomerCountryCode,
|
|
543
|
+
isFetching: isViesFetching,
|
|
544
|
+
warning: viesWarning,
|
|
545
|
+
} = useViesCheck({
|
|
533
546
|
issuerCountryCode: activeEntity?.country_code,
|
|
534
547
|
isTaxSubject: activeEntity?.is_tax_subject ?? true,
|
|
535
548
|
customerCountry,
|
|
@@ -538,6 +551,23 @@ export default function CreateInvoiceForm({
|
|
|
538
551
|
enabled: !!activeEntity,
|
|
539
552
|
});
|
|
540
553
|
|
|
554
|
+
// FINA non-domestic guard: hide FINA selectors for non-domestic transactions
|
|
555
|
+
const isFinaNonDomestic = isFinaEnabled && viesCustomerCountryCode != null && viesCustomerCountryCode !== "HR";
|
|
556
|
+
|
|
557
|
+
// Auto-populate tax_clause from entity settings when transaction type changes
|
|
558
|
+
const effectiveTransactionType = transactionType ?? "domestic";
|
|
559
|
+
const prevTransactionTypeRef = useRef<string | undefined>(undefined);
|
|
560
|
+
useEffect(() => {
|
|
561
|
+
if (effectiveTransactionType === prevTransactionTypeRef.current) return;
|
|
562
|
+
prevTransactionTypeRef.current = effectiveTransactionType;
|
|
563
|
+
|
|
564
|
+
const taxClauseDefaults = (activeEntity?.settings as any)?.tax_clause_defaults;
|
|
565
|
+
if (!taxClauseDefaults) return;
|
|
566
|
+
|
|
567
|
+
const clause = taxClauseDefaults[effectiveTransactionType] ?? "";
|
|
568
|
+
form.setValue("tax_clause", clause);
|
|
569
|
+
}, [effectiveTransactionType, activeEntity, form]);
|
|
570
|
+
|
|
541
571
|
// Extract customer management logic into a custom hook
|
|
542
572
|
const {
|
|
543
573
|
originalCustomer,
|
|
@@ -624,9 +654,9 @@ export default function CreateInvoiceForm({
|
|
|
624
654
|
: undefined
|
|
625
655
|
: undefined;
|
|
626
656
|
|
|
627
|
-
// Build FINA options (skip for drafts
|
|
657
|
+
// Build FINA options (skip for drafts, edit mode, and non-domestic transactions)
|
|
628
658
|
const finaOptions =
|
|
629
|
-
!isDraft && !isEditMode && isFinaEnabled && selectedFinaPremiseId && selectedFinaDeviceId
|
|
659
|
+
!isDraft && !isEditMode && isFinaEnabled && !isFinaNonDomestic && selectedFinaPremiseId && selectedFinaDeviceId
|
|
630
660
|
? { premise_id: selectedFinaPremiseId, device_id: selectedFinaDeviceId, payment_type: paymentTypes[0] }
|
|
631
661
|
: undefined;
|
|
632
662
|
|
|
@@ -674,6 +704,7 @@ export default function CreateInvoiceForm({
|
|
|
674
704
|
isEslogAvailable,
|
|
675
705
|
isFursEnabled,
|
|
676
706
|
isFinaEnabled,
|
|
707
|
+
isFinaNonDomestic,
|
|
677
708
|
markAsPaid,
|
|
678
709
|
originalCustomer,
|
|
679
710
|
paymentTypes,
|
|
@@ -717,7 +748,8 @@ export default function CreateInvoiceForm({
|
|
|
717
748
|
);
|
|
718
749
|
|
|
719
750
|
// Watch isDirty to get stable reference
|
|
720
|
-
|
|
751
|
+
// When form is pre-populated via initialValues (duplicate/merge), treat as dirty immediately
|
|
752
|
+
const isDirty = form.formState.isDirty || !!initialValues;
|
|
721
753
|
|
|
722
754
|
useFormFooterRegistration({
|
|
723
755
|
formId: "create-invoice-form",
|
|
@@ -931,7 +963,7 @@ export default function CreateInvoiceForm({
|
|
|
931
963
|
: undefined
|
|
932
964
|
}
|
|
933
965
|
finaInline={
|
|
934
|
-
!isEditMode && isFinaEnabled && hasFinaPremises
|
|
966
|
+
!isEditMode && isFinaEnabled && hasFinaPremises && !isFinaNonDomestic
|
|
935
967
|
? {
|
|
936
968
|
premises: activeFinaPremises.map((p: any) => ({ id: p.id, premise_id: p.premise_id })),
|
|
937
969
|
devices: activeFinaDevices.map((d: any) => ({ id: d.id, device_id: d.device_id })),
|
|
@@ -993,6 +1025,22 @@ export default function CreateInvoiceForm({
|
|
|
993
1025
|
}}
|
|
994
1026
|
/>
|
|
995
1027
|
|
|
1028
|
+
<DocumentTaxClauseField
|
|
1029
|
+
control={form.control}
|
|
1030
|
+
t={t}
|
|
1031
|
+
entity={activeEntity}
|
|
1032
|
+
document={{
|
|
1033
|
+
number: watchedNumber,
|
|
1034
|
+
date: watchedDate,
|
|
1035
|
+
date_due: watchedDateDue,
|
|
1036
|
+
currency_code: watchedCurrencyCode,
|
|
1037
|
+
customer: watchedCustomer as any,
|
|
1038
|
+
}}
|
|
1039
|
+
transactionType={transactionType}
|
|
1040
|
+
isTransactionTypeFetching={isViesFetching}
|
|
1041
|
+
isFinaNonDomestic={isFinaNonDomestic}
|
|
1042
|
+
/>
|
|
1043
|
+
|
|
996
1044
|
<DocumentPaymentTermsField
|
|
997
1045
|
control={form.control}
|
|
998
1046
|
t={t}
|
|
@@ -126,4 +126,19 @@ export default {
|
|
|
126
126
|
"Date Range": "Zeitraum",
|
|
127
127
|
From: "Von",
|
|
128
128
|
To: "Bis",
|
|
129
|
+
// Separator items
|
|
130
|
+
"Add separator": "Trennzeile hinzufügen",
|
|
131
|
+
"Section header": "Abschnittsüberschrift",
|
|
132
|
+
"Section title...": "Abschnittstitel...",
|
|
133
|
+
// Transaction type
|
|
134
|
+
"Transaction type": "Transaktionstyp",
|
|
135
|
+
Domestic: "Inland",
|
|
136
|
+
"EU B2B": "EU B2B",
|
|
137
|
+
"EU B2C": "EU B2C",
|
|
138
|
+
Export: "Export",
|
|
139
|
+
"Determining transaction type...": "Transaktionstyp wird ermittelt...",
|
|
140
|
+
"This invoice will not be fiscalized (non-domestic transaction)":
|
|
141
|
+
"Diese Rechnung wird nicht fiskalisiert (nicht-inländische Transaktion)",
|
|
142
|
+
"Tax Clause": "Steuerklausel",
|
|
143
|
+
"Add tax clause...": "Steuerklausel hinzufügen...",
|
|
129
144
|
} as const;
|
|
@@ -111,4 +111,19 @@ export default {
|
|
|
111
111
|
"Date Range": "Rango de fechas",
|
|
112
112
|
From: "Desde",
|
|
113
113
|
To: "Hasta",
|
|
114
|
+
// Separator items
|
|
115
|
+
"Add separator": "Añadir separador",
|
|
116
|
+
"Section header": "Encabezado de sección",
|
|
117
|
+
"Section title...": "Título de sección...",
|
|
118
|
+
// Transaction type
|
|
119
|
+
"Transaction type": "Tipo de transacción",
|
|
120
|
+
Domestic: "Nacional",
|
|
121
|
+
"EU B2B": "EU B2B",
|
|
122
|
+
"EU B2C": "EU B2C",
|
|
123
|
+
Export: "Exportación",
|
|
124
|
+
"Determining transaction type...": "Determinando tipo de transacción...",
|
|
125
|
+
"This invoice will not be fiscalized (non-domestic transaction)":
|
|
126
|
+
"Esta factura no será fiscalizada (transacción no nacional)",
|
|
127
|
+
"Tax Clause": "Cláusula fiscal",
|
|
128
|
+
"Add tax clause...": "Agregar cláusula fiscal...",
|
|
114
129
|
} as const;
|
|
@@ -113,4 +113,19 @@ export default {
|
|
|
113
113
|
"Date Range": "Plage de dates",
|
|
114
114
|
From: "Du",
|
|
115
115
|
To: "Au",
|
|
116
|
+
// Separator items
|
|
117
|
+
"Add separator": "Ajouter un séparateur",
|
|
118
|
+
"Section header": "En-tête de section",
|
|
119
|
+
"Section title...": "Titre de section...",
|
|
120
|
+
// Transaction type
|
|
121
|
+
"Transaction type": "Type de transaction",
|
|
122
|
+
Domestic: "Nationale",
|
|
123
|
+
"EU B2B": "EU B2B",
|
|
124
|
+
"EU B2C": "EU B2C",
|
|
125
|
+
Export: "Exportation",
|
|
126
|
+
"Determining transaction type...": "Détermination du type de transaction...",
|
|
127
|
+
"This invoice will not be fiscalized (non-domestic transaction)":
|
|
128
|
+
"Cette facture ne sera pas fiscalisée (transaction non nationale)",
|
|
129
|
+
"Tax Clause": "Clause fiscale",
|
|
130
|
+
"Add tax clause...": "Ajouter une clause fiscale...",
|
|
116
131
|
} as const;
|
|
@@ -110,4 +110,19 @@ export default {
|
|
|
110
110
|
"Date Range": "Raspon datuma",
|
|
111
111
|
From: "Od",
|
|
112
112
|
To: "Do",
|
|
113
|
+
// Separator items
|
|
114
|
+
"Add separator": "Dodaj separator",
|
|
115
|
+
"Section header": "Naslov odjeljka",
|
|
116
|
+
"Section title...": "Naslov odjeljka...",
|
|
117
|
+
// Transaction type
|
|
118
|
+
"Transaction type": "Vrsta transakcije",
|
|
119
|
+
Domestic: "Domaća",
|
|
120
|
+
"EU B2B": "EU B2B",
|
|
121
|
+
"EU B2C": "EU B2C",
|
|
122
|
+
Export: "Izvoz",
|
|
123
|
+
"Determining transaction type...": "Određivanje vrste transakcije...",
|
|
124
|
+
"This invoice will not be fiscalized (non-domestic transaction)":
|
|
125
|
+
"Ovaj račun neće biti fiskaliziran (nedomaća transakcija)",
|
|
126
|
+
"Tax Clause": "Porezna klauzula",
|
|
127
|
+
"Add tax clause...": "Dodajte poreznu klauzulu...",
|
|
113
128
|
} as const;
|
|
@@ -113,4 +113,19 @@ export default {
|
|
|
113
113
|
"Date Range": "Intervallo di date",
|
|
114
114
|
From: "Da",
|
|
115
115
|
To: "A",
|
|
116
|
+
// Separator items
|
|
117
|
+
"Add separator": "Aggiungi separatore",
|
|
118
|
+
"Section header": "Intestazione sezione",
|
|
119
|
+
"Section title...": "Titolo sezione...",
|
|
120
|
+
// Transaction type
|
|
121
|
+
"Transaction type": "Tipo di transazione",
|
|
122
|
+
Domestic: "Nazionale",
|
|
123
|
+
"EU B2B": "EU B2B",
|
|
124
|
+
"EU B2C": "EU B2C",
|
|
125
|
+
Export: "Esportazione",
|
|
126
|
+
"Determining transaction type...": "Determinazione tipo di transazione...",
|
|
127
|
+
"This invoice will not be fiscalized (non-domestic transaction)":
|
|
128
|
+
"Questa fattura non sarà fiscalizzata (transazione non nazionale)",
|
|
129
|
+
"Tax Clause": "Clausola fiscale",
|
|
130
|
+
"Add tax clause...": "Aggiungi clausola fiscale...",
|
|
116
131
|
} as const;
|
|
@@ -112,4 +112,19 @@ export default {
|
|
|
112
112
|
"Date Range": "Datumbereik",
|
|
113
113
|
From: "Van",
|
|
114
114
|
To: "Tot",
|
|
115
|
+
// Separator items
|
|
116
|
+
"Add separator": "Scheidingslijn toevoegen",
|
|
117
|
+
"Section header": "Sectiekop",
|
|
118
|
+
"Section title...": "Sectietitel...",
|
|
119
|
+
// Transaction type
|
|
120
|
+
"Transaction type": "Transactietype",
|
|
121
|
+
Domestic: "Binnenland",
|
|
122
|
+
"EU B2B": "EU B2B",
|
|
123
|
+
"EU B2C": "EU B2C",
|
|
124
|
+
Export: "Export",
|
|
125
|
+
"Determining transaction type...": "Transactietype bepalen...",
|
|
126
|
+
"This invoice will not be fiscalized (non-domestic transaction)":
|
|
127
|
+
"Deze factuur wordt niet gefiscaliseerd (niet-binnenlandse transactie)",
|
|
128
|
+
"Tax Clause": "Belastingclausule",
|
|
129
|
+
"Add tax clause...": "Belastingclausule toevoegen...",
|
|
115
130
|
} as const;
|
|
@@ -111,4 +111,19 @@ export default {
|
|
|
111
111
|
"Date Range": "Zakres dat",
|
|
112
112
|
From: "Od",
|
|
113
113
|
To: "Do",
|
|
114
|
+
// Separator items
|
|
115
|
+
"Add separator": "Dodaj separator",
|
|
116
|
+
"Section header": "Nagłówek sekcji",
|
|
117
|
+
"Section title...": "Tytuł sekcji...",
|
|
118
|
+
// Transaction type
|
|
119
|
+
"Transaction type": "Typ transakcji",
|
|
120
|
+
Domestic: "Krajowa",
|
|
121
|
+
"EU B2B": "EU B2B",
|
|
122
|
+
"EU B2C": "EU B2C",
|
|
123
|
+
Export: "Eksport",
|
|
124
|
+
"Determining transaction type...": "Określanie typu transakcji...",
|
|
125
|
+
"This invoice will not be fiscalized (non-domestic transaction)":
|
|
126
|
+
"Ta faktura nie będzie fiskalizowana (transakcja niekrajowa)",
|
|
127
|
+
"Tax Clause": "Klauzula podatkowa",
|
|
128
|
+
"Add tax clause...": "Dodaj klauzulę podatkową...",
|
|
114
129
|
} as const;
|
|
@@ -112,4 +112,19 @@ export default {
|
|
|
112
112
|
"Date Range": "Intervalo de datas",
|
|
113
113
|
From: "De",
|
|
114
114
|
To: "Até",
|
|
115
|
+
// Separator items
|
|
116
|
+
"Add separator": "Adicionar separador",
|
|
117
|
+
"Section header": "Cabeçalho da secção",
|
|
118
|
+
"Section title...": "Título da secção...",
|
|
119
|
+
// Transaction type
|
|
120
|
+
"Transaction type": "Tipo de transação",
|
|
121
|
+
Domestic: "Nacional",
|
|
122
|
+
"EU B2B": "EU B2B",
|
|
123
|
+
"EU B2C": "EU B2C",
|
|
124
|
+
Export: "Exportação",
|
|
125
|
+
"Determining transaction type...": "Determinando tipo de transação...",
|
|
126
|
+
"This invoice will not be fiscalized (non-domestic transaction)":
|
|
127
|
+
"Esta fatura não será fiscalizada (transação não nacional)",
|
|
128
|
+
"Tax Clause": "Cláusula fiscal",
|
|
129
|
+
"Add tax clause...": "Adicionar cláusula fiscal...",
|
|
115
130
|
} as const;
|