shutro-erp 0.3.6 → 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 (623) hide show
  1. package/dist/account_asset/.kosh/bindings.js +1 -1
  2. package/dist/account_asset/.kosh/schema.d.ts +530 -8
  3. package/dist/account_asset/i18n/bn.d.ts +2 -0
  4. package/dist/account_asset/i18n/bn.js +97 -0
  5. package/dist/account_asset/index.js +2 -0
  6. package/dist/account_asset/module.d.ts +4899 -1445
  7. package/dist/account_budget/.kosh/bindings.js +1 -1
  8. package/dist/account_budget/.kosh/schema.d.ts +1130 -56
  9. package/dist/account_budget/i18n/bn.d.ts +2 -0
  10. package/dist/account_budget/i18n/bn.js +63 -0
  11. package/dist/account_budget/index.js +14 -0
  12. package/dist/account_budget/module.d.ts +17958 -4532
  13. package/dist/account_budget/module.js +15 -0
  14. package/dist/account_portal/.kosh/bindings.js +1 -1
  15. package/dist/account_portal/.kosh/schema.d.ts +530 -8
  16. package/dist/account_portal/i18n/bn.d.ts +2 -0
  17. package/dist/account_portal/i18n/bn.js +6 -0
  18. package/dist/account_portal/index.js +2 -0
  19. package/dist/account_portal/module.d.ts +5167 -1693
  20. package/dist/accounting/.kosh/bindings.js +1 -1
  21. package/dist/accounting/.kosh/schema.d.ts +530 -8
  22. package/dist/accounting/closing.js +1 -0
  23. package/dist/accounting/fiscal.d.ts +578 -0
  24. package/dist/accounting/fiscal.js +401 -0
  25. package/dist/accounting/followups.d.ts +618 -0
  26. package/dist/accounting/followups.js +420 -0
  27. package/dist/accounting/i18n/bn.d.ts +2 -0
  28. package/dist/accounting/i18n/bn.js +425 -0
  29. package/dist/accounting/index.d.ts +2 -0
  30. package/dist/accounting/index.js +649 -2
  31. package/dist/accounting/module.d.ts +4998 -1451
  32. package/dist/accounting/module.js +124 -18
  33. package/dist/accounting/statements.d.ts +878 -0
  34. package/dist/accounting/statements.js +728 -0
  35. package/dist/accounting/web/BankReconcilePage.d.ts +9 -0
  36. package/dist/accounting/web/BankReconcilePage.js +138 -0
  37. package/dist/accounting/web/FollowupsPage.d.ts +8 -0
  38. package/dist/accounting/web/FollowupsPage.js +54 -0
  39. package/dist/accounting/web/PostingPreview.d.ts +8 -0
  40. package/dist/accounting/web/PostingPreview.js +26 -0
  41. package/dist/accounting/web/index.d.ts +3 -0
  42. package/dist/accounting/web/index.js +9 -0
  43. package/dist/accounting/web/messages.js +140 -0
  44. package/dist/approvals/.kosh/bindings.js +1 -1
  45. package/dist/approvals/.kosh/schema.d.ts +272 -4
  46. package/dist/approvals/demo.d.ts +7 -0
  47. package/dist/approvals/demo.js +41 -0
  48. package/dist/approvals/i18n/bn.d.ts +2 -0
  49. package/dist/approvals/i18n/bn.js +133 -0
  50. package/dist/approvals/index.d.ts +19 -1
  51. package/dist/approvals/index.js +477 -7
  52. package/dist/approvals/mails.d.ts +7 -2
  53. package/dist/approvals/mails.js +8 -3
  54. package/dist/approvals/module.d.ts +2930 -1
  55. package/dist/approvals/module.js +468 -7
  56. package/dist/approvals/web/Config.d.ts +12 -0
  57. package/dist/approvals/web/Config.js +60 -0
  58. package/dist/approvals/web/Matrix.d.ts +9 -0
  59. package/dist/approvals/web/Matrix.js +26 -0
  60. package/dist/approvals/web/index.d.ts +3 -1
  61. package/dist/approvals/web/index.js +8 -1
  62. package/dist/approvals/web/messages.js +92 -0
  63. package/dist/approvals_purchase/.kosh/bindings.js +15 -0
  64. package/dist/approvals_purchase/.kosh/schema.d.ts +1997 -0
  65. package/dist/approvals_purchase/i18n/bn.d.ts +2 -0
  66. package/dist/approvals_purchase/i18n/bn.js +5 -0
  67. package/dist/approvals_purchase/index.d.ts +3 -0
  68. package/dist/approvals_purchase/index.js +47 -0
  69. package/dist/approvals_purchase/module.d.ts +12670 -0
  70. package/dist/approvals_purchase/module.js +84 -0
  71. package/dist/attendance/.kosh/bindings.js +1 -1
  72. package/dist/attendance/.kosh/schema.d.ts +59 -1
  73. package/dist/attendance/i18n/bn.d.ts +2 -0
  74. package/dist/attendance/i18n/bn.js +147 -0
  75. package/dist/attendance/index.js +3 -1
  76. package/dist/attendance/module.d.ts +452 -8
  77. package/dist/automation/engine.js +1 -1
  78. package/dist/calendar/.kosh/bindings.js +1 -1
  79. package/dist/calendar/.kosh/schema.d.ts +2 -1
  80. package/dist/calendar/i18n/bn.d.ts +2 -0
  81. package/dist/calendar/i18n/bn.js +80 -0
  82. package/dist/calendar/index.js +77 -0
  83. package/dist/calendar/module.d.ts +26 -0
  84. package/dist/calendar/module.js +14 -4
  85. package/dist/cli/apps.js +25 -5
  86. package/dist/cli/init.js +14 -4
  87. package/dist/cli/templates.d.ts +1 -1
  88. package/dist/cli/templates.js +34 -5
  89. package/dist/contacts/.kosh/bindings.js +1 -1
  90. package/dist/contacts/.kosh/schema.d.ts +2 -1
  91. package/dist/contacts/i18n/bn.d.ts +2 -0
  92. package/dist/contacts/i18n/bn.js +67 -0
  93. package/dist/contacts/index.js +3 -0
  94. package/dist/contacts/module.d.ts +42 -0
  95. package/dist/contacts/module.js +6 -1
  96. package/dist/crm/.kosh/bindings.js +1 -1
  97. package/dist/crm/.kosh/schema.d.ts +2 -1
  98. package/dist/crm/i18n/bn.d.ts +2 -0
  99. package/dist/crm/i18n/bn.js +80 -0
  100. package/dist/crm/index.js +22 -0
  101. package/dist/crm/module.d.ts +20 -0
  102. package/dist/crm/module.js +4 -2
  103. package/dist/documents/.kosh/bindings.js +1 -1
  104. package/dist/documents/.kosh/schema.d.ts +2 -1
  105. package/dist/documents/i18n/bn.d.ts +2 -0
  106. package/dist/documents/i18n/bn.js +83 -0
  107. package/dist/documents/index.js +128 -1
  108. package/dist/documents/module.d.ts +20 -0
  109. package/dist/documents/module.js +1 -0
  110. package/dist/event/.kosh/bindings.js +1 -1
  111. package/dist/event/.kosh/schema.d.ts +2 -1
  112. package/dist/event/i18n/bn.d.ts +2 -0
  113. package/dist/event/i18n/bn.js +101 -0
  114. package/dist/event/index.js +66 -0
  115. package/dist/event/module.d.ts +20 -0
  116. package/dist/event/module.js +8 -1
  117. package/dist/event_account/.kosh/bindings.js +1 -1
  118. package/dist/event_account/.kosh/schema.d.ts +530 -8
  119. package/dist/event_account/i18n/bn.d.ts +2 -0
  120. package/dist/event_account/i18n/bn.js +5 -0
  121. package/dist/event_account/index.js +2 -0
  122. package/dist/event_account/module.d.ts +4905 -1431
  123. package/dist/expense/.kosh/bindings.js +1 -1
  124. package/dist/expense/.kosh/schema.d.ts +323 -2
  125. package/dist/expense/i18n/bn.d.ts +2 -0
  126. package/dist/expense/i18n/bn.js +155 -0
  127. package/dist/expense/index.js +8 -1
  128. package/dist/expense/module.d.ts +2715 -694
  129. package/dist/expense/module.js +3 -1
  130. package/dist/expense_account/.kosh/bindings.js +1 -1
  131. package/dist/expense_account/.kosh/schema.d.ts +587 -8
  132. package/dist/expense_account/i18n/bn.d.ts +2 -0
  133. package/dist/expense_account/i18n/bn.js +15 -0
  134. package/dist/expense_account/index.js +2 -0
  135. package/dist/expense_account/module.d.ts +8094 -2619
  136. package/dist/helpdesk/.kosh/bindings.js +1 -1
  137. package/dist/helpdesk/.kosh/schema.d.ts +2 -1
  138. package/dist/helpdesk/i18n/bn.d.ts +2 -0
  139. package/dist/helpdesk/i18n/bn.js +127 -0
  140. package/dist/helpdesk/index.js +2 -0
  141. package/dist/helpdesk/module.d.ts +20 -0
  142. package/dist/hr/.kosh/bindings.js +1 -1
  143. package/dist/hr/.kosh/schema.d.ts +59 -1
  144. package/dist/hr/demo.js +11 -1
  145. package/dist/hr/i18n/bn.d.ts +2 -0
  146. package/dist/hr/i18n/bn.js +126 -0
  147. package/dist/hr/index.d.ts +1 -1
  148. package/dist/hr/index.js +158 -12
  149. package/dist/hr/module.d.ts +932 -59
  150. package/dist/hr/module.js +114 -17
  151. package/dist/{mrp → indent}/.kosh/bindings.js +2 -2
  152. package/dist/indent/.kosh/schema.d.ts +2084 -0
  153. package/dist/indent/demo.d.ts +7 -0
  154. package/dist/indent/demo.js +48 -0
  155. package/dist/indent/i18n/bn.d.ts +2 -0
  156. package/dist/indent/i18n/bn.js +143 -0
  157. package/dist/indent/index.d.ts +3 -0
  158. package/dist/indent/index.js +450 -0
  159. package/dist/{mrp → indent}/module.d.ts +7164 -3075
  160. package/dist/indent/module.js +792 -0
  161. package/dist/indent_purchase/.kosh/bindings.d.ts +22 -0
  162. package/dist/indent_purchase/.kosh/bindings.js +15 -0
  163. package/dist/indent_purchase/.kosh/schema.d.ts +2710 -0
  164. package/dist/indent_purchase/i18n/bn.d.ts +2 -0
  165. package/dist/indent_purchase/i18n/bn.js +13 -0
  166. package/dist/indent_purchase/index.d.ts +3 -0
  167. package/dist/indent_purchase/index.js +61 -0
  168. package/dist/indent_purchase/module.d.ts +27950 -0
  169. package/dist/indent_purchase/module.js +163 -0
  170. package/dist/l10n_bd/.kosh/bindings.js +1 -1
  171. package/dist/l10n_bd/.kosh/schema.d.ts +530 -8
  172. package/dist/l10n_bd/i18n/bn.d.ts +2 -0
  173. package/dist/l10n_bd/i18n/bn.js +69 -0
  174. package/dist/l10n_bd/index.js +2 -0
  175. package/dist/l10n_bd/module.d.ts +5167 -1693
  176. package/dist/l10n_bd_payroll/.kosh/bindings.js +1 -1
  177. package/dist/l10n_bd_payroll/.kosh/schema.d.ts +587 -8
  178. package/dist/l10n_bd_payroll/i18n/bn.d.ts +2 -0
  179. package/dist/l10n_bd_payroll/i18n/bn.js +4 -0
  180. package/dist/l10n_bd_payroll/index.js +2 -0
  181. package/dist/l10n_bd_payroll/module.d.ts +5910 -1548
  182. package/dist/l10n_bd_pos/.kosh/bindings.d.ts +22 -0
  183. package/dist/{mrp_account → l10n_bd_pos}/.kosh/bindings.js +2 -2
  184. package/dist/{mrp_account → l10n_bd_pos}/.kosh/schema.d.ts +693 -651
  185. package/dist/l10n_bd_pos/i18n/bn.d.ts +2 -0
  186. package/dist/l10n_bd_pos/i18n/bn.js +32 -0
  187. package/dist/l10n_bd_pos/index.d.ts +3 -0
  188. package/dist/l10n_bd_pos/index.js +111 -0
  189. package/dist/{mrp_account → l10n_bd_pos}/module.d.ts +7402 -7647
  190. package/dist/l10n_bd_pos/module.js +43 -0
  191. package/dist/l10n_in/.kosh/bindings.js +1 -1
  192. package/dist/l10n_in/.kosh/schema.d.ts +530 -8
  193. package/dist/l10n_in/i18n/bn.d.ts +2 -0
  194. package/dist/l10n_in/i18n/bn.js +95 -0
  195. package/dist/l10n_in/index.js +2 -0
  196. package/dist/l10n_in/module.d.ts +6703 -1652
  197. package/dist/l10n_in/module.js +25 -5
  198. package/dist/l10n_in/web/GstSettings.js +2 -2
  199. package/dist/mail/inbound/handle.js +2 -4
  200. package/dist/mail/inbound/models.js +5 -3
  201. package/dist/mail/index.d.ts +12 -1
  202. package/dist/mail/index.js +139 -2
  203. package/dist/mail/send.d.ts +56 -0
  204. package/dist/mail/send.js +394 -0
  205. package/dist/mail/web/SendButton.d.ts +9 -0
  206. package/dist/mail/web/SendButton.js +71 -0
  207. package/dist/mail/web/SendSelected.d.ts +8 -0
  208. package/dist/mail/web/SendSelected.js +33 -0
  209. package/dist/mail/web/index.d.ts +2 -0
  210. package/dist/mail/web/index.js +6 -0
  211. package/dist/mail/web/messages.js +36 -0
  212. package/dist/maintenance/.kosh/bindings.js +1 -1
  213. package/dist/maintenance/.kosh/schema.d.ts +2 -1
  214. package/dist/maintenance/i18n/bn.d.ts +2 -0
  215. package/dist/maintenance/i18n/bn.js +132 -0
  216. package/dist/maintenance/index.js +85 -0
  217. package/dist/maintenance/module.d.ts +25 -0
  218. package/dist/maintenance/module.js +27 -9
  219. package/dist/maintenance_stock/.kosh/bindings.js +1 -1
  220. package/dist/maintenance_stock/.kosh/schema.d.ts +298 -2
  221. package/dist/maintenance_stock/i18n/bn.d.ts +2 -0
  222. package/dist/maintenance_stock/i18n/bn.js +21 -0
  223. package/dist/maintenance_stock/index.js +2 -0
  224. package/dist/maintenance_stock/module.d.ts +5302 -1256
  225. package/dist/maintenance_stock/module.js +1 -0
  226. package/dist/modules-sdk/apps.d.ts +10 -0
  227. package/dist/modules-sdk/apps.js +32 -0
  228. package/dist/modules-sdk/index.d.ts +1 -1
  229. package/dist/modules-sdk/manifest.d.ts +68 -2
  230. package/dist/payment/.kosh/bindings.js +1 -1
  231. package/dist/payment/.kosh/schema.d.ts +530 -8
  232. package/dist/payment/i18n/bn.d.ts +2 -0
  233. package/dist/payment/i18n/bn.js +59 -0
  234. package/dist/payment/index.js +85 -0
  235. package/dist/payment/module.d.ts +5134 -1660
  236. package/dist/payment/module.js +17 -3
  237. package/dist/payment/settle.js +1 -0
  238. package/dist/payroll/.kosh/bindings.js +1 -1
  239. package/dist/payroll/.kosh/schema.d.ts +59 -1
  240. package/dist/payroll/i18n/bn.d.ts +2 -0
  241. package/dist/payroll/i18n/bn.js +206 -0
  242. package/dist/payroll/index.js +2 -0
  243. package/dist/payroll/module.d.ts +936 -48
  244. package/dist/payroll_account/.kosh/bindings.js +1 -1
  245. package/dist/payroll_account/.kosh/schema.d.ts +587 -8
  246. package/dist/payroll_account/i18n/bn.d.ts +2 -0
  247. package/dist/payroll_account/i18n/bn.js +10 -0
  248. package/dist/payroll_account/index.js +2 -0
  249. package/dist/payroll_account/module.d.ts +7534 -3192
  250. package/dist/permissions/approvals.d.ts +97 -4
  251. package/dist/permissions/approvals.js +780 -31
  252. package/dist/permissions/index.d.ts +1 -1
  253. package/dist/permissions/index.js +2 -2
  254. package/dist/permissions/models.js +177 -5
  255. package/dist/permissions/routes.d.ts +3 -0
  256. package/dist/permissions/routes.js +36 -2
  257. package/dist/permissions/web/ApprovalPanel.js +43 -5
  258. package/dist/permissions/web/messages.js +52 -0
  259. package/dist/portal/.kosh/bindings.js +1 -1
  260. package/dist/portal/.kosh/schema.d.ts +2 -1
  261. package/dist/portal/documents.d.ts +3 -0
  262. package/dist/portal/documents.js +21 -1
  263. package/dist/portal/i18n/bn.d.ts +2 -0
  264. package/dist/portal/i18n/bn.js +33 -0
  265. package/dist/portal/index.js +2 -0
  266. package/dist/portal/module.d.ts +20 -0
  267. package/dist/portal/routes-documents.js +76 -0
  268. package/dist/pos/.kosh/bindings.js +1 -1
  269. package/dist/pos/.kosh/schema.d.ts +531 -8
  270. package/dist/pos/i18n/bn.d.ts +2 -0
  271. package/dist/pos/i18n/bn.js +133 -0
  272. package/dist/pos/index.js +83 -1
  273. package/dist/pos/module.d.ts +6888 -1777
  274. package/dist/pos/module.js +49 -5
  275. package/dist/pos/routes.js +80 -7
  276. package/dist/pos/web/Register.js +2 -5
  277. package/dist/pos_stock/.kosh/bindings.js +1 -1
  278. package/dist/pos_stock/.kosh/schema.d.ts +626 -9
  279. package/dist/pos_stock/i18n/bn.d.ts +2 -0
  280. package/dist/pos_stock/i18n/bn.js +6 -0
  281. package/dist/pos_stock/index.js +2 -0
  282. package/dist/pos_stock/module.d.ts +10798 -3276
  283. package/dist/product/.kosh/bindings.js +1 -1
  284. package/dist/product/.kosh/schema.d.ts +202 -1
  285. package/dist/product/i18n/bn.d.ts +2 -0
  286. package/dist/product/i18n/bn.js +175 -0
  287. package/dist/product/index.d.ts +1 -0
  288. package/dist/product/index.js +288 -1
  289. package/dist/product/module.d.ts +1725 -0
  290. package/dist/product/module.js +66 -6
  291. package/dist/product/pricelist.d.ts +575 -0
  292. package/dist/product/pricelist.js +257 -0
  293. package/dist/product/variants.d.ts +908 -0
  294. package/dist/product/variants.js +251 -0
  295. package/dist/production/.kosh/bindings.d.ts +22 -0
  296. package/dist/production/.kosh/bindings.js +15 -0
  297. package/dist/production/.kosh/schema.d.ts +2345 -0
  298. package/dist/{mrp → production}/demo.d.ts +1 -1
  299. package/dist/{mrp → production}/demo.js +5 -5
  300. package/dist/production/depth.d.ts +790 -0
  301. package/dist/production/depth.js +262 -0
  302. package/dist/production/i18n/bn.d.ts +2 -0
  303. package/dist/production/i18n/bn.js +350 -0
  304. package/dist/production/index.d.ts +6 -0
  305. package/dist/production/index.js +1256 -0
  306. package/dist/production/module.d.ts +17327 -0
  307. package/dist/production/module.js +1333 -0
  308. package/dist/production/plan.d.ts +921 -0
  309. package/dist/production/plan.js +511 -0
  310. package/dist/production/schedule.d.ts +656 -0
  311. package/dist/production/schedule.js +309 -0
  312. package/dist/production_account/.kosh/bindings.d.ts +22 -0
  313. package/dist/production_account/.kosh/bindings.js +15 -0
  314. package/dist/production_account/.kosh/schema.d.ts +3496 -0
  315. package/dist/production_account/i18n/bn.d.ts +2 -0
  316. package/dist/production_account/i18n/bn.js +93 -0
  317. package/dist/production_account/index.d.ts +4 -0
  318. package/dist/production_account/index.js +246 -0
  319. package/dist/production_account/module.d.ts +1192 -0
  320. package/dist/{mrp_account → production_account}/module.js +72 -18
  321. package/dist/production_account/overhead.d.ts +1195 -0
  322. package/dist/production_account/overhead.js +554 -0
  323. package/dist/project/.kosh/bindings.js +1 -1
  324. package/dist/project/.kosh/schema.d.ts +65 -2
  325. package/dist/project/i18n/bn.d.ts +2 -0
  326. package/dist/project/i18n/bn.js +383 -0
  327. package/dist/project/index.js +123 -0
  328. package/dist/project/module.d.ts +20 -0
  329. package/dist/project/module.js +73 -14
  330. package/dist/project_account/.kosh/bindings.js +1 -1
  331. package/dist/project_account/.kosh/schema.d.ts +530 -8
  332. package/dist/project_account/i18n/bn.d.ts +2 -0
  333. package/dist/project_account/i18n/bn.js +6 -0
  334. package/dist/project_account/index.js +2 -0
  335. package/dist/project_account/module.d.ts +4926 -1452
  336. package/dist/project_portal/.kosh/bindings.js +1 -1
  337. package/dist/project_portal/.kosh/schema.d.ts +65 -2
  338. package/dist/project_portal/i18n/bn.d.ts +2 -0
  339. package/dist/project_portal/i18n/bn.js +6 -0
  340. package/dist/project_portal/index.js +2 -0
  341. package/dist/project_portal/module.d.ts +40 -0
  342. package/dist/project_purchase/.kosh/bindings.js +1 -1
  343. package/dist/project_purchase/.kosh/schema.d.ts +1126 -53
  344. package/dist/project_purchase/i18n/bn.d.ts +2 -0
  345. package/dist/project_purchase/i18n/bn.js +4 -0
  346. package/dist/project_purchase/index.js +2 -0
  347. package/dist/project_purchase/module.d.ts +17912 -4446
  348. package/dist/purchase/.kosh/bindings.js +1 -1
  349. package/dist/purchase/.kosh/schema.d.ts +813 -3
  350. package/dist/purchase/comparison.d.ts +993 -0
  351. package/dist/purchase/comparison.js +415 -0
  352. package/dist/purchase/extras.d.ts +1509 -0
  353. package/dist/purchase/extras.js +445 -0
  354. package/dist/purchase/i18n/bn.d.ts +2 -0
  355. package/dist/purchase/i18n/bn.js +413 -0
  356. package/dist/purchase/index.d.ts +5 -0
  357. package/dist/purchase/index.js +1280 -4
  358. package/dist/purchase/module.d.ts +7139 -398
  359. package/dist/purchase/module.js +295 -11
  360. package/dist/purchase/request.d.ts +696 -0
  361. package/dist/purchase/request.js +446 -0
  362. package/dist/purchase/tender.d.ts +1208 -0
  363. package/dist/purchase/tender.js +507 -0
  364. package/dist/purchase/vendorprice.d.ts +340 -0
  365. package/dist/purchase/vendorprice.js +153 -0
  366. package/dist/purchase_account/.kosh/bindings.js +1 -1
  367. package/dist/purchase_account/.kosh/schema.d.ts +1130 -57
  368. package/dist/purchase_account/i18n/bn.d.ts +2 -0
  369. package/dist/purchase_account/i18n/bn.js +22 -0
  370. package/dist/purchase_account/index.js +19 -0
  371. package/dist/purchase_account/module.d.ts +12276 -2247
  372. package/dist/purchase_account/module.js +241 -9
  373. package/dist/purchase_portal/.kosh/bindings.js +1 -1
  374. package/dist/purchase_portal/.kosh/schema.d.ts +813 -3
  375. package/dist/purchase_portal/i18n/bn.d.ts +2 -0
  376. package/dist/purchase_portal/i18n/bn.js +5 -0
  377. package/dist/purchase_portal/index.js +2 -0
  378. package/dist/purchase_portal/module.d.ts +6849 -353
  379. package/dist/purchase_stock/.kosh/bindings.js +1 -1
  380. package/dist/purchase_stock/.kosh/schema.d.ts +910 -4
  381. package/dist/purchase_stock/i18n/bn.d.ts +2 -0
  382. package/dist/purchase_stock/i18n/bn.js +19 -0
  383. package/dist/purchase_stock/index.d.ts +1 -1
  384. package/dist/purchase_stock/index.js +29 -0
  385. package/dist/purchase_stock/module.d.ts +12410 -1864
  386. package/dist/purchase_stock/module.js +81 -9
  387. package/dist/purchase_stock/scorecard.d.ts +22 -0
  388. package/dist/purchase_stock/scorecard.js +77 -0
  389. package/dist/purchase_stock/web/Scorecard.d.ts +7 -0
  390. package/dist/purchase_stock/web/Scorecard.js +22 -0
  391. package/dist/purchase_stock/web/index.d.ts +11 -0
  392. package/dist/purchase_stock/web/index.js +16 -0
  393. package/dist/purchase_stock/web/messages.d.ts +2 -0
  394. package/dist/purchase_stock/web/messages.js +27 -0
  395. package/dist/purchase_stock_account/.kosh/bindings.js +1 -1
  396. package/dist/purchase_stock_account/.kosh/schema.d.ts +1286 -58
  397. package/dist/purchase_stock_account/i18n/bn.d.ts +2 -0
  398. package/dist/purchase_stock_account/i18n/bn.js +8 -0
  399. package/dist/purchase_stock_account/index.js +18 -0
  400. package/dist/purchase_stock_account/module.d.ts +7 -37995
  401. package/dist/purchase_stock_account/module.js +24 -3
  402. package/dist/recruitment/.kosh/bindings.js +1 -1
  403. package/dist/recruitment/.kosh/schema.d.ts +59 -1
  404. package/dist/recruitment/i18n/bn.d.ts +2 -0
  405. package/dist/recruitment/i18n/bn.js +93 -0
  406. package/dist/recruitment/index.js +64 -0
  407. package/dist/recruitment/module.d.ts +458 -8
  408. package/dist/recruitment/module.js +11 -3
  409. package/dist/reporting/documents.d.ts +5 -0
  410. package/dist/reporting/documents.js +11 -1
  411. package/dist/reporting/index.d.ts +1 -1
  412. package/dist/reporting/index.js +1 -1
  413. package/dist/reporting/web/CalendarView.d.ts +18 -5
  414. package/dist/reporting/web/CalendarView.js +163 -29
  415. package/dist/reporting/web/messages.js +18 -0
  416. package/dist/sale_account/.kosh/bindings.js +1 -1
  417. package/dist/sale_account/.kosh/schema.d.ts +642 -16
  418. package/dist/sale_account/i18n/bn.d.ts +2 -0
  419. package/dist/sale_account/i18n/bn.js +48 -0
  420. package/dist/sale_account/index.d.ts +1 -1
  421. package/dist/sale_account/index.js +102 -4
  422. package/dist/sale_account/module.d.ts +8254 -2212
  423. package/dist/sale_account/module.js +535 -46
  424. package/dist/sale_crm/.kosh/bindings.d.ts +22 -0
  425. package/dist/sale_crm/.kosh/bindings.js +15 -0
  426. package/dist/{mrp → sale_crm}/.kosh/schema.d.ts +389 -567
  427. package/dist/sale_crm/i18n/bn.d.ts +2 -0
  428. package/dist/sale_crm/i18n/bn.js +9 -0
  429. package/dist/sale_crm/index.d.ts +7 -0
  430. package/dist/sale_crm/index.js +104 -0
  431. package/dist/sale_crm/module.d.ts +5609 -0
  432. package/dist/sale_crm/module.js +73 -0
  433. package/dist/sale_portal/.kosh/bindings.js +1 -1
  434. package/dist/sale_portal/.kosh/schema.d.ts +291 -4
  435. package/dist/sale_portal/i18n/bn.d.ts +2 -0
  436. package/dist/sale_portal/i18n/bn.js +7 -0
  437. package/dist/sale_portal/index.js +10 -0
  438. package/dist/sale_portal/module.d.ts +2564 -294
  439. package/dist/sale_project/.kosh/bindings.js +1 -1
  440. package/dist/sale_project/.kosh/schema.d.ts +354 -5
  441. package/dist/sale_project/i18n/bn.d.ts +2 -0
  442. package/dist/sale_project/i18n/bn.js +12 -0
  443. package/dist/sale_project/index.js +2 -0
  444. package/dist/sale_project/module.d.ts +6249 -2402
  445. package/dist/sale_stock/.kosh/bindings.js +1 -1
  446. package/dist/sale_stock/.kosh/schema.d.ts +387 -5
  447. package/dist/sale_stock/i18n/bn.d.ts +2 -0
  448. package/dist/sale_stock/i18n/bn.js +15 -0
  449. package/dist/sale_stock/index.js +2 -0
  450. package/dist/sale_stock/module.d.ts +8057 -1759
  451. package/dist/sale_stock/module.js +20 -3
  452. package/dist/sales/.kosh/bindings.js +1 -1
  453. package/dist/sales/.kosh/schema.d.ts +291 -4
  454. package/dist/sales/i18n/bn.d.ts +2 -0
  455. package/dist/sales/i18n/bn.js +128 -0
  456. package/dist/sales/index.js +120 -5
  457. package/dist/sales/module.d.ts +3567 -633
  458. package/dist/sales/module.js +306 -11
  459. package/dist/server/api/duplicate.d.ts +14 -0
  460. package/dist/server/api/duplicate.js +75 -0
  461. package/dist/server/api/explain.d.ts +70 -0
  462. package/dist/server/api/explain.js +111 -0
  463. package/dist/server/api/metadata.d.ts +2 -0
  464. package/dist/server/api/metadata.js +9 -0
  465. package/dist/server/api/openapi.js +15 -0
  466. package/dist/server/api/rest.d.ts +1 -0
  467. package/dist/server/api/rest.js +76 -12
  468. package/dist/server/api/views.js +1 -1
  469. package/dist/server/apps.d.ts +16 -1
  470. package/dist/server/apps.js +164 -2
  471. package/dist/server/auth/base.js +2 -0
  472. package/dist/server/auth/service.d.ts +8 -0
  473. package/dist/server/auth/service.js +19 -0
  474. package/dist/server/events.d.ts +13 -0
  475. package/dist/server/events.js +22 -0
  476. package/dist/server/i18n.d.ts +27 -0
  477. package/dist/server/i18n.js +143 -0
  478. package/dist/server/index.d.ts +2 -0
  479. package/dist/server/index.js +2 -0
  480. package/dist/server/server.js +6 -0
  481. package/dist/settings/company.d.ts +3 -1
  482. package/dist/settings/company.js +26 -5
  483. package/dist/settings/routes.d.ts +10 -0
  484. package/dist/settings/routes.js +19 -3
  485. package/dist/settings/web/AppsPage.d.ts +3 -2
  486. package/dist/settings/web/AppsPage.js +26 -8
  487. package/dist/settings/web/CompaniesPage.js +91 -6
  488. package/dist/settings/web/messages.js +64 -0
  489. package/dist/sign/.kosh/bindings.js +1 -1
  490. package/dist/sign/.kosh/schema.d.ts +2 -1
  491. package/dist/sign/i18n/bn.d.ts +2 -0
  492. package/dist/sign/i18n/bn.js +97 -0
  493. package/dist/sign/index.d.ts +15 -0
  494. package/dist/sign/index.js +129 -1
  495. package/dist/sign/module.d.ts +40 -0
  496. package/dist/sign/module.js +11 -2
  497. package/dist/stock/.kosh/bindings.js +1 -1
  498. package/dist/stock/.kosh/schema.d.ts +298 -2
  499. package/dist/stock/i18n/bn.d.ts +2 -0
  500. package/dist/stock/i18n/bn.js +311 -0
  501. package/dist/stock/index.d.ts +3 -1
  502. package/dist/stock/index.js +442 -3
  503. package/dist/stock/ledger.d.ts +78 -0
  504. package/dist/stock/ledger.js +582 -0
  505. package/dist/stock/module.d.ts +5280 -2044
  506. package/dist/stock/module.js +222 -23
  507. package/dist/stock/replenish.js +16 -1
  508. package/dist/stock/returns.d.ts +157 -0
  509. package/dist/stock/returns.js +163 -0
  510. package/dist/stock/web/Ledger.d.ts +9 -0
  511. package/dist/stock/web/Ledger.js +108 -0
  512. package/dist/stock/web/Operations.d.ts +8 -0
  513. package/dist/stock/web/Operations.js +33 -0
  514. package/dist/stock/web/ReturnButton.d.ts +7 -0
  515. package/dist/stock/web/ReturnButton.js +62 -0
  516. package/dist/stock/web/index.d.ts +3 -0
  517. package/dist/stock/web/index.js +9 -0
  518. package/dist/stock/web/messages.js +154 -0
  519. package/dist/stock_account/.kosh/bindings.js +1 -1
  520. package/dist/stock_account/.kosh/schema.d.ts +682 -9
  521. package/dist/stock_account/i18n/bn.d.ts +2 -0
  522. package/dist/stock_account/i18n/bn.js +73 -0
  523. package/dist/stock_account/index.d.ts +1 -0
  524. package/dist/stock_account/index.js +131 -3
  525. package/dist/stock_account/landed.d.ts +429 -0
  526. package/dist/stock_account/landed.js +335 -0
  527. package/dist/stock_account/module.d.ts +11247 -3363
  528. package/dist/stock_account/module.js +135 -6
  529. package/dist/stock_account/web/LandedPreview.d.ts +7 -0
  530. package/dist/stock_account/web/LandedPreview.js +23 -0
  531. package/dist/stock_account/web/index.d.ts +11 -0
  532. package/dist/stock_account/web/index.js +16 -0
  533. package/dist/stock_account/web/messages.d.ts +2 -0
  534. package/dist/stock_account/web/messages.js +27 -0
  535. package/dist/todo/i18n/bn.d.ts +2 -0
  536. package/dist/todo/i18n/bn.js +66 -0
  537. package/dist/todo/index.js +59 -0
  538. package/dist/todo/module.d.ts +5 -0
  539. package/dist/todo/module.js +5 -3
  540. package/dist/trade_finance/.kosh/bindings.js +1 -1
  541. package/dist/trade_finance/.kosh/schema.d.ts +2 -1
  542. package/dist/trade_finance/i18n/bn.d.ts +2 -0
  543. package/dist/trade_finance/i18n/bn.js +162 -0
  544. package/dist/trade_finance/index.js +93 -0
  545. package/dist/trade_finance/module.d.ts +26 -0
  546. package/dist/trade_finance/module.js +27 -8
  547. package/dist/trade_finance_account/.kosh/bindings.js +1 -1
  548. package/dist/trade_finance_account/.kosh/schema.d.ts +530 -8
  549. package/dist/trade_finance_account/i18n/bn.d.ts +2 -0
  550. package/dist/trade_finance_account/i18n/bn.js +27 -0
  551. package/dist/trade_finance_account/index.js +2 -0
  552. package/dist/trade_finance_account/module.d.ts +4906 -1432
  553. package/dist/trade_finance_account/module.js +1 -0
  554. package/dist/trade_finance_purchase/.kosh/bindings.js +1 -1
  555. package/dist/trade_finance_purchase/.kosh/schema.d.ts +813 -3
  556. package/dist/trade_finance_purchase/i18n/bn.d.ts +2 -0
  557. package/dist/trade_finance_purchase/i18n/bn.js +6 -0
  558. package/dist/trade_finance_purchase/index.js +2 -0
  559. package/dist/trade_finance_purchase/module.d.ts +6909 -413
  560. package/dist/trade_finance_sale/.kosh/bindings.js +1 -1
  561. package/dist/trade_finance_sale/.kosh/schema.d.ts +291 -4
  562. package/dist/trade_finance_sale/i18n/bn.d.ts +2 -0
  563. package/dist/trade_finance_sale/i18n/bn.js +6 -0
  564. package/dist/trade_finance_sale/index.js +2 -0
  565. package/dist/trade_finance_sale/module.d.ts +2601 -331
  566. package/dist/ui/api.d.ts +2 -0
  567. package/dist/ui/app.d.ts +9 -0
  568. package/dist/ui/app.js +24 -4
  569. package/dist/ui/components/AppIcon.js +2 -2
  570. package/dist/ui/components/Explain.d.ts +69 -0
  571. package/dist/ui/components/Explain.js +62 -0
  572. package/dist/ui/context.d.ts +8 -1
  573. package/dist/ui/context.js +34 -1
  574. package/dist/ui/i18n/messages.d.ts +36 -0
  575. package/dist/ui/i18n/messages.js +72 -0
  576. package/dist/ui/index.d.ts +2 -1
  577. package/dist/ui/index.js +1 -0
  578. package/dist/ui/registry.d.ts +14 -0
  579. package/dist/ui/registry.js +10 -0
  580. package/dist/ui/views/FormView.d.ts +6 -0
  581. package/dist/ui/views/FormView.js +47 -10
  582. package/dist/ui/views/ListView.d.ts +8 -0
  583. package/dist/ui/views/ListView.js +10 -3
  584. package/dist/ui/views/StatsRow.js +2 -1
  585. package/dist/views/extend.js +12 -0
  586. package/dist/views/types.d.ts +13 -2
  587. package/dist/views/validate.js +8 -1
  588. package/dist/website/.kosh/bindings.js +1 -1
  589. package/dist/website/.kosh/schema.d.ts +2 -1
  590. package/dist/website/i18n/bn.d.ts +2 -0
  591. package/dist/website/i18n/bn.js +113 -0
  592. package/dist/website/index.js +36 -0
  593. package/dist/website/module.d.ts +20 -0
  594. package/dist/website/module.js +29 -5
  595. package/dist/website_crm/.kosh/bindings.js +1 -1
  596. package/dist/website_crm/.kosh/schema.d.ts +2 -1
  597. package/dist/website_crm/i18n/bn.d.ts +2 -0
  598. package/dist/website_crm/i18n/bn.js +5 -0
  599. package/dist/website_crm/index.js +2 -0
  600. package/dist/website_crm/module.d.ts +40 -0
  601. package/dist/website_sale/.kosh/bindings.js +1 -1
  602. package/dist/website_sale/.kosh/schema.d.ts +642 -17
  603. package/dist/website_sale/i18n/bn.d.ts +2 -0
  604. package/dist/website_sale/i18n/bn.js +132 -0
  605. package/dist/website_sale/index.js +83 -1
  606. package/dist/website_sale/module.d.ts +18705 -5550
  607. package/dist/website_sale/module.js +32 -10
  608. package/dist/website_sale/shop.js +22 -9
  609. package/dist/website_sale_stock/.kosh/bindings.js +1 -1
  610. package/dist/website_sale_stock/.kosh/schema.d.ts +737 -18
  611. package/dist/website_sale_stock/i18n/bn.d.ts +2 -0
  612. package/dist/website_sale_stock/i18n/bn.js +4 -0
  613. package/dist/website_sale_stock/index.js +2 -0
  614. package/dist/website_sale_stock/module.d.ts +10 -24997
  615. package/dist/website_sale_stock/module.js +7 -3
  616. package/package.json +36 -8
  617. package/dist/mrp/index.d.ts +0 -3
  618. package/dist/mrp/index.js +0 -393
  619. package/dist/mrp/module.js +0 -757
  620. package/dist/mrp_account/index.d.ts +0 -3
  621. package/dist/mrp_account/index.js +0 -22
  622. /package/dist/{mrp → approvals_purchase}/.kosh/bindings.d.ts +0 -0
  623. /package/dist/{mrp_account → indent}/.kosh/bindings.d.ts +0 -0
@@ -1,12 +1,473 @@
1
1
  /**
2
- * The data layer of the Approvals app (RFC 0025): the models are the engine's (`approval.policy`, `approval.level`,
3
- * `approval.request`, `approval.vote` in `shutro-erp/permissions`); this module adds the app around them.
2
+ * The data layer of the Approvals app (RFC 0025). The engine's models (`approval.policy`, `approval.level`,
3
+ * `approval.request`, `approval.vote`) are in `shutro-erp/permissions`; this module adds **generic requests** (step 4):
4
+ * categories (Business trip, Payment, Equipment…) saying which fields a request has and what it leads to, and the
5
+ * requests themselves, decided through the category's own policy — a policy on `approval.ask` whose condition is the
6
+ * category, made when the category's first request is submitted (or from the category), its levels edited like any
7
+ * policy's. On approval, the category's **outcome** runs: nothing here; apps add theirs (`approvals_purchase`: a
8
+ * request for quotation from the lines).
4
9
  */
5
- import { permissionsShutro } from '../permissions/index.js';
6
- import { defineModule } from './.kosh/bindings.js';
10
+ import { contactsShutro } from '../contacts/index.js';
11
+ import { approvalGuard, decidersOf, permissionsShutro, requestApprovals, requestsOf, } from '../permissions/index.js';
12
+ import { orm } from '../server/orm.js';
13
+ import { check, compute, defineModel, defineModule, f, method, record, records, } from './.kosh/bindings.js';
14
+ const ALL = ['read', 'write', 'create', 'unlink', 'export', 'import'];
15
+ const me = { $env: 'uid' };
16
+ const ZERO = orm.toDecimal(0);
17
+ /** Whether a request of the category shows a field, and whether it must be filled. */
18
+ const PRESENCE = { none: 'Not asked', optional: 'Optional', required: 'Required' };
19
+ /** The presence fields of a category, by the request field they govern. */
20
+ export const ASKED = {
21
+ amount: 'askAmount',
22
+ period: 'askPeriod',
23
+ partner: 'askPartner',
24
+ location: 'askLocation',
25
+ quantity: 'askQuantity',
26
+ lines: 'askLines',
27
+ attachment: 'askAttachment',
28
+ };
29
+ const asksOf = (env, ids) => env.model('approval.ask').browse(ids);
30
+ /** The outcomes the installed apps offer, by code (`approval.ask.outcomes()`, which they extend). */
31
+ export async function outcomesOffered(env) {
32
+ return asksOf(env, []).outcomes();
33
+ }
34
+ /** A kind of request, its fields and its outcome. */
35
+ export const ApprovalCategory = defineModel('approval.category', {
36
+ label: 'Request category',
37
+ recName: 'name',
38
+ order: ['sequence asc', 'name asc'],
39
+ archivable: true,
40
+ access: { 'base.user': ['read'], 'approvals.manager': ALL },
41
+ fields: {
42
+ name: f.char({ required: true, translate: true }),
43
+ code: f.char({ size: 32 }),
44
+ /** Empty: every company's. */
45
+ company: f.many2one('res.company', { ondelete: 'cascade' }),
46
+ sequence: f.integer({ required: true, default: 10 }),
47
+ description: f.text({ translate: true, help: 'Shown to whoever asks: what to give and why.' }),
48
+ askAmount: f.selection(PRESENCE, {
49
+ required: true,
50
+ default: 'optional',
51
+ label: 'Amount',
52
+ help: 'Whether a request of this category asks for an amount: not asked, optional or required.',
53
+ }),
54
+ askPeriod: f.selection(PRESENCE, {
55
+ required: true,
56
+ default: 'none',
57
+ label: 'Period',
58
+ help: 'Whether a request of this category asks for a period, from and until: not asked, optional or required.',
59
+ }),
60
+ askPartner: f.selection(PRESENCE, {
61
+ required: true,
62
+ default: 'none',
63
+ label: 'Contact',
64
+ help: 'Whether a request of this category asks for a contact: not asked, optional or required.',
65
+ }),
66
+ askLocation: f.selection(PRESENCE, {
67
+ required: true,
68
+ default: 'none',
69
+ label: 'Location',
70
+ help: 'Whether a request of this category asks for a location: not asked, optional or required.',
71
+ }),
72
+ askQuantity: f.selection(PRESENCE, {
73
+ required: true,
74
+ default: 'none',
75
+ label: 'Quantity',
76
+ help: 'Whether a request of this category asks for a quantity: not asked, optional or required.',
77
+ }),
78
+ askLines: f.selection(PRESENCE, {
79
+ required: true,
80
+ default: 'none',
81
+ label: 'Lines',
82
+ help: 'Whether a request of this category asks for lines with quantities and prices: not asked, optional or required.',
83
+ }),
84
+ askAttachment: f.selection(PRESENCE, {
85
+ required: true,
86
+ default: 'none',
87
+ label: 'Attachment',
88
+ help: 'Required: the request is submitted only with a file attached.',
89
+ }),
90
+ /** What an approved request leads to: one of the outcomes the installed apps offer (empty: nothing). */
91
+ outcome: f.char({
92
+ size: 32,
93
+ label: 'On approval',
94
+ help: 'Empty: nothing more. `purchase`: a request for quotation from the lines (with Purchase).',
95
+ }),
96
+ /** Its policy on requests (made when the first request is submitted; its levels are edited there). */
97
+ policy: f.many2one('approval.policy', { ondelete: 'set null', label: 'Approval policy' }),
98
+ requestCount: f.integer({
99
+ label: 'Requests',
100
+ ...compute('approval.category', 'requestCount', ['asks'], (categories) => {
101
+ for (const c of categories)
102
+ c.requestCount = c.asks.length;
103
+ }),
104
+ }),
105
+ asks: f.one2many('approval.ask', 'category'),
106
+ },
107
+ sqlConstraints: {
108
+ oneCode: { unique: ['company', 'code'], message: 'Another category has this code.' },
109
+ },
110
+ constraints: {
111
+ // An outcome is one an installed app offers.
112
+ knownOutcome: {
113
+ ...check('approval.category', ['outcome'], async (categories) => {
114
+ const offered = await outcomesOffered(categories.env);
115
+ return categories
116
+ .filter((c) => c.outcome !== null && c.outcome !== '' && !offered.has(c.outcome))
117
+ .map((c) => c.id);
118
+ }),
119
+ message: 'No installed app offers this outcome.',
120
+ },
121
+ },
122
+ });
123
+ const STATES = {
124
+ draft: 'Draft',
125
+ submitted: 'Waiting for approval',
126
+ approved: 'Approved',
127
+ refused: 'Refused',
128
+ cancelled: 'Cancelled',
129
+ };
130
+ /** A request of a category: what is asked, by whom, with its fields, lines and outcome. */
131
+ export const ApprovalAsk = defineModel('approval.ask', {
132
+ label: 'Request',
133
+ recName: 'title',
134
+ order: ['id desc'],
135
+ companyScoped: { required: true },
136
+ tracking: ['state', 'amount', 'dateFrom', 'dateTo'],
137
+ access: { 'base.user': ['read', 'write', 'create'], 'approvals.manager': ALL },
138
+ rules: {
139
+ // One's own requests (deciders see them through the inbox, as the system); changed while a draft or refused.
140
+ own: { groups: ['base.user'], perms: ['read'], domain: { requester: me } },
141
+ // Who may decide it reads it (named when it is submitted).
142
+ deciding: { groups: ['base.user'], perms: ['read'], domain: { deciders: { any: { id: me } } } },
143
+ ownDraft: {
144
+ groups: ['base.user'],
145
+ perms: ['write', 'create'],
146
+ domain: { requester: me, state: { in: ['draft', 'refused'] } },
147
+ },
148
+ managers: {
149
+ groups: ['approvals.manager'],
150
+ perms: ['read', 'write', 'create', 'unlink'],
151
+ domain: {},
152
+ },
153
+ },
154
+ fields: {
155
+ name: f.char({ readonly: true, sequence: 'approval.ask', label: 'Number' }),
156
+ category: f.many2one('approval.category', { required: true, ondelete: 'restrict' }),
157
+ title: f.char({ required: true, label: 'What for' }),
158
+ requester: f.many2one('res.users', {
159
+ required: true,
160
+ default: (env) => env.userId,
161
+ ondelete: 'restrict',
162
+ label: 'Asked by',
163
+ }),
164
+ description: f.text(),
165
+ amount: f.decimal({ scale: 2 }),
166
+ dateFrom: f.date({ label: 'From' }),
167
+ dateTo: f.date({ label: 'Until' }),
168
+ partner: f.many2one('res.partner', { ondelete: 'set null', label: 'Contact' }),
169
+ location: f.char(),
170
+ quantity: f.decimal({ scale: 3 }),
171
+ lines: f.one2many('approval.ask.line', 'ask'),
172
+ linesTotal: f.decimal({
173
+ scale: 2,
174
+ store: true,
175
+ label: 'Lines total',
176
+ help: 'The sum of the lines’ subtotals.',
177
+ ...compute('approval.ask', 'linesTotal', ['lines.subtotal'], (asks) => {
178
+ for (const a of asks)
179
+ a.linesTotal = [...a.lines].reduce((s, l) => s.plus(l.subtotal ?? 0), ZERO);
180
+ }),
181
+ }),
182
+ /** The document the outcome made (`purchase.order` 12…), shown on the request. */
183
+ resultModel: f.char({ label: 'Made' }),
184
+ resultId: f.integer(),
185
+ resultName: f.char({ label: 'Made document' }),
186
+ approvedAt: f.datetime({ label: 'Approved on' }),
187
+ /** What the category asks for (the form shows and marks the fields by them). */
188
+ askAmount: f.selection(PRESENCE, {
189
+ store: true,
190
+ help: 'Whether this request asks for an amount, as its category says.',
191
+ ...compute('approval.ask', 'askAmount', ['category.askAmount'], (asks) => {
192
+ for (const a of asks)
193
+ a.askAmount = a.category?.askAmount ?? 'none';
194
+ }),
195
+ }),
196
+ askPeriod: f.selection(PRESENCE, {
197
+ store: true,
198
+ help: 'Whether this request asks for a period, as its category says.',
199
+ ...compute('approval.ask', 'askPeriod', ['category.askPeriod'], (asks) => {
200
+ for (const a of asks)
201
+ a.askPeriod = a.category?.askPeriod ?? 'none';
202
+ }),
203
+ }),
204
+ askPartner: f.selection(PRESENCE, {
205
+ store: true,
206
+ help: 'Whether this request asks for a contact, as its category says.',
207
+ ...compute('approval.ask', 'askPartner', ['category.askPartner'], (asks) => {
208
+ for (const a of asks)
209
+ a.askPartner = a.category?.askPartner ?? 'none';
210
+ }),
211
+ }),
212
+ askLocation: f.selection(PRESENCE, {
213
+ store: true,
214
+ help: 'Whether this request asks for a location, as its category says.',
215
+ ...compute('approval.ask', 'askLocation', ['category.askLocation'], (asks) => {
216
+ for (const a of asks)
217
+ a.askLocation = a.category?.askLocation ?? 'none';
218
+ }),
219
+ }),
220
+ askQuantity: f.selection(PRESENCE, {
221
+ store: true,
222
+ help: 'Whether this request asks for a quantity, as its category says.',
223
+ ...compute('approval.ask', 'askQuantity', ['category.askQuantity'], (asks) => {
224
+ for (const a of asks)
225
+ a.askQuantity = a.category?.askQuantity ?? 'none';
226
+ }),
227
+ }),
228
+ askLines: f.selection(PRESENCE, {
229
+ store: true,
230
+ help: 'Whether this request asks for lines, as its category says.',
231
+ ...compute('approval.ask', 'askLines', ['category.askLines'], (asks) => {
232
+ for (const a of asks)
233
+ a.askLines = a.category?.askLines ?? 'none';
234
+ }),
235
+ }),
236
+ askAttachment: f.selection(PRESENCE, {
237
+ store: true,
238
+ help: 'Whether this request asks for an attached file, as its category says.',
239
+ ...compute('approval.ask', 'askAttachment', ['category.askAttachment'], (asks) => {
240
+ for (const a of asks)
241
+ a.askAttachment = a.category?.askAttachment ?? 'none';
242
+ }),
243
+ }),
244
+ /** Who may decide it: its levels' approvers and their delegates, when it was submitted. */
245
+ deciders: f.many2many('res.users', {
246
+ relation: 'approval_ask_decider_rel',
247
+ label: 'Decided by',
248
+ }),
249
+ state: f.state({
250
+ states: STATES,
251
+ initial: 'draft',
252
+ help: 'Submitted to the category’s approvers; approved, its outcome runs.',
253
+ transitions: {
254
+ submit: {
255
+ from: ['draft', 'refused'],
256
+ to: 'submitted',
257
+ guard: records('approval.ask', async (asks) => missingFields(asks.env, asks.ids)),
258
+ message: 'Fill in what the category asks for (and attach a file when it is required).',
259
+ before: records('approval.ask', async (asks) => {
260
+ // The category's policy exists before the engine looks for it.
261
+ const env = asks.env;
262
+ const categories = new Set();
263
+ for (const a of await asks.load(['category']))
264
+ categories.add(a.category.id);
265
+ await env.asSuperuser({ reason: 'request category policy' }, async (su) => {
266
+ for (const c of categories)
267
+ await ensureCategoryPolicy(su, c);
268
+ });
269
+ }),
270
+ after: records('approval.ask', async (asks) => {
271
+ await requestApprovals(asks);
272
+ const env = asks.env;
273
+ const today = new Date().toISOString().slice(0, 10);
274
+ await env.asSuperuser({ reason: 'request deciders' }, async (su) => {
275
+ for (const id of asks.ids) {
276
+ const people = new Set();
277
+ for (const r of await requestsOf(su, 'approval.ask', id))
278
+ if (r.state === 'pending')
279
+ for (const u of await decidersOf(su, r, today))
280
+ people.add(u);
281
+ await su
282
+ .model('approval.ask')
283
+ .browse([id])
284
+ .write({ deciders: { set: [...people] } });
285
+ }
286
+ });
287
+ }),
288
+ },
289
+ approve: {
290
+ from: ['submitted'],
291
+ to: 'approved',
292
+ guard: records('approval.ask', (asks) => approvalGuard(asks)),
293
+ message: 'Waiting for approvals.',
294
+ // Run as the system by the engine: the outcome of each request's category.
295
+ after: records('approval.ask', async (asks) => {
296
+ const env = asks.env;
297
+ await env
298
+ .model('approval.ask')
299
+ .browse(asks.ids)
300
+ .write({ approvedAt: new Date() });
301
+ await asksOf(env, asks.ids).runOutcome();
302
+ for (const id of asks.ids)
303
+ await env.emit('approval.ask.approved', { id });
304
+ }),
305
+ },
306
+ refuse: { from: ['submitted'], to: 'refused' },
307
+ redraft: { from: ['submitted', 'refused', 'cancelled'], to: 'draft' },
308
+ cancel: { from: ['draft', 'submitted', 'refused'], to: 'cancelled' },
309
+ },
310
+ }),
311
+ },
312
+ sqlConstraints: {
313
+ amountPositive: {
314
+ check: orm.sql `amount IS NULL OR amount >= 0`,
315
+ message: 'An amount is not negative.',
316
+ },
317
+ period: {
318
+ check: orm.sql `date_from IS NULL OR date_to IS NULL OR date_to >= date_from`,
319
+ message: 'A period ends on or after it starts.',
320
+ },
321
+ },
322
+ methods: {
323
+ /** The outcomes the installed apps offer, by code. None here; apps add theirs. */
324
+ outcomes: method('approval.ask', async () => new Map()),
325
+ /**
326
+ * Runs the outcome of each approved request's category (as the system). Nothing here; an app that offers an
327
+ * outcome makes its document for the requests of that outcome and writes `resultModel` / `resultId`.
328
+ */
329
+ runOutcome: method('approval.ask', async () => undefined),
330
+ },
331
+ });
332
+ /** A line of a request: what, how many, at what price. Apps add theirs (a product, with Purchase). */
333
+ export const ApprovalAskLine = defineModel('approval.ask.line', {
334
+ label: 'Request line',
335
+ order: ['ask asc', 'sequence asc', 'id asc'],
336
+ access: { 'base.user': ['read', 'write', 'create', 'unlink'], 'approvals.manager': ALL },
337
+ fields: {
338
+ ask: f.many2one('approval.ask', { required: true, ondelete: 'cascade' }),
339
+ sequence: f.integer({ required: true, default: 10 }),
340
+ name: f.char({ required: true, label: 'Description' }),
341
+ quantity: f.decimal({ scale: 3, required: true, default: '1' }),
342
+ priceUnit: f.decimal({ scale: 2, required: true, default: '0', label: 'Unit price' }),
343
+ subtotal: f.decimal({
344
+ scale: 2,
345
+ store: true,
346
+ help: 'The quantity times the unit price.',
347
+ ...compute('approval.ask.line', 'subtotal', ['quantity', 'priceUnit'], (lines) => {
348
+ for (const l of lines)
349
+ l.subtotal = l.quantity.times(l.priceUnit).toDecimalPlaces(2);
350
+ }),
351
+ }),
352
+ },
353
+ sqlConstraints: {
354
+ positive: {
355
+ check: orm.sql `quantity > 0 AND price_unit >= 0`,
356
+ message: 'A line asks for a positive quantity at a price not below zero.',
357
+ },
358
+ },
359
+ });
360
+ /** The requests (of `ids`) missing a field their category requires. */
361
+ export async function missingFields(env, ids) {
362
+ const bad = [];
363
+ for (const a of await env
364
+ .model('approval.ask')
365
+ .browse(ids)
366
+ .load({ category: true, lines: ['id'] })) {
367
+ const c = a.category;
368
+ const required = (key) => c[ASKED[key]] === 'required';
369
+ const empty = (required('amount') && a.amount === null) ||
370
+ (required('period') && (a.dateFrom === null || a.dateTo === null)) ||
371
+ (required('partner') && a.partner === null) ||
372
+ (required('location') && (a.location ?? '').trim() === '') ||
373
+ (required('quantity') && a.quantity === null) ||
374
+ (required('lines') && a.lines.length === 0);
375
+ if (empty) {
376
+ bad.push(a.id);
377
+ continue;
378
+ }
379
+ if (required('attachment')) {
380
+ const files = await env.asSuperuser({ reason: 'request attachments' }, (su) => su.model('storage.attachment').search({
381
+ where: { resModel: 'approval.ask', resId: a.id },
382
+ limit: 1,
383
+ }));
384
+ if (files.ids.length === 0)
385
+ bad.push(a.id);
386
+ }
387
+ }
388
+ return bad;
389
+ }
390
+ /**
391
+ * The category's policy on requests (as the system): made when missing — its condition the category, one level
392
+ * decided by the requester's manager (an Approvals manager without one) —, kept as it is when it exists.
393
+ */
394
+ export async function ensureCategoryPolicy(su, category) {
395
+ const [c] = await su
396
+ .model('approval.category')
397
+ .browse([category])
398
+ .load(['name', 'policy', 'company']);
399
+ if (c === undefined)
400
+ throw new Error(`approval.category ${category} is missing`);
401
+ if (c.policy !== null)
402
+ return c.policy.id;
403
+ const policy = await su.model('approval.policy').create([
404
+ {
405
+ name: `Requests: ${String(c.name)}`,
406
+ targetModel: 'approval.ask',
407
+ condition: { category },
408
+ company: c.company?.id ?? null,
409
+ onApproved: 'approve',
410
+ onRejected: 'refuse',
411
+ onSentBack: 'redraft',
412
+ onWithdrawn: 'redraft',
413
+ },
414
+ ]);
415
+ const id = policy.ids[0];
416
+ await su.model('approval.level').create([
417
+ {
418
+ policy: id,
419
+ sequence: 10,
420
+ name: 'Manager',
421
+ approverKind: 'manager',
422
+ approverRole: 'approvals.manager',
423
+ },
424
+ ]);
425
+ await su
426
+ .model('approval.category')
427
+ .browse([category])
428
+ .write({ policy: id });
429
+ return id;
430
+ }
7
431
  export const approvalsShutro = defineModule({
8
432
  name: 'approvals',
9
- version: '0.1.0',
10
- depends: [permissionsShutro],
11
- models: [],
433
+ version: '0.2.0',
434
+ depends: [permissionsShutro, contactsShutro],
435
+ sequences: [orm.defineSequence({ code: 'approval.ask', prefix: 'REQ-', padding: 5 })],
436
+ models: [ApprovalCategory, ApprovalAsk, ApprovalAskLine],
437
+ // The categories every installation starts with (theirs to change afterwards).
438
+ data: [
439
+ record('approval.category', 'category_trip', {
440
+ name: 'Business trip',
441
+ code: 'TRIP',
442
+ sequence: 10,
443
+ description: 'Where, when and the estimated cost.',
444
+ askAmount: 'required',
445
+ askPeriod: 'required',
446
+ askLocation: 'required',
447
+ }, { noupdate: true }),
448
+ record('approval.category', 'category_payment', {
449
+ name: 'Payment',
450
+ code: 'PAY',
451
+ sequence: 20,
452
+ description: 'To whom, how much and why; attach the invoice or quotation.',
453
+ askAmount: 'required',
454
+ askPartner: 'required',
455
+ askAttachment: 'required',
456
+ }, { noupdate: true }),
457
+ record('approval.category', 'category_purchase', {
458
+ name: 'Purchase request',
459
+ code: 'PR',
460
+ sequence: 30,
461
+ description: 'What to buy: the lines, and the vendor when known.',
462
+ askAmount: 'none',
463
+ askPartner: 'optional',
464
+ askLines: 'required',
465
+ }, { noupdate: true }),
466
+ record('approval.category', 'category_general', {
467
+ name: 'General',
468
+ code: 'GEN',
469
+ sequence: 90,
470
+ description: 'Anything else that needs a decision.',
471
+ }, { noupdate: true }),
472
+ ],
12
473
  });
@@ -0,0 +1,12 @@
1
+ /**
2
+ * The policy and category editor's helpers (RFC 0025 step 4), node components of their forms:
3
+ * - `approvals.PolicyPreview`: which of the last 50 records each level of the policy would have asked about, so a
4
+ * condition is checked before anyone submits; and "Sync waiting requests" (RFC 0027 §2.6);
5
+ * - `approvals.CategoryPolicy`: a request category's approval policy — made on demand when it has none, opened when
6
+ * it has one (its levels are edited there).
7
+ * Shown to Approvals managers (the server decides).
8
+ */
9
+ import { type NodeComponentProps } from '../../ui/index.js';
10
+ import { type ReactElement } from 'react';
11
+ export declare function PolicyPreview({ api, record, version }: NodeComponentProps): ReactElement | null;
12
+ export declare function CategoryPolicy({ api, record, reload }: NodeComponentProps): ReactElement | null;
@@ -0,0 +1,60 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * The policy and category editor's helpers (RFC 0025 step 4), node components of their forms:
4
+ * - `approvals.PolicyPreview`: which of the last 50 records each level of the policy would have asked about, so a
5
+ * condition is checked before anyone submits; and "Sync waiting requests" (RFC 0027 §2.6);
6
+ * - `approvals.CategoryPolicy`: a request category's approval policy — made on demand when it has none, opened when
7
+ * it has one (its levels are edited there).
8
+ * Shown to Approvals managers (the server decides).
9
+ */
10
+ import { Alert, Button } from '../../ui/index.js';
11
+ import { useMutation, useQuery } from '@tanstack/react-query';
12
+ import { useState } from 'react';
13
+ import { useTranslation } from 'react-i18next';
14
+ export function PolicyPreview({ api, record, version }) {
15
+ const { t } = useTranslation('approvals');
16
+ const id = typeof record?.id === 'number' ? record.id : null;
17
+ const preview = useQuery({
18
+ queryKey: ['approvals.preview', id, version],
19
+ enabled: id !== null,
20
+ queryFn: () => api.call('GET', `/api/v1/approvals/policies/${String(id)}/preview`),
21
+ });
22
+ const [synced, setSynced] = useState(null);
23
+ const sync = useMutation({
24
+ mutationFn: () => api.call('POST', `/api/v1/approvals/policies/${String(id)}/sync`, {}),
25
+ onSuccess: (r) => setSynced(r.synced),
26
+ });
27
+ if (id === null || preview.isError)
28
+ return null;
29
+ if (preview.isPending)
30
+ return _jsx("p", { className: "text-sm text-muted-foreground", children: t('loading') });
31
+ const { records, levels, covers } = preview.data;
32
+ return (_jsxs("section", { "aria-label": t('preview.title'), className: "grid gap-1 rounded-md border border-border p-3", children: [_jsx("h3", { className: "text-sm font-semibold", children: t('preview.title') }), covers === undefined ? null : (_jsx("p", { className: "text-xs", children: covers.all
33
+ ? t('preview.everyCompany')
34
+ : covers.companies.length === 0
35
+ ? t('preview.noCompany')
36
+ : t('preview.covers', { companies: covers.companies.join(', ') }) })), _jsx("p", { className: "text-xs text-muted-foreground", children: t('preview.explain', { count: records }) }), _jsx("ul", { className: "grid gap-1 text-sm", children: levels.map((l) => (_jsxs("li", { className: "flex items-center justify-between gap-2", children: [_jsx("span", { children: l.name }), _jsx("span", { className: "tabular-nums text-muted-foreground", children: t('preview.matched', { matched: l.matched.length, count: records }) })] }, l.id))) }), _jsxs("div", { className: "flex flex-wrap items-center gap-2 pt-1", children: [_jsx(Button, { size: "sm", variant: "secondary", disabled: sync.isPending, onClick: () => sync.mutate(), children: t('preview.sync') }), synced === null ? null : (_jsx("span", { role: "status", className: "text-xs text-muted-foreground", children: t('preview.synced', { count: synced }) }))] })] }));
37
+ }
38
+ export function CategoryPolicy({ api, record, reload }) {
39
+ const { t } = useTranslation('approvals');
40
+ const [error, setError] = useState(null);
41
+ const id = typeof record?.id === 'number' ? record.id : null;
42
+ const make = useMutation({
43
+ mutationFn: () => api.call('POST', `/api/v1/approvals/categories/${String(id)}/policy`, {}),
44
+ onSuccess: (r) => {
45
+ setError(null);
46
+ reload();
47
+ window.location.assign(`/approvals/a/approvals.action_policies/${r.policy}`);
48
+ },
49
+ onError: (e) => setError(e.message),
50
+ });
51
+ if (id === null)
52
+ return null;
53
+ const policy = record?.['policy'];
54
+ const policyId = typeof policy === 'number'
55
+ ? policy
56
+ : typeof policy === 'object' && policy !== null
57
+ ? Number(policy.id)
58
+ : null;
59
+ return (_jsxs("div", { className: "grid gap-2", children: [error === null ? null : _jsx(Alert, { tone: "danger", children: error }), policyId === null ? (_jsx("div", { children: _jsx(Button, { busy: make.isPending, onClick: () => make.mutate(), children: t('category.setUp') }) })) : (_jsx("a", { className: "text-sm text-primary underline", href: `/approvals/a/approvals.action_policies/${policyId}`, children: t('category.editLevels') }))] }));
60
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The matrix (RFC 0027 §2.7): the requests of a period the user decides — directly (named, or holding the role) or
3
+ * for others (as a backup, or for someone away) — a card per policy with what waits, what was approved and what was
4
+ * rejected; for Approvals managers also how long each level takes and who has the most requests late. The waiting
5
+ * counts open the inbox.
6
+ */
7
+ import { type PageProps } from '../../ui/index.js';
8
+ import { type ReactElement } from 'react';
9
+ export declare function Matrix({ api, label }: PageProps): ReactElement;
@@ -0,0 +1,26 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * The matrix (RFC 0027 §2.7): the requests of a period the user decides — directly (named, or holding the role) or
4
+ * for others (as a backup, or for someone away) — a card per policy with what waits, what was approved and what was
5
+ * rejected; for Approvals managers also how long each level takes and who has the most requests late. The waiting
6
+ * counts open the inbox.
7
+ */
8
+ import { Badge, Card, EmptyState, Select } from '../../ui/index.js';
9
+ import { useQuery } from '@tanstack/react-query';
10
+ import { useId, useState } from 'react';
11
+ import { useTranslation } from 'react-i18next';
12
+ const PERIODS = ['7d', '30d', '3m', '6m', '1y', 'all'];
13
+ export function Matrix({ api, label }) {
14
+ const { t } = useTranslation('approvals');
15
+ const id = useId();
16
+ const [period, setPeriod] = useState('3m');
17
+ const [mode, setMode] = useState('direct');
18
+ const data = useQuery({
19
+ queryKey: ['approvals', 'matrix', period, mode],
20
+ queryFn: () => api.call('GET', `/api/v1/approvals/matrix?period=${period}&mode=${mode}`),
21
+ });
22
+ const m = data.data;
23
+ return (_jsxs("div", { className: "grid gap-4 p-4", children: [_jsxs("header", { className: "flex flex-wrap items-end justify-between gap-3", children: [_jsx("h1", { className: "text-xl font-semibold", children: label ?? t('matrix.title') }), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("div", { role: "tablist", "aria-label": t('matrix.mode'), className: "flex rounded-md border p-0.5", children: ['direct', 'delegated'].map((k) => (_jsxs("button", { type: "button", role: "tab", "aria-selected": mode === k, className: `rounded px-3 py-1 text-sm ${mode === k ? 'bg-primary text-primary-foreground' : 'text-foreground hover:bg-muted'}`, onClick: () => setMode(k), children: [t(`matrix.${k}`), _jsx(Badge, { tone: "neutral", className: "ms-2", children: k === 'direct' ? (m?.direct ?? 0) : (m?.delegated ?? 0) })] }, k))) }), _jsx(Select, { id: `${id}-period`, label: t('matrix.period'), value: period, options: PERIODS.map((p) => ({ value: p, label: t(`matrix.periods.${p}`) })), onChange: (v) => setPeriod(v) })] })] }), m === undefined ? (_jsx(EmptyState, { title: t('loading') })) : m.cards.length === 0 ? (_jsx(EmptyState, { title: t('matrix.empty') })) : (_jsx("ul", { className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-3", children: m.cards.map((c) => (_jsx("li", { children: _jsxs(Card, { className: "grid gap-3 p-4", children: [_jsx("h2", { className: "font-medium", children: c.title }), _jsxs("dl", { className: "grid grid-cols-3 gap-2 text-center", children: [_jsxs("div", { children: [_jsx("dt", { className: "text-xs text-muted-foreground", children: t('matrix.waiting') }), _jsx("dd", { className: "text-lg font-semibold tabular-nums", children: c.waiting > 0 ? (_jsx("a", { className: "text-primary underline-offset-4 hover:underline", href: "/approvals/a/approvals.action_inbox", children: c.waiting })) : (0) })] }), _jsxs("div", { children: [_jsx("dt", { className: "text-xs text-muted-foreground", children: t('matrix.approved') }), _jsx("dd", { className: "text-lg font-semibold tabular-nums text-success", children: c.approved })] }), _jsxs("div", { children: [_jsx("dt", { className: "text-xs text-muted-foreground", children: t('matrix.rejected') }), _jsx("dd", { className: "text-lg font-semibold tabular-nums text-danger", children: c.rejected })] })] })] }) }, String(c.policy)))) })), m?.levels === null || m?.levels === undefined || m.levels.length === 0 ? null : (_jsxs("section", { "aria-labelledby": `${id}-levels`, className: "grid gap-2", children: [_jsx("h2", { id: `${id}-levels`, className: "font-semibold", children: t('matrix.levels') }), _jsx("div", { className: "overflow-x-auto", children: _jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { className: "bg-muted", children: _jsxs("tr", { children: [_jsx("th", { className: "px-2 py-1 text-start", children: t('matrix.policy') }), _jsx("th", { className: "px-2 py-1 text-start", children: t('matrix.level') }), _jsx("th", { className: "px-2 py-1 text-end", children: t('matrix.decided') }), _jsx("th", { className: "px-2 py-1 text-end", children: t('matrix.hours') })] }) }), _jsx("tbody", { children: m.levels.map((l) => (_jsxs("tr", { className: "border-b", children: [_jsx("td", { className: "px-2 py-1", children: l.policy }), _jsx("td", { className: "px-2 py-1", children: l.level }), _jsx("td", { className: "px-2 py-1 text-end tabular-nums", children: l.decided }), _jsx("td", { className: "px-2 py-1 text-end tabular-nums", children: l.averageHours })] }, `${l.policy}-${l.level}`))) })] }) })] })), m?.bottlenecks === null ||
24
+ m?.bottlenecks === undefined ||
25
+ m.bottlenecks.length === 0 ? null : (_jsxs("section", { "aria-labelledby": `${id}-late`, className: "grid gap-2", children: [_jsx("h2", { id: `${id}-late`, className: "font-semibold", children: t('matrix.bottlenecks') }), _jsx("ul", { className: "grid gap-1 text-sm", children: m.bottlenecks.map((b) => (_jsxs("li", { className: "flex items-center justify-between gap-2 border-b py-1", children: [_jsx("span", { children: b.name }), _jsxs("span", { className: "flex gap-2", children: [b.late > 0 ? (_jsx(Badge, { tone: "danger", children: t('matrix.late', { count: b.late }) })) : null, _jsx(Badge, { tone: "neutral", children: t('matrix.waitingCount', { count: b.waiting }) })] })] }, b.user))) })] }))] }));
26
+ }
@@ -1,12 +1,14 @@
1
1
  /**
2
2
  * @packageDocumentation
3
- * The web contribution of `shutro-erp/approvals`: the inbox, my requests and what I decided.
3
+ * The web contribution of `shutro-erp/approvals`: the inbox, my requests and what I decided; the policy preview and a request category's policy.
4
4
  */
5
5
  import { type Registry } from '../../ui/index.js';
6
6
  import type { i18n } from 'i18next';
7
7
  import { messages } from './messages.js';
8
+ export { CategoryPolicy, PolicyPreview } from './Config.js';
8
9
  export { History } from './History.js';
9
10
  export { Inbox } from './Inbox.js';
11
+ export { Matrix } from './Matrix.js';
10
12
  export { Mine } from './Mine.js';
11
13
  /** Registers the pages (and the messages in `i18n`, when given). */
12
14
  export declare function registerApprovalsWeb(registry: Registry, i18n?: i18n): Registry;
@@ -1,20 +1,27 @@
1
1
  /**
2
2
  * @packageDocumentation
3
- * The web contribution of `shutro-erp/approvals`: the inbox, my requests and what I decided.
3
+ * The web contribution of `shutro-erp/approvals`: the inbox, my requests and what I decided; the policy preview and a request category's policy.
4
4
  */
5
5
  import { addMessages } from '../../ui/index.js';
6
+ import { CategoryPolicy, PolicyPreview } from './Config.js';
6
7
  import { History } from './History.js';
7
8
  import { Inbox } from './Inbox.js';
9
+ import { Matrix } from './Matrix.js';
8
10
  import { Mine } from './Mine.js';
9
11
  import { messages } from './messages.js';
12
+ export { CategoryPolicy, PolicyPreview } from './Config.js';
10
13
  export { History } from './History.js';
11
14
  export { Inbox } from './Inbox.js';
15
+ export { Matrix } from './Matrix.js';
12
16
  export { Mine } from './Mine.js';
13
17
  /** Registers the pages (and the messages in `i18n`, when given). */
14
18
  export function registerApprovalsWeb(registry, i18n) {
15
19
  registry.registerPage('approvals.Inbox', Inbox);
16
20
  registry.registerPage('approvals.Mine', Mine);
17
21
  registry.registerPage('approvals.History', History);
22
+ registry.registerPage('approvals.Matrix', Matrix);
23
+ registry.registerComponent('approvals.PolicyPreview', PolicyPreview);
24
+ registry.registerComponent('approvals.CategoryPolicy', CategoryPolicy);
18
25
  if (i18n !== undefined)
19
26
  addMessages(i18n, 'approvals', messages);
20
27
  return registry;