shutro-erp 0.3.4 → 0.3.6

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 (618) hide show
  1. package/dist/account_asset/.kosh/bindings.d.ts +22 -0
  2. package/dist/account_asset/.kosh/bindings.js +15 -0
  3. package/dist/account_asset/.kosh/schema.d.ts +1755 -0
  4. package/dist/account_asset/board.d.ts +61 -0
  5. package/dist/account_asset/board.js +86 -0
  6. package/dist/account_asset/books.d.ts +42 -0
  7. package/dist/account_asset/books.js +398 -0
  8. package/dist/account_asset/demo.d.ts +7 -0
  9. package/dist/account_asset/demo.js +72 -0
  10. package/dist/account_asset/index.d.ts +9 -0
  11. package/dist/account_asset/index.js +335 -0
  12. package/dist/account_asset/module.d.ts +7622 -0
  13. package/dist/account_asset/module.js +230 -0
  14. package/dist/account_budget/.kosh/bindings.d.ts +22 -0
  15. package/dist/account_budget/.kosh/bindings.js +15 -0
  16. package/dist/account_budget/.kosh/schema.d.ts +1767 -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/index.d.ts +4 -0
  22. package/dist/account_budget/index.js +223 -0
  23. package/dist/account_budget/module.d.ts +13863 -0
  24. package/dist/account_budget/module.js +167 -0
  25. package/dist/account_portal/.kosh/bindings.js +1 -1
  26. package/dist/account_portal/.kosh/schema.d.ts +176 -6
  27. package/dist/account_portal/module.d.ts +505 -6
  28. package/dist/accounting/.kosh/bindings.js +1 -1
  29. package/dist/accounting/.kosh/schema.d.ts +176 -6
  30. package/dist/accounting/index.d.ts +1 -1
  31. package/dist/accounting/index.js +344 -4
  32. package/dist/accounting/module.d.ts +513 -5
  33. package/dist/accounting/module.js +55 -3
  34. package/dist/approvals/.kosh/bindings.d.ts +22 -0
  35. package/dist/approvals/.kosh/bindings.js +15 -0
  36. package/dist/approvals/.kosh/schema.d.ts +611 -0
  37. package/dist/approvals/index.d.ts +18 -0
  38. package/dist/approvals/index.js +302 -0
  39. package/dist/approvals/mails.d.ts +25 -0
  40. package/dist/approvals/mails.js +82 -0
  41. package/dist/approvals/module.d.ts +1 -0
  42. package/dist/approvals/module.js +12 -0
  43. package/dist/approvals/web/History.d.ts +4 -0
  44. package/dist/approvals/web/History.js +13 -0
  45. package/dist/approvals/web/Inbox.d.ts +9 -0
  46. package/dist/approvals/web/Inbox.js +114 -0
  47. package/dist/approvals/web/Mine.d.ts +7 -0
  48. package/dist/approvals/web/Mine.js +27 -0
  49. package/dist/approvals/web/index.d.ts +13 -0
  50. package/dist/approvals/web/index.js +22 -0
  51. package/dist/approvals/web/messages.d.ts +2 -0
  52. package/dist/approvals/web/messages.js +119 -0
  53. package/dist/approvals/web/shared.d.ts +59 -0
  54. package/dist/approvals/web/shared.js +46 -0
  55. package/dist/attendance/.kosh/bindings.d.ts +22 -0
  56. package/dist/attendance/.kosh/bindings.js +15 -0
  57. package/dist/attendance/.kosh/schema.d.ts +1048 -0
  58. package/dist/attendance/days.d.ts +96 -0
  59. package/dist/attendance/days.js +430 -0
  60. package/dist/attendance/demo.d.ts +7 -0
  61. package/dist/attendance/demo.js +58 -0
  62. package/dist/attendance/index.d.ts +4 -0
  63. package/dist/attendance/index.js +513 -0
  64. package/dist/attendance/module.d.ts +3969 -0
  65. package/dist/attendance/module.js +412 -0
  66. package/dist/attendance/routes.d.ts +16 -0
  67. package/dist/attendance/routes.js +266 -0
  68. package/dist/attendance/web/Check.d.ts +8 -0
  69. package/dist/attendance/web/Check.js +40 -0
  70. package/dist/attendance/web/Kiosk.d.ts +8 -0
  71. package/dist/attendance/web/Kiosk.js +62 -0
  72. package/dist/attendance/web/PinButton.d.ts +7 -0
  73. package/dist/attendance/web/PinButton.js +29 -0
  74. package/dist/attendance/web/index.d.ts +13 -0
  75. package/dist/attendance/web/index.js +22 -0
  76. package/dist/attendance/web/messages.d.ts +2 -0
  77. package/dist/attendance/web/messages.js +61 -0
  78. package/dist/calendar/.kosh/bindings.d.ts +22 -0
  79. package/dist/calendar/.kosh/bindings.js +15 -0
  80. package/dist/calendar/.kosh/schema.d.ts +795 -0
  81. package/dist/calendar/demo.d.ts +6 -0
  82. package/dist/calendar/demo.js +24 -0
  83. package/dist/calendar/index.d.ts +3 -0
  84. package/dist/calendar/index.js +291 -0
  85. package/dist/calendar/module.d.ts +1705 -0
  86. package/dist/calendar/module.js +180 -0
  87. package/dist/cli/init.js +80 -0
  88. package/dist/cli/templates.d.ts +1 -1
  89. package/dist/cli/templates.js +226 -0
  90. package/dist/contacts/.kosh/bindings.js +1 -1
  91. package/dist/contacts/.kosh/schema.d.ts +78 -3
  92. package/dist/contacts/demo.js +30 -1
  93. package/dist/contacts/index.d.ts +1 -1
  94. package/dist/contacts/index.js +155 -9
  95. package/dist/contacts/module.d.ts +338 -2
  96. package/dist/contacts/module.js +93 -5
  97. package/dist/crm/.kosh/bindings.d.ts +22 -0
  98. package/dist/crm/.kosh/bindings.js +15 -0
  99. package/dist/crm/.kosh/schema.d.ts +800 -0
  100. package/dist/crm/demo.d.ts +6 -0
  101. package/dist/crm/demo.js +45 -0
  102. package/dist/crm/index.d.ts +3 -0
  103. package/dist/crm/index.js +361 -0
  104. package/dist/crm/module.d.ts +1845 -0
  105. package/dist/crm/module.js +208 -0
  106. package/dist/documents/.kosh/bindings.d.ts +22 -0
  107. package/dist/documents/.kosh/bindings.js +15 -0
  108. package/dist/documents/.kosh/schema.d.ts +862 -0
  109. package/dist/documents/demo.d.ts +6 -0
  110. package/dist/documents/demo.js +22 -0
  111. package/dist/documents/documents.d.ts +98 -0
  112. package/dist/documents/documents.js +318 -0
  113. package/dist/documents/index.d.ts +30 -0
  114. package/dist/documents/index.js +442 -0
  115. package/dist/documents/module.d.ts +2781 -0
  116. package/dist/documents/module.js +214 -0
  117. package/dist/documents/web/Versions.d.ts +7 -0
  118. package/dist/documents/web/Versions.js +45 -0
  119. package/dist/documents/web/index.d.ts +11 -0
  120. package/dist/documents/web/index.js +16 -0
  121. package/dist/documents/web/messages.d.ts +2 -0
  122. package/dist/documents/web/messages.js +21 -0
  123. package/dist/event/.kosh/bindings.d.ts +22 -0
  124. package/dist/event/.kosh/bindings.js +15 -0
  125. package/dist/event/.kosh/schema.d.ts +843 -0
  126. package/dist/event/demo.d.ts +6 -0
  127. package/dist/event/demo.js +65 -0
  128. package/dist/event/index.d.ts +14 -0
  129. package/dist/event/index.js +333 -0
  130. package/dist/event/mails.d.ts +15 -0
  131. package/dist/event/mails.js +112 -0
  132. package/dist/event/module.d.ts +2800 -0
  133. package/dist/event/module.js +323 -0
  134. package/dist/event/web/CheckInBox.d.ts +9 -0
  135. package/dist/event/web/CheckInBox.js +87 -0
  136. package/dist/event/web/index.d.ts +11 -0
  137. package/dist/event/web/index.js +16 -0
  138. package/dist/event/web/messages.d.ts +2 -0
  139. package/dist/event/web/messages.js +23 -0
  140. package/dist/event_account/.kosh/bindings.d.ts +22 -0
  141. package/dist/event_account/.kosh/bindings.js +15 -0
  142. package/dist/event_account/.kosh/schema.d.ts +1758 -0
  143. package/dist/event_account/index.d.ts +3 -0
  144. package/dist/event_account/index.js +28 -0
  145. package/dist/event_account/module.d.ts +7114 -0
  146. package/dist/event_account/module.js +90 -0
  147. package/dist/expense/.kosh/bindings.d.ts +22 -0
  148. package/dist/expense/.kosh/bindings.js +15 -0
  149. package/dist/expense/.kosh/schema.d.ts +1299 -0
  150. package/dist/expense/demo.d.ts +7 -0
  151. package/dist/expense/demo.js +69 -0
  152. package/dist/expense/index.d.ts +3 -0
  153. package/dist/expense/index.js +495 -0
  154. package/dist/expense/module.d.ts +4747 -0
  155. package/dist/expense/module.js +647 -0
  156. package/dist/expense_account/.kosh/bindings.d.ts +22 -0
  157. package/dist/expense_account/.kosh/bindings.js +15 -0
  158. package/dist/expense_account/.kosh/schema.d.ts +1936 -0
  159. package/dist/expense_account/index.d.ts +3 -0
  160. package/dist/expense_account/index.js +74 -0
  161. package/dist/expense_account/module.d.ts +9153 -0
  162. package/dist/expense_account/module.js +318 -0
  163. package/dist/helpdesk/.kosh/bindings.d.ts +22 -0
  164. package/dist/helpdesk/.kosh/bindings.js +15 -0
  165. package/dist/helpdesk/.kosh/schema.d.ts +885 -0
  166. package/dist/helpdesk/demo.d.ts +7 -0
  167. package/dist/helpdesk/demo.js +65 -0
  168. package/dist/helpdesk/hours.d.ts +17 -0
  169. package/dist/helpdesk/hours.js +94 -0
  170. package/dist/helpdesk/index.d.ts +10 -0
  171. package/dist/helpdesk/index.js +461 -0
  172. package/dist/helpdesk/module.d.ts +2940 -0
  173. package/dist/helpdesk/module.js +326 -0
  174. package/dist/helpdesk/routes.d.ts +12 -0
  175. package/dist/helpdesk/routes.js +132 -0
  176. package/dist/helpdesk/sla.d.ts +37 -0
  177. package/dist/helpdesk/sla.js +226 -0
  178. package/dist/hr/.kosh/bindings.d.ts +22 -0
  179. package/dist/hr/.kosh/bindings.js +15 -0
  180. package/dist/hr/.kosh/schema.d.ts +878 -0
  181. package/dist/hr/demo.d.ts +6 -0
  182. package/dist/hr/demo.js +60 -0
  183. package/dist/hr/index.d.ts +3 -0
  184. package/dist/hr/index.js +483 -0
  185. package/dist/hr/module.d.ts +2611 -0
  186. package/dist/hr/module.js +350 -0
  187. package/dist/l10n_bd/.kosh/bindings.js +1 -1
  188. package/dist/l10n_bd/.kosh/schema.d.ts +176 -6
  189. package/dist/l10n_bd/module.d.ts +505 -6
  190. package/dist/l10n_bd_payroll/.kosh/bindings.d.ts +22 -0
  191. package/dist/l10n_bd_payroll/.kosh/bindings.js +15 -0
  192. package/dist/l10n_bd_payroll/.kosh/schema.d.ts +2312 -0
  193. package/dist/l10n_bd_payroll/data.d.ts +47 -0
  194. package/dist/l10n_bd_payroll/data.js +347 -0
  195. package/dist/l10n_bd_payroll/index.d.ts +4 -0
  196. package/dist/l10n_bd_payroll/index.js +24 -0
  197. package/dist/l10n_bd_payroll/module.d.ts +12932 -0
  198. package/dist/l10n_bd_payroll/module.js +86 -0
  199. package/dist/l10n_in/.kosh/bindings.js +1 -1
  200. package/dist/l10n_in/.kosh/schema.d.ts +176 -6
  201. package/dist/l10n_in/module.d.ts +527 -7
  202. package/dist/mail/inbound/handle.js +6 -1
  203. package/dist/maintenance/.kosh/bindings.d.ts +22 -0
  204. package/dist/maintenance/.kosh/bindings.js +15 -0
  205. package/dist/maintenance/.kosh/schema.d.ts +911 -0
  206. package/dist/maintenance/demo.d.ts +6 -0
  207. package/dist/maintenance/demo.js +60 -0
  208. package/dist/maintenance/index.d.ts +3 -0
  209. package/dist/maintenance/index.js +422 -0
  210. package/dist/maintenance/module.d.ts +3545 -0
  211. package/dist/maintenance/module.js +446 -0
  212. package/dist/maintenance_stock/.kosh/bindings.d.ts +22 -0
  213. package/dist/maintenance_stock/.kosh/bindings.js +15 -0
  214. package/dist/maintenance_stock/.kosh/schema.d.ts +1446 -0
  215. package/dist/maintenance_stock/index.d.ts +9 -0
  216. package/dist/maintenance_stock/index.js +52 -0
  217. package/dist/maintenance_stock/module.d.ts +7675 -0
  218. package/dist/maintenance_stock/module.js +192 -0
  219. package/dist/modules-sdk/index.d.ts +1 -1
  220. package/dist/modules-sdk/manifest.d.ts +109 -2
  221. package/dist/modules-sdk/manifest.js +35 -1
  222. package/dist/mrp/.kosh/bindings.d.ts +22 -0
  223. package/dist/mrp/.kosh/bindings.js +15 -0
  224. package/dist/mrp/.kosh/schema.d.ts +1453 -0
  225. package/dist/mrp/demo.d.ts +7 -0
  226. package/dist/mrp/demo.js +42 -0
  227. package/dist/mrp/index.d.ts +3 -0
  228. package/dist/mrp/index.js +393 -0
  229. package/dist/mrp/module.d.ts +9335 -0
  230. package/dist/mrp/module.js +757 -0
  231. package/dist/mrp_account/.kosh/bindings.d.ts +22 -0
  232. package/dist/mrp_account/.kosh/bindings.js +15 -0
  233. package/dist/mrp_account/.kosh/schema.d.ts +2299 -0
  234. package/dist/mrp_account/index.d.ts +3 -0
  235. package/dist/mrp_account/index.js +22 -0
  236. package/dist/mrp_account/module.d.ts +23151 -0
  237. package/dist/mrp_account/module.js +123 -0
  238. package/dist/payment/.kosh/bindings.js +1 -1
  239. package/dist/payment/.kosh/schema.d.ts +178 -7
  240. package/dist/payment/index.d.ts +41 -0
  241. package/dist/payment/index.js +131 -74
  242. package/dist/payment/module.d.ts +569 -12
  243. package/dist/payment/module.js +19 -3
  244. package/dist/payment/settle.js +10 -1
  245. package/dist/payroll/.kosh/bindings.d.ts +22 -0
  246. package/dist/payroll/.kosh/bindings.js +15 -0
  247. package/dist/payroll/.kosh/schema.d.ts +1390 -0
  248. package/dist/payroll/compute.d.ts +35 -0
  249. package/dist/payroll/compute.js +398 -0
  250. package/dist/payroll/demo.d.ts +55 -0
  251. package/dist/payroll/demo.js +121 -0
  252. package/dist/payroll/formula.d.ts +62 -0
  253. package/dist/payroll/formula.js +320 -0
  254. package/dist/payroll/index.d.ts +230 -0
  255. package/dist/payroll/index.js +713 -0
  256. package/dist/payroll/module.d.ts +9390 -0
  257. package/dist/payroll/module.js +606 -0
  258. package/dist/payroll/routes.d.ts +10 -0
  259. package/dist/payroll/routes.js +112 -0
  260. package/dist/payroll_account/.kosh/bindings.d.ts +22 -0
  261. package/dist/payroll_account/.kosh/bindings.js +15 -0
  262. package/dist/payroll_account/.kosh/schema.d.ts +2308 -0
  263. package/dist/payroll_account/index.d.ts +3 -0
  264. package/dist/payroll_account/index.js +40 -0
  265. package/dist/payroll_account/module.d.ts +12396 -0
  266. package/dist/payroll_account/module.js +256 -0
  267. package/dist/permissions/approvals.d.ts +131 -9
  268. package/dist/permissions/approvals.js +662 -57
  269. package/dist/permissions/index.d.ts +1 -1
  270. package/dist/permissions/index.js +2 -2
  271. package/dist/permissions/models.js +191 -12
  272. package/dist/permissions/routes.d.ts +6 -1
  273. package/dist/permissions/routes.js +37 -4
  274. package/dist/permissions/web/ApprovalPanel.d.ts +5 -4
  275. package/dist/permissions/web/ApprovalPanel.js +39 -13
  276. package/dist/permissions/web/index.d.ts +6 -4
  277. package/dist/permissions/web/index.js +13 -4
  278. package/dist/permissions/web/messages.d.ts +2 -0
  279. package/dist/permissions/web/messages.js +43 -0
  280. package/dist/portal/.kosh/bindings.js +1 -1
  281. package/dist/portal/.kosh/schema.d.ts +78 -3
  282. package/dist/portal/index.js +1 -1
  283. package/dist/portal/module.d.ts +166 -2
  284. package/dist/pos/.kosh/bindings.d.ts +22 -0
  285. package/dist/pos/.kosh/bindings.js +15 -0
  286. package/dist/pos/.kosh/schema.d.ts +1809 -0
  287. package/dist/pos/accounting.d.ts +10 -0
  288. package/dist/pos/accounting.js +149 -0
  289. package/dist/pos/demo.d.ts +6 -0
  290. package/dist/pos/demo.js +90 -0
  291. package/dist/pos/index.d.ts +9 -0
  292. package/dist/pos/index.js +353 -0
  293. package/dist/pos/module.d.ts +9783 -0
  294. package/dist/pos/module.js +423 -0
  295. package/dist/pos/routes.d.ts +39 -0
  296. package/dist/pos/routes.js +368 -0
  297. package/dist/pos/web/Register.d.ts +9 -0
  298. package/dist/pos/web/Register.js +252 -0
  299. package/dist/pos/web/index.d.ts +11 -0
  300. package/dist/pos/web/index.js +16 -0
  301. package/dist/pos/web/messages.d.ts +2 -0
  302. package/dist/pos/web/messages.js +87 -0
  303. package/dist/pos_stock/.kosh/bindings.d.ts +22 -0
  304. package/dist/pos_stock/.kosh/bindings.js +15 -0
  305. package/dist/pos_stock/.kosh/schema.d.ts +2208 -0
  306. package/dist/pos_stock/index.d.ts +9 -0
  307. package/dist/pos_stock/index.js +35 -0
  308. package/dist/pos_stock/module.d.ts +12803 -0
  309. package/dist/pos_stock/module.js +115 -0
  310. package/dist/product/.kosh/bindings.js +1 -1
  311. package/dist/product/.kosh/schema.d.ts +52 -1
  312. package/dist/product/index.js +94 -4
  313. package/dist/product/module.d.ts +45 -1
  314. package/dist/product/module.js +11 -3
  315. package/dist/project/.kosh/bindings.js +1 -1
  316. package/dist/project/.kosh/schema.d.ts +725 -3
  317. package/dist/project/index.d.ts +3 -1
  318. package/dist/project/index.js +1045 -18
  319. package/dist/project/module.d.ts +10168 -458
  320. package/dist/project/module.js +1578 -14
  321. package/dist/project/routes.d.ts +44 -0
  322. package/dist/project/routes.js +314 -0
  323. package/dist/project/schedule.d.ts +72 -0
  324. package/dist/project/schedule.js +192 -0
  325. package/dist/project/web/Refresh.d.ts +8 -0
  326. package/dist/project/web/Refresh.js +29 -0
  327. package/dist/project/web/Schedule.d.ts +9 -0
  328. package/dist/project/web/Schedule.js +93 -0
  329. package/dist/project/web/Structure.d.ts +8 -0
  330. package/dist/project/web/Structure.js +86 -0
  331. package/dist/project/web/Workload.d.ts +8 -0
  332. package/dist/project/web/Workload.js +43 -0
  333. package/dist/project/web/index.d.ts +14 -0
  334. package/dist/project/web/index.js +25 -0
  335. package/dist/project/web/messages.d.ts +2 -0
  336. package/dist/project/web/messages.js +85 -0
  337. package/dist/project_account/.kosh/bindings.d.ts +22 -0
  338. package/dist/project_account/.kosh/bindings.js +15 -0
  339. package/dist/project_account/.kosh/schema.d.ts +2241 -0
  340. package/dist/project_account/index.d.ts +3 -0
  341. package/dist/project_account/index.js +27 -0
  342. package/dist/project_account/module.d.ts +11539 -0
  343. package/dist/project_account/module.js +76 -0
  344. package/dist/project_portal/.kosh/bindings.js +1 -1
  345. package/dist/project_portal/.kosh/schema.d.ts +725 -3
  346. package/dist/project_portal/module.d.ts +5137 -119
  347. package/dist/project_purchase/.kosh/bindings.d.ts +22 -0
  348. package/dist/project_purchase/.kosh/bindings.js +15 -0
  349. package/dist/project_purchase/.kosh/schema.d.ts +2320 -0
  350. package/dist/project_purchase/index.d.ts +9 -0
  351. package/dist/project_purchase/index.js +22 -0
  352. package/dist/project_purchase/module.d.ts +25147 -0
  353. package/dist/project_purchase/module.js +56 -0
  354. package/dist/purchase/.kosh/bindings.js +1 -1
  355. package/dist/purchase/.kosh/schema.d.ts +150 -6
  356. package/dist/purchase/index.js +163 -3
  357. package/dist/purchase/module.d.ts +228 -5
  358. package/dist/purchase/module.js +30 -3
  359. package/dist/purchase_account/.kosh/bindings.js +1 -1
  360. package/dist/purchase_account/.kosh/schema.d.ts +180 -8
  361. package/dist/purchase_account/index.js +27 -1
  362. package/dist/purchase_account/module.d.ts +591 -30
  363. package/dist/purchase_account/module.js +13 -2
  364. package/dist/purchase_portal/.kosh/bindings.js +1 -1
  365. package/dist/purchase_portal/.kosh/schema.d.ts +150 -6
  366. package/dist/purchase_portal/module.d.ts +372 -6
  367. package/dist/purchase_stock/.kosh/bindings.d.ts +22 -0
  368. package/dist/purchase_stock/.kosh/bindings.js +15 -0
  369. package/dist/purchase_stock/.kosh/schema.d.ts +1479 -0
  370. package/dist/purchase_stock/index.d.ts +7 -0
  371. package/dist/purchase_stock/index.js +98 -0
  372. package/dist/purchase_stock/module.d.ts +7535 -0
  373. package/dist/purchase_stock/module.js +380 -0
  374. package/dist/purchase_stock_account/.kosh/bindings.d.ts +22 -0
  375. package/dist/purchase_stock_account/.kosh/bindings.js +15 -0
  376. package/dist/purchase_stock_account/.kosh/schema.d.ts +2155 -0
  377. package/dist/purchase_stock_account/index.d.ts +3 -0
  378. package/dist/purchase_stock_account/index.js +24 -0
  379. package/dist/purchase_stock_account/module.d.ts +38015 -0
  380. package/dist/purchase_stock_account/module.js +168 -0
  381. package/dist/recruitment/.kosh/bindings.d.ts +22 -0
  382. package/dist/recruitment/.kosh/bindings.js +15 -0
  383. package/dist/recruitment/.kosh/schema.d.ts +991 -0
  384. package/dist/recruitment/demo.d.ts +6 -0
  385. package/dist/recruitment/demo.js +45 -0
  386. package/dist/recruitment/index.d.ts +3 -0
  387. package/dist/recruitment/index.js +385 -0
  388. package/dist/recruitment/module.d.ts +3249 -0
  389. package/dist/recruitment/module.js +194 -0
  390. package/dist/recruitment/web/HireButton.d.ts +9 -0
  391. package/dist/recruitment/web/HireButton.js +32 -0
  392. package/dist/recruitment/web/index.d.ts +11 -0
  393. package/dist/recruitment/web/index.js +16 -0
  394. package/dist/recruitment/web/messages.d.ts +2 -0
  395. package/dist/recruitment/web/messages.js +19 -0
  396. package/dist/reporting/documents.d.ts +5 -0
  397. package/dist/reporting/documents.js +28 -1
  398. package/dist/reporting/index.d.ts +1 -1
  399. package/dist/reporting/index.js +4 -2
  400. package/dist/reporting/models.js +9 -0
  401. package/dist/reporting/overviews.d.ts +16 -0
  402. package/dist/reporting/overviews.js +56 -0
  403. package/dist/reporting/routes-documents.js +1 -1
  404. package/dist/reporting/routes.js +138 -80
  405. package/dist/reporting/web/DashboardView.d.ts +11 -0
  406. package/dist/reporting/web/DashboardView.js +2 -2
  407. package/dist/reporting/web/DesignerView.js +5 -0
  408. package/dist/reporting/web/Overview.d.ts +9 -0
  409. package/dist/reporting/web/Overview.js +53 -0
  410. package/dist/reporting/web/index.d.ts +1 -0
  411. package/dist/reporting/web/index.js +4 -1
  412. package/dist/reporting/web/messages.js +9 -0
  413. package/dist/sale_account/.kosh/bindings.js +1 -1
  414. package/dist/sale_account/.kosh/schema.d.ts +181 -6
  415. package/dist/sale_account/index.js +22 -1
  416. package/dist/sale_account/module.d.ts +639 -38
  417. package/dist/sale_portal/.kosh/bindings.js +1 -1
  418. package/dist/sale_portal/.kosh/schema.d.ts +59 -3
  419. package/dist/sale_portal/module.d.ts +435 -5
  420. package/dist/sale_project/.kosh/bindings.js +1 -1
  421. package/dist/sale_project/.kosh/schema.d.ts +732 -3
  422. package/dist/sale_project/module.d.ts +5349 -208
  423. package/dist/sale_project/module.js +17 -1
  424. package/dist/sale_stock/.kosh/bindings.d.ts +22 -0
  425. package/dist/sale_stock/.kosh/bindings.js +15 -0
  426. package/dist/sale_stock/.kosh/schema.d.ts +1303 -0
  427. package/dist/sale_stock/index.d.ts +7 -0
  428. package/dist/sale_stock/index.js +84 -0
  429. package/dist/sale_stock/module.d.ts +7514 -0
  430. package/dist/sale_stock/module.js +146 -0
  431. package/dist/sales/.kosh/bindings.js +1 -1
  432. package/dist/sales/.kosh/schema.d.ts +59 -3
  433. package/dist/sales/index.js +195 -4
  434. package/dist/sales/module.d.ts +356 -3
  435. package/dist/sales/module.js +78 -3
  436. package/dist/server/api/metadata.d.ts +5 -0
  437. package/dist/server/api/metadata.js +5 -0
  438. package/dist/server/api/rest.js +64 -1
  439. package/dist/server/api/views.js +1 -0
  440. package/dist/server/app-settings.d.ts +7 -0
  441. package/dist/server/app-settings.js +10 -0
  442. package/dist/server/auth/base.js +9 -0
  443. package/dist/server/index.d.ts +1 -0
  444. package/dist/server/index.js +1 -0
  445. package/dist/settings/app-settings.d.ts +2 -0
  446. package/dist/settings/app-settings.js +518 -0
  447. package/dist/settings/index.d.ts +1 -0
  448. package/dist/settings/index.js +15 -0
  449. package/dist/settings/people.js +29 -5
  450. package/dist/settings/web/AppSettingsPage.d.ts +11 -0
  451. package/dist/settings/web/AppSettingsPage.js +210 -0
  452. package/dist/settings/web/OverviewPage.js +16 -3
  453. package/dist/settings/web/PeoplePage.js +20 -6
  454. package/dist/settings/web/index.d.ts +1 -0
  455. package/dist/settings/web/index.js +3 -0
  456. package/dist/settings/web/messages.js +118 -2
  457. package/dist/sign/.kosh/bindings.d.ts +22 -0
  458. package/dist/sign/.kosh/bindings.js +15 -0
  459. package/dist/sign/.kosh/schema.d.ts +990 -0
  460. package/dist/sign/index.d.ts +14 -0
  461. package/dist/sign/index.js +350 -0
  462. package/dist/sign/module.d.ts +4478 -0
  463. package/dist/sign/module.js +158 -0
  464. package/dist/sign/sign.d.ts +82 -0
  465. package/dist/sign/sign.js +474 -0
  466. package/dist/stock/.kosh/bindings.d.ts +22 -0
  467. package/dist/stock/.kosh/bindings.js +15 -0
  468. package/dist/stock/.kosh/schema.d.ts +1222 -0
  469. package/dist/stock/demo.d.ts +8 -0
  470. package/dist/stock/demo.js +82 -0
  471. package/dist/stock/index.d.ts +4 -0
  472. package/dist/stock/index.js +903 -0
  473. package/dist/stock/module.d.ts +7856 -0
  474. package/dist/stock/module.js +1880 -0
  475. package/dist/stock/replenish.d.ts +38 -0
  476. package/dist/stock/replenish.js +176 -0
  477. package/dist/stock/web/Replenishment.d.ts +8 -0
  478. package/dist/stock/web/Replenishment.js +84 -0
  479. package/dist/stock/web/ScanBox.d.ts +8 -0
  480. package/dist/stock/web/ScanBox.js +90 -0
  481. package/dist/stock/web/index.d.ts +13 -0
  482. package/dist/stock/web/index.js +20 -0
  483. package/dist/stock/web/messages.d.ts +2 -0
  484. package/dist/stock/web/messages.js +77 -0
  485. package/dist/stock_account/.kosh/bindings.d.ts +22 -0
  486. package/dist/stock_account/.kosh/bindings.js +15 -0
  487. package/dist/stock_account/.kosh/schema.d.ts +2068 -0
  488. package/dist/stock_account/index.d.ts +3 -0
  489. package/dist/stock_account/index.js +140 -0
  490. package/dist/stock_account/module.d.ts +11523 -0
  491. package/dist/stock_account/module.js +339 -0
  492. package/dist/storage/attachments.d.ts +5 -0
  493. package/dist/storage/attachments.js +12 -1
  494. package/dist/storage/models.js +3 -0
  495. package/dist/storage/routes.js +13 -2
  496. package/dist/todo/.kosh/bindings.d.ts +22 -0
  497. package/dist/todo/.kosh/bindings.js +15 -0
  498. package/dist/todo/.kosh/schema.d.ts +732 -0
  499. package/dist/todo/demo.d.ts +6 -0
  500. package/dist/todo/demo.js +35 -0
  501. package/dist/todo/index.d.ts +3 -0
  502. package/dist/todo/index.js +187 -0
  503. package/dist/todo/module.d.ts +1180 -0
  504. package/dist/todo/module.js +130 -0
  505. package/dist/trade_finance/.kosh/bindings.d.ts +22 -0
  506. package/dist/trade_finance/.kosh/bindings.js +15 -0
  507. package/dist/trade_finance/.kosh/schema.d.ts +884 -0
  508. package/dist/trade_finance/demo.d.ts +6 -0
  509. package/dist/trade_finance/demo.js +63 -0
  510. package/dist/trade_finance/index.d.ts +3 -0
  511. package/dist/trade_finance/index.js +415 -0
  512. package/dist/trade_finance/module.d.ts +3779 -0
  513. package/dist/trade_finance/module.js +507 -0
  514. package/dist/trade_finance_account/.kosh/bindings.d.ts +22 -0
  515. package/dist/trade_finance_account/.kosh/bindings.js +15 -0
  516. package/dist/trade_finance_account/.kosh/schema.d.ts +1830 -0
  517. package/dist/trade_finance_account/index.d.ts +3 -0
  518. package/dist/trade_finance_account/index.js +93 -0
  519. package/dist/trade_finance_account/module.d.ts +8074 -0
  520. package/dist/trade_finance_account/module.js +245 -0
  521. package/dist/trade_finance_purchase/.kosh/bindings.d.ts +22 -0
  522. package/dist/trade_finance_purchase/.kosh/bindings.js +15 -0
  523. package/dist/trade_finance_purchase/.kosh/schema.d.ts +1246 -0
  524. package/dist/trade_finance_purchase/index.d.ts +8 -0
  525. package/dist/trade_finance_purchase/index.js +50 -0
  526. package/dist/trade_finance_purchase/module.d.ts +4257 -0
  527. package/dist/trade_finance_purchase/module.js +44 -0
  528. package/dist/trade_finance_sale/.kosh/bindings.d.ts +22 -0
  529. package/dist/trade_finance_sale/.kosh/bindings.js +15 -0
  530. package/dist/trade_finance_sale/.kosh/schema.d.ts +1072 -0
  531. package/dist/trade_finance_sale/index.d.ts +8 -0
  532. package/dist/trade_finance_sale/index.js +50 -0
  533. package/dist/trade_finance_sale/module.d.ts +4281 -0
  534. package/dist/trade_finance_sale/module.js +44 -0
  535. package/dist/ui/api.d.ts +2 -1
  536. package/dist/ui/api.js +2 -1
  537. package/dist/ui/app.js +26 -13
  538. package/dist/ui/components/AppIcon.js +30 -1
  539. package/dist/ui/components/primitives.d.ts +2 -0
  540. package/dist/ui/components/primitives.js +7 -1
  541. package/dist/ui/i18n/messages.d.ts +27 -0
  542. package/dist/ui/i18n/messages.js +46 -0
  543. package/dist/ui/index.d.ts +1 -0
  544. package/dist/ui/index.js +1 -0
  545. package/dist/ui/offline/queue.d.ts +5 -1
  546. package/dist/ui/offline/queue.js +2 -0
  547. package/dist/ui/registry.d.ts +5 -0
  548. package/dist/ui/shell/Home.js +55 -4
  549. package/dist/ui/views/FormView.js +102 -19
  550. package/dist/ui/views/KanbanView.d.ts +2 -0
  551. package/dist/ui/views/KanbanView.js +40 -3
  552. package/dist/ui/views/ListView.js +110 -11
  553. package/dist/ui/views/StatsRow.d.ts +14 -0
  554. package/dist/ui/views/StatsRow.js +88 -0
  555. package/dist/ui/views/widgets.d.ts +2 -1
  556. package/dist/ui/views/widgets.js +200 -1
  557. package/dist/views/builders.d.ts +19 -2
  558. package/dist/views/builders.js +21 -1
  559. package/dist/views/condition.d.ts +6 -0
  560. package/dist/views/condition.js +20 -0
  561. package/dist/views/documents.d.ts +8 -0
  562. package/dist/views/extend.d.ts +2 -2
  563. package/dist/views/extend.js +11 -1
  564. package/dist/views/index.d.ts +2 -2
  565. package/dist/views/index.js +2 -2
  566. package/dist/views/types.d.ts +52 -5
  567. package/dist/views/validate.js +39 -1
  568. package/dist/website/.kosh/bindings.d.ts +22 -0
  569. package/dist/website/.kosh/bindings.js +15 -0
  570. package/dist/website/.kosh/schema.d.ts +881 -0
  571. package/dist/website/demo.d.ts +6 -0
  572. package/dist/website/demo.js +115 -0
  573. package/dist/website/index.d.ts +9 -0
  574. package/dist/website/index.js +251 -0
  575. package/dist/website/module.d.ts +2987 -0
  576. package/dist/website/module.js +282 -0
  577. package/dist/website/render.d.ts +45 -0
  578. package/dist/website/render.js +102 -0
  579. package/dist/website/routes.d.ts +12 -0
  580. package/dist/website/routes.js +246 -0
  581. package/dist/website/web/PagePreview.d.ts +7 -0
  582. package/dist/website/web/PagePreview.js +33 -0
  583. package/dist/website/web/index.d.ts +11 -0
  584. package/dist/website/web/index.js +16 -0
  585. package/dist/website/web/messages.d.ts +2 -0
  586. package/dist/website/web/messages.js +15 -0
  587. package/dist/website_crm/.kosh/bindings.d.ts +22 -0
  588. package/dist/website_crm/.kosh/bindings.js +15 -0
  589. package/dist/website_crm/.kosh/schema.d.ts +967 -0
  590. package/dist/website_crm/index.d.ts +3 -0
  591. package/dist/website_crm/index.js +39 -0
  592. package/dist/website_crm/module.d.ts +2956 -0
  593. package/dist/website_crm/module.js +44 -0
  594. package/dist/website_sale/.kosh/bindings.d.ts +22 -0
  595. package/dist/website_sale/.kosh/bindings.js +15 -0
  596. package/dist/website_sale/.kosh/schema.d.ts +2284 -0
  597. package/dist/website_sale/couriers.d.ts +50 -0
  598. package/dist/website_sale/couriers.js +59 -0
  599. package/dist/website_sale/demo.d.ts +7 -0
  600. package/dist/website_sale/demo.js +90 -0
  601. package/dist/website_sale/growth.d.ts +31 -0
  602. package/dist/website_sale/growth.js +163 -0
  603. package/dist/website_sale/index.d.ts +49 -0
  604. package/dist/website_sale/index.js +538 -0
  605. package/dist/website_sale/module.d.ts +22027 -0
  606. package/dist/website_sale/module.js +397 -0
  607. package/dist/website_sale/shipments.d.ts +16 -0
  608. package/dist/website_sale/shipments.js +113 -0
  609. package/dist/website_sale/shop.d.ts +81 -0
  610. package/dist/website_sale/shop.js +649 -0
  611. package/dist/website_sale_stock/.kosh/bindings.d.ts +22 -0
  612. package/dist/website_sale_stock/.kosh/bindings.js +15 -0
  613. package/dist/website_sale_stock/.kosh/schema.d.ts +2681 -0
  614. package/dist/website_sale_stock/index.d.ts +9 -0
  615. package/dist/website_sale_stock/index.js +20 -0
  616. package/dist/website_sale_stock/module.d.ts +24998 -0
  617. package/dist/website_sale_stock/module.js +28 -0
  618. package/package.json +200 -2
@@ -0,0 +1,474 @@
1
+ /**
2
+ * Sign's logic (RFC 0024 §2.8). Sending checks the template (its PDF, a signer for every role of its fields), keeps
3
+ * the PDF's hash and asks the signers — the first in order, or all at once — each by email with a link of their
4
+ * own. A signer asks for a one-time code by email (10 minutes, five tries), fills in their fields and signs (or
5
+ * refuses, with why); the next signer is then asked. Once the last one signed the PDF is sealed with pdf-lib: each
6
+ * value stamped where its field is, a certificate page added (who, their email and role, when, from which address,
7
+ * the hash of the PDF that was sent), and the result stored — on the request, in Documents (Signed documents), and on
8
+ * the record it was signed from — with its own hash.
9
+ */
10
+ import { createHash, randomBytes, randomInt } from 'node:crypto';
11
+ import { addVersion } from '../documents/index.js';
12
+ import { layout } from '../mail/index.js';
13
+ import { digest, HttpProblem } from '../server/index.js';
14
+ import { orm } from '../server/orm.js';
15
+ import { saveAttachment } from '../storage/index.js';
16
+ import { PDFDocument, rgb, StandardFonts } from 'pdf-lib';
17
+ const CODE_MINUTES = 10;
18
+ const MAX_TRIES = 5;
19
+ const MAX_IMAGE = 300 * 1024;
20
+ const PNG = 'data:image/png;base64,';
21
+ const invalid = (field, detail) => new HttpProblem(422, 'invalid-input', `Invalid ${field}`, detail);
22
+ const notFound = () => new HttpProblem(404, 'not-found', 'Not found', 'There is no signature waiting for this link.');
23
+ export const sha256 = (bytes) => createHash('sha256').update(bytes).digest('hex');
24
+ /** Bytes are digested with the link: a code is never valid for another signer. */
25
+ const codeDigest = (signer, code) => digest(`${signer}:${code}`);
26
+ let config = {
27
+ mailer: undefined,
28
+ apiUrl: 'http://localhost:3000',
29
+ storage: null,
30
+ };
31
+ export function configureSign(next) {
32
+ config = { ...config, ...next };
33
+ }
34
+ const storageNow = () => {
35
+ if (config.storage === null)
36
+ throw new HttpProblem(503, 'no-storage', 'File storage unavailable', 'Files are not set up.');
37
+ return config.storage();
38
+ };
39
+ function mail(env, to, subject, paragraphs, action) {
40
+ const mailer = config.mailer;
41
+ if (mailer === undefined)
42
+ return;
43
+ const body = layout({ title: subject, paragraphs, ...(action === undefined ? {} : { action }) });
44
+ env.afterCommit(async () => {
45
+ await mailer.send({ to, subject, html: body.html, text: body.text }).catch(() => undefined);
46
+ });
47
+ }
48
+ async function readAll(stream) {
49
+ const chunks = [];
50
+ for await (const chunk of stream)
51
+ chunks.push(Buffer.from(chunk));
52
+ return new Uint8Array(Buffer.concat(chunks));
53
+ }
54
+ const attachments = (env) => env.model('storage.attachment');
55
+ /** A template's PDF, as bytes. */
56
+ export async function templatePdf(env, template) {
57
+ const [t] = await env
58
+ .model('sign.template')
59
+ .browse([template])
60
+ .load({});
61
+ if (t?.attachment === null || t?.attachment === undefined)
62
+ throw invalid('template', 'The template has no PDF yet.');
63
+ const [a] = [...(await attachments(env).browse([t.attachment.id]).load(['key']))];
64
+ if (a === undefined)
65
+ throw invalid('template', 'The template’s PDF is missing.');
66
+ return readAll(await storageNow().read(a.key));
67
+ }
68
+ /** Stores a PDF as the template's (as the system, the template read by the caller): its page count follows. */
69
+ export async function setTemplatePdf(env, template, file) {
70
+ let pages;
71
+ try {
72
+ pages = (await PDFDocument.load(file.data)).getPageCount();
73
+ }
74
+ catch {
75
+ throw invalid('file', 'This is not a PDF that can be read.');
76
+ }
77
+ const saved = await saveAttachment(env, storageNow(), new Set(['sign.template']), {
78
+ model: 'sign.template',
79
+ id: template,
80
+ name: file.name,
81
+ mime: 'application/pdf',
82
+ data: file.data,
83
+ });
84
+ await env
85
+ .model('sign.template')
86
+ .browse([template])
87
+ .write({ attachment: saved.id, pages });
88
+ await env.flush();
89
+ return { pages };
90
+ }
91
+ /** Asks a signer: a new link of their own, by email. */
92
+ async function ask(env, signer) {
93
+ const [s] = await env
94
+ .model('sign.signer')
95
+ .browse([signer])
96
+ .load({ request: { company: true } });
97
+ if (s === undefined)
98
+ return;
99
+ const token = randomBytes(24).toString('base64url');
100
+ await env
101
+ .model('sign.signer')
102
+ .browse([s.id])
103
+ .write({ tokenHash: digest(token), state: 'sent', sentAt: new Date() });
104
+ const company = s.request.company.name ?? '';
105
+ mail(env, s.email, `${company} asks you to sign ${s.request.name}`, [
106
+ `${s.name}, ${company} asks you to sign ${s.request.name}${s.request.message === null ? '.' : `: ${s.request.message}`}`,
107
+ 'The link is yours alone; a code sent to this address confirms it is you.',
108
+ ], { label: 'Review and sign', url: `${config.apiUrl}/api/v1/public/sign/${token}` });
109
+ }
110
+ /**
111
+ * As requests are sent: the template has its PDF and a signer for every role of its fields; the PDF's hash is
112
+ * kept; the first signer (in order) or all of them are asked.
113
+ */
114
+ export async function beforeSend(env, ids) {
115
+ for (const r of await env
116
+ .model('sign.request')
117
+ .browse(ids)
118
+ .load({ template: { fields: true }, signers: true })) {
119
+ const roles = new Set([...r.template.fields].map((f) => f.role));
120
+ const signers = [...r.signers].sort((a, b) => a.sequence - b.sequence || a.id - b.id);
121
+ if (signers.length === 0)
122
+ throw invalid('signers', 'Add who signs.');
123
+ const missing = [...roles].filter((role) => !signers.some((s) => s.role === role));
124
+ if (missing.length > 0)
125
+ throw invalid('signers', `Nobody signs as ${missing.join(', ')}: add a signer for each role.`);
126
+ const pdf = await templatePdf(env, r.template.id);
127
+ await env
128
+ .model('sign.request')
129
+ .browse([r.id])
130
+ .write({ hashBefore: sha256(pdf) });
131
+ for (const s of r.ordered ? signers.slice(0, 1) : signers)
132
+ await ask(env, s.id);
133
+ }
134
+ }
135
+ /** The signer a link belongs to, while they are asked and the request is out for signature. */
136
+ export async function signerOf(env, token) {
137
+ if (token === '' || token.length > 100)
138
+ return null;
139
+ const [s] = await (await env
140
+ .model('sign.signer')
141
+ .search({ where: { tokenHash: digest(token), state: 'sent' }, limit: 1 })).load({ request: { template: { fields: true }, company: true } });
142
+ if (s === undefined || s.request.state !== 'sent')
143
+ return null;
144
+ return {
145
+ id: s.id,
146
+ name: s.name,
147
+ role: s.role,
148
+ request: {
149
+ id: s.request.id,
150
+ name: s.request.name,
151
+ company: s.request.company.name ?? '',
152
+ message: s.request.message,
153
+ },
154
+ fields: [...s.request.template.fields]
155
+ .filter((f) => f.role === s.role)
156
+ .map((f) => ({ id: f.id, kind: f.kind, label: f.label, page: f.page, required: f.required })),
157
+ };
158
+ }
159
+ /** A one-time code by email to the link's signer (a new one replaces the last). */
160
+ export async function sendCode(env, token) {
161
+ const s = await signerOf(env, token);
162
+ if (s === null)
163
+ throw notFound();
164
+ const code = String(randomInt(0, 1_000_000)).padStart(6, '0');
165
+ await env
166
+ .model('sign.signer')
167
+ .browse([s.id])
168
+ .write({
169
+ codeHash: codeDigest(s.id, code),
170
+ codeExpiresAt: new Date(Date.now() + CODE_MINUTES * 60_000),
171
+ codeAttempts: 0,
172
+ });
173
+ const [row] = await env
174
+ .model('sign.signer')
175
+ .browse([s.id])
176
+ .load({});
177
+ mail(env, row?.email ?? '', `Your code to sign ${s.request.name}: ${code}`, [
178
+ `Your code is ${code}. It works for ${CODE_MINUTES} minutes.`,
179
+ 'If you did not ask for it, ignore this email.',
180
+ ]);
181
+ await env.flush();
182
+ }
183
+ /** A wrong or expired code: counted (the count commits), then answered with 401 by the route. */
184
+ export class WrongCode extends Error {
185
+ }
186
+ /** Checks the code of the link's signer. @throws 429 after five wrong tries; {@link WrongCode} for a wrong one */
187
+ async function checkCode(env, signer, code) {
188
+ const [s] = await env
189
+ .model('sign.signer')
190
+ .browse([signer])
191
+ .load({});
192
+ if (s === undefined)
193
+ throw notFound();
194
+ if (s.codeAttempts >= MAX_TRIES)
195
+ throw new HttpProblem(429, 'too-many-tries', 'Too many tries', 'Ask for a new code.');
196
+ const ok = s.codeHash !== null &&
197
+ s.codeExpiresAt !== null &&
198
+ s.codeExpiresAt.getTime() > Date.now() &&
199
+ s.codeHash === codeDigest(s.id, code.trim());
200
+ if (!ok) {
201
+ await env
202
+ .model('sign.signer')
203
+ .browse([s.id])
204
+ .write({ codeAttempts: s.codeAttempts + 1 });
205
+ await env.flush();
206
+ throw new WrongCode();
207
+ }
208
+ }
209
+ /** Checks what a signer filled in against their fields; the date is the server's. */
210
+ function cleanValues(fields, values, today) {
211
+ const out = {};
212
+ for (const f of fields) {
213
+ const raw = values[String(f.id)];
214
+ const what = f.label ?? f.kind;
215
+ if (f.kind === 'date') {
216
+ out[String(f.id)] = today;
217
+ continue;
218
+ }
219
+ if (f.kind === 'checkbox') {
220
+ if (raw !== undefined && typeof raw !== 'boolean')
221
+ throw invalid(what, 'is ticked or not.');
222
+ if (f.required && raw !== true)
223
+ throw invalid(what, 'must be ticked.');
224
+ out[String(f.id)] = raw === true;
225
+ continue;
226
+ }
227
+ if (raw === undefined || raw === null || raw === '') {
228
+ if (f.required)
229
+ throw invalid(what, 'is required.');
230
+ continue;
231
+ }
232
+ if (typeof raw !== 'string')
233
+ throw invalid(what, 'is text or a drawn signature.');
234
+ if (f.kind === 'signature' || f.kind === 'initials') {
235
+ if (!raw.startsWith(PNG) || raw.length > (MAX_IMAGE * 4) / 3 + PNG.length)
236
+ throw invalid(what, 'is a drawn signature (a PNG of up to 300 KB).');
237
+ }
238
+ else if (raw.length > 200)
239
+ throw invalid(what, 'is at most 200 characters.');
240
+ out[String(f.id)] = raw;
241
+ }
242
+ return out;
243
+ }
244
+ /**
245
+ * Signs for the link's signer with their code: their values kept with when and from where; the next signer asked
246
+ * (in order), or — the last — the PDF sealed and the request completed.
247
+ */
248
+ export async function signWith(env, token, input) {
249
+ const s = await signerOf(env, token);
250
+ if (s === null)
251
+ throw notFound();
252
+ await checkCode(env, s.id, input.code);
253
+ const values = cleanValues(s.fields, input.values, env.today());
254
+ await env
255
+ .model('sign.signer')
256
+ .browse([s.id])
257
+ .write({
258
+ values,
259
+ state: 'signed',
260
+ signedAt: new Date(),
261
+ ip: input.ip.slice(0, 64),
262
+ userAgent: input.userAgent.slice(0, 200),
263
+ tokenHash: null,
264
+ codeHash: null,
265
+ });
266
+ await env.flush();
267
+ const [r] = await env
268
+ .model('sign.request')
269
+ .browse([s.request.id])
270
+ .load({ signers: true });
271
+ if (r === undefined)
272
+ throw notFound();
273
+ const waiting = [...r.signers]
274
+ .filter((x) => x.state === 'waiting')
275
+ .sort((a, b) => a.sequence - b.sequence || a.id - b.id);
276
+ if ([...r.signers].every((x) => x.state === 'signed')) {
277
+ await seal(env, r.id);
278
+ return { completed: true };
279
+ }
280
+ if (r.ordered && waiting[0] !== undefined)
281
+ await ask(env, waiting[0].id);
282
+ await env.flush();
283
+ return { completed: false };
284
+ }
285
+ /** Refuses for the link's signer, with their code and why: the request is refused, the others told. */
286
+ export async function refuseWith(env, token, input) {
287
+ const s = await signerOf(env, token);
288
+ if (s === null)
289
+ throw notFound();
290
+ await checkCode(env, s.id, input.code);
291
+ const reason = input.reason.trim().slice(0, 1000);
292
+ if (reason === '')
293
+ throw invalid('reason', 'Say why you refuse.');
294
+ await env
295
+ .model('sign.signer')
296
+ .browse([s.id])
297
+ .write({ state: 'refused', tokenHash: null, codeHash: null });
298
+ const request = env.model('sign.request').browse([s.request.id]);
299
+ await request.write({ refusal: `${s.name}: ${reason}` });
300
+ await request.refuse();
301
+ for (const other of await (await env.model('sign.signer').search({ where: { request: s.request.id } })).load({}))
302
+ if (other.id !== s.id && other.state === 'sent')
303
+ await env
304
+ .model('sign.signer')
305
+ .browse([other.id])
306
+ .write({ state: 'waiting', tokenHash: null });
307
+ await env.flush();
308
+ }
309
+ /** Where a field goes on its page, in PDF units (origin bottom-left). */
310
+ const place = (page, f) => {
311
+ const W = page.getWidth();
312
+ const H = page.getHeight();
313
+ const w = f.width.toNumber() * W;
314
+ const h = f.height.toNumber() * H;
315
+ return { x: f.x.toNumber() * W, y: H - f.y.toNumber() * H - h, w, h };
316
+ };
317
+ /** Seals a completed request: the values stamped, the certificate page added, the result stored three times. */
318
+ async function seal(env, id) {
319
+ const [r] = await env
320
+ .model('sign.request')
321
+ .browse([id])
322
+ .load({ template: { fields: true }, signers: true, company: true });
323
+ if (r === undefined)
324
+ return;
325
+ const source = await templatePdf(env, r.template.id);
326
+ const pdf = await PDFDocument.load(source);
327
+ const font = await pdf.embedFont(StandardFonts.Helvetica);
328
+ const bold = await pdf.embedFont(StandardFonts.HelveticaBold);
329
+ const signers = [...r.signers].sort((a, b) => a.sequence - b.sequence || a.id - b.id);
330
+ for (const s of signers) {
331
+ const values = (s.values ?? {});
332
+ for (const f of [...r.template.fields].filter((x) => x.role === s.role)) {
333
+ const value = values[String(f.id)];
334
+ if (value === undefined || value === false || f.page > pdf.getPageCount())
335
+ continue;
336
+ const page = pdf.getPage(f.page - 1);
337
+ const at = place(page, f);
338
+ if ((f.kind === 'signature' || f.kind === 'initials') && typeof value === 'string') {
339
+ const image = await pdf.embedPng(Buffer.from(value.slice(PNG.length), 'base64'));
340
+ const scale = Math.min(at.w / image.width, at.h / image.height);
341
+ page.drawImage(image, {
342
+ x: at.x,
343
+ y: at.y,
344
+ width: image.width * scale,
345
+ height: image.height * scale,
346
+ });
347
+ }
348
+ else {
349
+ const text = value === true ? 'X' : String(value);
350
+ const size = Math.max(6, Math.min(at.h * 0.7, 14));
351
+ page.drawText(text.replace(/[^\x20-\x7e]/g, '?'), {
352
+ x: at.x + 2,
353
+ y: at.y + at.h * 0.25,
354
+ size,
355
+ font,
356
+ });
357
+ }
358
+ }
359
+ }
360
+ // The certificate: who signed, when, from where, and the hash of what was sent.
361
+ const cert = pdf.addPage();
362
+ const line = (text, y, size = 10, f = font) => cert.drawText(text.replace(/[^\x20-\x7e]/g, '?'), {
363
+ x: 50,
364
+ y,
365
+ size,
366
+ font: f,
367
+ color: rgb(0.1, 0.1, 0.1),
368
+ });
369
+ let y = cert.getHeight() - 60;
370
+ line('Certificate of signature', y, 16, bold);
371
+ y -= 26;
372
+ line(`Document: ${r.name}`, y);
373
+ y -= 16;
374
+ line(`Company: ${r.company.name ?? ''}`, y);
375
+ y -= 16;
376
+ line(`SHA-256 of the document sent: ${r.hashBefore ?? ''}`, y, 8);
377
+ y -= 24;
378
+ for (const s of signers) {
379
+ line(`${s.name} <${s.email}> — ${s.role}`, y, 11, bold);
380
+ y -= 15;
381
+ line(`Signed at ${s.signedAt?.toISOString() ?? ''} from ${s.ip ?? 'unknown'}`, y);
382
+ y -= 13;
383
+ line(`Confirmed with a one-time code sent to ${s.email}`, y, 9);
384
+ y -= 22;
385
+ }
386
+ const bytes = await pdf.save();
387
+ const hashAfter = sha256(bytes);
388
+ const name = `${r.name} (signed).pdf`;
389
+ const storage = storageNow();
390
+ const saved = await saveAttachment(env, storage, new Set(['sign.request']), {
391
+ model: 'sign.request',
392
+ id: r.id,
393
+ name,
394
+ mime: 'application/pdf',
395
+ data: bytes,
396
+ });
397
+ // In Documents, in Signed documents.
398
+ const [folder] = (await env.model('documents.folder').search({
399
+ where: { name: 'Signed documents', company: r.company.id },
400
+ limit: 1,
401
+ })).ids;
402
+ const folderId = folder ??
403
+ (await env
404
+ .model('documents.folder')
405
+ .create([{ name: 'Signed documents', company: r.company.id, owner: null }])).ids[0];
406
+ const doc = await env.model('documents.document').create([
407
+ {
408
+ name,
409
+ folder: folderId,
410
+ company: r.company.id,
411
+ owner: null,
412
+ ...(r.resModel === null ? {} : { resModel: r.resModel, resId: r.resId }),
413
+ },
414
+ ]);
415
+ await env.flush();
416
+ await addVersion(env, storage, doc.ids[0], {
417
+ name,
418
+ mime: 'application/pdf',
419
+ data: bytes,
420
+ });
421
+ // On the record it was signed from.
422
+ if (r.resModel !== null && r.resId !== null)
423
+ await saveAttachment(env, storage, new Set([r.resModel]), {
424
+ model: r.resModel,
425
+ id: r.resId,
426
+ name,
427
+ mime: 'application/pdf',
428
+ data: bytes,
429
+ }).catch(() => undefined);
430
+ const request = env.model('sign.request').browse([r.id]);
431
+ await request.write({
432
+ sealed: saved.id,
433
+ document: doc.ids[0],
434
+ hashAfter,
435
+ completedAt: new Date(),
436
+ });
437
+ await request.complete();
438
+ for (const s of signers)
439
+ mail(env, s.email, `${r.name} is signed`, [
440
+ `${r.name} is signed by everyone. ${r.company.name ?? ''} keeps the signed copy.`,
441
+ `Its SHA-256: ${hashAfter}.`,
442
+ ]);
443
+ await env.flush();
444
+ }
445
+ /** Makes a request from a template for a record (or none), with its signers; a draft, to send. */
446
+ export async function requestFrom(env, input) {
447
+ const [t] = await (await env
448
+ .model('sign.template')
449
+ .search({ where: { id: orm.asId(input.template, 'sign.template') }, limit: 1 })).load({});
450
+ if (t === undefined)
451
+ throw invalid('template', 'Choose a template.');
452
+ if (input.signers.length === 0 || input.signers.length > 20)
453
+ throw invalid('signers', 'From 1 to 20 signers.');
454
+ const made = await env.model('sign.request').create([
455
+ {
456
+ name: input.name ?? t.name,
457
+ template: t.id,
458
+ ordered: input.ordered ?? true,
459
+ message: input.message ?? null,
460
+ ...(input.model === undefined ? {} : { resModel: input.model, resId: input.id ?? null }),
461
+ signers: {
462
+ create: input.signers.map((s, i) => ({
463
+ role: s.role,
464
+ name: s.name,
465
+ email: s.email,
466
+ partner: s.partner ?? null,
467
+ sequence: (i + 1) * 10,
468
+ })),
469
+ },
470
+ },
471
+ ]);
472
+ await env.flush();
473
+ return made.ids[0];
474
+ }
@@ -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'];
@@ -0,0 +1,15 @@
1
+ // GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash: 96342905ee009545
2
+ // Bindings of module `stock`: import the definition API from here to get types scoped to what it can see.
3
+ export { defineModel, defineModule, extendModel, f, replace } from '../../server/orm.js';
4
+ import { definitions } from '../../server/orm.js';
5
+ /** Definition callbacks typed against this module's view: no casts in computes, checks, onchange, methods. */
6
+ const helpers = definitions();
7
+ export const compute = helpers.compute;
8
+ export const check = helpers.check;
9
+ export const onchange = helpers.onchange;
10
+ export const records = helpers.records;
11
+ export const method = helpers.method;
12
+ /** Module data (RFC 0017): records, overrides of dependencies' records, and references, typed like creates. */
13
+ export const record = helpers.record;
14
+ export const override = helpers.override;
15
+ export const ref = helpers.ref;