shutro-erp 0.2.1 → 0.3.0

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 (229) hide show
  1. package/README.md +17 -10
  2. package/dist/account_portal/.kosh/bindings.d.ts +22 -0
  3. package/dist/account_portal/.kosh/bindings.js +15 -0
  4. package/dist/account_portal/.kosh/schema.d.ts +1350 -0
  5. package/dist/account_portal/index.d.ts +3 -0
  6. package/dist/account_portal/index.js +73 -0
  7. package/dist/account_portal/module.d.ts +5983 -0
  8. package/dist/account_portal/module.js +18 -0
  9. package/dist/accounting/.kosh/bindings.js +1 -1
  10. package/dist/accounting/.kosh/schema.d.ts +142 -9
  11. package/dist/accounting/chart.d.ts +40 -8
  12. package/dist/accounting/chart.js +124 -30
  13. package/dist/accounting/closing.d.ts +6 -1
  14. package/dist/accounting/closing.js +5 -1
  15. package/dist/accounting/demo.js +6 -5
  16. package/dist/accounting/index.d.ts +3 -3
  17. package/dist/accounting/index.js +200 -23
  18. package/dist/accounting/module.d.ts +3326 -1086
  19. package/dist/accounting/module.js +408 -66
  20. package/dist/accounting/payments.d.ts +25 -0
  21. package/dist/accounting/payments.js +96 -4
  22. package/dist/accounting/web/RegisterPayment.d.ts +3 -2
  23. package/dist/accounting/web/RegisterPayment.js +39 -6
  24. package/dist/accounting/web/SettingsPage.js +5 -1
  25. package/dist/accounting/web/messages.js +10 -0
  26. package/dist/cli/init.js +172 -48
  27. package/dist/cli/launch.d.ts +16 -0
  28. package/dist/cli/launch.js +138 -0
  29. package/dist/cli/prompt.d.ts +35 -0
  30. package/dist/cli/prompt.js +46 -0
  31. package/dist/cli/templates.d.ts +11 -3
  32. package/dist/cli/templates.js +32 -7
  33. package/dist/cli/tui.d.ts +7 -0
  34. package/dist/cli/tui.js +254 -0
  35. package/dist/cli/ui.d.ts +25 -5
  36. package/dist/cli/ui.js +49 -9
  37. package/dist/contacts/.kosh/bindings.js +1 -1
  38. package/dist/contacts/.kosh/schema.d.ts +3 -1
  39. package/dist/contacts/index.js +24 -1
  40. package/dist/contacts/module.d.ts +42 -0
  41. package/dist/contacts/module.js +3 -1
  42. package/dist/import/convert.d.ts +55 -0
  43. package/dist/import/convert.js +224 -0
  44. package/dist/import/csv.d.ts +28 -0
  45. package/dist/import/csv.js +115 -0
  46. package/dist/import/index.d.ts +33 -0
  47. package/dist/import/index.js +60 -0
  48. package/dist/import/mapping.d.ts +15 -0
  49. package/dist/import/mapping.js +33 -0
  50. package/dist/import/match.d.ts +24 -0
  51. package/dist/import/match.js +60 -0
  52. package/dist/import/models.d.ts +2 -0
  53. package/dist/import/models.js +102 -0
  54. package/dist/import/routes.d.ts +13 -0
  55. package/dist/import/routes.js +392 -0
  56. package/dist/import/run.d.ts +131 -0
  57. package/dist/import/run.js +568 -0
  58. package/dist/import/service.d.ts +153 -0
  59. package/dist/import/service.js +367 -0
  60. package/dist/import/web/ImportButton.d.ts +7 -0
  61. package/dist/import/web/ImportButton.js +31 -0
  62. package/dist/import/web/ImportWizard.d.ts +75 -0
  63. package/dist/import/web/ImportWizard.js +217 -0
  64. package/dist/import/web/index.d.ts +13 -0
  65. package/dist/import/web/index.js +18 -0
  66. package/dist/import/web/messages.d.ts +2 -0
  67. package/dist/import/web/messages.js +139 -0
  68. package/dist/import/worker.d.ts +3 -0
  69. package/dist/import/worker.js +52 -0
  70. package/dist/import/xlsx.d.ts +20 -0
  71. package/dist/import/xlsx.js +192 -0
  72. package/dist/l10n_bd/.kosh/bindings.d.ts +22 -0
  73. package/dist/l10n_bd/.kosh/bindings.js +15 -0
  74. package/dist/l10n_bd/.kosh/schema.d.ts +1281 -0
  75. package/dist/l10n_bd/documents.d.ts +8 -0
  76. package/dist/l10n_bd/documents.js +183 -0
  77. package/dist/l10n_bd/index.d.ts +8 -0
  78. package/dist/l10n_bd/index.js +156 -0
  79. package/dist/l10n_bd/module.d.ts +5705 -0
  80. package/dist/l10n_bd/module.js +163 -0
  81. package/dist/l10n_bd/mushak.d.ts +67 -0
  82. package/dist/l10n_bd/mushak.js +139 -0
  83. package/dist/l10n_bd/routes.d.ts +3 -0
  84. package/dist/l10n_bd/routes.js +205 -0
  85. package/dist/l10n_bd/web/MushakPage.d.ts +7 -0
  86. package/dist/l10n_bd/web/MushakPage.js +53 -0
  87. package/dist/l10n_bd/web/index.d.ts +13 -0
  88. package/dist/l10n_bd/web/index.js +18 -0
  89. package/dist/l10n_bd/web/messages.d.ts +2 -0
  90. package/dist/l10n_bd/web/messages.js +101 -0
  91. package/dist/l10n_in/.kosh/bindings.d.ts +22 -0
  92. package/dist/l10n_in/.kosh/bindings.js +15 -0
  93. package/dist/l10n_in/.kosh/schema.d.ts +1343 -0
  94. package/dist/l10n_in/documents.d.ts +8 -0
  95. package/dist/l10n_in/documents.js +114 -0
  96. package/dist/l10n_in/einvoice.d.ts +253 -0
  97. package/dist/l10n_in/einvoice.js +485 -0
  98. package/dist/l10n_in/gstr.d.ts +109 -0
  99. package/dist/l10n_in/gstr.js +430 -0
  100. package/dist/l10n_in/index.d.ts +20 -0
  101. package/dist/l10n_in/index.js +232 -0
  102. package/dist/l10n_in/module.d.ts +7823 -0
  103. package/dist/l10n_in/module.js +427 -0
  104. package/dist/l10n_in/routes-einvoice.d.ts +15 -0
  105. package/dist/l10n_in/routes-einvoice.js +124 -0
  106. package/dist/l10n_in/routes.d.ts +17 -0
  107. package/dist/l10n_in/routes.js +282 -0
  108. package/dist/l10n_in/web/EInvoicePanel.d.ts +8 -0
  109. package/dist/l10n_in/web/EInvoicePanel.js +63 -0
  110. package/dist/l10n_in/web/GstPage.d.ts +7 -0
  111. package/dist/l10n_in/web/GstPage.js +57 -0
  112. package/dist/l10n_in/web/GstSettings.d.ts +10 -0
  113. package/dist/l10n_in/web/GstSettings.js +36 -0
  114. package/dist/l10n_in/web/index.d.ts +15 -0
  115. package/dist/l10n_in/web/index.js +22 -0
  116. package/dist/l10n_in/web/messages.d.ts +2 -0
  117. package/dist/l10n_in/web/messages.js +166 -0
  118. package/dist/modules-sdk/demo.d.ts +2 -0
  119. package/dist/modules-sdk/demo.js +7 -3
  120. package/dist/modules-sdk/index.d.ts +2 -2
  121. package/dist/modules-sdk/index.js +1 -1
  122. package/dist/modules-sdk/manifest.d.ts +132 -0
  123. package/dist/modules-sdk/manifest.js +22 -0
  124. package/dist/notify/inbox.js +21 -0
  125. package/dist/notify/messages.js +4 -0
  126. package/dist/notify/models.d.ts +1 -1
  127. package/dist/notify/models.js +2 -0
  128. package/dist/notify/web/messages.js +4 -0
  129. package/dist/portal/.kosh/bindings.d.ts +22 -0
  130. package/dist/portal/.kosh/bindings.js +15 -0
  131. package/dist/portal/.kosh/schema.d.ts +346 -0
  132. package/dist/portal/announce.d.ts +16 -0
  133. package/dist/portal/announce.js +117 -0
  134. package/dist/portal/documents.d.ts +17 -0
  135. package/dist/portal/documents.js +61 -0
  136. package/dist/portal/index.d.ts +20 -0
  137. package/dist/portal/index.js +65 -0
  138. package/dist/portal/module.d.ts +1405 -0
  139. package/dist/portal/module.js +84 -0
  140. package/dist/portal/routes-documents.d.ts +2 -0
  141. package/dist/portal/routes-documents.js +391 -0
  142. package/dist/portal/routes.d.ts +13 -0
  143. package/dist/portal/routes.js +313 -0
  144. package/dist/portal/rules.d.ts +11 -0
  145. package/dist/portal/rules.js +25 -0
  146. package/dist/portal/web/PortalAccess.d.ts +8 -0
  147. package/dist/portal/web/PortalAccess.js +66 -0
  148. package/dist/portal/web/index.d.ts +12 -0
  149. package/dist/portal/web/index.js +17 -0
  150. package/dist/portal/web/messages.d.ts +2 -0
  151. package/dist/portal/web/messages.js +33 -0
  152. package/dist/product/.kosh/bindings.js +1 -1
  153. package/dist/product/.kosh/schema.d.ts +12 -3
  154. package/dist/product/demo.js +6 -5
  155. package/dist/product/index.d.ts +1 -0
  156. package/dist/product/index.js +17 -4
  157. package/dist/product/module.d.ts +346 -14
  158. package/dist/product/module.js +48 -18
  159. package/dist/product/taxes.d.ts +59 -0
  160. package/dist/product/taxes.js +61 -0
  161. package/dist/project/.kosh/bindings.js +1 -1
  162. package/dist/project/.kosh/schema.d.ts +3 -1
  163. package/dist/project/module.d.ts +20 -0
  164. package/dist/project_portal/.kosh/bindings.d.ts +22 -0
  165. package/dist/project_portal/.kosh/bindings.js +15 -0
  166. package/dist/project_portal/.kosh/schema.d.ts +671 -0
  167. package/dist/project_portal/index.d.ts +9 -0
  168. package/dist/project_portal/index.js +42 -0
  169. package/dist/project_portal/module.d.ts +2142 -0
  170. package/dist/project_portal/module.js +22 -0
  171. package/dist/purchase/.kosh/bindings.js +1 -1
  172. package/dist/purchase/.kosh/schema.d.ts +15 -4
  173. package/dist/purchase/demo.js +3 -3
  174. package/dist/purchase/index.js +1 -1
  175. package/dist/purchase/module.d.ts +232 -8
  176. package/dist/purchase/module.js +51 -9
  177. package/dist/purchase_account/.kosh/bindings.js +1 -1
  178. package/dist/purchase_account/.kosh/schema.d.ts +144 -10
  179. package/dist/purchase_account/module.d.ts +2008 -641
  180. package/dist/purchase_account/module.js +2 -2
  181. package/dist/purchase_portal/.kosh/bindings.d.ts +22 -0
  182. package/dist/purchase_portal/.kosh/bindings.js +15 -0
  183. package/dist/purchase_portal/.kosh/schema.d.ts +822 -0
  184. package/dist/purchase_portal/index.d.ts +9 -0
  185. package/dist/purchase_portal/index.js +53 -0
  186. package/dist/purchase_portal/module.d.ts +2758 -0
  187. package/dist/purchase_portal/module.js +18 -0
  188. package/dist/reporting/documents.js +20 -3
  189. package/dist/reporting/index.d.ts +1 -0
  190. package/dist/reporting/index.js +1 -0
  191. package/dist/reporting/routes-documents.js +9 -2
  192. package/dist/reporting/words.d.ts +11 -0
  193. package/dist/reporting/words.js +229 -0
  194. package/dist/sale_account/.kosh/bindings.js +1 -1
  195. package/dist/sale_account/.kosh/schema.d.ts +144 -10
  196. package/dist/sale_account/module.d.ts +2008 -641
  197. package/dist/sale_account/module.js +3 -3
  198. package/dist/sale_portal/.kosh/bindings.d.ts +22 -0
  199. package/dist/sale_portal/.kosh/bindings.js +15 -0
  200. package/dist/sale_portal/.kosh/schema.d.ts +736 -0
  201. package/dist/sale_portal/index.d.ts +9 -0
  202. package/dist/sale_portal/index.js +71 -0
  203. package/dist/sale_portal/module.d.ts +2718 -0
  204. package/dist/sale_portal/module.js +19 -0
  205. package/dist/sale_project/.kosh/bindings.js +1 -1
  206. package/dist/sale_project/.kosh/schema.d.ts +15 -4
  207. package/dist/sale_project/module.d.ts +390 -10
  208. package/dist/sales/.kosh/bindings.js +1 -1
  209. package/dist/sales/.kosh/schema.d.ts +15 -4
  210. package/dist/sales/demo.js +3 -3
  211. package/dist/sales/index.js +67 -1
  212. package/dist/sales/module.d.ts +232 -8
  213. package/dist/sales/module.js +51 -12
  214. package/dist/server/auth/base.js +2 -0
  215. package/dist/server/auth/service.d.ts +2 -0
  216. package/dist/server/auth/service.js +7 -1
  217. package/dist/server/index.d.ts +1 -1
  218. package/dist/server/index.js +1 -1
  219. package/dist/server/server.js +26 -1
  220. package/dist/ui/api.d.ts +2 -0
  221. package/dist/ui/app.js +1 -1
  222. package/dist/ui/context.d.ts +3 -1
  223. package/dist/ui/context.js +2 -2
  224. package/dist/ui/index.d.ts +1 -1
  225. package/dist/ui/index.js +1 -1
  226. package/dist/ui/lib/format.d.ts +2 -0
  227. package/dist/ui/lib/format.js +3 -1
  228. package/dist/ui/views/FormView.js +19 -6
  229. package/package.json +50 -2
@@ -272,6 +272,26 @@ export declare const AccountTax: import("../server/orm.js").Model<"account.tax",
272
272
  readonly hasDefault: true;
273
273
  readonly readonly: false;
274
274
  }>;
275
+ readonly sequence: import("../server/orm.js").ScalarField<"integer", number, number, {
276
+ readonly required: true;
277
+ readonly computed: false;
278
+ readonly inverse: false;
279
+ readonly sequence: false;
280
+ readonly computeName: undefined;
281
+ readonly store: true;
282
+ readonly hasDefault: true;
283
+ readonly readonly: false;
284
+ }>;
285
+ readonly amountType: import("../server/orm.js").SelectionField<"fixed" | "percent", {
286
+ readonly required: true;
287
+ readonly computed: false;
288
+ readonly inverse: false;
289
+ readonly sequence: false;
290
+ readonly computeName: undefined;
291
+ readonly store: true;
292
+ readonly hasDefault: true;
293
+ readonly readonly: false;
294
+ }>;
275
295
  readonly rate: import("../server/orm.js").DecimalField<{
276
296
  readonly required: true;
277
297
  readonly computed: false;
@@ -282,6 +302,46 @@ export declare const AccountTax: import("../server/orm.js").Model<"account.tax",
282
302
  readonly hasDefault: true;
283
303
  readonly readonly: false;
284
304
  }>;
305
+ readonly fixedAmount: import("../server/orm.js").DecimalField<{
306
+ readonly required: true;
307
+ readonly computed: false;
308
+ readonly inverse: false;
309
+ readonly sequence: false;
310
+ readonly computeName: undefined;
311
+ readonly store: true;
312
+ readonly hasDefault: true;
313
+ readonly readonly: false;
314
+ }>;
315
+ readonly affectsBase: import("../server/orm.js").ScalarField<"boolean", boolean, boolean, {
316
+ readonly required: true;
317
+ readonly computed: false;
318
+ readonly inverse: false;
319
+ readonly sequence: false;
320
+ readonly computeName: undefined;
321
+ readonly store: true;
322
+ readonly hasDefault: true;
323
+ readonly readonly: false;
324
+ }>;
325
+ readonly priceIncluded: import("../server/orm.js").ScalarField<"boolean", boolean, boolean, {
326
+ readonly required: true;
327
+ readonly computed: false;
328
+ readonly inverse: false;
329
+ readonly sequence: false;
330
+ readonly computeName: undefined;
331
+ readonly store: true;
332
+ readonly hasDefault: true;
333
+ readonly readonly: false;
334
+ }>;
335
+ readonly reverseCharge: import("../server/orm.js").ScalarField<"boolean", boolean, boolean, {
336
+ readonly required: true;
337
+ readonly computed: false;
338
+ readonly inverse: false;
339
+ readonly sequence: false;
340
+ readonly computeName: undefined;
341
+ readonly store: true;
342
+ readonly hasDefault: true;
343
+ readonly readonly: false;
344
+ }>;
285
345
  }, {} & import("../server/orm.js").TransitionMethods<{
286
346
  readonly name: import("../server/orm.js").CharField<{
287
347
  readonly required: true;
@@ -303,7 +363,28 @@ export declare const AccountTax: import("../server/orm.js").Model<"account.tax",
303
363
  readonly hasDefault: true;
304
364
  readonly readonly: false;
305
365
  }>;
306
- /** 0.15 for 15 %. */
366
+ /** The order a line's taxes apply in (lower first): supplementary duty before VAT. */
367
+ readonly sequence: import("../server/orm.js").ScalarField<"integer", number, number, {
368
+ readonly required: true;
369
+ readonly computed: false;
370
+ readonly inverse: false;
371
+ readonly sequence: false;
372
+ readonly computeName: undefined;
373
+ readonly store: true;
374
+ readonly hasDefault: true;
375
+ readonly readonly: false;
376
+ }>;
377
+ readonly amountType: import("../server/orm.js").SelectionField<"fixed" | "percent", {
378
+ readonly required: true;
379
+ readonly computed: false;
380
+ readonly inverse: false;
381
+ readonly sequence: false;
382
+ readonly computeName: undefined;
383
+ readonly store: true;
384
+ readonly hasDefault: true;
385
+ readonly readonly: false;
386
+ }>;
387
+ /** 0.15 for 15 % (percentage taxes). */
307
388
  readonly rate: import("../server/orm.js").DecimalField<{
308
389
  readonly required: true;
309
390
  readonly computed: false;
@@ -314,6 +395,50 @@ export declare const AccountTax: import("../server/orm.js").Model<"account.tax",
314
395
  readonly hasDefault: true;
315
396
  readonly readonly: false;
316
397
  }>;
398
+ /** Per unit, in the document's currency (fixed taxes). */
399
+ readonly fixedAmount: import("../server/orm.js").DecimalField<{
400
+ readonly required: true;
401
+ readonly computed: false;
402
+ readonly inverse: false;
403
+ readonly sequence: false;
404
+ readonly computeName: undefined;
405
+ readonly store: true;
406
+ readonly hasDefault: true;
407
+ readonly readonly: false;
408
+ }>;
409
+ /** Its amount is added to the base of the taxes after it (supplementary duty, then VAT on price + SD). */
410
+ readonly affectsBase: import("../server/orm.js").ScalarField<"boolean", boolean, boolean, {
411
+ readonly required: true;
412
+ readonly computed: false;
413
+ readonly inverse: false;
414
+ readonly sequence: false;
415
+ readonly computeName: undefined;
416
+ readonly store: true;
417
+ readonly hasDefault: true;
418
+ readonly readonly: false;
419
+ }>;
420
+ /** Included in the unit price (the price is gross). */
421
+ readonly priceIncluded: import("../server/orm.js").ScalarField<"boolean", boolean, boolean, {
422
+ readonly required: true;
423
+ readonly computed: false;
424
+ readonly inverse: false;
425
+ readonly sequence: false;
426
+ readonly computeName: undefined;
427
+ readonly store: true;
428
+ readonly hasDefault: true;
429
+ readonly readonly: false;
430
+ }>;
431
+ /** Reverse charge (RFC 0016 step 5): the buyer pays the tax to the state; not in the document's total. */
432
+ readonly reverseCharge: import("../server/orm.js").ScalarField<"boolean", boolean, boolean, {
433
+ readonly required: true;
434
+ readonly computed: false;
435
+ readonly inverse: false;
436
+ readonly sequence: false;
437
+ readonly computeName: undefined;
438
+ readonly store: true;
439
+ readonly hasDefault: true;
440
+ readonly readonly: false;
441
+ }>;
317
442
  }>>;
318
443
  export declare const ProductProduct: import("../server/orm.js").Model<"product.product", {
319
444
  readonly id: import("../server/orm.js").IdField<"product.product">;
@@ -458,6 +583,26 @@ export declare const ProductProduct: import("../server/orm.js").Model<"product.p
458
583
  readonly hasDefault: true;
459
584
  readonly readonly: false;
460
585
  }>;
586
+ readonly taxes: import("../server/orm.js").Many2manyField<"account.tax", {
587
+ readonly required: true;
588
+ readonly computed: false;
589
+ readonly inverse: false;
590
+ readonly sequence: false;
591
+ readonly computeName: undefined;
592
+ readonly store: true;
593
+ readonly hasDefault: true;
594
+ readonly readonly: false;
595
+ }>;
596
+ readonly purchaseTaxes: import("../server/orm.js").Many2manyField<"account.tax", {
597
+ readonly required: true;
598
+ readonly computed: false;
599
+ readonly inverse: false;
600
+ readonly sequence: false;
601
+ readonly computeName: undefined;
602
+ readonly store: true;
603
+ readonly hasDefault: true;
604
+ readonly readonly: false;
605
+ }>;
461
606
  readonly tax: import("../server/orm.js").Many2oneField<"account.tax", {
462
607
  readonly required: false;
463
608
  readonly computed: false;
@@ -466,7 +611,7 @@ export declare const ProductProduct: import("../server/orm.js").Model<"product.p
466
611
  readonly computeName: undefined;
467
612
  readonly store: true;
468
613
  readonly hasDefault: false;
469
- readonly readonly: false;
614
+ readonly readonly: true;
470
615
  }>;
471
616
  readonly purchaseTax: import("../server/orm.js").Many2oneField<"account.tax", {
472
617
  readonly required: false;
@@ -476,7 +621,7 @@ export declare const ProductProduct: import("../server/orm.js").Model<"product.p
476
621
  readonly computeName: undefined;
477
622
  readonly store: true;
478
623
  readonly hasDefault: false;
479
- readonly readonly: false;
624
+ readonly readonly: true;
480
625
  }>;
481
626
  readonly description: import("../server/orm.js").ScalarField<"text", string, string | Readonly<Record<string, string>>, {
482
627
  readonly required: false;
@@ -592,7 +737,29 @@ export declare const ProductProduct: import("../server/orm.js").Model<"product.p
592
737
  readonly hasDefault: true;
593
738
  readonly readonly: false;
594
739
  }>;
595
- /** The default tax on sales. */
740
+ /** The taxes on sales, in order (RFC 0016). */
741
+ readonly taxes: import("../server/orm.js").Many2manyField<"account.tax", {
742
+ readonly required: true;
743
+ readonly computed: false;
744
+ readonly inverse: false;
745
+ readonly sequence: false;
746
+ readonly computeName: undefined;
747
+ readonly store: true;
748
+ readonly hasDefault: true;
749
+ readonly readonly: false;
750
+ }>;
751
+ /** The taxes on purchases, in order. */
752
+ readonly purchaseTaxes: import("../server/orm.js").Many2manyField<"account.tax", {
753
+ readonly required: true;
754
+ readonly computed: false;
755
+ readonly inverse: false;
756
+ readonly sequence: false;
757
+ readonly computeName: undefined;
758
+ readonly store: true;
759
+ readonly hasDefault: true;
760
+ readonly readonly: false;
761
+ }>;
762
+ /** Before 0.2.0, one tax each: copied into `taxes` / `purchaseTaxes` by the migration; dropped later. */
596
763
  readonly tax: import("../server/orm.js").Many2oneField<"account.tax", {
597
764
  readonly required: false;
598
765
  readonly computed: false;
@@ -601,9 +768,8 @@ export declare const ProductProduct: import("../server/orm.js").Model<"product.p
601
768
  readonly computeName: undefined;
602
769
  readonly store: true;
603
770
  readonly hasDefault: false;
604
- readonly readonly: false;
771
+ readonly readonly: true;
605
772
  }>;
606
- /** The default tax on purchases. */
607
773
  readonly purchaseTax: import("../server/orm.js").Many2oneField<"account.tax", {
608
774
  readonly required: false;
609
775
  readonly computed: false;
@@ -612,7 +778,7 @@ export declare const ProductProduct: import("../server/orm.js").Model<"product.p
612
778
  readonly computeName: undefined;
613
779
  readonly store: true;
614
780
  readonly hasDefault: false;
615
- readonly readonly: false;
781
+ readonly readonly: true;
616
782
  }>;
617
783
  readonly description: import("../server/orm.js").ScalarField<"text", string, string | Readonly<Record<string, string>>, {
618
784
  readonly required: false;
@@ -897,6 +1063,26 @@ export declare const productShutro: import("../server/orm.js").Module<readonly [
897
1063
  readonly hasDefault: true;
898
1064
  readonly readonly: false;
899
1065
  }>;
1066
+ readonly sequence: import("../server/orm.js").ScalarField<"integer", number, number, {
1067
+ readonly required: true;
1068
+ readonly computed: false;
1069
+ readonly inverse: false;
1070
+ readonly sequence: false;
1071
+ readonly computeName: undefined;
1072
+ readonly store: true;
1073
+ readonly hasDefault: true;
1074
+ readonly readonly: false;
1075
+ }>;
1076
+ readonly amountType: import("../server/orm.js").SelectionField<"fixed" | "percent", {
1077
+ readonly required: true;
1078
+ readonly computed: false;
1079
+ readonly inverse: false;
1080
+ readonly sequence: false;
1081
+ readonly computeName: undefined;
1082
+ readonly store: true;
1083
+ readonly hasDefault: true;
1084
+ readonly readonly: false;
1085
+ }>;
900
1086
  readonly rate: import("../server/orm.js").DecimalField<{
901
1087
  readonly required: true;
902
1088
  readonly computed: false;
@@ -907,6 +1093,46 @@ export declare const productShutro: import("../server/orm.js").Module<readonly [
907
1093
  readonly hasDefault: true;
908
1094
  readonly readonly: false;
909
1095
  }>;
1096
+ readonly fixedAmount: import("../server/orm.js").DecimalField<{
1097
+ readonly required: true;
1098
+ readonly computed: false;
1099
+ readonly inverse: false;
1100
+ readonly sequence: false;
1101
+ readonly computeName: undefined;
1102
+ readonly store: true;
1103
+ readonly hasDefault: true;
1104
+ readonly readonly: false;
1105
+ }>;
1106
+ readonly affectsBase: import("../server/orm.js").ScalarField<"boolean", boolean, boolean, {
1107
+ readonly required: true;
1108
+ readonly computed: false;
1109
+ readonly inverse: false;
1110
+ readonly sequence: false;
1111
+ readonly computeName: undefined;
1112
+ readonly store: true;
1113
+ readonly hasDefault: true;
1114
+ readonly readonly: false;
1115
+ }>;
1116
+ readonly priceIncluded: import("../server/orm.js").ScalarField<"boolean", boolean, boolean, {
1117
+ readonly required: true;
1118
+ readonly computed: false;
1119
+ readonly inverse: false;
1120
+ readonly sequence: false;
1121
+ readonly computeName: undefined;
1122
+ readonly store: true;
1123
+ readonly hasDefault: true;
1124
+ readonly readonly: false;
1125
+ }>;
1126
+ readonly reverseCharge: import("../server/orm.js").ScalarField<"boolean", boolean, boolean, {
1127
+ readonly required: true;
1128
+ readonly computed: false;
1129
+ readonly inverse: false;
1130
+ readonly sequence: false;
1131
+ readonly computeName: undefined;
1132
+ readonly store: true;
1133
+ readonly hasDefault: true;
1134
+ readonly readonly: false;
1135
+ }>;
910
1136
  }, {} & import("../server/orm.js").TransitionMethods<{
911
1137
  readonly name: import("../server/orm.js").CharField<{
912
1138
  readonly required: true;
@@ -928,7 +1154,28 @@ export declare const productShutro: import("../server/orm.js").Module<readonly [
928
1154
  readonly hasDefault: true;
929
1155
  readonly readonly: false;
930
1156
  }>;
931
- /** 0.15 for 15 %. */
1157
+ /** The order a line's taxes apply in (lower first): supplementary duty before VAT. */
1158
+ readonly sequence: import("../server/orm.js").ScalarField<"integer", number, number, {
1159
+ readonly required: true;
1160
+ readonly computed: false;
1161
+ readonly inverse: false;
1162
+ readonly sequence: false;
1163
+ readonly computeName: undefined;
1164
+ readonly store: true;
1165
+ readonly hasDefault: true;
1166
+ readonly readonly: false;
1167
+ }>;
1168
+ readonly amountType: import("../server/orm.js").SelectionField<"fixed" | "percent", {
1169
+ readonly required: true;
1170
+ readonly computed: false;
1171
+ readonly inverse: false;
1172
+ readonly sequence: false;
1173
+ readonly computeName: undefined;
1174
+ readonly store: true;
1175
+ readonly hasDefault: true;
1176
+ readonly readonly: false;
1177
+ }>;
1178
+ /** 0.15 for 15 % (percentage taxes). */
932
1179
  readonly rate: import("../server/orm.js").DecimalField<{
933
1180
  readonly required: true;
934
1181
  readonly computed: false;
@@ -939,6 +1186,50 @@ export declare const productShutro: import("../server/orm.js").Module<readonly [
939
1186
  readonly hasDefault: true;
940
1187
  readonly readonly: false;
941
1188
  }>;
1189
+ /** Per unit, in the document's currency (fixed taxes). */
1190
+ readonly fixedAmount: import("../server/orm.js").DecimalField<{
1191
+ readonly required: true;
1192
+ readonly computed: false;
1193
+ readonly inverse: false;
1194
+ readonly sequence: false;
1195
+ readonly computeName: undefined;
1196
+ readonly store: true;
1197
+ readonly hasDefault: true;
1198
+ readonly readonly: false;
1199
+ }>;
1200
+ /** Its amount is added to the base of the taxes after it (supplementary duty, then VAT on price + SD). */
1201
+ readonly affectsBase: import("../server/orm.js").ScalarField<"boolean", boolean, boolean, {
1202
+ readonly required: true;
1203
+ readonly computed: false;
1204
+ readonly inverse: false;
1205
+ readonly sequence: false;
1206
+ readonly computeName: undefined;
1207
+ readonly store: true;
1208
+ readonly hasDefault: true;
1209
+ readonly readonly: false;
1210
+ }>;
1211
+ /** Included in the unit price (the price is gross). */
1212
+ readonly priceIncluded: import("../server/orm.js").ScalarField<"boolean", boolean, boolean, {
1213
+ readonly required: true;
1214
+ readonly computed: false;
1215
+ readonly inverse: false;
1216
+ readonly sequence: false;
1217
+ readonly computeName: undefined;
1218
+ readonly store: true;
1219
+ readonly hasDefault: true;
1220
+ readonly readonly: false;
1221
+ }>;
1222
+ /** Reverse charge (RFC 0016 step 5): the buyer pays the tax to the state; not in the document's total. */
1223
+ readonly reverseCharge: import("../server/orm.js").ScalarField<"boolean", boolean, boolean, {
1224
+ readonly required: true;
1225
+ readonly computed: false;
1226
+ readonly inverse: false;
1227
+ readonly sequence: false;
1228
+ readonly computeName: undefined;
1229
+ readonly store: true;
1230
+ readonly hasDefault: true;
1231
+ readonly readonly: false;
1232
+ }>;
942
1233
  }>>, import("../server/orm.js").Model<"product.product", {
943
1234
  readonly id: import("../server/orm.js").IdField<"product.product">;
944
1235
  readonly createdAt: import("../server/orm.js").ScalarField<'datetime', Date, Date, {
@@ -1082,6 +1373,26 @@ export declare const productShutro: import("../server/orm.js").Module<readonly [
1082
1373
  readonly hasDefault: true;
1083
1374
  readonly readonly: false;
1084
1375
  }>;
1376
+ readonly taxes: import("../server/orm.js").Many2manyField<"account.tax", {
1377
+ readonly required: true;
1378
+ readonly computed: false;
1379
+ readonly inverse: false;
1380
+ readonly sequence: false;
1381
+ readonly computeName: undefined;
1382
+ readonly store: true;
1383
+ readonly hasDefault: true;
1384
+ readonly readonly: false;
1385
+ }>;
1386
+ readonly purchaseTaxes: import("../server/orm.js").Many2manyField<"account.tax", {
1387
+ readonly required: true;
1388
+ readonly computed: false;
1389
+ readonly inverse: false;
1390
+ readonly sequence: false;
1391
+ readonly computeName: undefined;
1392
+ readonly store: true;
1393
+ readonly hasDefault: true;
1394
+ readonly readonly: false;
1395
+ }>;
1085
1396
  readonly tax: import("../server/orm.js").Many2oneField<"account.tax", {
1086
1397
  readonly required: false;
1087
1398
  readonly computed: false;
@@ -1090,7 +1401,7 @@ export declare const productShutro: import("../server/orm.js").Module<readonly [
1090
1401
  readonly computeName: undefined;
1091
1402
  readonly store: true;
1092
1403
  readonly hasDefault: false;
1093
- readonly readonly: false;
1404
+ readonly readonly: true;
1094
1405
  }>;
1095
1406
  readonly purchaseTax: import("../server/orm.js").Many2oneField<"account.tax", {
1096
1407
  readonly required: false;
@@ -1100,7 +1411,7 @@ export declare const productShutro: import("../server/orm.js").Module<readonly [
1100
1411
  readonly computeName: undefined;
1101
1412
  readonly store: true;
1102
1413
  readonly hasDefault: false;
1103
- readonly readonly: false;
1414
+ readonly readonly: true;
1104
1415
  }>;
1105
1416
  readonly description: import("../server/orm.js").ScalarField<"text", string, string | Readonly<Record<string, string>>, {
1106
1417
  readonly required: false;
@@ -1216,7 +1527,29 @@ export declare const productShutro: import("../server/orm.js").Module<readonly [
1216
1527
  readonly hasDefault: true;
1217
1528
  readonly readonly: false;
1218
1529
  }>;
1219
- /** The default tax on sales. */
1530
+ /** The taxes on sales, in order (RFC 0016). */
1531
+ readonly taxes: import("../server/orm.js").Many2manyField<"account.tax", {
1532
+ readonly required: true;
1533
+ readonly computed: false;
1534
+ readonly inverse: false;
1535
+ readonly sequence: false;
1536
+ readonly computeName: undefined;
1537
+ readonly store: true;
1538
+ readonly hasDefault: true;
1539
+ readonly readonly: false;
1540
+ }>;
1541
+ /** The taxes on purchases, in order. */
1542
+ readonly purchaseTaxes: import("../server/orm.js").Many2manyField<"account.tax", {
1543
+ readonly required: true;
1544
+ readonly computed: false;
1545
+ readonly inverse: false;
1546
+ readonly sequence: false;
1547
+ readonly computeName: undefined;
1548
+ readonly store: true;
1549
+ readonly hasDefault: true;
1550
+ readonly readonly: false;
1551
+ }>;
1552
+ /** Before 0.2.0, one tax each: copied into `taxes` / `purchaseTaxes` by the migration; dropped later. */
1220
1553
  readonly tax: import("../server/orm.js").Many2oneField<"account.tax", {
1221
1554
  readonly required: false;
1222
1555
  readonly computed: false;
@@ -1225,9 +1558,8 @@ export declare const productShutro: import("../server/orm.js").Module<readonly [
1225
1558
  readonly computeName: undefined;
1226
1559
  readonly store: true;
1227
1560
  readonly hasDefault: false;
1228
- readonly readonly: false;
1561
+ readonly readonly: true;
1229
1562
  }>;
1230
- /** The default tax on purchases. */
1231
1563
  readonly purchaseTax: import("../server/orm.js").Many2oneField<"account.tax", {
1232
1564
  readonly required: false;
1233
1565
  readonly computed: false;
@@ -1236,7 +1568,7 @@ export declare const productShutro: import("../server/orm.js").Module<readonly [
1236
1568
  readonly computeName: undefined;
1237
1569
  readonly store: true;
1238
1570
  readonly hasDefault: false;
1239
- readonly readonly: false;
1571
+ readonly readonly: true;
1240
1572
  }>;
1241
1573
  readonly description: import("../server/orm.js").ScalarField<"text", string, string | Readonly<Record<string, string>>, {
1242
1574
  readonly required: false;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * The data layer of Products (Shutro): units of measure (what Shutro's `quantity` fields are counted in), product
3
3
  * categories, taxes and products. Taxes live here rather than in Accounting, so Sales and Purchase work without the
4
- * Accounting app; Accounting extends them with their accounts.
4
+ * Accounting app; Accounting extends them with their accounts. A country's taxes come with its localization (l10n_bd).
5
5
  */
6
6
  import { baseShutro } from '../server/index.js';
7
7
  import { orm } from '../server/orm.js';
@@ -46,13 +46,28 @@ export const ProductCategory = defineModel('product.category', {
46
46
  export const AccountTax = defineModel('account.tax', {
47
47
  label: 'Tax',
48
48
  archivable: true,
49
- order: ['use asc', 'rate desc'],
49
+ order: ['use asc', 'sequence asc', 'rate desc'],
50
50
  access: { 'product.user': READ, 'product.manager': ALL },
51
51
  fields: {
52
52
  name: f.char({ required: true, translate: true }),
53
53
  use: f.selection({ sale: 'Sales', purchase: 'Purchases' }, { required: true, default: 'sale' }),
54
- /** 0.15 for 15 %. */
54
+ /** The order a line's taxes apply in (lower first): supplementary duty before VAT. */
55
+ sequence: f.integer({ required: true, default: 10 }),
56
+ amountType: f.selection({ percent: 'Percentage of the base', fixed: 'Fixed amount per unit' }, { required: true, default: 'percent', label: 'Computed as' }),
57
+ /** 0.15 for 15 % (percentage taxes). */
55
58
  rate: f.decimal({ scale: 4, required: true, default: '0' }),
59
+ /** Per unit, in the document's currency (fixed taxes). */
60
+ fixedAmount: f.decimal({ scale: 4, required: true, default: '0', label: 'Amount per unit' }),
61
+ /** Its amount is added to the base of the taxes after it (supplementary duty, then VAT on price + SD). */
62
+ affectsBase: f.boolean({
63
+ required: true,
64
+ default: false,
65
+ label: 'Affects the base of later taxes',
66
+ }),
67
+ /** Included in the unit price (the price is gross). */
68
+ priceIncluded: f.boolean({ required: true, default: false, label: 'Included in price' }),
69
+ /** Reverse charge (RFC 0016 step 5): the buyer pays the tax to the state; not in the document's total. */
70
+ reverseCharge: f.boolean({ required: true, default: false, label: 'Reverse charge' }),
56
71
  },
57
72
  constraints: {
58
73
  rateRange: {
@@ -81,10 +96,19 @@ export const ProductProduct = defineModel('product.product', {
81
96
  standardPrice: f.decimal({ scale: 2, required: true, default: '0', label: 'Cost' }),
82
97
  saleOk: f.boolean({ default: true, label: 'Can be sold' }),
83
98
  purchaseOk: f.boolean({ default: true, label: 'Can be purchased' }),
84
- /** The default tax on sales. */
85
- tax: f.many2one('account.tax', { label: 'Sales tax' }),
86
- /** The default tax on purchases. */
87
- purchaseTax: f.many2one('account.tax', { label: 'Purchase tax' }),
99
+ /** The taxes on sales, in order (RFC 0016). */
100
+ taxes: f.many2many('account.tax', { relation: 'product_sale_tax_rel', label: 'Sales taxes' }),
101
+ /** The taxes on purchases, in order. */
102
+ purchaseTaxes: f.many2many('account.tax', {
103
+ relation: 'product_purchase_tax_rel',
104
+ label: 'Purchase taxes',
105
+ }),
106
+ /** Before 0.2.0, one tax each: copied into `taxes` / `purchaseTaxes` by the migration; dropped later. */
107
+ tax: f.many2one('account.tax', { label: 'Sales tax (before 0.2.0)', readonly: true }),
108
+ purchaseTax: f.many2one('account.tax', {
109
+ label: 'Purchase tax (before 0.2.0)',
110
+ readonly: true,
111
+ }),
88
112
  description: f.text({ translate: true }),
89
113
  },
90
114
  constraints: {
@@ -95,10 +119,25 @@ export const ProductProduct = defineModel('product.product', {
95
119
  },
96
120
  });
97
121
  const uom = (id, name, category, ratio, rounding) => record('uom.uom', id, { name, category: category, ratio, rounding }, { noupdate: true });
98
- const tax = (id, name, use, rate) => record('account.tax', id, { name, use, rate }, { noupdate: true });
99
122
  export const productShutro = defineModule({
100
123
  name: 'product',
101
- version: '0.1.0',
124
+ version: '0.3.0',
125
+ migrations: [
126
+ {
127
+ version: '0.2.0',
128
+ description: 'Several taxes per product: the single sales and purchase taxes become the first of each list',
129
+ up: async (ctx) => {
130
+ await ctx.sql `INSERT INTO product_sale_tax_rel (product_product_id, account_tax_id)
131
+ SELECT id, tax_id FROM product_product WHERE tax_id IS NOT NULL ON CONFLICT DO NOTHING`;
132
+ await ctx.sql `INSERT INTO product_purchase_tax_rel (product_product_id, account_tax_id)
133
+ SELECT id, purchase_tax_id FROM product_product WHERE purchase_tax_id IS NOT NULL ON CONFLICT DO NOTHING`;
134
+ // The Bangladeshi taxes move to the Bangladesh localization (RFC 0016): their records stay, and l10n_bd
135
+ // finds them as its own when installed (no duplicates, nothing deleted here).
136
+ await ctx.sql `UPDATE shutro_external_id SET module = 'l10n_bd'
137
+ WHERE module = 'product' AND model = 'account.tax'`;
138
+ },
139
+ },
140
+ ],
102
141
  depends: [baseShutro],
103
142
  groups: [
104
143
  orm.defineGroup({ code: 'product.user', label: 'Products user', implies: ['base.user'] }),
@@ -123,14 +162,5 @@ export const productShutro = defineModule({
123
162
  uom('uom_meter', 'm', 'length', '1', '0.01'),
124
163
  uom('uom_litre', 'L', 'volume', '1', '0.001'),
125
164
  record('product.category', 'category_all', { name: 'All' }, { noupdate: true }),
126
- // Bangladesh VAT (VAT and Supplementary Duty Act 2012): standard 15 %, reduced 10 %, 7.5 % and 5 %.
127
- tax('tax_sale_vat15', 'VAT 15%', 'sale', '0.15'),
128
- tax('tax_sale_vat10', 'VAT 10%', 'sale', '0.10'),
129
- tax('tax_sale_vat7_5', 'VAT 7.5%', 'sale', '0.075'),
130
- tax('tax_sale_vat5', 'VAT 5%', 'sale', '0.05'),
131
- tax('tax_sale_exempt', 'VAT exempt', 'sale', '0'),
132
- tax('tax_purchase_vat15', 'VAT 15% (purchases)', 'purchase', '0.15'),
133
- tax('tax_purchase_vat5', 'VAT 5% (purchases)', 'purchase', '0.05'),
134
- tax('tax_purchase_exempt', 'VAT exempt (purchases)', 'purchase', '0'),
135
165
  ],
136
166
  });
@@ -0,0 +1,59 @@
1
+ /**
2
+ * The tax engine (RFC 0016 §5.1), shared by Sales, Purchase and Accounting: the taxes of a line, in order. A tax is
3
+ * a percentage of its base or a fixed amount per unit; a tax that `affectsBase` adds its amount to the base of the
4
+ * taxes after it (supplementary duty before VAT); taxes `priceIncluded` are inside the unit price, which is then
5
+ * gross. A reverse-charge tax is computed like the others but not added to the total: the buyer pays it to the state,
6
+ * not to the supplier. Exact decimals throughout; rounding is the caller's (per document at posting).
7
+ */
8
+ import { orm } from '../server/orm.js';
9
+ type Decimal = ReturnType<typeof orm.toDecimal>;
10
+ /** What the engine needs of a tax. */
11
+ export interface TaxRule {
12
+ readonly id: number;
13
+ readonly sequence: number;
14
+ readonly amountType: 'percent' | 'fixed';
15
+ /** 0.15 for 15 % (percent taxes). */
16
+ readonly rate: Decimal;
17
+ /** Per unit, in the document currency (fixed taxes). */
18
+ readonly fixedAmount: Decimal;
19
+ readonly affectsBase: boolean;
20
+ readonly priceIncluded: boolean;
21
+ /** Paid by the buyer to the state (reverse charge): not in the line's total. */
22
+ readonly reverseCharge: boolean;
23
+ }
24
+ export interface TaxLine {
25
+ readonly tax: number;
26
+ readonly reverseCharge: boolean;
27
+ /** What the tax was computed on (the untaxed amount, plus the taxes before it that affect the base). */
28
+ readonly base: Decimal;
29
+ readonly amount: Decimal;
30
+ }
31
+ export interface TaxResult {
32
+ /** The amount without taxes. */
33
+ readonly untaxed: Decimal;
34
+ /** Each tax, in order (reverse-charge ones too). */
35
+ readonly taxes: readonly TaxLine[];
36
+ /** The taxes the supplier charges (reverse-charge ones are not). */
37
+ readonly taxTotal: Decimal;
38
+ readonly total: Decimal;
39
+ }
40
+ /** The rules in the order they apply: by sequence, then as given. */
41
+ export declare function ordered(rules: readonly TaxRule[]): TaxRule[];
42
+ /**
43
+ * The taxes of a line whose price amounts to `amount` (quantity × unit price, after discount) for `quantity` units.
44
+ * With taxes included in the price, `amount` is gross: the untaxed amount is what, taxed by the included taxes,
45
+ * gives it back.
46
+ */
47
+ export declare function computeTaxes(amount: Decimal, quantity: Decimal, rules: readonly TaxRule[]): TaxResult;
48
+ /** A tax record (as loaded) as the engine's rule. */
49
+ export declare function taxRule(tax: {
50
+ readonly id: number;
51
+ readonly sequence?: number | null;
52
+ readonly amountType?: string | null;
53
+ readonly rate?: Decimal | null;
54
+ readonly fixedAmount?: Decimal | null;
55
+ readonly affectsBase?: boolean | null;
56
+ readonly priceIncluded?: boolean | null;
57
+ readonly reverseCharge?: boolean | null;
58
+ }): TaxRule;
59
+ export {};