shutro-erp 0.3.5 → 0.3.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 (768) hide show
  1. package/dist/account_asset/.kosh/bindings.js +15 -0
  2. package/dist/{mrp_account → account_asset}/.kosh/schema.d.ts +785 -614
  3. package/dist/account_asset/board.d.ts +61 -0
  4. package/dist/account_asset/board.js +86 -0
  5. package/dist/account_asset/books.d.ts +42 -0
  6. package/dist/account_asset/books.js +398 -0
  7. package/dist/account_asset/demo.d.ts +7 -0
  8. package/dist/account_asset/demo.js +72 -0
  9. package/dist/account_asset/i18n/bn.d.ts +2 -0
  10. package/dist/account_asset/i18n/bn.js +97 -0
  11. package/dist/account_asset/index.d.ts +9 -0
  12. package/dist/account_asset/index.js +337 -0
  13. package/dist/account_asset/module.d.ts +11076 -0
  14. package/dist/account_asset/module.js +230 -0
  15. package/dist/account_budget/.kosh/bindings.js +15 -0
  16. package/dist/account_budget/.kosh/schema.d.ts +2841 -0
  17. package/dist/account_budget/budget.d.ts +5 -0
  18. package/dist/account_budget/budget.js +142 -0
  19. package/dist/account_budget/demo.d.ts +6 -0
  20. package/dist/account_budget/demo.js +30 -0
  21. package/dist/account_budget/i18n/bn.d.ts +2 -0
  22. package/dist/account_budget/i18n/bn.js +63 -0
  23. package/dist/account_budget/index.d.ts +4 -0
  24. package/dist/account_budget/index.js +237 -0
  25. package/dist/account_budget/module.d.ts +27289 -0
  26. package/dist/account_budget/module.js +182 -0
  27. package/dist/account_portal/.kosh/bindings.js +1 -1
  28. package/dist/account_portal/.kosh/schema.d.ts +651 -10
  29. package/dist/account_portal/i18n/bn.d.ts +2 -0
  30. package/dist/account_portal/i18n/bn.js +6 -0
  31. package/dist/account_portal/index.js +2 -0
  32. package/dist/account_portal/module.d.ts +5212 -1592
  33. package/dist/accounting/.kosh/bindings.js +1 -1
  34. package/dist/accounting/.kosh/schema.d.ts +651 -10
  35. package/dist/accounting/closing.js +1 -0
  36. package/dist/accounting/fiscal.d.ts +578 -0
  37. package/dist/accounting/fiscal.js +401 -0
  38. package/dist/accounting/followups.d.ts +618 -0
  39. package/dist/accounting/followups.js +420 -0
  40. package/dist/accounting/i18n/bn.d.ts +2 -0
  41. package/dist/accounting/i18n/bn.js +425 -0
  42. package/dist/accounting/index.d.ts +3 -1
  43. package/dist/accounting/index.js +780 -5
  44. package/dist/accounting/module.d.ts +5386 -1543
  45. package/dist/accounting/module.js +155 -18
  46. package/dist/accounting/statements.d.ts +878 -0
  47. package/dist/accounting/statements.js +728 -0
  48. package/dist/accounting/web/BankReconcilePage.d.ts +9 -0
  49. package/dist/accounting/web/BankReconcilePage.js +138 -0
  50. package/dist/accounting/web/FollowupsPage.d.ts +8 -0
  51. package/dist/accounting/web/FollowupsPage.js +54 -0
  52. package/dist/accounting/web/PostingPreview.d.ts +8 -0
  53. package/dist/accounting/web/PostingPreview.js +26 -0
  54. package/dist/accounting/web/index.d.ts +3 -0
  55. package/dist/accounting/web/index.js +9 -0
  56. package/dist/accounting/web/messages.js +140 -0
  57. package/dist/approvals/.kosh/bindings.d.ts +22 -0
  58. package/dist/approvals/.kosh/bindings.js +15 -0
  59. package/dist/approvals/.kosh/schema.d.ts +879 -0
  60. package/dist/approvals/demo.d.ts +7 -0
  61. package/dist/approvals/demo.js +41 -0
  62. package/dist/approvals/i18n/bn.d.ts +2 -0
  63. package/dist/approvals/i18n/bn.js +133 -0
  64. package/dist/approvals/index.d.ts +36 -0
  65. package/dist/approvals/index.js +772 -0
  66. package/dist/approvals/mails.d.ts +30 -0
  67. package/dist/approvals/mails.js +87 -0
  68. package/dist/approvals/module.d.ts +2930 -0
  69. package/dist/approvals/module.js +473 -0
  70. package/dist/approvals/web/Config.d.ts +12 -0
  71. package/dist/approvals/web/Config.js +60 -0
  72. package/dist/approvals/web/History.d.ts +4 -0
  73. package/dist/approvals/web/History.js +13 -0
  74. package/dist/approvals/web/Inbox.d.ts +9 -0
  75. package/dist/approvals/web/Inbox.js +114 -0
  76. package/dist/approvals/web/Matrix.d.ts +9 -0
  77. package/dist/approvals/web/Matrix.js +26 -0
  78. package/dist/approvals/web/Mine.d.ts +7 -0
  79. package/dist/approvals/web/Mine.js +27 -0
  80. package/dist/approvals/web/index.d.ts +15 -0
  81. package/dist/approvals/web/index.js +29 -0
  82. package/dist/approvals/web/messages.d.ts +2 -0
  83. package/dist/approvals/web/messages.js +211 -0
  84. package/dist/approvals/web/shared.d.ts +59 -0
  85. package/dist/approvals/web/shared.js +46 -0
  86. package/dist/approvals_purchase/.kosh/bindings.d.ts +22 -0
  87. package/dist/approvals_purchase/.kosh/bindings.js +15 -0
  88. package/dist/approvals_purchase/.kosh/schema.d.ts +1997 -0
  89. package/dist/approvals_purchase/i18n/bn.d.ts +2 -0
  90. package/dist/approvals_purchase/i18n/bn.js +5 -0
  91. package/dist/approvals_purchase/index.d.ts +3 -0
  92. package/dist/approvals_purchase/index.js +47 -0
  93. package/dist/approvals_purchase/module.d.ts +12670 -0
  94. package/dist/approvals_purchase/module.js +84 -0
  95. package/dist/attendance/.kosh/bindings.d.ts +22 -0
  96. package/dist/attendance/.kosh/bindings.js +15 -0
  97. package/dist/attendance/.kosh/schema.d.ts +1106 -0
  98. package/dist/attendance/days.d.ts +96 -0
  99. package/dist/attendance/days.js +430 -0
  100. package/dist/attendance/demo.d.ts +7 -0
  101. package/dist/attendance/demo.js +58 -0
  102. package/dist/attendance/i18n/bn.d.ts +2 -0
  103. package/dist/attendance/i18n/bn.js +147 -0
  104. package/dist/attendance/index.d.ts +4 -0
  105. package/dist/attendance/index.js +515 -0
  106. package/dist/attendance/module.d.ts +4413 -0
  107. package/dist/attendance/module.js +412 -0
  108. package/dist/attendance/routes.d.ts +16 -0
  109. package/dist/attendance/routes.js +266 -0
  110. package/dist/attendance/web/Check.d.ts +8 -0
  111. package/dist/attendance/web/Check.js +40 -0
  112. package/dist/attendance/web/Kiosk.d.ts +8 -0
  113. package/dist/attendance/web/Kiosk.js +62 -0
  114. package/dist/attendance/web/PinButton.d.ts +7 -0
  115. package/dist/attendance/web/PinButton.js +29 -0
  116. package/dist/attendance/web/index.d.ts +13 -0
  117. package/dist/attendance/web/index.js +22 -0
  118. package/dist/attendance/web/messages.d.ts +2 -0
  119. package/dist/attendance/web/messages.js +61 -0
  120. package/dist/automation/engine.js +1 -1
  121. package/dist/calendar/.kosh/bindings.js +1 -1
  122. package/dist/calendar/.kosh/schema.d.ts +2 -1
  123. package/dist/calendar/i18n/bn.d.ts +2 -0
  124. package/dist/calendar/i18n/bn.js +80 -0
  125. package/dist/calendar/index.js +77 -0
  126. package/dist/calendar/module.d.ts +26 -0
  127. package/dist/calendar/module.js +14 -4
  128. package/dist/cli/apps.js +25 -5
  129. package/dist/cli/init.js +46 -4
  130. package/dist/cli/templates.d.ts +1 -1
  131. package/dist/cli/templates.js +123 -5
  132. package/dist/contacts/.kosh/bindings.js +1 -1
  133. package/dist/contacts/.kosh/schema.d.ts +2 -1
  134. package/dist/contacts/i18n/bn.d.ts +2 -0
  135. package/dist/contacts/i18n/bn.js +67 -0
  136. package/dist/contacts/index.js +3 -0
  137. package/dist/contacts/module.d.ts +42 -0
  138. package/dist/contacts/module.js +19 -3
  139. package/dist/crm/.kosh/bindings.js +1 -1
  140. package/dist/crm/.kosh/schema.d.ts +3 -1
  141. package/dist/crm/i18n/bn.d.ts +2 -0
  142. package/dist/crm/i18n/bn.js +80 -0
  143. package/dist/crm/index.js +22 -0
  144. package/dist/crm/module.d.ts +22 -0
  145. package/dist/crm/module.js +6 -3
  146. package/dist/documents/.kosh/bindings.d.ts +22 -0
  147. package/dist/documents/.kosh/bindings.js +15 -0
  148. package/dist/documents/.kosh/schema.d.ts +863 -0
  149. package/dist/documents/demo.d.ts +6 -0
  150. package/dist/documents/demo.js +22 -0
  151. package/dist/documents/documents.d.ts +98 -0
  152. package/dist/documents/documents.js +318 -0
  153. package/dist/documents/i18n/bn.d.ts +2 -0
  154. package/dist/documents/i18n/bn.js +83 -0
  155. package/dist/documents/index.d.ts +30 -0
  156. package/dist/documents/index.js +569 -0
  157. package/dist/documents/module.d.ts +2801 -0
  158. package/dist/documents/module.js +215 -0
  159. package/dist/documents/web/Versions.d.ts +7 -0
  160. package/dist/documents/web/Versions.js +45 -0
  161. package/dist/documents/web/index.d.ts +11 -0
  162. package/dist/documents/web/index.js +16 -0
  163. package/dist/documents/web/messages.d.ts +2 -0
  164. package/dist/documents/web/messages.js +21 -0
  165. package/dist/event/.kosh/bindings.js +1 -1
  166. package/dist/event/.kosh/schema.d.ts +2 -1
  167. package/dist/event/i18n/bn.d.ts +2 -0
  168. package/dist/event/i18n/bn.js +101 -0
  169. package/dist/event/index.js +66 -0
  170. package/dist/event/module.d.ts +20 -0
  171. package/dist/event/module.js +8 -1
  172. package/dist/event_account/.kosh/bindings.js +1 -1
  173. package/dist/event_account/.kosh/schema.d.ts +651 -10
  174. package/dist/event_account/i18n/bn.d.ts +2 -0
  175. package/dist/event_account/i18n/bn.js +5 -0
  176. package/dist/event_account/index.js +2 -0
  177. package/dist/event_account/module.d.ts +5133 -1513
  178. package/dist/expense/.kosh/bindings.d.ts +22 -0
  179. package/dist/expense/.kosh/bindings.js +15 -0
  180. package/dist/expense/.kosh/schema.d.ts +1620 -0
  181. package/dist/expense/demo.d.ts +7 -0
  182. package/dist/expense/demo.js +69 -0
  183. package/dist/expense/i18n/bn.d.ts +2 -0
  184. package/dist/expense/i18n/bn.js +155 -0
  185. package/dist/expense/index.d.ts +3 -0
  186. package/dist/expense/index.js +502 -0
  187. package/dist/expense/module.d.ts +6768 -0
  188. package/dist/expense/module.js +649 -0
  189. package/dist/expense_account/.kosh/bindings.d.ts +22 -0
  190. package/dist/expense_account/.kosh/bindings.js +15 -0
  191. package/dist/expense_account/.kosh/schema.d.ts +2515 -0
  192. package/dist/expense_account/i18n/bn.d.ts +2 -0
  193. package/dist/expense_account/i18n/bn.js +15 -0
  194. package/dist/expense_account/index.d.ts +3 -0
  195. package/dist/expense_account/index.js +76 -0
  196. package/dist/expense_account/module.d.ts +14628 -0
  197. package/dist/expense_account/module.js +318 -0
  198. package/dist/helpdesk/.kosh/bindings.d.ts +22 -0
  199. package/dist/helpdesk/.kosh/bindings.js +15 -0
  200. package/dist/helpdesk/.kosh/schema.d.ts +886 -0
  201. package/dist/helpdesk/demo.d.ts +7 -0
  202. package/dist/helpdesk/demo.js +65 -0
  203. package/dist/helpdesk/hours.d.ts +17 -0
  204. package/dist/helpdesk/hours.js +94 -0
  205. package/dist/helpdesk/i18n/bn.d.ts +2 -0
  206. package/dist/helpdesk/i18n/bn.js +127 -0
  207. package/dist/helpdesk/index.d.ts +10 -0
  208. package/dist/helpdesk/index.js +463 -0
  209. package/dist/helpdesk/module.d.ts +2960 -0
  210. package/dist/helpdesk/module.js +326 -0
  211. package/dist/helpdesk/routes.d.ts +12 -0
  212. package/dist/helpdesk/routes.js +132 -0
  213. package/dist/helpdesk/sla.d.ts +37 -0
  214. package/dist/helpdesk/sla.js +226 -0
  215. package/dist/hr/.kosh/bindings.js +1 -1
  216. package/dist/hr/.kosh/schema.d.ts +59 -1
  217. package/dist/hr/demo.js +11 -1
  218. package/dist/hr/i18n/bn.d.ts +2 -0
  219. package/dist/hr/i18n/bn.js +126 -0
  220. package/dist/hr/index.d.ts +1 -1
  221. package/dist/hr/index.js +158 -12
  222. package/dist/hr/module.d.ts +932 -59
  223. package/dist/hr/module.js +114 -17
  224. package/dist/indent/.kosh/bindings.d.ts +22 -0
  225. package/dist/indent/.kosh/bindings.js +15 -0
  226. package/dist/indent/.kosh/schema.d.ts +2084 -0
  227. package/dist/indent/demo.d.ts +7 -0
  228. package/dist/indent/demo.js +48 -0
  229. package/dist/indent/i18n/bn.d.ts +2 -0
  230. package/dist/indent/i18n/bn.js +143 -0
  231. package/dist/indent/index.d.ts +3 -0
  232. package/dist/indent/index.js +450 -0
  233. package/dist/indent/module.d.ts +13424 -0
  234. package/dist/indent/module.js +792 -0
  235. package/dist/indent_purchase/.kosh/bindings.d.ts +22 -0
  236. package/dist/indent_purchase/.kosh/bindings.js +15 -0
  237. package/dist/indent_purchase/.kosh/schema.d.ts +2710 -0
  238. package/dist/indent_purchase/i18n/bn.d.ts +2 -0
  239. package/dist/indent_purchase/i18n/bn.js +13 -0
  240. package/dist/indent_purchase/index.d.ts +3 -0
  241. package/dist/indent_purchase/index.js +61 -0
  242. package/dist/indent_purchase/module.d.ts +27950 -0
  243. package/dist/indent_purchase/module.js +163 -0
  244. package/dist/l10n_bd/.kosh/bindings.js +1 -1
  245. package/dist/l10n_bd/.kosh/schema.d.ts +651 -10
  246. package/dist/l10n_bd/i18n/bn.d.ts +2 -0
  247. package/dist/l10n_bd/i18n/bn.js +69 -0
  248. package/dist/l10n_bd/index.js +2 -0
  249. package/dist/l10n_bd/module.d.ts +5212 -1592
  250. package/dist/l10n_bd_payroll/.kosh/bindings.d.ts +22 -0
  251. package/dist/l10n_bd_payroll/.kosh/bindings.js +15 -0
  252. package/dist/l10n_bd_payroll/.kosh/schema.d.ts +2891 -0
  253. package/dist/l10n_bd_payroll/data.d.ts +47 -0
  254. package/dist/l10n_bd_payroll/data.js +347 -0
  255. package/dist/l10n_bd_payroll/i18n/bn.d.ts +2 -0
  256. package/dist/l10n_bd_payroll/i18n/bn.js +4 -0
  257. package/dist/l10n_bd_payroll/index.d.ts +4 -0
  258. package/dist/l10n_bd_payroll/index.js +26 -0
  259. package/dist/l10n_bd_payroll/module.d.ts +17294 -0
  260. package/dist/l10n_bd_payroll/module.js +86 -0
  261. package/dist/l10n_bd_pos/.kosh/bindings.d.ts +22 -0
  262. package/dist/{mrp_account → l10n_bd_pos}/.kosh/bindings.js +2 -2
  263. package/dist/l10n_bd_pos/.kosh/schema.d.ts +2341 -0
  264. package/dist/l10n_bd_pos/i18n/bn.d.ts +2 -0
  265. package/dist/l10n_bd_pos/i18n/bn.js +32 -0
  266. package/dist/l10n_bd_pos/index.d.ts +3 -0
  267. package/dist/l10n_bd_pos/index.js +111 -0
  268. package/dist/{mrp_account → l10n_bd_pos}/module.d.ts +9047 -6981
  269. package/dist/l10n_bd_pos/module.js +43 -0
  270. package/dist/l10n_in/.kosh/bindings.js +1 -1
  271. package/dist/l10n_in/.kosh/schema.d.ts +651 -10
  272. package/dist/l10n_in/i18n/bn.d.ts +2 -0
  273. package/dist/l10n_in/i18n/bn.js +95 -0
  274. package/dist/l10n_in/index.js +2 -0
  275. package/dist/l10n_in/module.d.ts +6778 -1580
  276. package/dist/l10n_in/module.js +25 -5
  277. package/dist/l10n_in/web/GstSettings.js +2 -2
  278. package/dist/mail/inbound/handle.js +8 -5
  279. package/dist/mail/inbound/models.js +5 -3
  280. package/dist/mail/index.d.ts +12 -1
  281. package/dist/mail/index.js +139 -2
  282. package/dist/mail/send.d.ts +56 -0
  283. package/dist/mail/send.js +394 -0
  284. package/dist/mail/web/SendButton.d.ts +9 -0
  285. package/dist/mail/web/SendButton.js +71 -0
  286. package/dist/mail/web/SendSelected.d.ts +8 -0
  287. package/dist/mail/web/SendSelected.js +33 -0
  288. package/dist/mail/web/index.d.ts +2 -0
  289. package/dist/mail/web/index.js +6 -0
  290. package/dist/mail/web/messages.js +36 -0
  291. package/dist/maintenance/.kosh/bindings.js +1 -1
  292. package/dist/maintenance/.kosh/schema.d.ts +2 -1
  293. package/dist/maintenance/i18n/bn.d.ts +2 -0
  294. package/dist/maintenance/i18n/bn.js +132 -0
  295. package/dist/maintenance/index.js +85 -0
  296. package/dist/maintenance/module.d.ts +25 -0
  297. package/dist/maintenance/module.js +27 -9
  298. package/dist/maintenance_stock/.kosh/bindings.js +1 -1
  299. package/dist/maintenance_stock/.kosh/schema.d.ts +374 -3
  300. package/dist/maintenance_stock/i18n/bn.d.ts +2 -0
  301. package/dist/maintenance_stock/i18n/bn.js +21 -0
  302. package/dist/maintenance_stock/index.js +2 -0
  303. package/dist/maintenance_stock/module.d.ts +6095 -1327
  304. package/dist/maintenance_stock/module.js +1 -0
  305. package/dist/modules-sdk/apps.d.ts +10 -0
  306. package/dist/modules-sdk/apps.js +32 -0
  307. package/dist/modules-sdk/index.d.ts +1 -1
  308. package/dist/modules-sdk/manifest.d.ts +105 -2
  309. package/dist/payment/.kosh/bindings.js +1 -1
  310. package/dist/payment/.kosh/schema.d.ts +653 -11
  311. package/dist/payment/i18n/bn.d.ts +2 -0
  312. package/dist/payment/i18n/bn.js +59 -0
  313. package/dist/payment/index.d.ts +41 -0
  314. package/dist/payment/index.js +216 -74
  315. package/dist/payment/module.d.ts +5353 -1675
  316. package/dist/payment/module.js +36 -6
  317. package/dist/payment/settle.js +11 -1
  318. package/dist/payroll/.kosh/bindings.d.ts +22 -0
  319. package/dist/payroll/.kosh/bindings.js +15 -0
  320. package/dist/payroll/.kosh/schema.d.ts +1448 -0
  321. package/dist/payroll/compute.d.ts +35 -0
  322. package/dist/payroll/compute.js +398 -0
  323. package/dist/payroll/demo.d.ts +55 -0
  324. package/dist/payroll/demo.js +121 -0
  325. package/dist/payroll/formula.d.ts +62 -0
  326. package/dist/payroll/formula.js +320 -0
  327. package/dist/payroll/i18n/bn.d.ts +2 -0
  328. package/dist/payroll/i18n/bn.js +206 -0
  329. package/dist/payroll/index.d.ts +230 -0
  330. package/dist/payroll/index.js +715 -0
  331. package/dist/{mrp → payroll}/module.d.ts +4294 -2624
  332. package/dist/payroll/module.js +606 -0
  333. package/dist/payroll/routes.d.ts +10 -0
  334. package/dist/payroll/routes.js +112 -0
  335. package/dist/payroll_account/.kosh/bindings.d.ts +22 -0
  336. package/dist/payroll_account/.kosh/bindings.js +15 -0
  337. package/dist/payroll_account/.kosh/schema.d.ts +2887 -0
  338. package/dist/payroll_account/i18n/bn.d.ts +2 -0
  339. package/dist/payroll_account/i18n/bn.js +10 -0
  340. package/dist/payroll_account/index.d.ts +3 -0
  341. package/dist/payroll_account/index.js +42 -0
  342. package/dist/payroll_account/module.d.ts +16738 -0
  343. package/dist/payroll_account/module.js +256 -0
  344. package/dist/permissions/approvals.d.ts +227 -12
  345. package/dist/permissions/approvals.js +1421 -67
  346. package/dist/permissions/index.d.ts +1 -1
  347. package/dist/permissions/index.js +2 -2
  348. package/dist/permissions/models.js +364 -13
  349. package/dist/permissions/routes.d.ts +9 -1
  350. package/dist/permissions/routes.js +72 -5
  351. package/dist/permissions/web/ApprovalPanel.d.ts +5 -4
  352. package/dist/permissions/web/ApprovalPanel.js +75 -11
  353. package/dist/permissions/web/index.d.ts +6 -4
  354. package/dist/permissions/web/index.js +13 -4
  355. package/dist/permissions/web/messages.d.ts +2 -0
  356. package/dist/permissions/web/messages.js +95 -0
  357. package/dist/portal/.kosh/bindings.js +1 -1
  358. package/dist/portal/.kosh/schema.d.ts +2 -1
  359. package/dist/portal/documents.d.ts +3 -0
  360. package/dist/portal/documents.js +21 -1
  361. package/dist/portal/i18n/bn.d.ts +2 -0
  362. package/dist/portal/i18n/bn.js +33 -0
  363. package/dist/portal/index.js +3 -1
  364. package/dist/portal/module.d.ts +20 -0
  365. package/dist/portal/routes-documents.js +76 -0
  366. package/dist/pos/.kosh/bindings.js +1 -1
  367. package/dist/pos/.kosh/schema.d.ts +652 -10
  368. package/dist/pos/i18n/bn.d.ts +2 -0
  369. package/dist/pos/i18n/bn.js +133 -0
  370. package/dist/pos/index.js +87 -1
  371. package/dist/pos/module.d.ts +6967 -1709
  372. package/dist/pos/module.js +49 -5
  373. package/dist/pos/routes.js +80 -7
  374. package/dist/pos/web/Register.js +2 -5
  375. package/dist/pos_stock/.kosh/bindings.js +1 -1
  376. package/dist/pos_stock/.kosh/schema.d.ts +822 -12
  377. package/dist/pos_stock/i18n/bn.d.ts +2 -0
  378. package/dist/pos_stock/i18n/bn.js +6 -0
  379. package/dist/pos_stock/index.js +2 -0
  380. package/dist/pos_stock/module.d.ts +11241 -2851
  381. package/dist/product/.kosh/bindings.js +1 -1
  382. package/dist/product/.kosh/schema.d.ts +203 -1
  383. package/dist/product/i18n/bn.d.ts +2 -0
  384. package/dist/product/i18n/bn.js +175 -0
  385. package/dist/product/index.d.ts +1 -0
  386. package/dist/product/index.js +301 -1
  387. package/dist/product/module.d.ts +1727 -0
  388. package/dist/product/module.js +67 -6
  389. package/dist/product/pricelist.d.ts +575 -0
  390. package/dist/product/pricelist.js +257 -0
  391. package/dist/product/variants.d.ts +908 -0
  392. package/dist/product/variants.js +251 -0
  393. package/dist/production/.kosh/bindings.d.ts +22 -0
  394. package/dist/production/.kosh/bindings.js +15 -0
  395. package/dist/production/.kosh/schema.d.ts +2345 -0
  396. package/dist/{mrp → production}/demo.d.ts +1 -1
  397. package/dist/{mrp → production}/demo.js +5 -5
  398. package/dist/production/depth.d.ts +790 -0
  399. package/dist/production/depth.js +262 -0
  400. package/dist/production/i18n/bn.d.ts +2 -0
  401. package/dist/production/i18n/bn.js +350 -0
  402. package/dist/production/index.d.ts +6 -0
  403. package/dist/production/index.js +1256 -0
  404. package/dist/production/module.d.ts +17327 -0
  405. package/dist/production/module.js +1333 -0
  406. package/dist/production/plan.d.ts +921 -0
  407. package/dist/production/plan.js +511 -0
  408. package/dist/production/schedule.d.ts +656 -0
  409. package/dist/production/schedule.js +309 -0
  410. package/dist/production_account/.kosh/bindings.d.ts +22 -0
  411. package/dist/production_account/.kosh/bindings.js +15 -0
  412. package/dist/production_account/.kosh/schema.d.ts +3496 -0
  413. package/dist/production_account/i18n/bn.d.ts +2 -0
  414. package/dist/production_account/i18n/bn.js +93 -0
  415. package/dist/production_account/index.d.ts +4 -0
  416. package/dist/production_account/index.js +246 -0
  417. package/dist/production_account/module.d.ts +1192 -0
  418. package/dist/{mrp_account → production_account}/module.js +72 -18
  419. package/dist/production_account/overhead.d.ts +1195 -0
  420. package/dist/production_account/overhead.js +554 -0
  421. package/dist/project/.kosh/bindings.js +1 -1
  422. package/dist/project/.kosh/schema.d.ts +735 -1
  423. package/dist/project/i18n/bn.d.ts +2 -0
  424. package/dist/project/i18n/bn.js +383 -0
  425. package/dist/project/index.d.ts +3 -1
  426. package/dist/project/index.js +1024 -14
  427. package/dist/project/module.d.ts +9912 -390
  428. package/dist/project/module.js +1590 -14
  429. package/dist/project/routes.d.ts +44 -0
  430. package/dist/project/routes.js +314 -0
  431. package/dist/project/schedule.d.ts +72 -0
  432. package/dist/project/schedule.js +192 -0
  433. package/dist/project/web/Refresh.d.ts +8 -0
  434. package/dist/project/web/Refresh.js +29 -0
  435. package/dist/project/web/Schedule.d.ts +9 -0
  436. package/dist/project/web/Schedule.js +93 -0
  437. package/dist/project/web/Structure.d.ts +8 -0
  438. package/dist/project/web/Structure.js +86 -0
  439. package/dist/project/web/Workload.d.ts +8 -0
  440. package/dist/project/web/Workload.js +43 -0
  441. package/dist/project/web/index.d.ts +14 -0
  442. package/dist/project/web/index.js +25 -0
  443. package/dist/project/web/messages.d.ts +2 -0
  444. package/dist/project/web/messages.js +85 -0
  445. package/dist/project_account/.kosh/bindings.d.ts +22 -0
  446. package/dist/project_account/.kosh/bindings.js +15 -0
  447. package/dist/project_account/.kosh/schema.d.ts +2763 -0
  448. package/dist/project_account/i18n/bn.d.ts +2 -0
  449. package/dist/project_account/i18n/bn.js +6 -0
  450. package/dist/project_account/index.d.ts +3 -0
  451. package/dist/project_account/index.js +29 -0
  452. package/dist/project_account/module.d.ts +15013 -0
  453. package/dist/project_account/module.js +76 -0
  454. package/dist/project_portal/.kosh/bindings.js +1 -1
  455. package/dist/project_portal/.kosh/schema.d.ts +735 -1
  456. package/dist/project_portal/i18n/bn.d.ts +2 -0
  457. package/dist/project_portal/i18n/bn.js +6 -0
  458. package/dist/project_portal/index.js +2 -0
  459. package/dist/project_portal/module.d.ts +4796 -87
  460. package/dist/project_purchase/.kosh/bindings.d.ts +22 -0
  461. package/dist/project_purchase/.kosh/bindings.js +15 -0
  462. package/dist/project_purchase/.kosh/schema.d.ts +3393 -0
  463. package/dist/project_purchase/i18n/bn.d.ts +2 -0
  464. package/dist/project_purchase/i18n/bn.js +4 -0
  465. package/dist/project_purchase/index.d.ts +9 -0
  466. package/dist/project_purchase/index.js +24 -0
  467. package/dist/project_purchase/module.d.ts +38613 -0
  468. package/dist/project_purchase/module.js +56 -0
  469. package/dist/purchase/.kosh/bindings.js +1 -1
  470. package/dist/purchase/.kosh/schema.d.ts +908 -5
  471. package/dist/purchase/comparison.d.ts +993 -0
  472. package/dist/purchase/comparison.js +415 -0
  473. package/dist/purchase/extras.d.ts +1509 -0
  474. package/dist/purchase/extras.js +445 -0
  475. package/dist/purchase/i18n/bn.d.ts +2 -0
  476. package/dist/purchase/i18n/bn.js +413 -0
  477. package/dist/purchase/index.d.ts +5 -0
  478. package/dist/purchase/index.js +1280 -4
  479. package/dist/purchase/module.d.ts +7147 -395
  480. package/dist/purchase/module.js +303 -10
  481. package/dist/purchase/request.d.ts +696 -0
  482. package/dist/purchase/request.js +446 -0
  483. package/dist/purchase/tender.d.ts +1208 -0
  484. package/dist/purchase/tender.js +507 -0
  485. package/dist/purchase/vendorprice.d.ts +340 -0
  486. package/dist/purchase/vendorprice.js +153 -0
  487. package/dist/purchase_account/.kosh/bindings.js +1 -1
  488. package/dist/purchase_account/.kosh/schema.d.ts +1209 -16
  489. package/dist/purchase_account/i18n/bn.d.ts +2 -0
  490. package/dist/purchase_account/i18n/bn.js +22 -0
  491. package/dist/purchase_account/index.js +20 -0
  492. package/dist/purchase_account/module.d.ts +12232 -2028
  493. package/dist/purchase_account/module.js +252 -9
  494. package/dist/purchase_portal/.kosh/bindings.js +1 -1
  495. package/dist/purchase_portal/.kosh/schema.d.ts +908 -5
  496. package/dist/purchase_portal/i18n/bn.d.ts +2 -0
  497. package/dist/purchase_portal/i18n/bn.js +5 -0
  498. package/dist/purchase_portal/index.js +2 -0
  499. package/dist/purchase_portal/module.d.ts +6853 -352
  500. package/dist/purchase_stock/.kosh/bindings.js +1 -1
  501. package/dist/purchase_stock/.kosh/schema.d.ts +1096 -21
  502. package/dist/purchase_stock/i18n/bn.d.ts +2 -0
  503. package/dist/purchase_stock/i18n/bn.js +19 -0
  504. package/dist/purchase_stock/index.d.ts +2 -2
  505. package/dist/purchase_stock/index.js +38 -2
  506. package/dist/purchase_stock/module.d.ts +12930 -1612
  507. package/dist/purchase_stock/module.js +317 -9
  508. package/dist/purchase_stock/scorecard.d.ts +22 -0
  509. package/dist/purchase_stock/scorecard.js +77 -0
  510. package/dist/purchase_stock/web/Scorecard.d.ts +7 -0
  511. package/dist/purchase_stock/web/Scorecard.js +22 -0
  512. package/dist/purchase_stock/web/index.d.ts +11 -0
  513. package/dist/purchase_stock/web/index.js +16 -0
  514. package/dist/purchase_stock/web/messages.d.ts +2 -0
  515. package/dist/purchase_stock/web/messages.js +27 -0
  516. package/dist/purchase_stock_account/.kosh/bindings.js +1 -1
  517. package/dist/purchase_stock_account/.kosh/schema.d.ts +1444 -20
  518. package/dist/purchase_stock_account/i18n/bn.d.ts +2 -0
  519. package/dist/purchase_stock_account/i18n/bn.js +8 -0
  520. package/dist/purchase_stock_account/index.js +18 -0
  521. package/dist/purchase_stock_account/module.d.ts +7 -35346
  522. package/dist/purchase_stock_account/module.js +35 -8
  523. package/dist/recruitment/.kosh/bindings.js +1 -1
  524. package/dist/recruitment/.kosh/schema.d.ts +60 -1
  525. package/dist/recruitment/i18n/bn.d.ts +2 -0
  526. package/dist/recruitment/i18n/bn.js +93 -0
  527. package/dist/recruitment/index.js +64 -0
  528. package/dist/recruitment/module.d.ts +460 -8
  529. package/dist/recruitment/module.js +13 -4
  530. package/dist/reporting/documents.d.ts +5 -0
  531. package/dist/reporting/documents.js +11 -1
  532. package/dist/reporting/index.d.ts +1 -1
  533. package/dist/reporting/index.js +1 -1
  534. package/dist/reporting/web/CalendarView.d.ts +18 -5
  535. package/dist/reporting/web/CalendarView.js +163 -29
  536. package/dist/reporting/web/messages.js +18 -0
  537. package/dist/sale_account/.kosh/bindings.js +1 -1
  538. package/dist/sale_account/.kosh/schema.d.ts +763 -18
  539. package/dist/sale_account/i18n/bn.d.ts +2 -0
  540. package/dist/sale_account/i18n/bn.js +48 -0
  541. package/dist/sale_account/index.d.ts +1 -1
  542. package/dist/sale_account/index.js +102 -4
  543. package/dist/sale_account/module.d.ts +8241 -2052
  544. package/dist/sale_account/module.js +535 -46
  545. package/dist/sale_crm/.kosh/bindings.d.ts +22 -0
  546. package/dist/sale_crm/.kosh/bindings.js +15 -0
  547. package/dist/{mrp → sale_crm}/.kosh/schema.d.ts +391 -494
  548. package/dist/sale_crm/i18n/bn.d.ts +2 -0
  549. package/dist/sale_crm/i18n/bn.js +9 -0
  550. package/dist/sale_crm/index.d.ts +7 -0
  551. package/dist/sale_crm/index.js +104 -0
  552. package/dist/sale_crm/module.d.ts +5609 -0
  553. package/dist/sale_crm/module.js +73 -0
  554. package/dist/sale_portal/.kosh/bindings.js +1 -1
  555. package/dist/sale_portal/.kosh/schema.d.ts +292 -4
  556. package/dist/sale_portal/i18n/bn.d.ts +2 -0
  557. package/dist/sale_portal/i18n/bn.js +7 -0
  558. package/dist/sale_portal/index.js +10 -0
  559. package/dist/sale_portal/module.d.ts +2563 -292
  560. package/dist/sale_project/.kosh/bindings.js +1 -1
  561. package/dist/sale_project/.kosh/schema.d.ts +1025 -4
  562. package/dist/sale_project/i18n/bn.d.ts +2 -0
  563. package/dist/sale_project/i18n/bn.js +12 -0
  564. package/dist/sale_project/index.js +2 -0
  565. package/dist/sale_project/module.d.ts +9280 -762
  566. package/dist/sale_project/module.js +17 -1
  567. package/dist/sale_stock/.kosh/bindings.js +1 -1
  568. package/dist/sale_stock/.kosh/schema.d.ts +463 -6
  569. package/dist/sale_stock/i18n/bn.d.ts +2 -0
  570. package/dist/sale_stock/i18n/bn.js +15 -0
  571. package/dist/sale_stock/index.js +2 -0
  572. package/dist/sale_stock/module.d.ts +8355 -1334
  573. package/dist/sale_stock/module.js +20 -3
  574. package/dist/sales/.kosh/bindings.js +1 -1
  575. package/dist/sales/.kosh/schema.d.ts +292 -4
  576. package/dist/sales/i18n/bn.d.ts +2 -0
  577. package/dist/sales/i18n/bn.js +128 -0
  578. package/dist/sales/index.js +124 -5
  579. package/dist/sales/module.d.ts +3568 -633
  580. package/dist/sales/module.js +306 -11
  581. package/dist/server/api/duplicate.d.ts +14 -0
  582. package/dist/server/api/duplicate.js +75 -0
  583. package/dist/server/api/explain.d.ts +70 -0
  584. package/dist/server/api/explain.js +111 -0
  585. package/dist/server/api/metadata.d.ts +2 -0
  586. package/dist/server/api/metadata.js +9 -0
  587. package/dist/server/api/openapi.js +15 -0
  588. package/dist/server/api/rest.d.ts +1 -0
  589. package/dist/server/api/rest.js +76 -12
  590. package/dist/server/api/views.js +1 -1
  591. package/dist/server/apps.d.ts +16 -1
  592. package/dist/server/apps.js +164 -2
  593. package/dist/server/auth/base.js +2 -0
  594. package/dist/server/auth/service.d.ts +8 -0
  595. package/dist/server/auth/service.js +19 -0
  596. package/dist/server/events.d.ts +13 -0
  597. package/dist/server/events.js +22 -0
  598. package/dist/server/i18n.d.ts +27 -0
  599. package/dist/server/i18n.js +143 -0
  600. package/dist/server/index.d.ts +2 -0
  601. package/dist/server/index.js +2 -0
  602. package/dist/server/server.js +6 -0
  603. package/dist/settings/company.d.ts +3 -1
  604. package/dist/settings/company.js +26 -5
  605. package/dist/settings/routes.d.ts +10 -0
  606. package/dist/settings/routes.js +19 -3
  607. package/dist/settings/web/AppsPage.d.ts +3 -2
  608. package/dist/settings/web/AppsPage.js +26 -8
  609. package/dist/settings/web/CompaniesPage.js +91 -6
  610. package/dist/settings/web/messages.js +64 -0
  611. package/dist/sign/.kosh/bindings.d.ts +22 -0
  612. package/dist/{mrp → sign}/.kosh/bindings.js +2 -2
  613. package/dist/sign/.kosh/schema.d.ts +991 -0
  614. package/dist/sign/i18n/bn.d.ts +2 -0
  615. package/dist/sign/i18n/bn.js +97 -0
  616. package/dist/sign/index.d.ts +29 -0
  617. package/dist/sign/index.js +478 -0
  618. package/dist/sign/module.d.ts +4518 -0
  619. package/dist/sign/module.js +167 -0
  620. package/dist/sign/sign.d.ts +82 -0
  621. package/dist/sign/sign.js +474 -0
  622. package/dist/stock/.kosh/bindings.js +1 -1
  623. package/dist/stock/.kosh/schema.d.ts +374 -3
  624. package/dist/stock/demo.d.ts +2 -1
  625. package/dist/stock/demo.js +28 -1
  626. package/dist/stock/i18n/bn.d.ts +2 -0
  627. package/dist/stock/i18n/bn.js +311 -0
  628. package/dist/stock/index.d.ts +4 -1
  629. package/dist/stock/index.js +674 -6
  630. package/dist/stock/ledger.d.ts +78 -0
  631. package/dist/stock/ledger.js +582 -0
  632. package/dist/stock/module.d.ts +6142 -1380
  633. package/dist/stock/module.js +780 -26
  634. package/dist/stock/replenish.d.ts +38 -0
  635. package/dist/stock/replenish.js +191 -0
  636. package/dist/stock/returns.d.ts +157 -0
  637. package/dist/stock/returns.js +163 -0
  638. package/dist/stock/web/Ledger.d.ts +9 -0
  639. package/dist/stock/web/Ledger.js +108 -0
  640. package/dist/stock/web/Operations.d.ts +8 -0
  641. package/dist/stock/web/Operations.js +33 -0
  642. package/dist/stock/web/Replenishment.d.ts +8 -0
  643. package/dist/stock/web/Replenishment.js +84 -0
  644. package/dist/stock/web/ReturnButton.d.ts +7 -0
  645. package/dist/stock/web/ReturnButton.js +62 -0
  646. package/dist/stock/web/index.d.ts +7 -2
  647. package/dist/stock/web/index.js +15 -2
  648. package/dist/stock/web/messages.js +206 -0
  649. package/dist/stock_account/.kosh/bindings.js +1 -1
  650. package/dist/stock_account/.kosh/schema.d.ts +878 -12
  651. package/dist/stock_account/i18n/bn.d.ts +2 -0
  652. package/dist/stock_account/i18n/bn.js +73 -0
  653. package/dist/stock_account/index.d.ts +1 -0
  654. package/dist/stock_account/index.js +141 -3
  655. package/dist/stock_account/landed.d.ts +429 -0
  656. package/dist/stock_account/landed.js +335 -0
  657. package/dist/stock_account/module.d.ts +12143 -3391
  658. package/dist/stock_account/module.js +135 -6
  659. package/dist/stock_account/web/LandedPreview.d.ts +7 -0
  660. package/dist/stock_account/web/LandedPreview.js +23 -0
  661. package/dist/stock_account/web/index.d.ts +11 -0
  662. package/dist/stock_account/web/index.js +16 -0
  663. package/dist/stock_account/web/messages.d.ts +2 -0
  664. package/dist/stock_account/web/messages.js +27 -0
  665. package/dist/todo/i18n/bn.d.ts +2 -0
  666. package/dist/todo/i18n/bn.js +66 -0
  667. package/dist/todo/index.js +59 -0
  668. package/dist/todo/module.d.ts +5 -0
  669. package/dist/todo/module.js +5 -3
  670. package/dist/trade_finance/.kosh/bindings.js +1 -1
  671. package/dist/trade_finance/.kosh/schema.d.ts +2 -1
  672. package/dist/trade_finance/i18n/bn.d.ts +2 -0
  673. package/dist/trade_finance/i18n/bn.js +162 -0
  674. package/dist/trade_finance/index.js +95 -0
  675. package/dist/trade_finance/module.d.ts +26 -0
  676. package/dist/trade_finance/module.js +29 -8
  677. package/dist/trade_finance_account/.kosh/bindings.js +1 -1
  678. package/dist/trade_finance_account/.kosh/schema.d.ts +651 -10
  679. package/dist/trade_finance_account/i18n/bn.d.ts +2 -0
  680. package/dist/trade_finance_account/i18n/bn.js +27 -0
  681. package/dist/trade_finance_account/index.js +3 -0
  682. package/dist/trade_finance_account/module.d.ts +5129 -1509
  683. package/dist/trade_finance_account/module.js +2 -0
  684. package/dist/trade_finance_purchase/.kosh/bindings.js +1 -1
  685. package/dist/trade_finance_purchase/.kosh/schema.d.ts +908 -5
  686. package/dist/trade_finance_purchase/i18n/bn.d.ts +2 -0
  687. package/dist/trade_finance_purchase/i18n/bn.js +6 -0
  688. package/dist/trade_finance_purchase/index.js +2 -0
  689. package/dist/trade_finance_purchase/module.d.ts +6909 -408
  690. package/dist/trade_finance_sale/.kosh/bindings.js +1 -1
  691. package/dist/trade_finance_sale/.kosh/schema.d.ts +292 -4
  692. package/dist/trade_finance_sale/i18n/bn.d.ts +2 -0
  693. package/dist/trade_finance_sale/i18n/bn.js +6 -0
  694. package/dist/trade_finance_sale/index.js +2 -0
  695. package/dist/trade_finance_sale/module.d.ts +2602 -331
  696. package/dist/ui/api.d.ts +2 -0
  697. package/dist/ui/app.d.ts +9 -0
  698. package/dist/ui/app.js +47 -15
  699. package/dist/ui/components/AppIcon.js +9 -2
  700. package/dist/ui/components/Explain.d.ts +69 -0
  701. package/dist/ui/components/Explain.js +62 -0
  702. package/dist/ui/context.d.ts +8 -1
  703. package/dist/ui/context.js +34 -1
  704. package/dist/ui/i18n/messages.d.ts +40 -0
  705. package/dist/ui/i18n/messages.js +80 -0
  706. package/dist/ui/index.d.ts +2 -1
  707. package/dist/ui/index.js +1 -0
  708. package/dist/ui/registry.d.ts +14 -0
  709. package/dist/ui/registry.js +10 -0
  710. package/dist/ui/views/FormView.d.ts +6 -0
  711. package/dist/ui/views/FormView.js +51 -12
  712. package/dist/ui/views/KanbanView.js +9 -1
  713. package/dist/ui/views/ListView.d.ts +8 -0
  714. package/dist/ui/views/ListView.js +14 -5
  715. package/dist/ui/views/StatsRow.js +2 -1
  716. package/dist/ui/views/widgets.js +7 -1
  717. package/dist/views/extend.js +12 -0
  718. package/dist/views/types.d.ts +13 -2
  719. package/dist/views/validate.js +8 -1
  720. package/dist/website/.kosh/bindings.js +1 -1
  721. package/dist/website/.kosh/schema.d.ts +2 -1
  722. package/dist/website/i18n/bn.d.ts +2 -0
  723. package/dist/website/i18n/bn.js +113 -0
  724. package/dist/website/index.js +37 -0
  725. package/dist/website/module.d.ts +20 -0
  726. package/dist/website/module.js +30 -5
  727. package/dist/website_crm/.kosh/bindings.js +1 -1
  728. package/dist/website_crm/.kosh/schema.d.ts +3 -1
  729. package/dist/website_crm/i18n/bn.d.ts +2 -0
  730. package/dist/website_crm/i18n/bn.js +5 -0
  731. package/dist/website_crm/index.js +2 -0
  732. package/dist/website_crm/module.d.ts +41 -0
  733. package/dist/website_sale/.kosh/bindings.d.ts +22 -0
  734. package/dist/website_sale/.kosh/bindings.js +15 -0
  735. package/dist/website_sale/.kosh/schema.d.ts +2909 -0
  736. package/dist/website_sale/couriers.d.ts +50 -0
  737. package/dist/website_sale/couriers.js +59 -0
  738. package/dist/website_sale/demo.d.ts +7 -0
  739. package/dist/website_sale/demo.js +90 -0
  740. package/dist/website_sale/growth.d.ts +31 -0
  741. package/dist/website_sale/growth.js +163 -0
  742. package/dist/website_sale/i18n/bn.d.ts +2 -0
  743. package/dist/website_sale/i18n/bn.js +132 -0
  744. package/dist/website_sale/index.d.ts +49 -0
  745. package/dist/website_sale/index.js +620 -0
  746. package/dist/website_sale/module.d.ts +35182 -0
  747. package/dist/website_sale/module.js +419 -0
  748. package/dist/website_sale/shipments.d.ts +16 -0
  749. package/dist/website_sale/shipments.js +113 -0
  750. package/dist/website_sale/shop.d.ts +81 -0
  751. package/dist/website_sale/shop.js +662 -0
  752. package/dist/website_sale_stock/.kosh/bindings.d.ts +22 -0
  753. package/dist/website_sale_stock/.kosh/bindings.js +15 -0
  754. package/dist/website_sale_stock/.kosh/schema.d.ts +3400 -0
  755. package/dist/website_sale_stock/i18n/bn.d.ts +2 -0
  756. package/dist/website_sale_stock/i18n/bn.js +4 -0
  757. package/dist/website_sale_stock/index.d.ts +9 -0
  758. package/dist/website_sale_stock/index.js +22 -0
  759. package/dist/website_sale_stock/module.d.ts +11 -0
  760. package/dist/website_sale_stock/module.js +32 -0
  761. package/package.json +117 -8
  762. package/dist/mrp/index.d.ts +0 -3
  763. package/dist/mrp/index.js +0 -392
  764. package/dist/mrp/module.js +0 -695
  765. package/dist/mrp_account/index.d.ts +0 -3
  766. package/dist/mrp_account/index.js +0 -22
  767. /package/dist/{mrp → account_asset}/.kosh/bindings.d.ts +0 -0
  768. /package/dist/{mrp_account → account_budget}/.kosh/bindings.d.ts +0 -0
@@ -0,0 +1,649 @@
1
+ /**
2
+ * The data layer of Spend (RFC 0024 §2.1): expense categories with their **policy** (a limit per expense and per
3
+ * month, a receipt above an amount, a rate per day or per kilometre), expenses with their receipts, expense reports
4
+ * submitted together and decided through the approval engine, and **cash advances** that later reports settle.
5
+ *
6
+ * The server enforces the policy when a report is submitted: a missing receipt refuses it; an expense over a limit
7
+ * needs a reason and brings a further approval level (`overPolicy`); likely duplicates (the same amount, date and
8
+ * category, or the same receipt file) are flagged for the approvers. People file their own expenses; approvers see
9
+ * every report of their companies; Spend managers everything.
10
+ */
11
+ import { hrShutro } from '../hr/index.js';
12
+ import { approvalGuard, permissionsShutro, requestApprovals } from '../permissions/index.js';
13
+ import { productShutro } from '../product/index.js';
14
+ import { orm } from '../server/orm.js';
15
+ import { check, compute, defineModel, defineModule, f, method, onchange, record, records, } from './.kosh/bindings.js';
16
+ const READ = ['read'];
17
+ const ALL = ['read', 'write', 'create', 'unlink'];
18
+ const me = { $env: 'uid' };
19
+ const ZERO = orm.toDecimal(0);
20
+ export const ExpenseCategory = defineModel('expense.category', {
21
+ label: 'Expense category',
22
+ recName: 'name',
23
+ order: ['name asc'],
24
+ archivable: true,
25
+ access: { 'expense.user': READ, 'expense.manager': [...ALL, 'export', 'import'] },
26
+ fields: {
27
+ name: f.char({ required: true, translate: true }),
28
+ kind: f.selection({ amount: 'An amount', per_diem: 'Per day', mileage: 'Per kilometre' }, {
29
+ required: true,
30
+ default: 'amount',
31
+ label: 'Claimed as',
32
+ help: 'An amount as on the receipt, or a quantity of days or kilometres at the category’s rate.',
33
+ }),
34
+ rate: f.decimal({ scale: 2, label: 'Rate', help: 'Per day or per kilometre.' }),
35
+ limitPerExpense: f.decimal({
36
+ scale: 2,
37
+ label: 'Limit per expense',
38
+ help: 'An expense above it needs a reason and a further approval.',
39
+ }),
40
+ limitPerMonth: f.decimal({
41
+ scale: 2,
42
+ label: 'Limit per person per month',
43
+ help: 'A person’s expenses of this category in a month, together.',
44
+ }),
45
+ receiptAbove: f.decimal({
46
+ scale: 2,
47
+ label: 'Receipt required above',
48
+ help: 'Empty: always; 0 or more: a receipt is attached to expenses above this amount.',
49
+ }),
50
+ tax: f.many2one('account.tax', {
51
+ ondelete: 'set null',
52
+ label: 'Tax included',
53
+ help: 'The purchase tax included in the amounts of this category.',
54
+ }),
55
+ note: f.text({ label: 'Guidance', translate: true }),
56
+ },
57
+ sqlConstraints: {
58
+ ratedHasRate: {
59
+ check: orm.sql `kind = 'amount' OR (rate IS NOT NULL AND rate > 0)`,
60
+ message: 'A category per day or per kilometre has a rate.',
61
+ },
62
+ },
63
+ });
64
+ /** The employee of the acting user, if they have one. */
65
+ async function ownEmployee(env) {
66
+ const found = await env.model('hr.employee').search({ where: { user: env.userId }, limit: 1 });
67
+ return found.ids[0] ?? null;
68
+ }
69
+ /** Fills an empty employee with the user's own, and a rated category's amount from its quantity. */
70
+ async function fillExpense(d, env) {
71
+ if ((d.get('employee') ?? null) === null) {
72
+ const mine = await ownEmployee(env);
73
+ if (mine !== null)
74
+ d.set('employee', mine);
75
+ }
76
+ const category = (await d.record('category'));
77
+ if (category === null)
78
+ return;
79
+ if ((d.get('tax') ?? null) === null && category.tax !== null)
80
+ d.set('tax', category.tax.id);
81
+ if (category.kind !== 'amount' && category.rate !== null) {
82
+ const quantity = orm.toDecimal(String(d.get('quantity') ?? '1'));
83
+ d.set('amount', category.rate.times(quantity).toDecimalPlaces(2).toString());
84
+ }
85
+ }
86
+ export const ExpenseExpense = defineModel('expense.expense', {
87
+ label: 'Expense',
88
+ order: ['date desc', 'id desc'],
89
+ companyScoped: { required: true },
90
+ tracking: ['amount', 'category', 'sheet'],
91
+ access: {
92
+ 'expense.user': ALL,
93
+ 'expense.approver': ALL,
94
+ 'expense.manager': [...ALL, 'export', 'import'],
95
+ },
96
+ rules: {
97
+ // One's own expenses; changed while not yet submitted.
98
+ seeOwn: { groups: ['expense.user'], perms: ['read'], domain: { 'employee.user': me } },
99
+ draftOwn: {
100
+ groups: ['expense.user'],
101
+ perms: ['write', 'create', 'unlink'],
102
+ domain: {
103
+ 'employee.user': me,
104
+ or: [{ sheet: { isNull: true } }, { 'sheet.state': { in: ['draft', 'refused'] } }],
105
+ },
106
+ },
107
+ approvers: { groups: ['expense.approver'], perms: ['read'], domain: {} },
108
+ all: { groups: ['expense.manager'], perms: [...ALL], domain: {} },
109
+ },
110
+ fields: {
111
+ name: f.char({ required: true, label: 'Description' }),
112
+ employee: f.many2one('hr.employee', { required: true, ondelete: 'restrict' }),
113
+ date: f.date({ required: true, label: 'Spent on' }),
114
+ category: f.many2one('expense.category', { required: true, ondelete: 'restrict' }),
115
+ quantity: f.decimal({
116
+ scale: 2,
117
+ required: true,
118
+ default: '1',
119
+ help: 'Days or kilometres for a category claimed per day or per kilometre; 1 otherwise.',
120
+ }),
121
+ amount: f.decimal({ scale: 2, required: true, label: 'Amount (tax included)' }),
122
+ tax: f.many2one('account.tax', { ondelete: 'set null', label: 'Tax included' }),
123
+ taxAmount: f.decimal({
124
+ scale: 2,
125
+ label: 'Of which tax',
126
+ help: 'The tax included in the amount, from the tax’s rate.',
127
+ ...compute('expense.expense', 'taxAmount', ['amount', 'quantity', 'tax.amountType', 'tax.rate', 'tax.fixedAmount'], (expenses) => {
128
+ for (const e of expenses) {
129
+ const t = e.tax;
130
+ if (t === null)
131
+ e.taxAmount = ZERO;
132
+ else if (t.amountType === 'percent')
133
+ e.taxAmount = e.amount
134
+ .times(t.rate)
135
+ .div(orm.toDecimal(100).plus(t.rate))
136
+ .toDecimalPlaces(2);
137
+ else
138
+ e.taxAmount = t.fixedAmount.times(e.quantity).toDecimalPlaces(2);
139
+ }
140
+ }),
141
+ store: true,
142
+ }),
143
+ vendor: f.many2one('res.partner', { ondelete: 'set null', label: 'Paid to' }),
144
+ reference: f.char({ label: 'Receipt number' }),
145
+ paidBy: f.selection({ employee: 'The employee (to reimburse)', company: 'The company (company card)' }, {
146
+ required: true,
147
+ default: 'employee',
148
+ label: 'Paid by',
149
+ help: 'Expenses paid by the employee are reimbursed; company-card expenses only booked.',
150
+ }),
151
+ sheet: f.many2one('expense.sheet', { ondelete: 'set null', label: 'Report' }),
152
+ /** Why the expense goes beyond its category's policy (required then, at submission). */
153
+ policyReason: f.char({ size: 300, label: 'Reason beyond the policy' }),
154
+ overPolicy: f.boolean({
155
+ default: false,
156
+ label: 'Beyond the policy',
157
+ help: 'Set when the report is submitted: above a limit of its category.',
158
+ }),
159
+ duplicate: f.boolean({
160
+ default: false,
161
+ label: 'Possible duplicate',
162
+ help: 'Set when the report is submitted: the same amount, date and category, or the same receipt file, as another expense.',
163
+ }),
164
+ status: f.selection({
165
+ draft: 'Not reported',
166
+ reported: 'In a draft report',
167
+ submitted: 'Waiting for approval',
168
+ approved: 'Approved',
169
+ refused: 'Refused',
170
+ done: 'Done',
171
+ posted: 'Booked',
172
+ paid: 'Reimbursed',
173
+ }, {
174
+ label: 'Status',
175
+ help: 'Follows the report the expense is in.',
176
+ ...compute('expense.expense', 'status', ['sheet', 'sheet.state'], (expenses) => {
177
+ for (const e of expenses) {
178
+ const s = e.sheet?.state ?? null;
179
+ e.status =
180
+ s === null
181
+ ? 'draft'
182
+ : s === 'draft'
183
+ ? 'reported'
184
+ : s === 'to_approve'
185
+ ? 'submitted'
186
+ : s;
187
+ }
188
+ }),
189
+ store: true,
190
+ }),
191
+ },
192
+ sqlConstraints: {
193
+ positive: {
194
+ check: orm.sql `amount > 0 AND quantity > 0`,
195
+ message: 'Amounts and quantities are positive.',
196
+ },
197
+ },
198
+ constraints: {
199
+ // A category claimed per day or kilometre: the amount is its rate times the quantity.
200
+ rated: {
201
+ ...check('expense.expense', ['category', 'quantity', 'amount'], async (expenses) => [...(await expenses.load({ category: true }))]
202
+ .filter((e) => e.category.kind !== 'amount' &&
203
+ e.category.rate !== null &&
204
+ !e.category.rate.times(e.quantity).toDecimalPlaces(2).eq(e.amount))
205
+ .map((e) => e.id)),
206
+ message: 'The amount is the category’s rate times the days or kilometres.',
207
+ },
208
+ sameEmployee: {
209
+ ...check('expense.expense', ['sheet', 'employee'], async (expenses) => [...(await expenses.load({ sheet: true }))]
210
+ .filter((e) => e.sheet !== null && e.sheet.employee.id !== e.employee.id)
211
+ .map((e) => e.id)),
212
+ message: 'A report holds the expenses of its own employee.',
213
+ },
214
+ },
215
+ onchange: {
216
+ name: onchange('expense.expense', async (d, env) => fillExpense(d, env)),
217
+ category: onchange('expense.expense', async (d, env) => fillExpense(d, env)),
218
+ quantity: onchange('expense.expense', async (d, env) => fillExpense(d, env)),
219
+ },
220
+ });
221
+ /**
222
+ * The policy at submission: receipts where required (refused otherwise), limits (a reason then, and the flag that
223
+ * brings the further approval), and likely duplicates (flagged). Writes the flags and the advance used.
224
+ */
225
+ async function checkPolicy(sheets) {
226
+ const { env, ids } = sheets;
227
+ await env.asSuperuser({ reason: 'expense policy' }, async (su) => {
228
+ for (const sheet of await su
229
+ .model('expense.sheet')
230
+ .browse([...ids])
231
+ .load({
232
+ expenses: { category: true },
233
+ advance: true,
234
+ })) {
235
+ let over = false;
236
+ for (const e of sheet.expenses) {
237
+ const c = e.category;
238
+ // A receipt: an attachment of the expense, when the category asks for one at this amount.
239
+ const attachments = await su.model('storage.attachment').search({
240
+ where: { resModel: 'expense.expense', resId: e.id, variantOf: { isNull: true } },
241
+ });
242
+ const needsReceipt = c.receiptAbove === null || e.amount.gt(c.receiptAbove);
243
+ if (needsReceipt && c.kind === 'amount' && attachments.length === 0)
244
+ throw new orm.ValidationError('expense.sheet', ['expenses'], `${e.name}: attach the receipt (${c.name} needs one${c.receiptAbove === null ? '' : ` above ${c.receiptAbove.toString()}`}).`, 'Open the expense and attach a photo or a PDF of the receipt.');
245
+ // The limits: per expense, and per person and month with the category's other expenses.
246
+ let beyond = c.limitPerExpense !== null && e.amount.gt(c.limitPerExpense);
247
+ if (!beyond && c.limitPerMonth !== null) {
248
+ const date = isoDate(e.date);
249
+ const month = date.slice(0, 7);
250
+ const [y, m] = month.split('-').map(Number);
251
+ const next = m === 12 ? `${y + 1}-01` : `${y}-${String(m + 1).padStart(2, '0')}`;
252
+ const others = await (await su.model('expense.expense').search({
253
+ where: {
254
+ employee: e.employee.id,
255
+ category: c.id,
256
+ id: { ne: e.id },
257
+ status: { notIn: ['refused', 'draft'] },
258
+ date: { gte: `${month}-01`, lt: `${next}-01` },
259
+ },
260
+ })).load(['amount']);
261
+ const total = [...others].reduce((s, x) => s.plus(x.amount), e.amount);
262
+ beyond = total.gt(c.limitPerMonth);
263
+ }
264
+ if (beyond && (e.policyReason === null || e.policyReason.trim() === ''))
265
+ throw new orm.ValidationError('expense.sheet', ['expenses'], `${e.name}: beyond the ${c.name} policy — say why.`, 'Write the reason on the expense; a Spend manager approves it as well.');
266
+ over ||= beyond;
267
+ // Likely duplicates: the same amount, date and category, or the same receipt file.
268
+ const twins = await su.model('expense.expense').search({
269
+ where: {
270
+ id: { ne: e.id },
271
+ employee: e.employee.id,
272
+ category: c.id,
273
+ amount: e.amount,
274
+ date: e.date,
275
+ status: { ne: 'refused' },
276
+ },
277
+ limit: 1,
278
+ });
279
+ let duplicate = twins.length > 0;
280
+ if (!duplicate && attachments.length > 0) {
281
+ const hashes = [...(await attachments.load(['sha256']))].map((a) => a.sha256);
282
+ const same = await su.model('storage.attachment').search({
283
+ where: {
284
+ resModel: 'expense.expense',
285
+ resId: { ne: e.id },
286
+ sha256: { in: hashes },
287
+ },
288
+ limit: 1,
289
+ });
290
+ duplicate = same.length > 0;
291
+ }
292
+ await su.model('expense.expense').browse([e.id]).write({ overPolicy: beyond, duplicate });
293
+ }
294
+ // The advance this report settles: what is left of it, up to the report's total.
295
+ let used = ZERO;
296
+ if (sheet.advance !== null) {
297
+ const left = await advanceLeft(su, sheet.advance.id, sheet.id);
298
+ used = left.lt(sheet.total ?? ZERO) ? left : (sheet.total ?? ZERO);
299
+ if (used.lt(0))
300
+ used = ZERO;
301
+ }
302
+ await su
303
+ .model('expense.sheet')
304
+ .browse([sheet.id])
305
+ .write({ overPolicy: over, advanceUsed: used });
306
+ }
307
+ await su.flush();
308
+ });
309
+ }
310
+ /** What is left of an advance, other reports' use deducted (refused and draft reports aside). */
311
+ export async function advanceLeft(env, advance, except) {
312
+ const [a] = await env
313
+ .model('expense.advance')
314
+ .browse([advance])
315
+ .load(['amount']);
316
+ if (a === undefined)
317
+ return ZERO;
318
+ const users = await (await env.model('expense.sheet').search({
319
+ where: {
320
+ advance: advance,
321
+ state: { notIn: ['draft', 'refused'] },
322
+ ...(except === undefined ? {} : { id: { ne: except } }),
323
+ },
324
+ })).load(['advanceUsed']);
325
+ return [...users].reduce((s, x) => s.minus(x.advanceUsed), a.amount);
326
+ }
327
+ /** A date-only value as `YYYY-MM-DD` (PostgreSQL dates read as local midnights). */
328
+ export function isoDate(v) {
329
+ if (!(v instanceof Date))
330
+ return String(v ?? '').slice(0, 10);
331
+ const pad = (n) => String(n).padStart(2, '0');
332
+ return `${v.getFullYear()}-${pad(v.getMonth() + 1)}-${pad(v.getDate())}`;
333
+ }
334
+ const SHEET_STATES = {
335
+ draft: 'Draft',
336
+ to_approve: 'Waiting for approval',
337
+ approved: 'Approved',
338
+ done: 'Done',
339
+ refused: 'Refused',
340
+ };
341
+ export const ExpenseSheet = defineModel('expense.sheet', {
342
+ label: 'Expense report',
343
+ recName: 'name',
344
+ order: ['id desc'],
345
+ companyScoped: { required: true },
346
+ tracking: ['state', 'total', 'advance'],
347
+ access: {
348
+ 'expense.user': ALL,
349
+ 'expense.approver': ALL,
350
+ 'expense.manager': [...ALL, 'export', 'import'],
351
+ },
352
+ rules: {
353
+ seeOwn: { groups: ['expense.user'], perms: ['read'], domain: { 'employee.user': me } },
354
+ draftOwn: {
355
+ groups: ['expense.user'],
356
+ perms: ['write', 'create', 'unlink'],
357
+ domain: { 'employee.user': me, state: { in: ['draft', 'refused'] } },
358
+ },
359
+ approvers: { groups: ['expense.approver'], perms: ['read'], domain: {} },
360
+ all: { groups: ['expense.manager'], perms: [...ALL], domain: {} },
361
+ },
362
+ fields: {
363
+ name: f.char({ required: true, sequence: 'expense.sheet', label: 'Reference' }),
364
+ title: f.char({ label: 'Purpose' }),
365
+ employee: f.many2one('hr.employee', { required: true, ondelete: 'restrict' }),
366
+ expenses: f.one2many('expense.expense', 'sheet'),
367
+ expenseCount: f.integer({
368
+ label: 'Expenses',
369
+ ...compute('expense.sheet', 'expenseCount', ['expenses'], (sheets) => {
370
+ for (const s of sheets)
371
+ s.expenseCount = s.expenses.length;
372
+ }),
373
+ }),
374
+ total: f.decimal({
375
+ scale: 2,
376
+ label: 'Total',
377
+ help: 'The expenses of the report, tax included.',
378
+ ...compute('expense.sheet', 'total', ['expenses.amount'], (sheets) => {
379
+ for (const s of sheets)
380
+ s.total = [...s.expenses].reduce((t, e) => t.plus(e.amount), ZERO);
381
+ }),
382
+ store: true,
383
+ }),
384
+ toReimburse: f.decimal({
385
+ scale: 2,
386
+ label: 'To reimburse',
387
+ help: 'Paid by the employee, less what an advance already covered.',
388
+ ...compute('expense.sheet', 'toReimburse', ['expenses.amount', 'expenses.paidBy', 'advanceUsed'], (sheets) => {
389
+ for (const s of sheets) {
390
+ const own = [...s.expenses]
391
+ .filter((e) => e.paidBy === 'employee')
392
+ .reduce((t, e) => t.plus(e.amount), ZERO);
393
+ const left = own.minus(s.advanceUsed);
394
+ s.toReimburse = left.gt(0) ? left : ZERO;
395
+ }
396
+ }),
397
+ store: true,
398
+ }),
399
+ advance: f.many2one('expense.advance', {
400
+ ondelete: 'restrict',
401
+ label: 'Settles advance',
402
+ help: 'A cash advance paid to the employee that this report’s expenses settle.',
403
+ }),
404
+ advanceUsed: f.decimal({
405
+ scale: 2,
406
+ required: true,
407
+ default: '0',
408
+ label: 'From the advance',
409
+ help: 'Set when the report is submitted: what the advance covers.',
410
+ }),
411
+ overPolicy: f.boolean({
412
+ default: false,
413
+ label: 'Beyond the policy',
414
+ help: 'An expense of the report goes beyond its category’s policy: a Spend manager approves it too.',
415
+ }),
416
+ state: f.state({
417
+ states: SHEET_STATES,
418
+ initial: 'draft',
419
+ help: 'Draft, then submitted for approval; approved reports are booked and reimbursed (or settled outside the books).',
420
+ transitions: {
421
+ submit: {
422
+ from: ['draft', 'refused'],
423
+ to: 'to_approve',
424
+ guard: records('expense.sheet', async (sheets) => [...(await sheets.load({ expenses: true }))]
425
+ .filter((s) => s.expenses.length === 0)
426
+ .map((s) => s.id)),
427
+ message: 'Add the expenses to the report before submitting it.',
428
+ before: records('expense.sheet', (sheets) => checkPolicy(sheets)),
429
+ after: records('expense.sheet', async (sheets) => {
430
+ await requestApprovals(sheets);
431
+ for (const s of await sheets.load({}))
432
+ await sheets.env.emit('expense.sheet.submitted', { id: s.id });
433
+ }),
434
+ },
435
+ approve: {
436
+ from: ['to_approve'],
437
+ to: 'approved',
438
+ guard: records('expense.sheet', (sheets) => approvalGuard(sheets)),
439
+ message: 'Waiting for approvals.',
440
+ after: records('expense.sheet', async (sheets) => {
441
+ for (const s of await sheets.load({}))
442
+ await sheets.env.emit('expense.sheet.approved', { id: s.id });
443
+ }),
444
+ },
445
+ refuse: { from: ['to_approve'], to: 'refused' },
446
+ /** Settled outside the books (no accounting, or paid by other means). */
447
+ reimbursed: { from: ['approved'], to: 'done', requires: 'expense.settle' },
448
+ redraft: { from: ['refused'], to: 'draft' },
449
+ },
450
+ extensible: true, // expense_account books and reimburses
451
+ }),
452
+ },
453
+ constraints: {
454
+ // The advance is one of the employee's, paid, with something left.
455
+ advanceOfTheEmployee: {
456
+ ...check('expense.sheet', ['advance', 'employee'], async (sheets) => [...(await sheets.load({ advance: true }))]
457
+ .filter((s) => s.advance !== null &&
458
+ (s.advance.employee.id !== s.employee.id ||
459
+ !['paid', 'settled'].includes(s.advance.state)))
460
+ .map((s) => s.id)),
461
+ message: 'A report settles a paid advance of its own employee.',
462
+ },
463
+ },
464
+ onchange: {
465
+ title: onchange('expense.sheet', async (d, env) => {
466
+ const draft = d;
467
+ if ((draft.get('employee') ?? null) === null) {
468
+ const mine = await ownEmployee(env);
469
+ if (mine !== null)
470
+ draft.set('employee', mine);
471
+ }
472
+ }),
473
+ },
474
+ });
475
+ export const ExpenseAdvance = defineModel('expense.advance', {
476
+ label: 'Cash advance',
477
+ recName: 'name',
478
+ order: ['id desc'],
479
+ companyScoped: { required: true },
480
+ tracking: ['state', 'amount'],
481
+ access: {
482
+ 'expense.user': ALL,
483
+ 'expense.approver': ALL,
484
+ 'expense.manager': [...ALL, 'export', 'import'],
485
+ },
486
+ rules: {
487
+ seeOwn: { groups: ['expense.user'], perms: ['read'], domain: { 'employee.user': me } },
488
+ draftOwn: {
489
+ groups: ['expense.user'],
490
+ perms: ['write', 'create', 'unlink'],
491
+ domain: { 'employee.user': me, state: { in: ['draft', 'refused'] } },
492
+ },
493
+ approvers: { groups: ['expense.approver'], perms: ['read'], domain: {} },
494
+ all: { groups: ['expense.manager'], perms: [...ALL], domain: {} },
495
+ },
496
+ fields: {
497
+ name: f.char({ required: true, sequence: 'expense.advance', label: 'Reference' }),
498
+ employee: f.many2one('hr.employee', { required: true, ondelete: 'restrict' }),
499
+ purpose: f.char({ required: true }),
500
+ date: f.date({ required: true, label: 'Needed on' }),
501
+ amount: f.decimal({ scale: 2, required: true }),
502
+ sheets: f.one2many('expense.sheet', 'advance', { label: 'Settling reports' }),
503
+ settled: f.decimal({
504
+ scale: 2,
505
+ label: 'Settled',
506
+ help: 'Covered by the expenses of submitted and approved reports.',
507
+ ...compute('expense.advance', 'settled', ['sheets.advanceUsed', 'sheets.state'], (advances) => {
508
+ for (const a of advances)
509
+ a.settled = [...a.sheets]
510
+ .filter((s) => s.state !== 'draft' && s.state !== 'refused')
511
+ .reduce((t, s) => t.plus(s.advanceUsed), ZERO);
512
+ }),
513
+ store: true,
514
+ }),
515
+ balance: f.decimal({
516
+ scale: 2,
517
+ label: 'Left to settle',
518
+ help: 'The advance less what reports settled: returned by the employee when nothing more is spent.',
519
+ ...compute('expense.advance', 'balance', ['amount', 'settled'], (advances) => {
520
+ for (const a of advances)
521
+ a.balance = a.amount.minus(a.settled ?? ZERO);
522
+ }),
523
+ store: true,
524
+ }),
525
+ state: f.state({
526
+ states: {
527
+ draft: 'Draft',
528
+ to_approve: 'Waiting for approval',
529
+ approved: 'Approved',
530
+ paid: 'Paid out',
531
+ settled: 'Settled',
532
+ refused: 'Refused',
533
+ },
534
+ initial: 'draft',
535
+ help: 'Requested, approved, paid out, then settled by expense reports and the rest returned.',
536
+ transitions: {
537
+ submit: {
538
+ from: ['draft', 'refused'],
539
+ to: 'to_approve',
540
+ after: records('expense.advance', async (advances) => {
541
+ await requestApprovals(advances);
542
+ for (const a of await advances.load({}))
543
+ await advances.env.emit('expense.advance.submitted', { id: a.id });
544
+ }),
545
+ },
546
+ approve: {
547
+ from: ['to_approve'],
548
+ to: 'approved',
549
+ guard: records('expense.advance', (advances) => approvalGuard(advances)),
550
+ message: 'Waiting for approvals.',
551
+ },
552
+ refuse: { from: ['to_approve'], to: 'refused' },
553
+ pay: {
554
+ from: ['approved'],
555
+ to: 'paid',
556
+ requires: 'expense.settle',
557
+ // Accounting books the payout (expense_account overrides `paidOut`).
558
+ after: records('expense.advance', async (advances) => {
559
+ const env = advances.env;
560
+ await env.flush();
561
+ await env.model('expense.advance').browse(advances.ids).paidOut();
562
+ for (const id of advances.ids)
563
+ await env.emit('expense.advance.paid', { id });
564
+ }),
565
+ },
566
+ /** Spent in full by reports, or the rest returned. */
567
+ settle: {
568
+ from: ['paid'],
569
+ to: 'settled',
570
+ requires: 'expense.settle',
571
+ after: records('expense.advance', async (advances) => {
572
+ const env = advances.env;
573
+ await env.flush();
574
+ await env.model('expense.advance').browse(advances.ids).settledOut();
575
+ }),
576
+ },
577
+ redraft: { from: ['refused'], to: 'draft' },
578
+ },
579
+ extensible: true,
580
+ }),
581
+ },
582
+ sqlConstraints: {
583
+ positive: { check: orm.sql `amount > 0`, message: 'An advance is a positive amount.' },
584
+ },
585
+ methods: {
586
+ /** After the payout: nothing here; Accounting books it. */
587
+ paidOut: method('expense.advance', async () => undefined),
588
+ /** After the settlement: nothing here; Accounting books the cash returned. */
589
+ settledOut: method('expense.advance', async () => undefined),
590
+ },
591
+ });
592
+ export const expenseShutro = defineModule({
593
+ name: 'expense',
594
+ version: '0.1.0',
595
+ depends: [hrShutro, productShutro, permissionsShutro],
596
+ groups: [
597
+ orm.defineGroup({
598
+ code: 'expense.user',
599
+ label: 'Spend: own expenses',
600
+ // Receipts are attachments.
601
+ implies: ['hr.user', 'storage.user'],
602
+ }),
603
+ orm.defineGroup({
604
+ code: 'expense.approver',
605
+ label: 'Spend: approver',
606
+ implies: ['expense.user'],
607
+ }),
608
+ orm.defineGroup({
609
+ code: 'expense.manager',
610
+ label: 'Spend manager',
611
+ implies: ['expense.approver', 'product.user'],
612
+ }),
613
+ ],
614
+ permissions: [
615
+ orm.definePermission({
616
+ code: 'expense.settle',
617
+ label: 'Pay out advances and settle reports',
618
+ groups: ['expense.manager'],
619
+ }),
620
+ ],
621
+ sequences: [
622
+ orm.defineSequence({
623
+ code: 'expense.sheet',
624
+ prefix: 'EXP/{year}/',
625
+ padding: 5,
626
+ reset: 'yearly',
627
+ }),
628
+ orm.defineSequence({
629
+ code: 'expense.advance',
630
+ prefix: 'ADV/{year}/',
631
+ padding: 5,
632
+ reset: 'yearly',
633
+ }),
634
+ ],
635
+ models: [ExpenseCategory, ExpenseExpense, ExpenseSheet, ExpenseAdvance],
636
+ data: [
637
+ record('expense.category', 'category_travel', { name: 'Travel', kind: 'amount', receiptAbove: '500' }, { noupdate: true }),
638
+ record('expense.category', 'category_meals', {
639
+ name: 'Meals',
640
+ kind: 'amount',
641
+ limitPerExpense: '1500',
642
+ limitPerMonth: '6000',
643
+ receiptAbove: '300',
644
+ }, { noupdate: true }),
645
+ record('expense.category', 'category_per_diem', { name: 'Daily allowance', kind: 'per_diem', rate: '800' }, { noupdate: true }),
646
+ record('expense.category', 'category_mileage', { name: 'Own vehicle', kind: 'mileage', rate: '25' }, { noupdate: true }),
647
+ record('expense.category', 'category_office', { name: 'Office supplies', kind: 'amount' }, { noupdate: true }),
648
+ ],
649
+ });
@@ -0,0 +1,22 @@
1
+ export { defineModel, defineModule, extendModel, f, replace } from '../../server/orm.js';
2
+ import { type DefinitionHelpers } from '../../server/orm.js';
3
+ import type { DefaultLoaded, Env as CoreEnv, RecordSet as CoreRecordSet, Shutro as CoreShutro } from '../../server/orm.js';
4
+ import type { SchemaView } from './schema.js';
5
+ export type { SchemaView };
6
+ /** Every model visible in this view. */
7
+ export type ModelName = keyof SchemaView & string;
8
+ /** `Env` typed to this view. */
9
+ export type Env = CoreEnv<SchemaView>;
10
+ /** `Shutro` typed to this view. */
11
+ export type Shutro = CoreShutro<SchemaView>;
12
+ /** A recordset of `M`, with the default loaded shape unless `L` is given. */
13
+ export type Records<M extends ModelName, L = DefaultLoaded<SchemaView, M>> = CoreRecordSet<SchemaView, M, L>;
14
+ export declare const compute: DefinitionHelpers<SchemaView>['compute'];
15
+ export declare const check: DefinitionHelpers<SchemaView>['check'];
16
+ export declare const onchange: DefinitionHelpers<SchemaView>['onchange'];
17
+ export declare const records: DefinitionHelpers<SchemaView>['records'];
18
+ export declare const method: DefinitionHelpers<SchemaView>['method'];
19
+ /** Module data (RFC 0017): records, overrides of dependencies' records, and references, typed like creates. */
20
+ export declare const record: DefinitionHelpers<SchemaView>['record'];
21
+ export declare const override: DefinitionHelpers<SchemaView>['override'];
22
+ export declare const ref: DefinitionHelpers<SchemaView>['ref'];