@spaceinvoices/react-ui 0.4.8 → 0.4.11

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 (276) hide show
  1. package/README.md +24 -8
  2. package/cli/dist/index.js +89 -26
  3. package/package.json +4 -1
  4. package/spaceinvoices.schema.json +6 -1
  5. package/src/common/autocomplete.tsx +69 -6
  6. package/src/components/advance-invoices/create/create-advance-invoice-form.tsx +124 -285
  7. package/src/components/advance-invoices/list/list-table.tsx +10 -3
  8. package/src/components/advance-invoices/list/locales/de.ts +2 -0
  9. package/src/components/advance-invoices/list/locales/en.ts +1 -0
  10. package/src/components/advance-invoices/list/locales/es.ts +1 -0
  11. package/src/components/advance-invoices/list/locales/fr.ts +1 -0
  12. package/src/components/advance-invoices/list/locales/hr.ts +1 -0
  13. package/src/components/advance-invoices/list/locales/it.ts +1 -0
  14. package/src/components/advance-invoices/list/locales/nl.ts +1 -0
  15. package/src/components/advance-invoices/list/locales/pl.ts +1 -0
  16. package/src/components/advance-invoices/list/locales/pt.ts +1 -0
  17. package/src/components/advance-invoices/list/locales/sl.ts +1 -0
  18. package/src/components/advance-invoices/list/use-advance-invoice-download.ts +1 -12
  19. package/src/components/credit-notes/create/create-credit-note-form.tsx +116 -238
  20. package/src/components/credit-notes/list/list-table.tsx +6 -3
  21. package/src/components/credit-notes/list/use-credit-note-download.ts +1 -12
  22. package/src/components/customers/customer-autocomplete.tsx +64 -11
  23. package/src/components/customers/customer-list-table/customer-list-table.tsx +3 -2
  24. package/src/components/dashboard/collection-rate-card/collection-rate-card.tsx +9 -1
  25. package/src/components/dashboard/collection-rate-card/locales/bg.ts +3 -0
  26. package/src/components/dashboard/collection-rate-card/locales/cs.ts +3 -0
  27. package/src/components/dashboard/collection-rate-card/locales/et.ts +3 -0
  28. package/src/components/dashboard/collection-rate-card/locales/fi.ts +3 -0
  29. package/src/components/dashboard/collection-rate-card/locales/is.ts +3 -0
  30. package/src/components/dashboard/collection-rate-card/locales/nb.ts +3 -0
  31. package/src/components/dashboard/collection-rate-card/locales/sk.ts +3 -0
  32. package/src/components/dashboard/collection-rate-card/locales/sv.ts +3 -0
  33. package/src/components/dashboard/invoice-status-chart/invoice-status-chart.tsx +10 -2
  34. package/src/components/dashboard/invoice-status-chart/locales/bg.ts +10 -0
  35. package/src/components/dashboard/invoice-status-chart/locales/cs.ts +10 -0
  36. package/src/components/dashboard/invoice-status-chart/locales/de.ts +1 -0
  37. package/src/components/dashboard/invoice-status-chart/locales/es.ts +1 -0
  38. package/src/components/dashboard/invoice-status-chart/locales/et.ts +10 -0
  39. package/src/components/dashboard/invoice-status-chart/locales/fi.ts +10 -0
  40. package/src/components/dashboard/invoice-status-chart/locales/fr.ts +1 -0
  41. package/src/components/dashboard/invoice-status-chart/locales/hr.ts +1 -0
  42. package/src/components/dashboard/invoice-status-chart/locales/is.ts +10 -0
  43. package/src/components/dashboard/invoice-status-chart/locales/it.ts +1 -0
  44. package/src/components/dashboard/invoice-status-chart/locales/nb.ts +10 -0
  45. package/src/components/dashboard/invoice-status-chart/locales/nl.ts +1 -0
  46. package/src/components/dashboard/invoice-status-chart/locales/pl.ts +1 -0
  47. package/src/components/dashboard/invoice-status-chart/locales/pt.ts +1 -0
  48. package/src/components/dashboard/invoice-status-chart/locales/sk.ts +10 -0
  49. package/src/components/dashboard/invoice-status-chart/locales/sl.ts +1 -0
  50. package/src/components/dashboard/invoice-status-chart/locales/sv.ts +10 -0
  51. package/src/components/dashboard/payment-methods-chart/locales/bg.ts +12 -0
  52. package/src/components/dashboard/payment-methods-chart/locales/cs.ts +12 -0
  53. package/src/components/dashboard/payment-methods-chart/locales/et.ts +12 -0
  54. package/src/components/dashboard/payment-methods-chart/locales/fi.ts +12 -0
  55. package/src/components/dashboard/payment-methods-chart/locales/is.ts +12 -0
  56. package/src/components/dashboard/payment-methods-chart/locales/nb.ts +12 -0
  57. package/src/components/dashboard/payment-methods-chart/locales/sk.ts +12 -0
  58. package/src/components/dashboard/payment-methods-chart/locales/sv.ts +12 -0
  59. package/src/components/dashboard/payment-methods-chart/payment-methods-chart.tsx +9 -1
  60. package/src/components/dashboard/payment-trend-chart/locales/bg.ts +6 -0
  61. package/src/components/dashboard/payment-trend-chart/locales/cs.ts +6 -0
  62. package/src/components/dashboard/payment-trend-chart/locales/de.ts +1 -0
  63. package/src/components/dashboard/payment-trend-chart/locales/es.ts +1 -0
  64. package/src/components/dashboard/payment-trend-chart/locales/et.ts +6 -0
  65. package/src/components/dashboard/payment-trend-chart/locales/fi.ts +6 -0
  66. package/src/components/dashboard/payment-trend-chart/locales/fr.ts +1 -0
  67. package/src/components/dashboard/payment-trend-chart/locales/hr.ts +1 -0
  68. package/src/components/dashboard/payment-trend-chart/locales/is.ts +6 -0
  69. package/src/components/dashboard/payment-trend-chart/locales/it.ts +1 -0
  70. package/src/components/dashboard/payment-trend-chart/locales/nb.ts +6 -0
  71. package/src/components/dashboard/payment-trend-chart/locales/nl.ts +1 -0
  72. package/src/components/dashboard/payment-trend-chart/locales/pl.ts +1 -0
  73. package/src/components/dashboard/payment-trend-chart/locales/pt.ts +1 -0
  74. package/src/components/dashboard/payment-trend-chart/locales/sk.ts +6 -0
  75. package/src/components/dashboard/payment-trend-chart/locales/sl.ts +1 -0
  76. package/src/components/dashboard/payment-trend-chart/locales/sv.ts +6 -0
  77. package/src/components/dashboard/payment-trend-chart/payment-trend-chart.tsx +15 -8
  78. package/src/components/dashboard/revenue-trend-chart/locales/bg.ts +6 -0
  79. package/src/components/dashboard/revenue-trend-chart/locales/cs.ts +6 -0
  80. package/src/components/dashboard/revenue-trend-chart/locales/de.ts +1 -0
  81. package/src/components/dashboard/revenue-trend-chart/locales/es.ts +1 -0
  82. package/src/components/dashboard/revenue-trend-chart/locales/et.ts +6 -0
  83. package/src/components/dashboard/revenue-trend-chart/locales/fi.ts +6 -0
  84. package/src/components/dashboard/revenue-trend-chart/locales/fr.ts +1 -0
  85. package/src/components/dashboard/revenue-trend-chart/locales/hr.ts +1 -0
  86. package/src/components/dashboard/revenue-trend-chart/locales/is.ts +6 -0
  87. package/src/components/dashboard/revenue-trend-chart/locales/it.ts +1 -0
  88. package/src/components/dashboard/revenue-trend-chart/locales/nb.ts +6 -0
  89. package/src/components/dashboard/revenue-trend-chart/locales/nl.ts +1 -0
  90. package/src/components/dashboard/revenue-trend-chart/locales/pl.ts +1 -0
  91. package/src/components/dashboard/revenue-trend-chart/locales/pt.ts +1 -0
  92. package/src/components/dashboard/revenue-trend-chart/locales/sk.ts +6 -0
  93. package/src/components/dashboard/revenue-trend-chart/locales/sl.ts +1 -0
  94. package/src/components/dashboard/revenue-trend-chart/locales/sv.ts +6 -0
  95. package/src/components/dashboard/revenue-trend-chart/revenue-trend-chart.tsx +15 -8
  96. package/src/components/dashboard/tax-collected-card/locales.ts +110 -0
  97. package/src/components/dashboard/tax-collected-card/tax-collected-card.tsx +8 -2
  98. package/src/components/dashboard/tax-collected-card/use-tax-collected.ts +4 -4
  99. package/src/components/dashboard/top-customers-chart/locales/bg.ts +7 -0
  100. package/src/components/dashboard/top-customers-chart/locales/cs.ts +7 -0
  101. package/src/components/dashboard/top-customers-chart/locales/de.ts +2 -0
  102. package/src/components/dashboard/top-customers-chart/locales/es.ts +2 -0
  103. package/src/components/dashboard/top-customers-chart/locales/et.ts +7 -0
  104. package/src/components/dashboard/top-customers-chart/locales/fi.ts +7 -0
  105. package/src/components/dashboard/top-customers-chart/locales/fr.ts +2 -0
  106. package/src/components/dashboard/top-customers-chart/locales/hr.ts +2 -0
  107. package/src/components/dashboard/top-customers-chart/locales/is.ts +7 -0
  108. package/src/components/dashboard/top-customers-chart/locales/it.ts +2 -0
  109. package/src/components/dashboard/top-customers-chart/locales/nb.ts +7 -0
  110. package/src/components/dashboard/top-customers-chart/locales/nl.ts +2 -0
  111. package/src/components/dashboard/top-customers-chart/locales/pl.ts +2 -0
  112. package/src/components/dashboard/top-customers-chart/locales/pt.ts +2 -0
  113. package/src/components/dashboard/top-customers-chart/locales/sk.ts +7 -0
  114. package/src/components/dashboard/top-customers-chart/locales/sl.ts +2 -0
  115. package/src/components/dashboard/top-customers-chart/locales/sv.ts +7 -0
  116. package/src/components/dashboard/top-customers-chart/top-customers-chart.tsx +23 -12
  117. package/src/components/delivery-notes/create/create-delivery-note-form.tsx +33 -20
  118. package/src/components/delivery-notes/list/list-table.tsx +22 -13
  119. package/src/components/delivery-notes/list/locales/de.ts +2 -0
  120. package/src/components/delivery-notes/list/locales/en.ts +1 -0
  121. package/src/components/delivery-notes/list/locales/es.ts +1 -0
  122. package/src/components/delivery-notes/list/locales/fr.ts +1 -0
  123. package/src/components/delivery-notes/list/locales/hr.ts +1 -0
  124. package/src/components/delivery-notes/list/locales/it.ts +1 -0
  125. package/src/components/delivery-notes/list/locales/nl.ts +1 -0
  126. package/src/components/delivery-notes/list/locales/pl.ts +1 -0
  127. package/src/components/delivery-notes/list/locales/pt.ts +1 -0
  128. package/src/components/delivery-notes/list/locales/sl.ts +1 -0
  129. package/src/components/delivery-notes/list/use-delivery-note-download.ts +1 -12
  130. package/src/components/documents/create/document-add-item-form.tsx +28 -16
  131. package/src/components/documents/create/document-add-item-tax-rate-field.tsx +12 -2
  132. package/src/components/documents/create/document-items-section.tsx +70 -39
  133. package/src/components/documents/create/document-recipient-section.tsx +10 -1
  134. package/src/components/documents/create/live-preview.tsx +113 -15
  135. package/src/components/documents/create/prepare-document-submission.ts +35 -16
  136. package/src/components/documents/create/use-document-customer-form.ts +14 -3
  137. package/src/components/documents/documents.hooks.ts +7 -2
  138. package/src/components/documents/shared/document-preview-display.tsx +136 -67
  139. package/src/components/documents/shared/scaled-document-preview.tsx +45 -5
  140. package/src/components/documents/view/document-actions-bar.tsx +284 -182
  141. package/src/components/documents/view/document-activities-list.tsx +3 -0
  142. package/src/components/documents/view/document-payments-list.tsx +3 -0
  143. package/src/components/documents/view/locales/de.ts +8 -0
  144. package/src/components/documents/view/locales/es.ts +8 -0
  145. package/src/components/documents/view/locales/fr.ts +8 -0
  146. package/src/components/documents/view/locales/hr.ts +8 -0
  147. package/src/components/documents/view/locales/it.ts +8 -0
  148. package/src/components/documents/view/locales/nl.ts +8 -0
  149. package/src/components/documents/view/locales/pl.ts +8 -0
  150. package/src/components/documents/view/locales/pt.ts +8 -0
  151. package/src/components/documents/view/locales/sl.ts +8 -0
  152. package/src/components/documents/view/use-document-download.ts +14 -25
  153. package/src/components/entities/create-entity-form.tsx +101 -16
  154. package/src/components/entities/entity-settings-form/entity-settings-form.tsx +10 -10
  155. package/src/components/entities/entity-settings-form/locales/de.ts +10 -0
  156. package/src/components/entities/entity-settings-form/locales/es.ts +10 -0
  157. package/src/components/entities/entity-settings-form/locales/fr.ts +10 -0
  158. package/src/components/entities/entity-settings-form/locales/hr.ts +10 -0
  159. package/src/components/entities/entity-settings-form/locales/it.ts +10 -0
  160. package/src/components/entities/entity-settings-form/locales/nl.ts +10 -0
  161. package/src/components/entities/entity-settings-form/locales/pl.ts +10 -0
  162. package/src/components/entities/entity-settings-form/locales/pt.ts +10 -0
  163. package/src/components/entities/entity-settings-form/locales/sl.ts +10 -0
  164. package/src/components/entities/fina-settings-form/fina-operator-required-dialog.tsx +3 -3
  165. package/src/components/entities/fina-settings-form/fina-settings-form.tsx +78 -124
  166. package/src/components/entities/fina-settings-form/sections/certificate-settings-section.tsx +8 -1
  167. package/src/components/entities/fina-settings-form/sections/premises-management-section.tsx +14 -2
  168. package/src/components/entities/fina-settings-form/sections/register-premise-dialog.tsx +7 -2
  169. package/src/components/entities/furs-settings-form/furs-settings-form.tsx +56 -130
  170. package/src/components/entities/furs-settings-form/sections/certificate-settings-section.tsx +8 -1
  171. package/src/components/entities/furs-settings-form/sections/enable-fiscalization-section.tsx +1 -0
  172. package/src/components/entities/furs-settings-form/sections/general-settings-section.tsx +15 -2
  173. package/src/components/entities/furs-settings-form/sections/premises-management-section.tsx +20 -3
  174. package/src/components/entities/furs-settings-form/sections/register-premise-dialog.tsx +38 -12
  175. package/src/components/entities/settings/defaults-settings-form.tsx +6 -6
  176. package/src/components/entities/settings/eslog-settings-form.tsx +13 -1
  177. package/src/components/entities/settings/pdf-template-selector/demo-invoice-data.ts +3 -22
  178. package/src/components/entities/shared/fiscalization-step-flow.ts +77 -0
  179. package/src/components/entities/shared/fiscalization-step-tabs.tsx +71 -0
  180. package/src/components/estimates/create/create-estimate-form.tsx +34 -21
  181. package/src/components/estimates/list/list-table.tsx +23 -14
  182. package/src/components/estimates/list/locales/de.ts +2 -0
  183. package/src/components/estimates/list/locales/en.ts +1 -0
  184. package/src/components/estimates/list/locales/es.ts +1 -0
  185. package/src/components/estimates/list/locales/fr.ts +1 -0
  186. package/src/components/estimates/list/locales/hr.ts +1 -0
  187. package/src/components/estimates/list/locales/it.ts +1 -0
  188. package/src/components/estimates/list/locales/nl.ts +1 -0
  189. package/src/components/estimates/list/locales/pl.ts +1 -0
  190. package/src/components/estimates/list/locales/pt.ts +1 -0
  191. package/src/components/estimates/list/locales/sl.ts +1 -0
  192. package/src/components/estimates/list/use-estimate-download.ts +1 -12
  193. package/src/components/export/document-export-form.tsx +33 -7
  194. package/src/components/export/sales-per-item-export-form.tsx +23 -7
  195. package/src/components/invoices/create/create-invoice-form.tsx +295 -329
  196. package/src/components/invoices/create/prepare-invoice-submission.ts +0 -8
  197. package/src/components/invoices/list/list-table.tsx +7 -4
  198. package/src/components/invoices/list/use-invoice-download.ts +1 -11
  199. package/src/components/invoices/send-email-dialog/locales/de.ts +20 -0
  200. package/src/components/invoices/send-email-dialog/locales/es.ts +20 -0
  201. package/src/components/invoices/send-email-dialog/locales/fr.ts +20 -0
  202. package/src/components/invoices/send-email-dialog/locales/hr.ts +20 -0
  203. package/src/components/invoices/send-email-dialog/locales/it.ts +20 -0
  204. package/src/components/invoices/send-email-dialog/locales/nl.ts +20 -0
  205. package/src/components/invoices/send-email-dialog/locales/pl.ts +20 -0
  206. package/src/components/invoices/send-email-dialog/locales/pt.ts +20 -0
  207. package/src/components/invoices/send-email-dialog/locales/sl.ts +20 -0
  208. package/src/components/invoices/send-email-dialog/send-email-dialog.tsx +77 -8
  209. package/src/components/invoices/view/eslog-info-display.tsx +17 -1
  210. package/src/components/invoices/view/fiscalization-status-card.tsx +7 -3
  211. package/src/components/items/item-combobox.tsx +26 -6
  212. package/src/components/items/item-list-table/item-list-table.tsx +5 -2
  213. package/src/components/payments/create-payment-form/index.ts +1 -0
  214. package/src/components/payments/list/list-table.tsx +14 -4
  215. package/src/components/recurring-invoices/list/list-table.tsx +7 -4
  216. package/src/components/request-logs/locales.ts +412 -0
  217. package/src/components/request-logs/request-log-detail.tsx +37 -21
  218. package/src/components/request-logs/request-log-list-table.tsx +57 -11
  219. package/src/components/table/data-table.tsx +5 -2
  220. package/src/components/table/date-cell.tsx +3 -1
  221. package/src/components/table/filter-bar.tsx +14 -2
  222. package/src/components/table/hooks/use-table-query.ts +1 -1
  223. package/src/components/table/locales.ts +1116 -0
  224. package/src/components/table/search-input.tsx +12 -3
  225. package/src/components/table/selection-toolbar.tsx +23 -6
  226. package/src/components/table/table-empty-state.tsx +43 -3
  227. package/src/components/table/table-no-results.tsx +3 -3
  228. package/src/components/table/table-pagination.tsx +4 -3
  229. package/src/components/table/types.ts +1 -0
  230. package/src/components/tax-reports/index.ts +1 -0
  231. package/src/components/tax-reports/kir-export-form.tsx +46 -8
  232. package/src/components/tax-reports/slovenia-tax-profile-step.tsx +191 -0
  233. package/src/components/tax-reports/slovenia-yearly-export-form.tsx +509 -0
  234. package/src/components/tax-reports/slovenia-yearly-review-step.tsx +253 -0
  235. package/src/components/tax-reports/slovenia-yearly-summary.tsx +19 -0
  236. package/src/components/taxes/tax-list-table/tax-list-table.tsx +3 -2
  237. package/src/components/ui/sidebar.tsx +3 -2
  238. package/src/components/ui/sticky-form-footer.tsx +7 -1
  239. package/src/components/webhook-logs/index.ts +6 -0
  240. package/src/components/webhook-logs/locales.ts +392 -0
  241. package/src/components/webhook-logs/webhook-delivery-detail.tsx +255 -0
  242. package/src/components/webhook-logs/webhook-delivery-list-table.tsx +278 -0
  243. package/src/components/wl-subscription/index.ts +1 -0
  244. package/src/components/wl-subscription/locked-feature.tsx +1 -0
  245. package/src/components/wl-subscription/paywall.tsx +193 -0
  246. package/src/components/wl-subscription/upgrade-modal.tsx +93 -29
  247. package/src/generate-schemas.ts +12 -7
  248. package/src/generated/schemas/customer.ts +2 -0
  249. package/src/generated/schemas/entity.ts +134 -0
  250. package/src/generated/schemas/exportsloveniayearlynormiranireport_body.ts +27 -0
  251. package/src/generated/schemas/index.ts +2 -0
  252. package/src/generated/schemas/me.ts +20 -1
  253. package/src/generated/schemas/renderadvanceinvoicepreview_body.ts +40 -34
  254. package/src/generated/schemas/rendercreditnotepreview_body.ts +42 -36
  255. package/src/generated/schemas/renderdeliverynotepreview_body.ts +23 -13
  256. package/src/generated/schemas/renderestimatepreview_body.ts +23 -13
  257. package/src/generated/schemas/renderinvoicepreview_body.ts +40 -34
  258. package/src/generated/schemas/sendemail_body.ts +44 -0
  259. package/src/generated/schemas/sloveniataxprofile.ts +42 -0
  260. package/src/generated/schemas/startpdfexport_body.ts +91 -1
  261. package/src/generated/schemas/webhook.ts +10 -0
  262. package/src/hooks/use-duplicate-document.ts +51 -13
  263. package/src/hooks/use-eslog-validation.ts +59 -0
  264. package/src/hooks/use-premise-selection.ts +186 -0
  265. package/src/lib/browser-cookies.ts +4 -4
  266. package/src/lib/date-fns-locale.ts +48 -0
  267. package/src/lib/fiscalization-options.ts +81 -0
  268. package/src/lib/locale.ts +38 -0
  269. package/src/lib/template-variables.tsx +1 -1
  270. package/src/lib/translation.ts +14 -3
  271. package/src/providers/entities-context.tsx +1 -0
  272. package/src/providers/entities-provider.tsx +102 -3
  273. package/src/providers/form-footer-context.tsx +37 -4
  274. package/src/providers/sdk-provider.tsx +7 -2
  275. package/src/providers/white-label-provider.tsx +4 -1
  276. package/src/providers/wl-subscription-provider.tsx +90 -3
@@ -1,8 +1,11 @@
1
- import { Check, Crown, Sparkles, Zap } from "lucide-react";
1
+ import { Check, Crown, Loader2, Sparkles, Zap } from "lucide-react";
2
+ import { useState } from "react";
2
3
 
3
4
  import { type GatedFeature, useWLSubscription, type WhiteLabelPlan } from "../../providers/wl-subscription-provider";
5
+ import { Badge } from "../ui/badge";
4
6
  import { Button } from "../ui/button";
5
7
  import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "../ui/dialog";
8
+ import { Switch } from "../ui/switch";
6
9
 
7
10
  type UpgradeModalProps = {
8
11
  isOpen: boolean;
@@ -18,9 +21,13 @@ type UpgradeModalProps = {
18
21
  *
19
22
  * Shows available plans and allows users to upgrade their subscription.
20
23
  * Highlights the feature that triggered the modal and which plans include it.
24
+ * Includes monthly/yearly toggle with 20% yearly discount.
21
25
  */
22
26
  export function UpgradeModal({ isOpen, onClose, feature, onUpgrade }: UpgradeModalProps) {
23
- const { plan: currentPlan, availablePlans } = useWLSubscription();
27
+ const { plan: currentPlan, availablePlans, createCheckout } = useWLSubscription();
28
+ const [isRedirecting, setIsRedirecting] = useState<string | null>(null);
29
+ const [checkoutError, setCheckoutError] = useState<string | null>(null);
30
+ const [isYearly, setIsYearly] = useState(false);
24
31
 
25
32
  // Sort plans by display order
26
33
  const sortedPlans = [...availablePlans].sort((a, b) => a.display_order - b.display_order);
@@ -30,13 +37,21 @@ export function UpgradeModal({ isOpen, onClose, feature, onUpgrade }: UpgradeMod
30
37
  ? sortedPlans.find((p) => p.features.length === 0 || p.features.includes(feature))
31
38
  : null;
32
39
 
33
- const handleUpgrade = (planSlug: string) => {
40
+ const handleUpgrade = async (planSlug: string) => {
34
41
  if (onUpgrade) {
35
42
  onUpgrade(planSlug);
36
43
  }
37
- // In the future, this would redirect to Stripe Checkout
38
- // For now, just close the modal
39
- onClose();
44
+
45
+ try {
46
+ setIsRedirecting(planSlug);
47
+ setCheckoutError(null);
48
+ const billingInterval = isYearly ? "yearly" : "monthly";
49
+ const checkoutUrl = await createCheckout(planSlug, billingInterval);
50
+ window.location.href = checkoutUrl;
51
+ } catch (err) {
52
+ setCheckoutError(err instanceof Error ? err.message : "Failed to start checkout");
53
+ setIsRedirecting(null);
54
+ }
40
55
  };
41
56
 
42
57
  return (
@@ -54,17 +69,38 @@ export function UpgradeModal({ isOpen, onClose, feature, onUpgrade }: UpgradeMod
54
69
  </DialogDescription>
55
70
  </DialogHeader>
56
71
 
57
- <div className="grid gap-4 py-4 md:grid-cols-3">
58
- {sortedPlans.map((plan) => (
59
- <PlanCard
60
- key={plan.id}
61
- plan={plan}
62
- isCurrentPlan={plan.slug === currentPlan?.slug}
63
- isRecommended={minimumPlanForFeature?.slug === plan.slug}
64
- highlightFeature={feature}
65
- onSelect={() => handleUpgrade(plan.slug)}
66
- />
67
- ))}
72
+ {/* Monthly/Yearly toggle */}
73
+ <div className="flex items-center justify-center gap-3">
74
+ <span className={`text-sm ${!isYearly ? "font-medium" : "text-muted-foreground"}`}>Monthly</span>
75
+ <Switch checked={isYearly} onCheckedChange={setIsYearly} />
76
+ <span className={`text-sm ${isYearly ? "font-medium" : "text-muted-foreground"}`}>Yearly</span>
77
+ {isYearly && (
78
+ <Badge variant="secondary" className="ml-1">
79
+ Save 20%
80
+ </Badge>
81
+ )}
82
+ </div>
83
+
84
+ {checkoutError && (
85
+ <p className="rounded-md bg-destructive/10 px-3 py-2 text-destructive text-sm">{checkoutError}</p>
86
+ )}
87
+
88
+ <div className="grid gap-4 py-4 md:grid-cols-2">
89
+ {sortedPlans
90
+ .filter((p) => !p.is_free)
91
+ .map((plan) => (
92
+ <PlanCard
93
+ key={plan.id}
94
+ plan={plan}
95
+ isYearly={isYearly}
96
+ isCurrentPlan={plan.slug === currentPlan?.slug}
97
+ isRecommended={minimumPlanForFeature?.slug === plan.slug}
98
+ highlightFeature={feature}
99
+ isLoading={isRedirecting === plan.slug}
100
+ isDisabled={isRedirecting !== null}
101
+ onSelect={() => handleUpgrade(plan.slug)}
102
+ />
103
+ ))}
68
104
  </div>
69
105
 
70
106
  {sortedPlans.length === 0 && (
@@ -83,19 +119,30 @@ export function UpgradeModal({ isOpen, onClose, feature, onUpgrade }: UpgradeMod
83
119
 
84
120
  type PlanCardProps = {
85
121
  plan: WhiteLabelPlan;
122
+ isYearly: boolean;
86
123
  isCurrentPlan: boolean;
87
124
  isRecommended: boolean;
88
125
  highlightFeature?: GatedFeature;
126
+ isLoading?: boolean;
127
+ isDisabled?: boolean;
89
128
  onSelect: () => void;
90
129
  };
91
130
 
92
- function PlanCard({ plan, isCurrentPlan, isRecommended, highlightFeature, onSelect }: PlanCardProps) {
93
- const priceDisplay = plan.is_free
94
- ? "Free"
95
- : plan.base_price_cents
96
- ? `${(plan.base_price_cents / 100).toFixed(0)}/${plan.billing_interval === "yearly" ? "yr" : "mo"}`
97
- : "Contact us";
131
+ function PlanCard({
132
+ plan,
133
+ isYearly,
134
+ isCurrentPlan,
135
+ isRecommended,
136
+ highlightFeature,
137
+ isLoading,
138
+ isDisabled,
139
+ onSelect,
140
+ }: PlanCardProps) {
141
+ const monthlyPrice = plan.base_price_cents ? plan.base_price_cents / 100 : 0;
142
+ const yearlyTotal = Math.round(monthlyPrice * 12 * 0.8 * 100) / 100;
143
+ const yearlyMonthly = Math.round((yearlyTotal / 12) * 100) / 100;
98
144
 
145
+ const displayPrice = isYearly ? yearlyMonthly : monthlyPrice;
99
146
  const documentsLimit = plan.limits?.documents_per_month ?? "Unlimited";
100
147
 
101
148
  return (
@@ -115,11 +162,13 @@ function PlanCard({ plan, isCurrentPlan, isRecommended, highlightFeature, onSele
115
162
  <h3 className="font-semibold">{plan.name}</h3>
116
163
  </div>
117
164
 
118
- <div className="mb-1 font-bold text-2xl">
119
- {plan.is_free ? "" : "€"}
120
- {priceDisplay}
165
+ <div className="mb-1">
166
+ <span className="font-bold text-2xl">&euro;{displayPrice.toFixed(0)}</span>
167
+ <span className="text-muted-foreground">/mo</span>
121
168
  </div>
122
169
 
170
+ {isYearly && <p className="mb-1 text-muted-foreground text-xs">&euro;{yearlyTotal.toFixed(0)} billed yearly</p>}
171
+
123
172
  <p className="mb-4 text-muted-foreground text-sm">{documentsLimit} documents/month</p>
124
173
 
125
174
  <ul className="mb-4 flex-1 space-y-2">
@@ -141,10 +190,11 @@ function PlanCard({ plan, isCurrentPlan, isRecommended, highlightFeature, onSele
141
190
  <Button
142
191
  variant={isCurrentPlan ? "outline" : isRecommended ? "default" : "secondary"}
143
192
  className="w-full"
144
- disabled={isCurrentPlan}
193
+ disabled={isCurrentPlan || isDisabled}
145
194
  onClick={onSelect}
146
195
  >
147
- {isCurrentPlan ? "Current Plan" : `Upgrade to ${plan.name}`}
196
+ {isLoading ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : null}
197
+ {isCurrentPlan ? "Current Plan" : isLoading ? "Redirecting..." : `Upgrade to ${plan.name}`}
148
198
  </Button>
149
199
  </div>
150
200
  );
@@ -158,6 +208,8 @@ function PlanIcon({ slug }: { slug: string }) {
158
208
  switch (slug) {
159
209
  case "free":
160
210
  return <Zap className="h-5 w-5 text-muted-foreground" />;
211
+ case "basic":
212
+ return <Zap className="h-5 w-5 text-blue-500" />;
161
213
  case "starter":
162
214
  return <Sparkles className="h-5 w-5 text-blue-500" />;
163
215
  case "advanced":
@@ -178,6 +230,7 @@ function getFeatureDisplayName(feature: GatedFeature): string {
178
230
  api_access: "API Access",
179
231
  webhooks: "Webhooks",
180
232
  priority_support: "Priority Support",
233
+ e_invoicing: "E-Invoicing",
181
234
  };
182
235
  return names[feature] || feature;
183
236
  }
@@ -186,6 +239,16 @@ function getPlanFeatures(slug: string): string[] {
186
239
  switch (slug) {
187
240
  case "free":
188
241
  return ["Basic invoicing", "Estimates & quotes", "Customer management", "PDF export"];
242
+ case "basic":
243
+ return [
244
+ "Invoices & estimates",
245
+ "Customer management",
246
+ "PDF export",
247
+ "FURS fiscalization",
248
+ "eSlog export",
249
+ "Recurring invoices",
250
+ "Email sending",
251
+ ];
189
252
  case "starter":
190
253
  return [
191
254
  "Everything in Free",
@@ -197,7 +260,8 @@ function getPlanFeatures(slug: string): string[] {
197
260
  ];
198
261
  case "advanced":
199
262
  return [
200
- "Everything in Starter",
263
+ "Everything in Basic",
264
+ "All features unlocked",
201
265
  "Custom templates",
202
266
  "API access",
203
267
  "Webhooks",
@@ -26,17 +26,22 @@ async function main() {
26
26
  await fs.mkdir(SCHEMAS_DIR, { recursive: true });
27
27
  await fs.mkdir(GENERATED_DIR, { recursive: true });
28
28
 
29
- // Fetch OpenAPI spec from running API and generate schemas
30
- const API_URL = "http://localhost:3000/openapi.json";
29
+ // Default to the checked-in API spec so generation is deterministic across worktrees.
30
+ const API_URL = process.env.OPENAPI_TARGET || path.resolve(import.meta.dir, "../../../apps/api/openapi.json");
31
31
  const openApiPath = path.resolve(GENERATED_DIR, "openapi.json");
32
32
 
33
33
  try {
34
- const res = await fetch(API_URL);
35
- if (!res.ok) throw new Error(`HTTP ${res.status}`);
36
- await fs.writeFile(openApiPath, await res.text());
37
- console.log(`Fetched OpenAPI spec from ${API_URL}`);
34
+ if (/^https?:\/\//.test(API_URL)) {
35
+ const res = await fetch(API_URL);
36
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
37
+ await fs.writeFile(openApiPath, await res.text());
38
+ console.log(`Fetched OpenAPI spec from ${API_URL}`);
39
+ } else {
40
+ await fs.copyFile(API_URL, openApiPath);
41
+ console.log(`Copied OpenAPI spec from ${API_URL}`);
42
+ }
38
43
  } catch (_error) {
39
- console.error(`Failed to fetch OpenAPI spec from ${API_URL}. Is the API running?`);
44
+ console.error(`Failed to fetch OpenAPI spec from ${API_URL}.`);
40
45
  process.exit(1);
41
46
  }
42
47
 
@@ -20,6 +20,7 @@ const createCustomerSchemaDefinition = z.object({
20
20
  country_code: z.union([z.string(), z.null()]).optional(),
21
21
  tax_number: z.union([z.string(), z.null()]).optional(),
22
22
  company_number: z.union([z.string(), z.null()]).optional(),
23
+ peppol_id: z.union([z.string(), z.null()]).optional(),
23
24
  email: z.union([z.string(), z.null()]).optional(),
24
25
  is_tax_subject: z.boolean().optional(),
25
26
  is_end_consumer: z.union([z.boolean(), z.null()]).optional(),
@@ -43,6 +44,7 @@ const updateCustomerSchemaDefinition = z
43
44
  country_code: z.union([z.string(), z.null()]),
44
45
  tax_number: z.union([z.string(), z.null()]),
45
46
  company_number: z.union([z.string(), z.null()]),
47
+ peppol_id: z.union([z.string(), z.null()]),
46
48
  email: z.union([z.string(), z.null()]),
47
49
  is_tax_subject: z.boolean(),
48
50
  is_end_consumer: z.union([z.boolean(), z.null()]),
@@ -24,6 +24,7 @@ const createEntitySchemaDefinition = z.object({
24
24
  tax_number_2: z.union([z.string(), z.null()]).optional(),
25
25
  company_number: z.union([z.string(), z.null()]).optional(),
26
26
  email: z.union([z.string(), z.null()]).optional(),
27
+ website: z.union([z.string(), z.null()]).optional(),
27
28
  environment: z.enum(["live", "sandbox"]).optional(),
28
29
  is_tax_subject: z.boolean().optional(),
29
30
  is_enabled: z.boolean().optional(),
@@ -71,6 +72,56 @@ const createEntitySchemaDefinition = z.object({
71
72
  default_credit_note_payment_terms: z.union([z.string(), z.null()]),
72
73
  document_footer: z.union([z.string(), z.null()]),
73
74
  default_document_signature: z.union([z.string(), z.null()]),
75
+ slovenia: z.union([
76
+ z
77
+ .object({
78
+ business_form: z.union([
79
+ z.enum(["sp", "doo", "dno", "club"]),
80
+ z.null(),
81
+ ]),
82
+ income_tax_regime: z.union([
83
+ z.enum(["normirani", "dejanski"]),
84
+ z.null(),
85
+ ]),
86
+ vat_profile: z.union([
87
+ z.enum(["standard", "special_vat_identified"]),
88
+ z.null(),
89
+ ]),
90
+ tax_residency: z.union([
91
+ z.enum(["resident", "non_resident"]),
92
+ z.null(),
93
+ ]),
94
+ yearly_reporting: z.union([
95
+ z
96
+ .object({
97
+ activity_code: z.union([z.string(), z.null()]),
98
+ registration_number: z.union([z.string(), z.null()]),
99
+ accounting_type: z.union([
100
+ z.enum(["records", "single_entry", "double_entry"]),
101
+ z.null(),
102
+ ]),
103
+ normiranec_insurance_basis: z.union([
104
+ z.enum(["full_time_self_employed", "other"]),
105
+ z.null(),
106
+ ]),
107
+ default_withholding_tax_amount: z.union([
108
+ z.number(),
109
+ z.null(),
110
+ ]),
111
+ default_foreign_tax_credit_amount: z.union([
112
+ z.number(),
113
+ z.null(),
114
+ ]),
115
+ })
116
+ .partial()
117
+ .passthrough(),
118
+ z.null(),
119
+ ]),
120
+ })
121
+ .partial()
122
+ .passthrough(),
123
+ z.null(),
124
+ ]),
74
125
  furs: z.union([
75
126
  z
76
127
  .object({
@@ -141,6 +192,10 @@ const createEntitySchemaDefinition = z.object({
141
192
  bank_accounts: z.union([z.array(z.any()), z.null()]),
142
193
  eslog_validation_enabled: z.union([z.boolean(), z.null()]),
143
194
  delivery_note_hide_prices: z.union([z.boolean(), z.null()]),
195
+ credit_note_negative_values: z.union([z.boolean(), z.null()]),
196
+ receipt_note: z.union([z.string(), z.null()]),
197
+ receipt_footer: z.union([z.string(), z.null()]),
198
+ receipt_signature: z.union([z.string(), z.null()]),
144
199
  tax_clause_defaults: z.union([
145
200
  z
146
201
  .object({
@@ -155,6 +210,18 @@ const createEntitySchemaDefinition = z.object({
155
210
  .passthrough(),
156
211
  z.null(),
157
212
  ]),
213
+ e_invoicing: z.union([
214
+ z
215
+ .object({
216
+ enabled: z.boolean().default(false),
217
+ provider: z.literal("flowin").default("flowin"),
218
+ auto_send: z.boolean().default(false),
219
+ default_scheme_id: z.string(),
220
+ })
221
+ .partial()
222
+ .passthrough(),
223
+ z.null(),
224
+ ]),
158
225
  })
159
226
  .partial()
160
227
  .passthrough()
@@ -181,6 +248,7 @@ const patchEntitySchemaDefinition = z
181
248
  tax_number_2: z.union([z.string(), z.null()]),
182
249
  company_number: z.union([z.string(), z.null()]),
183
250
  email: z.union([z.string(), z.null()]),
251
+ website: z.union([z.string(), z.null()]),
184
252
  is_tax_subject: z.boolean(),
185
253
  is_enabled: z.boolean(),
186
254
  settings: z
@@ -227,6 +295,56 @@ const patchEntitySchemaDefinition = z
227
295
  default_credit_note_payment_terms: z.union([z.string(), z.null()]),
228
296
  document_footer: z.union([z.string(), z.null()]),
229
297
  default_document_signature: z.union([z.string(), z.null()]),
298
+ slovenia: z.union([
299
+ z
300
+ .object({
301
+ business_form: z.union([
302
+ z.enum(["sp", "doo", "dno", "club"]),
303
+ z.null(),
304
+ ]),
305
+ income_tax_regime: z.union([
306
+ z.enum(["normirani", "dejanski"]),
307
+ z.null(),
308
+ ]),
309
+ vat_profile: z.union([
310
+ z.enum(["standard", "special_vat_identified"]),
311
+ z.null(),
312
+ ]),
313
+ tax_residency: z.union([
314
+ z.enum(["resident", "non_resident"]),
315
+ z.null(),
316
+ ]),
317
+ yearly_reporting: z.union([
318
+ z
319
+ .object({
320
+ activity_code: z.union([z.string(), z.null()]),
321
+ registration_number: z.union([z.string(), z.null()]),
322
+ accounting_type: z.union([
323
+ z.enum(["records", "single_entry", "double_entry"]),
324
+ z.null(),
325
+ ]),
326
+ normiranec_insurance_basis: z.union([
327
+ z.enum(["full_time_self_employed", "other"]),
328
+ z.null(),
329
+ ]),
330
+ default_withholding_tax_amount: z.union([
331
+ z.number(),
332
+ z.null(),
333
+ ]),
334
+ default_foreign_tax_credit_amount: z.union([
335
+ z.number(),
336
+ z.null(),
337
+ ]),
338
+ })
339
+ .partial()
340
+ .passthrough(),
341
+ z.null(),
342
+ ]),
343
+ })
344
+ .partial()
345
+ .passthrough(),
346
+ z.null(),
347
+ ]),
230
348
  furs: z.union([
231
349
  z
232
350
  .object({
@@ -297,6 +415,10 @@ const patchEntitySchemaDefinition = z
297
415
  bank_accounts: z.union([z.array(z.any()), z.null()]),
298
416
  eslog_validation_enabled: z.union([z.boolean(), z.null()]),
299
417
  delivery_note_hide_prices: z.union([z.boolean(), z.null()]),
418
+ credit_note_negative_values: z.union([z.boolean(), z.null()]),
419
+ receipt_note: z.union([z.string(), z.null()]),
420
+ receipt_footer: z.union([z.string(), z.null()]),
421
+ receipt_signature: z.union([z.string(), z.null()]),
300
422
  tax_clause_defaults: z.union([
301
423
  z
302
424
  .object({
@@ -311,6 +433,18 @@ const patchEntitySchemaDefinition = z
311
433
  .passthrough(),
312
434
  z.null(),
313
435
  ]),
436
+ e_invoicing: z.union([
437
+ z
438
+ .object({
439
+ enabled: z.boolean().default(false),
440
+ provider: z.literal("flowin").default("flowin"),
441
+ auto_send: z.boolean().default(false),
442
+ default_scheme_id: z.string(),
443
+ })
444
+ .partial()
445
+ .passthrough(),
446
+ z.null(),
447
+ ]),
314
448
  })
315
449
  .partial()
316
450
  .passthrough(),
@@ -0,0 +1,27 @@
1
+ /**
2
+ * This file was automatically generated using 'bun generate-schemas'.
3
+ * Do not edit this file manually. To update, run the generator again.
4
+ * @generated
5
+ */
6
+
7
+ import { z } from 'zod';
8
+
9
+ // Schemas for exportsloveniayearlynormiranireport_body endpoints
10
+
11
+ // Dependency schema for exportsloveniayearlynormiranireport_body
12
+ const exportSloveniaYearlyNormiraniReport_Body = z
13
+ .object({
14
+ year: z.number().int().gte(2025).lte(2100),
15
+ manual_values: z
16
+ .object({
17
+ withholding_tax_amount: z.number().gte(0),
18
+ foreign_tax_credit_amount: z.number().gte(0),
19
+ prior_advance_income_tax_amount: z.number().gte(0),
20
+ revenue_adjustment_decrease: z.number().gte(0),
21
+ revenue_adjustment_increase: z.number().gte(0),
22
+ })
23
+ .passthrough(),
24
+ })
25
+ .passthrough();
26
+
27
+
@@ -19,6 +19,7 @@ export * from './entity';
19
19
  export * from './entityapikey';
20
20
  export * from './entityuserrole';
21
21
  export * from './estimate';
22
+ export * from './exportsloveniayearlynormiranireport_body';
22
23
  export * from './finasettings';
23
24
  export * from './furssettings';
24
25
  export * from './invoice';
@@ -42,6 +43,7 @@ export * from './renderestimatepreview_body';
42
43
  export * from './renderinvoicepreview_body';
43
44
  export * from './senddocument_body';
44
45
  export * from './sendemail_body';
46
+ export * from './sloveniataxprofile';
45
47
  export * from './startpdfexport_body';
46
48
  export * from './stripeappconnect_body';
47
49
  export * from './stripeappcreateinvoice_body';
@@ -12,7 +12,26 @@ import { z } from 'zod';
12
12
  const patchMeSchemaDefinition = z
13
13
  .object({
14
14
  name: z.union([z.string(), z.null()]),
15
- locale: z.enum(["en", "de", "sl"]),
15
+ locale: z.enum([
16
+ "en",
17
+ "de",
18
+ "sl",
19
+ "it",
20
+ "fr",
21
+ "es",
22
+ "pt",
23
+ "nl",
24
+ "pl",
25
+ "hr",
26
+ "sv",
27
+ "fi",
28
+ "et",
29
+ "bg",
30
+ "cs",
31
+ "sk",
32
+ "nb",
33
+ "is",
34
+ ]),
16
35
  })
17
36
  .partial();
18
37
 
@@ -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
+ peppol_id: z.union([z.string(), z.null()]),
26
27
  is_end_consumer: z.union([z.boolean(), z.null()]),
27
28
  bank_account: z.union([
28
29
  z
@@ -30,13 +31,13 @@ const DocumentEntity = z
30
31
  type: z
31
32
  .enum(["iban", "us_domestic", "uk_domestic", "other"])
32
33
  .default("iban"),
33
- name: z.string(),
34
- bank_name: z.string(),
35
- iban: z.string(),
36
- account_number: z.string(),
37
- bic: z.string(),
38
- routing_number: z.string(),
39
- sort_code: z.string(),
34
+ name: z.union([z.string(), z.null()]),
35
+ bank_name: z.union([z.string(), z.null()]),
36
+ iban: z.union([z.string(), z.null()]),
37
+ account_number: z.union([z.string(), z.null()]),
38
+ bic: z.union([z.string(), z.null()]),
39
+ routing_number: z.union([z.string(), z.null()]),
40
+ sort_code: z.union([z.string(), z.null()]),
40
41
  })
41
42
  .partial()
42
43
  .passthrough(),
@@ -51,7 +52,7 @@ const DocumentEntity = z
51
52
  const CreateDocumentCustomer = DocumentEntity.and(
52
53
  z.union([
53
54
  z
54
- .object({ save_customer: z.boolean().default(true) })
55
+ .object({ save_customer: z.union([z.boolean(), z.null()]) })
55
56
  .partial()
56
57
  .passthrough(),
57
58
  z.null(),
@@ -63,28 +64,24 @@ const CreateDocumentCustomer = DocumentEntity.and(
63
64
  const CreateFinaInvoiceData = z.union([
64
65
  z
65
66
  .object({
66
- business_premise_name: z
67
- .string()
68
- .min(1)
69
- .max(20)
70
- .regex(/^[0-9a-zA-Z]{1,20}$/),
71
- electronic_device_name: z
72
- .string()
73
- .min(1)
74
- .max(20)
75
- .regex(/^\d{1,20}$/),
76
- operator_oib: z.string().min(11).max(11),
77
- payment_type: z.enum([
78
- "cash",
79
- "card",
80
- "online",
81
- "bank_transfer",
82
- "paypal",
83
- "crypto",
84
- "coupon",
85
- "other",
67
+ business_premise_name: z.union([z.string(), z.null()]),
68
+ electronic_device_name: z.union([z.string(), z.null()]),
69
+ operator_oib: z.union([z.string(), z.null()]),
70
+ operator_label: z.union([z.string(), z.null()]),
71
+ payment_type: z.union([
72
+ z.enum([
73
+ "cash",
74
+ "card",
75
+ "online",
76
+ "bank_transfer",
77
+ "paypal",
78
+ "crypto",
79
+ "coupon",
80
+ "other",
81
+ ]),
82
+ z.null(),
86
83
  ]),
87
- subsequent_submit: z.boolean(),
84
+ subsequent_submit: z.union([z.boolean(), z.null()]),
88
85
  })
89
86
  .partial(),
90
87
  z.null(),
@@ -121,6 +118,15 @@ const PartialAdvanceInvoicePreview = z.object({
121
118
  price: z.number(),
122
119
  gross_price: z.number(),
123
120
  description: z.string(),
121
+ unit: z.string(),
122
+ discounts: z.array(
123
+ z
124
+ .object({
125
+ value: z.number(),
126
+ type: z.enum(["percent", "amount"]).optional(),
127
+ })
128
+ .passthrough()
129
+ ),
124
130
  taxes: z.array(
125
131
  z
126
132
  .object({ rate: z.number(), tax_id: z.string() })
@@ -141,7 +147,7 @@ const PartialAdvanceInvoicePreview = z.object({
141
147
  // Dependency schema for renderadvanceinvoicepreview_body
142
148
  const DocumentItemTax = z
143
149
  .object({
144
- rate: z.number(),
150
+ rate: z.union([z.number(), z.null()]),
145
151
  tax_id: z.union([z.string(), z.null()]),
146
152
  classification: z.union([z.string(), z.null()]),
147
153
  reverse_charge: z.union([z.boolean(), z.null()]),
@@ -161,17 +167,17 @@ const LineDiscount = z.object({
161
167
  const CreateDocumentItem = z
162
168
  .object({
163
169
  type: z.union([z.literal("separator"), z.null()]),
164
- name: z.string().min(1),
170
+ name: z.union([z.string(), z.null()]),
165
171
  description: z.union([z.string(), z.null()]),
166
- price: z.number(),
172
+ price: z.union([z.number(), z.null()]),
167
173
  gross_price: z.union([z.number(), z.null()]),
168
- quantity: z.number().gte(-140737488355328).lte(140737488355327),
174
+ quantity: z.union([z.number(), z.null()]),
169
175
  unit: z.union([z.string(), z.null()]),
170
176
  taxes: z.array(DocumentItemTax),
171
177
  discounts: z.array(LineDiscount).max(5),
172
178
  item_id: z.union([z.string(), z.null()]),
173
179
  metadata: z.union([z.record(z.string(), z.any()), z.null()]),
174
- save_item: z.boolean().default(true),
180
+ save_item: z.union([z.boolean(), z.null()]),
175
181
  })
176
182
  .partial();
177
183