@spaceinvoices/react-ui 0.4.6 → 0.4.7

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 (55) 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 +60 -44
  4. package/src/components/credit-notes/create/create-credit-note-form.tsx +52 -42
  5. package/src/components/dashboard/collection-rate-card/use-collection-rate.ts +48 -92
  6. package/src/components/dashboard/invoice-status-chart/use-invoice-status.ts +48 -82
  7. package/src/components/dashboard/payment-methods-chart/use-payment-methods.ts +22 -31
  8. package/src/components/dashboard/payment-trend-chart/use-payment-trend.ts +33 -48
  9. package/src/components/dashboard/revenue-trend-chart/use-revenue-trend.ts +56 -76
  10. package/src/components/dashboard/shared/index.ts +1 -1
  11. package/src/components/dashboard/shared/use-revenue-data.ts +106 -182
  12. package/src/components/dashboard/shared/use-stats-counts.ts +18 -68
  13. package/src/components/dashboard/shared/use-stats-query.ts +35 -5
  14. package/src/components/dashboard/tax-collected-card/use-tax-collected.ts +57 -75
  15. package/src/components/dashboard/top-customers-chart/use-top-customers.ts +38 -49
  16. package/src/components/delivery-notes/create/create-delivery-note-form.tsx +3 -2
  17. package/src/components/documents/create/document-details-section.tsx +6 -4
  18. package/src/components/documents/create/document-recipient-section.tsx +30 -1
  19. package/src/components/documents/create/live-preview.tsx +15 -28
  20. package/src/components/documents/create/prepare-document-submission.ts +1 -0
  21. package/src/components/documents/create/use-document-customer-form.ts +4 -0
  22. package/src/components/documents/shared/document-preview-skeleton.tsx +63 -0
  23. package/src/components/documents/shared/index.ts +1 -0
  24. package/src/components/documents/view/document-actions-bar.tsx +29 -7
  25. package/src/components/entities/settings/tax-rules-settings-form.tsx +31 -13
  26. package/src/components/estimates/create/create-estimate-form.tsx +3 -2
  27. package/src/components/invoices/create/create-invoice-form.tsx +134 -62
  28. package/src/components/invoices/create/locales/de.ts +6 -0
  29. package/src/components/invoices/create/locales/es.ts +6 -0
  30. package/src/components/invoices/create/locales/fr.ts +6 -0
  31. package/src/components/invoices/create/locales/hr.ts +6 -0
  32. package/src/components/invoices/create/locales/it.ts +6 -0
  33. package/src/components/invoices/create/locales/nl.ts +6 -0
  34. package/src/components/invoices/create/locales/pl.ts +6 -0
  35. package/src/components/invoices/create/locales/pt.ts +6 -0
  36. package/src/components/invoices/create/locales/sl.ts +6 -0
  37. package/src/components/invoices/invoices.hooks.ts +1 -1
  38. package/src/components/ui/progress.tsx +27 -0
  39. package/src/generate-schemas.ts +15 -2
  40. package/src/generated/schemas/advanceinvoice.ts +2 -0
  41. package/src/generated/schemas/creditnote.ts +2 -0
  42. package/src/generated/schemas/customer.ts +2 -0
  43. package/src/generated/schemas/deliverynote.ts +2 -0
  44. package/src/generated/schemas/entity.ts +10 -0
  45. package/src/generated/schemas/estimate.ts +2 -0
  46. package/src/generated/schemas/finasettings.ts +4 -3
  47. package/src/generated/schemas/invoice.ts +2 -0
  48. package/src/generated/schemas/renderadvanceinvoicepreview_body.ts +16 -10
  49. package/src/generated/schemas/rendercreditnotepreview_body.ts +16 -10
  50. package/src/generated/schemas/renderdeliverynotepreview_body.ts +14 -7
  51. package/src/generated/schemas/renderestimatepreview_body.ts +14 -7
  52. package/src/generated/schemas/renderinvoicepreview_body.ts +16 -10
  53. package/src/generated/schemas/startpdfexport_body.ts +12 -17
  54. package/src/hooks/use-transaction-type-check.ts +152 -0
  55. package/src/hooks/use-vies-check.ts +7 -131
@@ -23,6 +23,7 @@ const DocumentEntity = z
23
23
  tax_number: z.union([z.string(), z.null()]),
24
24
  tax_number_2: z.union([z.string(), z.null()]),
25
25
  company_number: z.union([z.string(), z.null()]),
26
+ is_end_consumer: z.union([z.boolean(), z.null()]),
26
27
  bank_account: z.union([
27
28
  z
28
29
  .object({
@@ -62,18 +63,17 @@ const CreateDocumentCustomer = DocumentEntity.and(
62
63
  const CreateFinaInvoiceData = z.union([
63
64
  z
64
65
  .object({
65
- premise_id: z
66
+ business_premise_name: z
66
67
  .string()
67
68
  .min(1)
68
69
  .max(20)
69
70
  .regex(/^[0-9a-zA-Z]{1,20}$/),
70
- device_id: z
71
+ electronic_device_name: z
71
72
  .string()
72
73
  .min(1)
73
74
  .max(20)
74
75
  .regex(/^\d{1,20}$/),
75
76
  operator_oib: z.string().min(11).max(11),
76
- is_end_consumer: z.boolean(),
77
77
  payment_type: z.enum([
78
78
  "cash",
79
79
  "card",
@@ -103,8 +103,11 @@ const PartialAdvanceInvoicePreview = z.object({
103
103
  customer: CreateDocumentCustomer.optional(),
104
104
  note: z.union([z.string(), z.null()]).optional(),
105
105
  tax_clause: z.union([z.string(), z.null()]).optional(),
106
+ footer: z.union([z.string(), z.null()]).optional(),
107
+ signature: z.union([z.string(), z.null()]).optional(),
106
108
  currency_code: z.string().max(3).optional(),
107
109
  metadata: z.union([z.record(z.string(), z.any()), z.null()]).optional(),
110
+ reference: z.union([z.string(), z.null()]).optional(),
108
111
  date_due: z.union([z.string(), z.null()]).optional(),
109
112
  date_service: z.union([z.string(), z.null()]).optional(),
110
113
  date_service_to: z.union([z.string(), z.null()]).optional(),
@@ -139,10 +142,10 @@ const PartialAdvanceInvoicePreview = z.object({
139
142
  const DocumentItemTax = z
140
143
  .object({
141
144
  rate: z.number(),
142
- tax_id: z.string(),
143
- classification: z.string(),
144
- reverse_charge: z.boolean(),
145
- amount: z.number(),
145
+ tax_id: z.union([z.string(), z.null()]),
146
+ classification: z.union([z.string(), z.null()]),
147
+ reverse_charge: z.union([z.boolean(), z.null()]),
148
+ amount: z.union([z.number(), z.null()]),
146
149
  })
147
150
  .partial();
148
151
 
@@ -157,16 +160,16 @@ const LineDiscount = z.object({
157
160
  // Dependency schema for renderadvanceinvoicepreview_body
158
161
  const CreateDocumentItem = z
159
162
  .object({
160
- type: z.literal("separator"),
163
+ type: z.union([z.literal("separator"), z.null()]),
161
164
  name: z.string().min(1),
162
165
  description: z.union([z.string(), z.null()]),
163
166
  price: z.number(),
164
- gross_price: z.number(),
167
+ gross_price: z.union([z.number(), z.null()]),
165
168
  quantity: z.number().gte(-140737488355328).lte(140737488355327),
166
169
  unit: z.union([z.string(), z.null()]),
167
170
  taxes: z.array(DocumentItemTax),
168
171
  discounts: z.array(LineDiscount).max(5),
169
- item_id: z.string(),
172
+ item_id: z.union([z.string(), z.null()]),
170
173
  metadata: z.union([z.record(z.string(), z.any()), z.null()]),
171
174
  save_item: z.boolean().default(true),
172
175
  })
@@ -185,8 +188,11 @@ const CompleteAdvanceInvoicePreview = z.object({
185
188
  customer: CreateDocumentCustomer.optional(),
186
189
  note: z.union([z.string(), z.null()]).optional(),
187
190
  tax_clause: z.union([z.string(), z.null()]).optional(),
191
+ footer: z.union([z.string(), z.null()]).optional(),
192
+ signature: z.union([z.string(), z.null()]).optional(),
188
193
  currency_code: z.string().max(3).optional(),
189
194
  metadata: z.union([z.record(z.string(), z.any()), z.null()]).optional(),
195
+ reference: z.union([z.string(), z.null()]).optional(),
190
196
  date_due: z.union([z.string(), z.null()]).optional(),
191
197
  date_service: z.union([z.string(), z.null()]).optional(),
192
198
  date_service_to: z.union([z.string(), z.null()]).optional(),
@@ -23,6 +23,7 @@ const DocumentEntity = z
23
23
  tax_number: z.union([z.string(), z.null()]),
24
24
  tax_number_2: z.union([z.string(), z.null()]),
25
25
  company_number: z.union([z.string(), z.null()]),
26
+ is_end_consumer: z.union([z.boolean(), z.null()]),
26
27
  bank_account: z.union([
27
28
  z
28
29
  .object({
@@ -62,18 +63,17 @@ const CreateDocumentCustomer = DocumentEntity.and(
62
63
  const CreateFinaInvoiceData = z.union([
63
64
  z
64
65
  .object({
65
- premise_id: z
66
+ business_premise_name: z
66
67
  .string()
67
68
  .min(1)
68
69
  .max(20)
69
70
  .regex(/^[0-9a-zA-Z]{1,20}$/),
70
- device_id: z
71
+ electronic_device_name: z
71
72
  .string()
72
73
  .min(1)
73
74
  .max(20)
74
75
  .regex(/^\d{1,20}$/),
75
76
  operator_oib: z.string().min(11).max(11),
76
- is_end_consumer: z.boolean(),
77
77
  payment_type: z.enum([
78
78
  "cash",
79
79
  "card",
@@ -104,8 +104,11 @@ const PartialCreditNotePreview = z.object({
104
104
  note: z.union([z.string(), z.null()]).optional(),
105
105
  payment_terms: z.union([z.string(), z.null()]).optional(),
106
106
  tax_clause: z.union([z.string(), z.null()]).optional(),
107
+ footer: z.union([z.string(), z.null()]).optional(),
108
+ signature: z.union([z.string(), z.null()]).optional(),
107
109
  currency_code: z.string().max(3).optional(),
108
110
  metadata: z.union([z.record(z.string(), z.any()), z.null()]).optional(),
111
+ reference: z.union([z.string(), z.null()]).optional(),
109
112
  date_due: z.union([z.string(), z.null()]).optional(),
110
113
  date_service: z.union([z.string(), z.null()]).optional(),
111
114
  date_service_to: z.union([z.string(), z.null()]).optional(),
@@ -140,10 +143,10 @@ const PartialCreditNotePreview = z.object({
140
143
  const DocumentItemTax = z
141
144
  .object({
142
145
  rate: z.number(),
143
- tax_id: z.string(),
144
- classification: z.string(),
145
- reverse_charge: z.boolean(),
146
- amount: z.number(),
146
+ tax_id: z.union([z.string(), z.null()]),
147
+ classification: z.union([z.string(), z.null()]),
148
+ reverse_charge: z.union([z.boolean(), z.null()]),
149
+ amount: z.union([z.number(), z.null()]),
147
150
  })
148
151
  .partial();
149
152
 
@@ -158,16 +161,16 @@ const LineDiscount = z.object({
158
161
  // Dependency schema for rendercreditnotepreview_body
159
162
  const CreateDocumentItem = z
160
163
  .object({
161
- type: z.literal("separator"),
164
+ type: z.union([z.literal("separator"), z.null()]),
162
165
  name: z.string().min(1),
163
166
  description: z.union([z.string(), z.null()]),
164
167
  price: z.number(),
165
- gross_price: z.number(),
168
+ gross_price: z.union([z.number(), z.null()]),
166
169
  quantity: z.number().gte(-140737488355328).lte(140737488355327),
167
170
  unit: z.union([z.string(), z.null()]),
168
171
  taxes: z.array(DocumentItemTax),
169
172
  discounts: z.array(LineDiscount).max(5),
170
- item_id: z.string(),
173
+ item_id: z.union([z.string(), z.null()]),
171
174
  metadata: z.union([z.record(z.string(), z.any()), z.null()]),
172
175
  save_item: z.boolean().default(true),
173
176
  })
@@ -187,8 +190,11 @@ const CompleteCreditNotePreview = z.object({
187
190
  note: z.union([z.string(), z.null()]).optional(),
188
191
  payment_terms: z.union([z.string(), z.null()]).optional(),
189
192
  tax_clause: z.union([z.string(), z.null()]).optional(),
193
+ footer: z.union([z.string(), z.null()]).optional(),
194
+ signature: z.union([z.string(), z.null()]).optional(),
190
195
  currency_code: z.string().max(3).optional(),
191
196
  metadata: z.union([z.record(z.string(), z.any()), z.null()]).optional(),
197
+ reference: z.union([z.string(), z.null()]).optional(),
192
198
  date_due: z.union([z.string(), z.null()]).optional(),
193
199
  date_service: z.union([z.string(), z.null()]).optional(),
194
200
  date_service_to: z.union([z.string(), z.null()]).optional(),
@@ -23,6 +23,7 @@ const DocumentEntity = z
23
23
  tax_number: z.union([z.string(), z.null()]),
24
24
  tax_number_2: z.union([z.string(), z.null()]),
25
25
  company_number: z.union([z.string(), z.null()]),
26
+ is_end_consumer: z.union([z.boolean(), z.null()]),
26
27
  bank_account: z.union([
27
28
  z
28
29
  .object({
@@ -71,8 +72,11 @@ const PartialDeliveryNotePreview = z.object({
71
72
  note: z.union([z.string(), z.null()]).optional(),
72
73
  payment_terms: z.union([z.string(), z.null()]).optional(),
73
74
  tax_clause: z.union([z.string(), z.null()]).optional(),
75
+ footer: z.union([z.string(), z.null()]).optional(),
76
+ signature: z.union([z.string(), z.null()]).optional(),
74
77
  currency_code: z.string().max(3).optional(),
75
78
  metadata: z.union([z.record(z.string(), z.any()), z.null()]).optional(),
79
+ reference: z.union([z.string(), z.null()]).optional(),
76
80
  hide_prices: z.boolean().optional(),
77
81
  date_due: z.union([z.string(), z.null()]).optional(),
78
82
  date_service: z.union([z.string(), z.null()]).optional(),
@@ -108,10 +112,10 @@ const PartialDeliveryNotePreview = z.object({
108
112
  const DocumentItemTax = z
109
113
  .object({
110
114
  rate: z.number(),
111
- tax_id: z.string(),
112
- classification: z.string(),
113
- reverse_charge: z.boolean(),
114
- amount: z.number(),
115
+ tax_id: z.union([z.string(), z.null()]),
116
+ classification: z.union([z.string(), z.null()]),
117
+ reverse_charge: z.union([z.boolean(), z.null()]),
118
+ amount: z.union([z.number(), z.null()]),
115
119
  })
116
120
  .partial();
117
121
 
@@ -126,16 +130,16 @@ const LineDiscount = z.object({
126
130
  // Dependency schema for renderdeliverynotepreview_body
127
131
  const CreateDocumentItem = z
128
132
  .object({
129
- type: z.literal("separator"),
133
+ type: z.union([z.literal("separator"), z.null()]),
130
134
  name: z.string().min(1),
131
135
  description: z.union([z.string(), z.null()]),
132
136
  price: z.number(),
133
- gross_price: z.number(),
137
+ gross_price: z.union([z.number(), z.null()]),
134
138
  quantity: z.number().gte(-140737488355328).lte(140737488355327),
135
139
  unit: z.union([z.string(), z.null()]),
136
140
  taxes: z.array(DocumentItemTax),
137
141
  discounts: z.array(LineDiscount).max(5),
138
- item_id: z.string(),
142
+ item_id: z.union([z.string(), z.null()]),
139
143
  metadata: z.union([z.record(z.string(), z.any()), z.null()]),
140
144
  save_item: z.boolean().default(true),
141
145
  })
@@ -155,8 +159,11 @@ const CompleteDeliveryNotePreview = z.object({
155
159
  note: z.union([z.string(), z.null()]).optional(),
156
160
  payment_terms: z.union([z.string(), z.null()]).optional(),
157
161
  tax_clause: z.union([z.string(), z.null()]).optional(),
162
+ footer: z.union([z.string(), z.null()]).optional(),
163
+ signature: z.union([z.string(), z.null()]).optional(),
158
164
  currency_code: z.string().max(3).optional(),
159
165
  metadata: z.union([z.record(z.string(), z.any()), z.null()]).optional(),
166
+ reference: z.union([z.string(), z.null()]).optional(),
160
167
  hide_prices: z.boolean().optional(),
161
168
  date_due: z.union([z.string(), z.null()]).optional(),
162
169
  date_service: z.union([z.string(), z.null()]).optional(),
@@ -23,6 +23,7 @@ const DocumentEntity = z
23
23
  tax_number: z.union([z.string(), z.null()]),
24
24
  tax_number_2: z.union([z.string(), z.null()]),
25
25
  company_number: z.union([z.string(), z.null()]),
26
+ is_end_consumer: z.union([z.boolean(), z.null()]),
26
27
  bank_account: z.union([
27
28
  z
28
29
  .object({
@@ -71,8 +72,11 @@ const PartialEstimatePreview = z.object({
71
72
  note: z.union([z.string(), z.null()]).optional(),
72
73
  payment_terms: z.union([z.string(), z.null()]).optional(),
73
74
  tax_clause: z.union([z.string(), z.null()]).optional(),
75
+ footer: z.union([z.string(), z.null()]).optional(),
76
+ signature: z.union([z.string(), z.null()]).optional(),
74
77
  currency_code: z.string().max(3).optional(),
75
78
  metadata: z.union([z.record(z.string(), z.any()), z.null()]).optional(),
79
+ reference: z.union([z.string(), z.null()]).optional(),
76
80
  date_valid_till: z.union([z.string(), z.null()]).optional(),
77
81
  title_type: z.union([z.enum(["estimate", "quote"]), z.null()]).optional(),
78
82
  date_due: z.union([z.string(), z.null()]).optional(),
@@ -108,10 +112,10 @@ const PartialEstimatePreview = z.object({
108
112
  const DocumentItemTax = z
109
113
  .object({
110
114
  rate: z.number(),
111
- tax_id: z.string(),
112
- classification: z.string(),
113
- reverse_charge: z.boolean(),
114
- amount: z.number(),
115
+ tax_id: z.union([z.string(), z.null()]),
116
+ classification: z.union([z.string(), z.null()]),
117
+ reverse_charge: z.union([z.boolean(), z.null()]),
118
+ amount: z.union([z.number(), z.null()]),
115
119
  })
116
120
  .partial();
117
121
 
@@ -126,16 +130,16 @@ const LineDiscount = z.object({
126
130
  // Dependency schema for renderestimatepreview_body
127
131
  const CreateDocumentItem = z
128
132
  .object({
129
- type: z.literal("separator"),
133
+ type: z.union([z.literal("separator"), z.null()]),
130
134
  name: z.string().min(1),
131
135
  description: z.union([z.string(), z.null()]),
132
136
  price: z.number(),
133
- gross_price: z.number(),
137
+ gross_price: z.union([z.number(), z.null()]),
134
138
  quantity: z.number().gte(-140737488355328).lte(140737488355327),
135
139
  unit: z.union([z.string(), z.null()]),
136
140
  taxes: z.array(DocumentItemTax),
137
141
  discounts: z.array(LineDiscount).max(5),
138
- item_id: z.string(),
142
+ item_id: z.union([z.string(), z.null()]),
139
143
  metadata: z.union([z.record(z.string(), z.any()), z.null()]),
140
144
  save_item: z.boolean().default(true),
141
145
  })
@@ -155,8 +159,11 @@ const CompleteEstimatePreview = z.object({
155
159
  note: z.union([z.string(), z.null()]).optional(),
156
160
  payment_terms: z.union([z.string(), z.null()]).optional(),
157
161
  tax_clause: z.union([z.string(), z.null()]).optional(),
162
+ footer: z.union([z.string(), z.null()]).optional(),
163
+ signature: z.union([z.string(), z.null()]).optional(),
158
164
  currency_code: z.string().max(3).optional(),
159
165
  metadata: z.union([z.record(z.string(), z.any()), z.null()]).optional(),
166
+ reference: z.union([z.string(), z.null()]).optional(),
160
167
  date_valid_till: z.union([z.string(), z.null()]).optional(),
161
168
  title_type: z.union([z.enum(["estimate", "quote"]), z.null()]).optional(),
162
169
  date_due: z.union([z.string(), z.null()]).optional(),
@@ -23,6 +23,7 @@ const DocumentEntity = z
23
23
  tax_number: z.union([z.string(), z.null()]),
24
24
  tax_number_2: z.union([z.string(), z.null()]),
25
25
  company_number: z.union([z.string(), z.null()]),
26
+ is_end_consumer: z.union([z.boolean(), z.null()]),
26
27
  bank_account: z.union([
27
28
  z
28
29
  .object({
@@ -62,18 +63,17 @@ const CreateDocumentCustomer = DocumentEntity.and(
62
63
  const CreateFinaInvoiceData = z.union([
63
64
  z
64
65
  .object({
65
- premise_id: z
66
+ business_premise_name: z
66
67
  .string()
67
68
  .min(1)
68
69
  .max(20)
69
70
  .regex(/^[0-9a-zA-Z]{1,20}$/),
70
- device_id: z
71
+ electronic_device_name: z
71
72
  .string()
72
73
  .min(1)
73
74
  .max(20)
74
75
  .regex(/^\d{1,20}$/),
75
76
  operator_oib: z.string().min(11).max(11),
76
- is_end_consumer: z.boolean(),
77
77
  payment_type: z.enum([
78
78
  "cash",
79
79
  "card",
@@ -104,8 +104,11 @@ const PartialInvoicePreview = z.object({
104
104
  note: z.union([z.string(), z.null()]).optional(),
105
105
  payment_terms: z.union([z.string(), z.null()]).optional(),
106
106
  tax_clause: z.union([z.string(), z.null()]).optional(),
107
+ footer: z.union([z.string(), z.null()]).optional(),
108
+ signature: z.union([z.string(), z.null()]).optional(),
107
109
  currency_code: z.string().max(3).optional(),
108
110
  metadata: z.union([z.record(z.string(), z.any()), z.null()]).optional(),
111
+ reference: z.union([z.string(), z.null()]).optional(),
109
112
  date_due: z.union([z.string(), z.null()]).optional(),
110
113
  date_service: z.union([z.string(), z.null()]).optional(),
111
114
  date_service_to: z.union([z.string(), z.null()]).optional(),
@@ -141,10 +144,10 @@ const PartialInvoicePreview = z.object({
141
144
  const DocumentItemTax = z
142
145
  .object({
143
146
  rate: z.number(),
144
- tax_id: z.string(),
145
- classification: z.string(),
146
- reverse_charge: z.boolean(),
147
- amount: z.number(),
147
+ tax_id: z.union([z.string(), z.null()]),
148
+ classification: z.union([z.string(), z.null()]),
149
+ reverse_charge: z.union([z.boolean(), z.null()]),
150
+ amount: z.union([z.number(), z.null()]),
148
151
  })
149
152
  .partial();
150
153
 
@@ -159,16 +162,16 @@ const LineDiscount = z.object({
159
162
  // Dependency schema for renderinvoicepreview_body
160
163
  const CreateDocumentItem = z
161
164
  .object({
162
- type: z.literal("separator"),
165
+ type: z.union([z.literal("separator"), z.null()]),
163
166
  name: z.string().min(1),
164
167
  description: z.union([z.string(), z.null()]),
165
168
  price: z.number(),
166
- gross_price: z.number(),
169
+ gross_price: z.union([z.number(), z.null()]),
167
170
  quantity: z.number().gte(-140737488355328).lte(140737488355327),
168
171
  unit: z.union([z.string(), z.null()]),
169
172
  taxes: z.array(DocumentItemTax),
170
173
  discounts: z.array(LineDiscount).max(5),
171
- item_id: z.string(),
174
+ item_id: z.union([z.string(), z.null()]),
172
175
  metadata: z.union([z.record(z.string(), z.any()), z.null()]),
173
176
  save_item: z.boolean().default(true),
174
177
  })
@@ -188,8 +191,11 @@ const CompleteInvoicePreview = z.object({
188
191
  note: z.union([z.string(), z.null()]).optional(),
189
192
  payment_terms: z.union([z.string(), z.null()]).optional(),
190
193
  tax_clause: z.union([z.string(), z.null()]).optional(),
194
+ footer: z.union([z.string(), z.null()]).optional(),
195
+ signature: z.union([z.string(), z.null()]).optional(),
191
196
  currency_code: z.string().max(3).optional(),
192
197
  metadata: z.union([z.record(z.string(), z.any()), z.null()]).optional(),
198
+ reference: z.union([z.string(), z.null()]).optional(),
193
199
  date_due: z.union([z.string(), z.null()]).optional(),
194
200
  date_service: z.union([z.string(), z.null()]).optional(),
195
201
  date_service_to: z.union([z.string(), z.null()]).optional(),
@@ -10,29 +10,24 @@ import { z } from 'zod';
10
10
 
11
11
  // Dependency schema for startpdfexport_body
12
12
  const PdfExportByDocumentIds = z
13
- .object({
14
- type: z.enum([
15
- "invoice",
16
- "estimate",
17
- "credit_note",
18
- "advance_invoice",
19
- "delivery_note",
20
- ]),
21
- document_ids: z.array(z.string()).min(1),
22
- })
13
+ .object({ document_ids: z.array(z.string()).min(1) })
23
14
  .passthrough();
24
15
 
25
16
 
26
17
  // Dependency schema for startpdfexport_body
27
18
  const PdfExportByDateRange = z
28
19
  .object({
29
- type: z.enum([
30
- "invoice",
31
- "estimate",
32
- "credit_note",
33
- "advance_invoice",
34
- "delivery_note",
35
- ]),
20
+ types: z
21
+ .array(
22
+ z.enum([
23
+ "invoice",
24
+ "estimate",
25
+ "credit_note",
26
+ "advance_invoice",
27
+ "delivery_note",
28
+ ])
29
+ )
30
+ .min(1),
36
31
  date_from: z.string().optional(),
37
32
  date_to: z.string().optional(),
38
33
  })
@@ -0,0 +1,152 @@
1
+ import type { TransactionTypeCheckRequest, TransactionTypeCheckResponse } from "@spaceinvoices/js-sdk";
2
+ import { useQuery } from "@tanstack/react-query";
3
+ import { useMemo } from "react";
4
+ import { useSDK } from "../providers/sdk-provider";
5
+ import { useDebounce } from "./use-debounce";
6
+
7
+ export const TRANSACTION_TYPE_CHECK_CACHE_KEY = "transaction-type-check";
8
+
9
+ /** Debounce delay for transaction type checks (ms) */
10
+ const CHECK_DEBOUNCE_DELAY = 500;
11
+
12
+ /** Cache time for results - 5 minutes */
13
+ const CHECK_STALE_TIME = 5 * 60 * 1000;
14
+
15
+ export interface UseTransactionTypeCheckParams {
16
+ /** Issuer country name or code */
17
+ issuerCountry?: string | null;
18
+ /** Issuer country code (takes precedence over country name) */
19
+ issuerCountryCode?: string | null;
20
+ /** Whether the issuer is a tax subject (default: true) */
21
+ isTaxSubject?: boolean;
22
+ /** Customer country name or code */
23
+ customerCountry?: string | null;
24
+ /** Customer country code (takes precedence over country name) */
25
+ customerCountryCode?: string | null;
26
+ /** Customer VAT/tax number */
27
+ customerTaxNumber?: string | null;
28
+ /** Whether the customer is an end consumer (B2C override) */
29
+ customerIsEndConsumer?: boolean;
30
+ /** Whether to enable the query (default: true) */
31
+ enabled?: boolean;
32
+ }
33
+
34
+ export interface UseTransactionTypeCheckResult {
35
+ /** The check result */
36
+ data: TransactionTypeCheckResponse | undefined;
37
+ /** Whether the query is loading */
38
+ isLoading: boolean;
39
+ /** Whether the query is fetching (includes background refetches) */
40
+ isFetching: boolean;
41
+ /** Error if the query failed */
42
+ error: Error | null;
43
+ /** Whether reverse charge should be applied */
44
+ reverseChargeApplies: boolean;
45
+ /** Transaction type determined by check */
46
+ transactionType: TransactionTypeCheckResponse["transaction_type"] | undefined;
47
+ /** Customer country code returned by check */
48
+ customerCountryCode: string | null;
49
+ /** Warning message from VIES validation */
50
+ warning: string | null;
51
+ /** Whether VIES validation was successful */
52
+ viesValid: boolean | null;
53
+ }
54
+
55
+ /**
56
+ * Hook to check transaction type for a given issuer/customer combination.
57
+ * Uses debouncing to avoid excessive API calls during typing.
58
+ *
59
+ * @example
60
+ * ```tsx
61
+ * const { reverseChargeApplies, transactionType, warning } = useTransactionTypeCheck({
62
+ * issuerCountryCode: entity.country_code,
63
+ * isTaxSubject: entity.is_tax_subject,
64
+ * customerCountry: customer.country,
65
+ * customerTaxNumber: customer.tax_number,
66
+ * customerIsEndConsumer: customer.is_end_consumer,
67
+ * });
68
+ * ```
69
+ */
70
+ export function useTransactionTypeCheck({
71
+ issuerCountry,
72
+ issuerCountryCode,
73
+ isTaxSubject = true,
74
+ customerCountry,
75
+ customerCountryCode,
76
+ customerTaxNumber,
77
+ customerIsEndConsumer,
78
+ enabled = true,
79
+ }: UseTransactionTypeCheckParams): UseTransactionTypeCheckResult {
80
+ const { sdk } = useSDK();
81
+
82
+ // Build the request object
83
+ const requestData = useMemo((): TransactionTypeCheckRequest | null => {
84
+ // Need at least issuer info to make a check
85
+ if (!issuerCountry && !issuerCountryCode) return null;
86
+
87
+ // Need at least some customer info to make a meaningful check
88
+ if (!customerCountry && !customerCountryCode && !customerTaxNumber) return null;
89
+
90
+ return {
91
+ issuer: {
92
+ country: issuerCountry || undefined,
93
+ country_code: issuerCountryCode || undefined,
94
+ is_tax_subject: isTaxSubject,
95
+ },
96
+ customer: {
97
+ country: customerCountry || undefined,
98
+ country_code: customerCountryCode || undefined,
99
+ tax_number: customerTaxNumber || undefined,
100
+ is_end_consumer: customerIsEndConsumer,
101
+ },
102
+ };
103
+ }, [
104
+ issuerCountry,
105
+ issuerCountryCode,
106
+ isTaxSubject,
107
+ customerCountry,
108
+ customerCountryCode,
109
+ customerTaxNumber,
110
+ customerIsEndConsumer,
111
+ ]);
112
+
113
+ // Debounce the request data to avoid excessive API calls
114
+ const debouncedRequest = useDebounce(requestData, CHECK_DEBOUNCE_DELAY);
115
+
116
+ // Create a stable query key
117
+ const queryKey = useMemo(() => [TRANSACTION_TYPE_CHECK_CACHE_KEY, debouncedRequest], [debouncedRequest]);
118
+
119
+ const query = useQuery({
120
+ queryKey,
121
+ queryFn: async () => {
122
+ if (!debouncedRequest) throw new Error("No request data");
123
+ // Use sdk.vies.checkVies which hits the same endpoint types
124
+ // (sdk.transactionType is not reliably available in Vite pre-bundled builds)
125
+ const checkFn = sdk.transactionType?.checkTransactionType ?? sdk.vies.checkVies;
126
+ return checkFn(debouncedRequest);
127
+ },
128
+ enabled: enabled && !!sdk && !!debouncedRequest,
129
+ staleTime: CHECK_STALE_TIME,
130
+ refetchOnWindowFocus: false,
131
+ });
132
+
133
+ return {
134
+ data: query.data,
135
+ isLoading: query.isLoading,
136
+ isFetching: query.isFetching,
137
+ error: query.error,
138
+ reverseChargeApplies: query.data?.reverse_charge_applies ?? false,
139
+ transactionType: query.data?.transaction_type,
140
+ customerCountryCode: query.data?.customer_country_code ?? null,
141
+ warning: query.data?.warning ?? null,
142
+ viesValid: query.data?.vies_valid ?? null,
143
+ };
144
+ }
145
+
146
+ /**
147
+ * @deprecated Use useTransactionTypeCheck instead
148
+ */
149
+ export const useViesCheck = useTransactionTypeCheck;
150
+ export type UseViesCheckParams = UseTransactionTypeCheckParams;
151
+ export type UseViesCheckResult = UseTransactionTypeCheckResult;
152
+ export const VIES_CHECK_CACHE_KEY = TRANSACTION_TYPE_CHECK_CACHE_KEY;