@spaceinvoices/react-ui 0.4.4 → 0.4.6
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/advance-invoices.hooks.ts +2 -2
- package/src/components/advance-invoices/create/create-advance-invoice-form.tsx +151 -45
- package/src/components/advance-invoices/create/locales/de.ts +20 -0
- package/src/components/advance-invoices/create/locales/es.ts +20 -0
- package/src/components/advance-invoices/create/locales/fr.ts +20 -0
- package/src/components/advance-invoices/create/locales/hr.ts +20 -0
- package/src/components/advance-invoices/create/locales/it.ts +20 -0
- package/src/components/advance-invoices/create/locales/nl.ts +20 -0
- package/src/components/advance-invoices/create/locales/pl.ts +20 -0
- package/src/components/advance-invoices/create/locales/pt.ts +20 -0
- package/src/components/advance-invoices/create/locales/sl.ts +20 -0
- package/src/components/advance-invoices/create/prepare-advance-invoice-submission.ts +5 -5
- 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 +161 -42
- package/src/components/credit-notes/create/locales/de.ts +21 -0
- package/src/components/credit-notes/create/locales/es.ts +21 -0
- package/src/components/credit-notes/create/locales/fr.ts +21 -0
- package/src/components/credit-notes/create/locales/hr.ts +21 -0
- package/src/components/credit-notes/create/locales/it.ts +21 -0
- package/src/components/credit-notes/create/locales/nl.ts +21 -0
- package/src/components/credit-notes/create/locales/pl.ts +21 -0
- package/src/components/credit-notes/create/locales/pt.ts +21 -0
- package/src/components/credit-notes/create/locales/sl.ts +22 -1
- package/src/components/credit-notes/credit-notes.hooks.ts +2 -2
- 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 +114 -7
- package/src/components/delivery-notes/create/locales/de.ts +21 -0
- package/src/components/delivery-notes/create/locales/es.ts +21 -0
- package/src/components/delivery-notes/create/locales/fr.ts +21 -0
- package/src/components/delivery-notes/create/locales/hr.ts +21 -0
- package/src/components/delivery-notes/create/locales/it.ts +21 -0
- package/src/components/delivery-notes/create/locales/nl.ts +21 -0
- package/src/components/delivery-notes/create/locales/pl.ts +21 -0
- package/src/components/delivery-notes/create/locales/pt.ts +21 -0
- package/src/components/delivery-notes/create/locales/sl.ts +22 -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 +590 -344
- 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 +22 -8
- package/src/components/documents/create/smart-code-insert-button.tsx +6 -0
- 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 +32 -9
- package/src/components/documents/view/locales/de.ts +3 -0
- package/src/components/documents/view/locales/es.ts +3 -0
- package/src/components/documents/view/locales/fr.ts +3 -0
- package/src/components/documents/view/locales/hr.ts +3 -0
- package/src/components/documents/view/locales/it.ts +3 -0
- package/src/components/documents/view/locales/nl.ts +3 -0
- package/src/components/documents/view/locales/pl.ts +3 -0
- package/src/components/documents/view/locales/pt.ts +3 -0
- package/src/components/documents/view/locales/sl.ts +4 -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/email-template-variables-info.tsx +6 -0
- package/src/components/entities/entity-settings-form/input-with-preview.tsx +2 -117
- package/src/components/entities/entity-settings-form/locales/de.ts +5 -0
- package/src/components/entities/entity-settings-form/locales/es.ts +5 -0
- package/src/components/entities/entity-settings-form/locales/fr.ts +5 -0
- package/src/components/entities/entity-settings-form/locales/hr.ts +5 -0
- package/src/components/entities/entity-settings-form/locales/it.ts +5 -0
- package/src/components/entities/entity-settings-form/locales/nl.ts +5 -0
- package/src/components/entities/entity-settings-form/locales/pl.ts +5 -0
- package/src/components/entities/entity-settings-form/locales/pt.ts +5 -0
- package/src/components/entities/entity-settings-form/locales/sl.ts +5 -0
- package/src/components/entities/fina-settings-form/fina-settings-form.tsx +15 -0
- package/src/components/entities/fina-settings-form/fina-settings.hooks.ts +5 -1
- package/src/components/entities/fina-settings-form/locales/de.ts +3 -0
- package/src/components/entities/fina-settings-form/locales/en.ts +3 -0
- package/src/components/entities/fina-settings-form/locales/es.ts +3 -0
- package/src/components/entities/fina-settings-form/locales/fr.ts +3 -0
- package/src/components/entities/fina-settings-form/locales/hr.ts +3 -0
- package/src/components/entities/fina-settings-form/locales/it.ts +3 -0
- package/src/components/entities/fina-settings-form/locales/nl.ts +3 -0
- package/src/components/entities/fina-settings-form/locales/pl.ts +3 -0
- package/src/components/entities/fina-settings-form/locales/pt.ts +3 -0
- package/src/components/entities/fina-settings-form/locales/sl.ts +3 -0
- package/src/components/entities/fina-settings-form/sections/premises-management-section.tsx +4 -4
- package/src/components/entities/fina-settings-form/sections/register-premise-dialog.tsx +3 -3
- package/src/components/entities/settings/company-settings-form.tsx +173 -20
- package/src/components/entities/settings/defaults-settings-form.tsx +38 -1
- package/src/components/entities/settings/tax-rules-settings-form.tsx +1 -2
- package/src/components/estimates/create/create-estimate-form.tsx +107 -8
- package/src/components/estimates/create/locales/de.ts +21 -0
- package/src/components/estimates/create/locales/es.ts +21 -0
- package/src/components/estimates/create/locales/fr.ts +21 -0
- package/src/components/estimates/create/locales/hr.ts +21 -0
- package/src/components/estimates/create/locales/it.ts +21 -0
- package/src/components/estimates/create/locales/nl.ts +21 -0
- package/src/components/estimates/create/locales/pl.ts +21 -0
- package/src/components/estimates/create/locales/pt.ts +21 -0
- package/src/components/estimates/create/locales/sl.ts +22 -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 +186 -48
- package/src/components/invoices/create/locales/de.ts +28 -0
- package/src/components/invoices/create/locales/es.ts +28 -0
- package/src/components/invoices/create/locales/fr.ts +28 -0
- package/src/components/invoices/create/locales/hr.ts +28 -0
- package/src/components/invoices/create/locales/it.ts +28 -0
- package/src/components/invoices/create/locales/nl.ts +28 -0
- package/src/components/invoices/create/locales/pl.ts +28 -0
- package/src/components/invoices/create/locales/pt.ts +28 -0
- package/src/components/invoices/create/locales/sl.ts +29 -1
- package/src/components/invoices/create/prepare-invoice-submission.ts +5 -5
- package/src/components/invoices/invoices.hooks.ts +2 -2
- package/src/components/invoices/view/fiscalization-status-card.tsx +10 -8
- package/src/components/table/search-input.tsx +17 -0
- package/src/components/table/table-pagination.tsx +1 -1
- package/src/generated/schemas/advanceinvoice.ts +6 -2
- package/src/generated/schemas/creditnote.ts +3 -1
- package/src/generated/schemas/deliverynote.ts +3 -1
- package/src/generated/schemas/entity.ts +4 -4
- package/src/generated/schemas/entityapikey.ts +19 -0
- package/src/generated/schemas/estimate.ts +6 -2
- package/src/generated/schemas/index.ts +1 -0
- package/src/generated/schemas/invoice.ts +4 -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/generated/schemas/startpdfexport_body.ts +14 -2
- package/src/generated/schemas/webhook.ts +4 -0
- package/src/hooks/use-duplicate-document.ts +16 -9
- package/src/hooks/use-vies-check.ts +3 -0
- package/src/lib/template-variables.tsx +167 -0
- package/src/providers/entities-context.tsx +2 -2
|
@@ -81,6 +81,7 @@ const PartialDeliveryNotePreview = z.object({
|
|
|
81
81
|
.array(
|
|
82
82
|
z
|
|
83
83
|
.object({
|
|
84
|
+
type: z.literal("separator"),
|
|
84
85
|
name: z.string(),
|
|
85
86
|
quantity: z.number(),
|
|
86
87
|
price: z.number(),
|
|
@@ -123,29 +124,22 @@ const LineDiscount = z.object({
|
|
|
123
124
|
|
|
124
125
|
|
|
125
126
|
// Dependency schema for renderdeliverynotepreview_body
|
|
126
|
-
const CreateDocumentItem = z
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
.
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
z.object({}).partial().passthrough(),
|
|
143
|
-
z.array(z.unknown()),
|
|
144
|
-
z.null(),
|
|
145
|
-
])
|
|
146
|
-
.optional(),
|
|
147
|
-
item_id: z.string().optional(),
|
|
148
|
-
});
|
|
127
|
+
const CreateDocumentItem = z
|
|
128
|
+
.object({
|
|
129
|
+
type: z.literal("separator"),
|
|
130
|
+
name: z.string().min(1),
|
|
131
|
+
description: z.union([z.string(), z.null()]),
|
|
132
|
+
price: z.number(),
|
|
133
|
+
gross_price: z.number(),
|
|
134
|
+
quantity: z.number().gte(-140737488355328).lte(140737488355327),
|
|
135
|
+
unit: z.union([z.string(), z.null()]),
|
|
136
|
+
taxes: z.array(DocumentItemTax),
|
|
137
|
+
discounts: z.array(LineDiscount).max(5),
|
|
138
|
+
item_id: z.string(),
|
|
139
|
+
metadata: z.union([z.record(z.string(), z.any()), z.null()]),
|
|
140
|
+
save_item: z.boolean().default(true),
|
|
141
|
+
})
|
|
142
|
+
.partial();
|
|
149
143
|
|
|
150
144
|
|
|
151
145
|
// Dependency schema for renderdeliverynotepreview_body
|
|
@@ -82,6 +82,7 @@ const PartialEstimatePreview = z.object({
|
|
|
82
82
|
.array(
|
|
83
83
|
z
|
|
84
84
|
.object({
|
|
85
|
+
type: z.literal("separator"),
|
|
85
86
|
name: z.string(),
|
|
86
87
|
quantity: z.number(),
|
|
87
88
|
price: z.number(),
|
|
@@ -123,29 +124,22 @@ const LineDiscount = z.object({
|
|
|
123
124
|
|
|
124
125
|
|
|
125
126
|
// Dependency schema for renderestimatepreview_body
|
|
126
|
-
const CreateDocumentItem = z
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
.
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
z.object({}).partial().passthrough(),
|
|
143
|
-
z.array(z.unknown()),
|
|
144
|
-
z.null(),
|
|
145
|
-
])
|
|
146
|
-
.optional(),
|
|
147
|
-
item_id: z.string().optional(),
|
|
148
|
-
});
|
|
127
|
+
const CreateDocumentItem = z
|
|
128
|
+
.object({
|
|
129
|
+
type: z.literal("separator"),
|
|
130
|
+
name: z.string().min(1),
|
|
131
|
+
description: z.union([z.string(), z.null()]),
|
|
132
|
+
price: z.number(),
|
|
133
|
+
gross_price: z.number(),
|
|
134
|
+
quantity: z.number().gte(-140737488355328).lte(140737488355327),
|
|
135
|
+
unit: z.union([z.string(), z.null()]),
|
|
136
|
+
taxes: z.array(DocumentItemTax),
|
|
137
|
+
discounts: z.array(LineDiscount).max(5),
|
|
138
|
+
item_id: z.string(),
|
|
139
|
+
metadata: z.union([z.record(z.string(), z.any()), z.null()]),
|
|
140
|
+
save_item: z.boolean().default(true),
|
|
141
|
+
})
|
|
142
|
+
.partial();
|
|
149
143
|
|
|
150
144
|
|
|
151
145
|
// Dependency schema for renderestimatepreview_body
|
|
@@ -113,6 +113,7 @@ const PartialInvoicePreview = z.object({
|
|
|
113
113
|
.array(
|
|
114
114
|
z
|
|
115
115
|
.object({
|
|
116
|
+
type: z.literal("separator"),
|
|
116
117
|
name: z.string(),
|
|
117
118
|
quantity: z.number(),
|
|
118
119
|
price: z.number(),
|
|
@@ -132,6 +133,7 @@ const PartialInvoicePreview = z.object({
|
|
|
132
133
|
.min(1),
|
|
133
134
|
fina: CreateFinaInvoiceData.optional(),
|
|
134
135
|
expected_total_with_tax: z.number().gt(0).optional(),
|
|
136
|
+
force_linked_documents: z.boolean().optional(),
|
|
135
137
|
});
|
|
136
138
|
|
|
137
139
|
|
|
@@ -155,29 +157,22 @@ const LineDiscount = z.object({
|
|
|
155
157
|
|
|
156
158
|
|
|
157
159
|
// Dependency schema for renderinvoicepreview_body
|
|
158
|
-
const CreateDocumentItem = z
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
.
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
z.object({}).partial().passthrough(),
|
|
175
|
-
z.array(z.unknown()),
|
|
176
|
-
z.null(),
|
|
177
|
-
])
|
|
178
|
-
.optional(),
|
|
179
|
-
item_id: z.string().optional(),
|
|
180
|
-
});
|
|
160
|
+
const CreateDocumentItem = z
|
|
161
|
+
.object({
|
|
162
|
+
type: z.literal("separator"),
|
|
163
|
+
name: z.string().min(1),
|
|
164
|
+
description: z.union([z.string(), z.null()]),
|
|
165
|
+
price: z.number(),
|
|
166
|
+
gross_price: z.number(),
|
|
167
|
+
quantity: z.number().gte(-140737488355328).lte(140737488355327),
|
|
168
|
+
unit: z.union([z.string(), z.null()]),
|
|
169
|
+
taxes: z.array(DocumentItemTax),
|
|
170
|
+
discounts: z.array(LineDiscount).max(5),
|
|
171
|
+
item_id: z.string(),
|
|
172
|
+
metadata: z.union([z.record(z.string(), z.any()), z.null()]),
|
|
173
|
+
save_item: z.boolean().default(true),
|
|
174
|
+
})
|
|
175
|
+
.partial();
|
|
181
176
|
|
|
182
177
|
|
|
183
178
|
// Dependency schema for renderinvoicepreview_body
|
|
@@ -201,6 +196,7 @@ const CompleteInvoicePreview = z.object({
|
|
|
201
196
|
items: z.array(CreateDocumentItem).min(1),
|
|
202
197
|
fina: CreateFinaInvoiceData.optional(),
|
|
203
198
|
expected_total_with_tax: z.number().gt(0).optional(),
|
|
199
|
+
force_linked_documents: z.boolean().optional(),
|
|
204
200
|
});
|
|
205
201
|
|
|
206
202
|
|
|
@@ -11,7 +11,13 @@ import { z } from 'zod';
|
|
|
11
11
|
// Dependency schema for startpdfexport_body
|
|
12
12
|
const PdfExportByDocumentIds = z
|
|
13
13
|
.object({
|
|
14
|
-
type: z.enum([
|
|
14
|
+
type: z.enum([
|
|
15
|
+
"invoice",
|
|
16
|
+
"estimate",
|
|
17
|
+
"credit_note",
|
|
18
|
+
"advance_invoice",
|
|
19
|
+
"delivery_note",
|
|
20
|
+
]),
|
|
15
21
|
document_ids: z.array(z.string()).min(1),
|
|
16
22
|
})
|
|
17
23
|
.passthrough();
|
|
@@ -20,7 +26,13 @@ const PdfExportByDocumentIds = z
|
|
|
20
26
|
// Dependency schema for startpdfexport_body
|
|
21
27
|
const PdfExportByDateRange = z
|
|
22
28
|
.object({
|
|
23
|
-
type: z.enum([
|
|
29
|
+
type: z.enum([
|
|
30
|
+
"invoice",
|
|
31
|
+
"estimate",
|
|
32
|
+
"credit_note",
|
|
33
|
+
"advance_invoice",
|
|
34
|
+
"delivery_note",
|
|
35
|
+
]),
|
|
24
36
|
date_from: z.string().optional(),
|
|
25
37
|
date_to: z.string().optional(),
|
|
26
38
|
})
|
|
@@ -49,6 +49,7 @@ const createWebhookSchemaDefinition = z.object({
|
|
|
49
49
|
"advance_invoice.created",
|
|
50
50
|
"advance_invoice.paid",
|
|
51
51
|
"advance_invoice.applied",
|
|
52
|
+
"advance_invoice.voided",
|
|
52
53
|
"advance_invoice.deleted",
|
|
53
54
|
"advance_invoice.restored",
|
|
54
55
|
"item.created",
|
|
@@ -87,6 +88,7 @@ const createWebhookSchemaDefinition = z.object({
|
|
|
87
88
|
"delivery_note.created",
|
|
88
89
|
"delivery_note.sent",
|
|
89
90
|
"delivery_note.cancelled",
|
|
91
|
+
"delivery_note.voided",
|
|
90
92
|
"delivery_note.deleted",
|
|
91
93
|
"delivery_note.restored",
|
|
92
94
|
])
|
|
@@ -142,6 +144,7 @@ const updateWebhookSchemaDefinition = z
|
|
|
142
144
|
"advance_invoice.created",
|
|
143
145
|
"advance_invoice.paid",
|
|
144
146
|
"advance_invoice.applied",
|
|
147
|
+
"advance_invoice.voided",
|
|
145
148
|
"advance_invoice.deleted",
|
|
146
149
|
"advance_invoice.restored",
|
|
147
150
|
"item.created",
|
|
@@ -180,6 +183,7 @@ const updateWebhookSchemaDefinition = z
|
|
|
180
183
|
"delivery_note.created",
|
|
181
184
|
"delivery_note.sent",
|
|
182
185
|
"delivery_note.cancelled",
|
|
186
|
+
"delivery_note.voided",
|
|
183
187
|
"delivery_note.deleted",
|
|
184
188
|
"delivery_note.restored",
|
|
185
189
|
])
|
|
@@ -64,6 +64,7 @@ function transformDocumentForDuplication(source: Document, targetType: DocumentT
|
|
|
64
64
|
// Transform items - copy only the fields needed for creation
|
|
65
65
|
// Use type assertion for items since all document item types share the same shape
|
|
66
66
|
const sourceItems = source.items as Array<{
|
|
67
|
+
type?: string | null;
|
|
67
68
|
name: string;
|
|
68
69
|
description: string | null;
|
|
69
70
|
quantity: number;
|
|
@@ -72,15 +73,21 @@ function transformDocumentForDuplication(source: Document, targetType: DocumentT
|
|
|
72
73
|
taxes: Array<{ tax_id?: string }>;
|
|
73
74
|
}>;
|
|
74
75
|
const items = sourceItems?.map((item) => ({
|
|
76
|
+
type: item.type ?? undefined,
|
|
75
77
|
name: item.name,
|
|
76
78
|
description: item.description,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
79
|
+
// Separator items skip financial fields
|
|
80
|
+
...(item.type !== "separator"
|
|
81
|
+
? {
|
|
82
|
+
quantity: item.quantity,
|
|
83
|
+
// Use gross_price if set, otherwise use price. The form uses is_gross_price as a UI toggle.
|
|
84
|
+
price: item.gross_price ?? item.price,
|
|
85
|
+
// Copy tax references (tax_id), not computed tax data
|
|
86
|
+
taxes: item.taxes?.map((tax) => ({ tax_id: tax.tax_id })),
|
|
87
|
+
// Derive is_gross_price from whether gross_price is set
|
|
88
|
+
gross_price: item.gross_price ?? undefined,
|
|
89
|
+
}
|
|
90
|
+
: {}),
|
|
84
91
|
}));
|
|
85
92
|
|
|
86
93
|
// Build customer data - always copy if available (form needs this for display)
|
|
@@ -108,8 +115,8 @@ function transformDocumentForDuplication(source: Document, targetType: DocumentT
|
|
|
108
115
|
// The form needs customer data for display, even when customer_id is set
|
|
109
116
|
...(source.customer_id ? { customer_id: source.customer_id } : {}),
|
|
110
117
|
...(customerData ? { customer: customerData } : {}),
|
|
111
|
-
// Items
|
|
112
|
-
items,
|
|
118
|
+
// Items (cast needed: separator items omit financial fields like quantity)
|
|
119
|
+
items: items as any,
|
|
113
120
|
// Currency
|
|
114
121
|
currency_code: source.currency_code,
|
|
115
122
|
// Notes
|
|
@@ -42,6 +42,8 @@ export interface UseViesCheckResult {
|
|
|
42
42
|
reverseChargeApplies: boolean;
|
|
43
43
|
/** Transaction type determined by VIES check */
|
|
44
44
|
transactionType: ViesCheckResponse["transaction_type"] | undefined;
|
|
45
|
+
/** Customer country code returned by VIES check */
|
|
46
|
+
customerCountryCode: string | null;
|
|
45
47
|
/** Warning message from VIES validation */
|
|
46
48
|
warning: string | null;
|
|
47
49
|
/** Whether VIES validation was successful */
|
|
@@ -124,6 +126,7 @@ export function useViesCheck({
|
|
|
124
126
|
error: query.error,
|
|
125
127
|
reverseChargeApplies: query.data?.reverse_charge_applies ?? false,
|
|
126
128
|
transactionType: query.data?.transaction_type,
|
|
129
|
+
customerCountryCode: query.data?.customer_country_code ?? null,
|
|
127
130
|
warning: query.data?.warning ?? null,
|
|
128
131
|
viesValid: query.data?.vies_valid ?? null,
|
|
129
132
|
};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import type { Entity, Estimate, Invoice } from "@spaceinvoices/js-sdk";
|
|
2
|
+
import { cn } from "@/ui/lib/utils";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Convert snake_case variable name to Title Case for display
|
|
6
|
+
* e.g., "document_number" -> "Document Number", "bank_account.iban" -> "Bank Account Iban"
|
|
7
|
+
*/
|
|
8
|
+
export function formatVariableName(varName: string): string {
|
|
9
|
+
return varName
|
|
10
|
+
.replace(/\./g, "_")
|
|
11
|
+
.split("_")
|
|
12
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
13
|
+
.join(" ");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Resolve a template variable to its actual value from entity/document data.
|
|
18
|
+
* Returns null if the variable can't be resolved (shown as a placeholder in preview).
|
|
19
|
+
*/
|
|
20
|
+
export function getVariableValue(
|
|
21
|
+
varName: string,
|
|
22
|
+
entity?: Entity | null,
|
|
23
|
+
document?: Partial<Invoice | Estimate> | null,
|
|
24
|
+
): string | null {
|
|
25
|
+
if (!entity) return null;
|
|
26
|
+
|
|
27
|
+
// Entity-related variables
|
|
28
|
+
if (varName === "entity_name") return entity.name || null;
|
|
29
|
+
if (varName === "entity_email") return (entity.settings as any)?.email || null;
|
|
30
|
+
if (varName === "entity_address") return entity.address || null;
|
|
31
|
+
if (varName === "entity_post_code") return entity.post_code || null;
|
|
32
|
+
if (varName === "entity_city") return entity.city || null;
|
|
33
|
+
if (varName === "entity_country") return entity.country || null;
|
|
34
|
+
if (varName === "entity_tax_number") return entity.tax_number || null;
|
|
35
|
+
if (varName === "entity_company_number") return entity.company_number || null;
|
|
36
|
+
|
|
37
|
+
// Date variables
|
|
38
|
+
if (varName === "current_date") {
|
|
39
|
+
return new Date().toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" });
|
|
40
|
+
}
|
|
41
|
+
if (varName === "current_year") return new Date().getFullYear().toString();
|
|
42
|
+
|
|
43
|
+
// Document-specific variables
|
|
44
|
+
if (document) {
|
|
45
|
+
if (varName === "document_number") return (document as any).number || null;
|
|
46
|
+
if (varName === "document_date" && (document as any).date) {
|
|
47
|
+
return new Date((document as any).date).toLocaleDateString("en-US", {
|
|
48
|
+
month: "long",
|
|
49
|
+
day: "numeric",
|
|
50
|
+
year: "numeric",
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
if (varName === "document_total" && (document as any).total_with_tax) {
|
|
54
|
+
return new Intl.NumberFormat("en-US", {
|
|
55
|
+
style: "currency",
|
|
56
|
+
currency: (document as any).currency_code || "USD",
|
|
57
|
+
}).format(Number((document as any).total_with_tax));
|
|
58
|
+
}
|
|
59
|
+
if (varName === "document_currency") return (document as any).currency_code || null;
|
|
60
|
+
|
|
61
|
+
// Invoice due date
|
|
62
|
+
if ("date_due" in document && varName === "document_due_date") {
|
|
63
|
+
return document.date_due
|
|
64
|
+
? new Date(document.date_due).toLocaleDateString("en-US", {
|
|
65
|
+
month: "long",
|
|
66
|
+
day: "numeric",
|
|
67
|
+
year: "numeric",
|
|
68
|
+
})
|
|
69
|
+
: null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Estimate valid until
|
|
73
|
+
if ("date_valid_till" in document && varName === "document_valid_until") {
|
|
74
|
+
return document.date_valid_till
|
|
75
|
+
? new Date(document.date_valid_till).toLocaleDateString("en-US", {
|
|
76
|
+
month: "long",
|
|
77
|
+
day: "numeric",
|
|
78
|
+
year: "numeric",
|
|
79
|
+
})
|
|
80
|
+
: null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Customer variables
|
|
84
|
+
if ((document as any).customer) {
|
|
85
|
+
if (varName === "customer_name") return (document as any).customer.name || null;
|
|
86
|
+
if (varName === "customer_email") return (document as any).customer.email || null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Bank account variables (from entity settings)
|
|
91
|
+
const bankAccounts = (entity.settings as any)?.bank_accounts as
|
|
92
|
+
| Array<{
|
|
93
|
+
iban?: string;
|
|
94
|
+
bank_name?: string;
|
|
95
|
+
bic?: string;
|
|
96
|
+
account_number?: string;
|
|
97
|
+
routing_number?: string;
|
|
98
|
+
sort_code?: string;
|
|
99
|
+
is_default?: boolean;
|
|
100
|
+
}>
|
|
101
|
+
| undefined;
|
|
102
|
+
const bankAccount = bankAccounts?.find((acc) => acc.is_default) ?? bankAccounts?.[0];
|
|
103
|
+
|
|
104
|
+
if (varName === "bank_account" && bankAccount) {
|
|
105
|
+
const lines: string[] = [];
|
|
106
|
+
if (bankAccount.bank_name) lines.push(bankAccount.bank_name);
|
|
107
|
+
if (bankAccount.iban) lines.push(`IBAN: ${bankAccount.iban}`);
|
|
108
|
+
else if (bankAccount.account_number) lines.push(`Account: ${bankAccount.account_number}`);
|
|
109
|
+
if (bankAccount.bic) lines.push(`BIC: ${bankAccount.bic}`);
|
|
110
|
+
return lines.join(", ") || null;
|
|
111
|
+
}
|
|
112
|
+
if (varName === "bank_account.iban") return bankAccount?.iban || null;
|
|
113
|
+
if (varName === "bank_account.bank_name") return bankAccount?.bank_name || null;
|
|
114
|
+
if (varName === "bank_account.bic") return bankAccount?.bic || null;
|
|
115
|
+
if (varName === "bank_account.account_number") return bankAccount?.account_number || null;
|
|
116
|
+
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Replace template variables in a string with styled React nodes for preview.
|
|
122
|
+
* Resolved values get a secondary bg, unresolved show as primary-colored placeholders.
|
|
123
|
+
*/
|
|
124
|
+
export function replaceTemplateVariablesForPreview(
|
|
125
|
+
template: string,
|
|
126
|
+
entity?: Entity | null,
|
|
127
|
+
document?: Partial<Invoice | Estimate> | null,
|
|
128
|
+
): React.ReactNode[] {
|
|
129
|
+
if (!template) return [];
|
|
130
|
+
|
|
131
|
+
const parts: React.ReactNode[] = [];
|
|
132
|
+
const regex = /\{([^}]+)\}/g;
|
|
133
|
+
let lastIndex = 0;
|
|
134
|
+
let match: RegExpExecArray | null = null;
|
|
135
|
+
|
|
136
|
+
match = regex.exec(template);
|
|
137
|
+
while (match !== null) {
|
|
138
|
+
if (match.index > lastIndex) {
|
|
139
|
+
parts.push(template.slice(lastIndex, match.index));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const varName = match[1];
|
|
143
|
+
const actualValue = getVariableValue(varName, entity, document);
|
|
144
|
+
const displayValue = actualValue || formatVariableName(varName);
|
|
145
|
+
|
|
146
|
+
parts.push(
|
|
147
|
+
<span
|
|
148
|
+
key={match.index}
|
|
149
|
+
className={cn(
|
|
150
|
+
"rounded px-1.5 py-0.5 font-medium text-xs",
|
|
151
|
+
actualValue ? "bg-secondary text-secondary-foreground" : "bg-primary/10 text-primary",
|
|
152
|
+
)}
|
|
153
|
+
>
|
|
154
|
+
{displayValue}
|
|
155
|
+
</span>,
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
lastIndex = regex.lastIndex;
|
|
159
|
+
match = regex.exec(template);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (lastIndex < template.length) {
|
|
163
|
+
parts.push(template.slice(lastIndex));
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return parts;
|
|
167
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Entity as SDKEntity } from "@spaceinvoices/js-sdk";
|
|
2
2
|
|
|
3
3
|
import { createContext, useContext } from "react";
|
|
4
4
|
|
|
5
5
|
/** Entity type with country_rules included (from getEntities response) */
|
|
6
|
-
export type Entity =
|
|
6
|
+
export type Entity = SDKEntity;
|
|
7
7
|
|
|
8
8
|
export type EntityEnvironment = "live" | "sandbox";
|
|
9
9
|
|