@ketvietlab/ketsuite 0.1.2 → 0.1.3

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 (2590) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +15 -1
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +59 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/deployment.d.ts +5 -0
  8. package/dist/deployment.d.ts.map +1 -0
  9. package/dist/deployment.js +152 -0
  10. package/dist/deployment.js.map +1 -0
  11. package/dist/development.d.ts +8 -0
  12. package/dist/development.d.ts.map +1 -0
  13. package/dist/development.js +40 -0
  14. package/dist/development.js.map +1 -0
  15. package/dist/index.d.ts +77 -6
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +66 -6
  18. package/dist/index.js.map +1 -1
  19. package/dist/modules/account/analytics.d.ts +32 -0
  20. package/dist/modules/account/analytics.d.ts.map +1 -0
  21. package/dist/modules/account/analytics.js +457 -0
  22. package/dist/modules/account/analytics.js.map +1 -0
  23. package/dist/modules/account/assets-costing.d.ts +4 -0
  24. package/dist/modules/account/assets-costing.d.ts.map +1 -0
  25. package/dist/modules/account/assets-costing.js +1134 -0
  26. package/dist/modules/account/assets-costing.js.map +1 -0
  27. package/dist/modules/account/audit.d.ts +3 -0
  28. package/dist/modules/account/audit.d.ts.map +1 -0
  29. package/dist/modules/account/audit.js +14 -0
  30. package/dist/modules/account/audit.js.map +1 -0
  31. package/dist/modules/account/books.d.ts +4 -0
  32. package/dist/modules/account/books.d.ts.map +1 -0
  33. package/dist/modules/account/books.js +150 -0
  34. package/dist/modules/account/books.js.map +1 -0
  35. package/dist/modules/account/cash-receivables.d.ts +3 -0
  36. package/dist/modules/account/cash-receivables.d.ts.map +1 -0
  37. package/dist/modules/account/cash-receivables.js +1087 -0
  38. package/dist/modules/account/cash-receivables.js.map +1 -0
  39. package/dist/modules/account/close.d.ts +4 -0
  40. package/dist/modules/account/close.d.ts.map +1 -0
  41. package/dist/modules/account/close.js +343 -0
  42. package/dist/modules/account/close.js.map +1 -0
  43. package/dist/modules/account/date.d.ts +21 -0
  44. package/dist/modules/account/date.d.ts.map +1 -0
  45. package/dist/modules/account/date.js +70 -0
  46. package/dist/modules/account/date.js.map +1 -0
  47. package/dist/modules/account/functions.d.ts +131 -3
  48. package/dist/modules/account/functions.d.ts.map +1 -1
  49. package/dist/modules/account/functions.js +2570 -389
  50. package/dist/modules/account/functions.js.map +1 -1
  51. package/dist/modules/account/index.d.ts +1 -2
  52. package/dist/modules/account/index.d.ts.map +1 -1
  53. package/dist/modules/account/index.js +403 -8
  54. package/dist/modules/account/index.js.map +1 -1
  55. package/dist/modules/account/models.d.ts.map +1 -1
  56. package/dist/modules/account/models.js +748 -0
  57. package/dist/modules/account/models.js.map +1 -1
  58. package/dist/modules/account/money.d.ts +60 -0
  59. package/dist/modules/account/money.d.ts.map +1 -0
  60. package/dist/modules/account/money.js +237 -0
  61. package/dist/modules/account/money.js.map +1 -0
  62. package/dist/modules/account/open-items.d.ts +3 -0
  63. package/dist/modules/account/open-items.d.ts.map +1 -0
  64. package/dist/modules/account/open-items.js +390 -0
  65. package/dist/modules/account/open-items.js.map +1 -0
  66. package/dist/modules/account/opening.d.ts +3 -0
  67. package/dist/modules/account/opening.d.ts.map +1 -0
  68. package/dist/modules/account/opening.js +323 -0
  69. package/dist/modules/account/opening.js.map +1 -0
  70. package/dist/modules/account/period.d.ts +21 -0
  71. package/dist/modules/account/period.d.ts.map +1 -0
  72. package/dist/modules/account/period.js +155 -0
  73. package/dist/modules/account/period.js.map +1 -0
  74. package/dist/modules/account/relations.d.ts.map +1 -1
  75. package/dist/modules/account/relations.js +46 -0
  76. package/dist/modules/account/relations.js.map +1 -1
  77. package/dist/modules/account/reports.d.ts +4 -0
  78. package/dist/modules/account/reports.d.ts.map +1 -0
  79. package/dist/modules/account/reports.js +125 -0
  80. package/dist/modules/account/reports.js.map +1 -0
  81. package/dist/modules/account/setup.d.ts +3 -1
  82. package/dist/modules/account/setup.d.ts.map +1 -1
  83. package/dist/modules/account/setup.js +45 -160
  84. package/dist/modules/account/setup.js.map +1 -1
  85. package/dist/modules/account_activity_backend/index.d.ts.map +1 -1
  86. package/dist/modules/account_activity_backend/index.js +0 -1
  87. package/dist/modules/account_activity_backend/index.js.map +1 -1
  88. package/dist/modules/account_backend/index.js +3339 -494
  89. package/dist/modules/account_backend/index.js.map +1 -1
  90. package/dist/modules/account_backend/overview.d.ts +92 -0
  91. package/dist/modules/account_backend/overview.d.ts.map +1 -0
  92. package/dist/modules/account_backend/overview.js +257 -0
  93. package/dist/modules/account_backend/overview.js.map +1 -0
  94. package/dist/modules/account_backend/relation-control.d.ts +48 -0
  95. package/dist/modules/account_backend/relation-control.d.ts.map +1 -0
  96. package/dist/modules/account_backend/relation-control.js +67 -0
  97. package/dist/modules/account_backend/relation-control.js.map +1 -0
  98. package/dist/modules/account_backend/screens/account-defaults.d.ts +28 -0
  99. package/dist/modules/account_backend/screens/account-defaults.d.ts.map +1 -0
  100. package/dist/modules/account_backend/screens/account-defaults.js +60 -0
  101. package/dist/modules/account_backend/screens/account-defaults.js.map +1 -0
  102. package/dist/modules/account_backend/screens/account-form.d.ts +16 -0
  103. package/dist/modules/account_backend/screens/account-form.d.ts.map +1 -0
  104. package/dist/modules/account_backend/screens/account-form.js +53 -0
  105. package/dist/modules/account_backend/screens/account-form.js.map +1 -0
  106. package/dist/modules/account_backend/screens/accounting-books.d.ts +15 -0
  107. package/dist/modules/account_backend/screens/accounting-books.d.ts.map +1 -0
  108. package/dist/modules/account_backend/screens/accounting-books.js +86 -0
  109. package/dist/modules/account_backend/screens/accounting-books.js.map +1 -0
  110. package/dist/modules/account_backend/screens/accounts-list.d.ts +50 -0
  111. package/dist/modules/account_backend/screens/accounts-list.d.ts.map +1 -0
  112. package/dist/modules/account_backend/screens/accounts-list.js +66 -0
  113. package/dist/modules/account_backend/screens/accounts-list.js.map +1 -0
  114. package/dist/modules/account_backend/screens/customer-invoice-form.d.ts +13 -0
  115. package/dist/modules/account_backend/screens/customer-invoice-form.d.ts.map +1 -0
  116. package/dist/modules/account_backend/screens/customer-invoice-form.js +20 -0
  117. package/dist/modules/account_backend/screens/customer-invoice-form.js.map +1 -0
  118. package/dist/modules/account_backend/screens/customer-invoices-list.d.ts +62 -0
  119. package/dist/modules/account_backend/screens/customer-invoices-list.d.ts.map +1 -0
  120. package/dist/modules/account_backend/screens/customer-invoices-list.js +82 -0
  121. package/dist/modules/account_backend/screens/customer-invoices-list.js.map +1 -0
  122. package/dist/modules/account_backend/screens/general-ledger.d.ts +24 -0
  123. package/dist/modules/account_backend/screens/general-ledger.d.ts.map +1 -0
  124. package/dist/modules/account_backend/screens/general-ledger.js +73 -0
  125. package/dist/modules/account_backend/screens/general-ledger.js.map +1 -0
  126. package/dist/modules/account_backend/screens/index.d.ts +27 -0
  127. package/dist/modules/account_backend/screens/index.d.ts.map +1 -0
  128. package/dist/modules/account_backend/screens/index.js +27 -0
  129. package/dist/modules/account_backend/screens/index.js.map +1 -0
  130. package/dist/modules/account_backend/screens/journal-entries-list.d.ts +48 -0
  131. package/dist/modules/account_backend/screens/journal-entries-list.d.ts.map +1 -0
  132. package/dist/modules/account_backend/screens/journal-entries-list.js +58 -0
  133. package/dist/modules/account_backend/screens/journal-entries-list.js.map +1 -0
  134. package/dist/modules/account_backend/screens/journal-entry-create.d.ts +14 -0
  135. package/dist/modules/account_backend/screens/journal-entry-create.d.ts.map +1 -0
  136. package/dist/modules/account_backend/screens/journal-entry-create.js +41 -0
  137. package/dist/modules/account_backend/screens/journal-entry-create.js.map +1 -0
  138. package/dist/modules/account_backend/screens/journal-form.d.ts +15 -0
  139. package/dist/modules/account_backend/screens/journal-form.d.ts.map +1 -0
  140. package/dist/modules/account_backend/screens/journal-form.js +53 -0
  141. package/dist/modules/account_backend/screens/journal-form.js.map +1 -0
  142. package/dist/modules/account_backend/screens/journals-list.d.ts +51 -0
  143. package/dist/modules/account_backend/screens/journals-list.d.ts.map +1 -0
  144. package/dist/modules/account_backend/screens/journals-list.js +70 -0
  145. package/dist/modules/account_backend/screens/journals-list.js.map +1 -0
  146. package/dist/modules/account_backend/screens/move-detail.d.ts +26 -0
  147. package/dist/modules/account_backend/screens/move-detail.d.ts.map +1 -0
  148. package/dist/modules/account_backend/screens/move-detail.js +130 -0
  149. package/dist/modules/account_backend/screens/move-detail.js.map +1 -0
  150. package/dist/modules/account_backend/screens/opening-balances.d.ts +28 -0
  151. package/dist/modules/account_backend/screens/opening-balances.d.ts.map +1 -0
  152. package/dist/modules/account_backend/screens/opening-balances.js +96 -0
  153. package/dist/modules/account_backend/screens/opening-balances.js.map +1 -0
  154. package/dist/modules/account_backend/screens/overview.d.ts +62 -0
  155. package/dist/modules/account_backend/screens/overview.d.ts.map +1 -0
  156. package/dist/modules/account_backend/screens/overview.js +215 -0
  157. package/dist/modules/account_backend/screens/overview.js.map +1 -0
  158. package/dist/modules/account_backend/screens/partner-statement.d.ts +26 -0
  159. package/dist/modules/account_backend/screens/partner-statement.d.ts.map +1 -0
  160. package/dist/modules/account_backend/screens/partner-statement.js +82 -0
  161. package/dist/modules/account_backend/screens/partner-statement.js.map +1 -0
  162. package/dist/modules/account_backend/screens/payment-form.d.ts +14 -0
  163. package/dist/modules/account_backend/screens/payment-form.d.ts.map +1 -0
  164. package/dist/modules/account_backend/screens/payment-form.js +21 -0
  165. package/dist/modules/account_backend/screens/payment-form.js.map +1 -0
  166. package/dist/modules/account_backend/screens/payment-term-form.d.ts +25 -0
  167. package/dist/modules/account_backend/screens/payment-term-form.d.ts.map +1 -0
  168. package/dist/modules/account_backend/screens/payment-term-form.js +96 -0
  169. package/dist/modules/account_backend/screens/payment-term-form.js.map +1 -0
  170. package/dist/modules/account_backend/screens/payment-terms-list.d.ts +23 -0
  171. package/dist/modules/account_backend/screens/payment-terms-list.d.ts.map +1 -0
  172. package/dist/modules/account_backend/screens/payment-terms-list.js +104 -0
  173. package/dist/modules/account_backend/screens/payment-terms-list.js.map +1 -0
  174. package/dist/modules/account_backend/screens/payments-list.d.ts +62 -0
  175. package/dist/modules/account_backend/screens/payments-list.d.ts.map +1 -0
  176. package/dist/modules/account_backend/screens/payments-list.js +71 -0
  177. package/dist/modules/account_backend/screens/payments-list.js.map +1 -0
  178. package/dist/modules/account_backend/screens/period-closes.d.ts +21 -0
  179. package/dist/modules/account_backend/screens/period-closes.d.ts.map +1 -0
  180. package/dist/modules/account_backend/screens/period-closes.js +123 -0
  181. package/dist/modules/account_backend/screens/period-closes.js.map +1 -0
  182. package/dist/modules/account_backend/screens/shared.d.ts +16 -0
  183. package/dist/modules/account_backend/screens/shared.d.ts.map +1 -0
  184. package/dist/modules/account_backend/screens/shared.js +15 -0
  185. package/dist/modules/account_backend/screens/shared.js.map +1 -0
  186. package/dist/modules/account_backend/screens/tax-form.d.ts +14 -0
  187. package/dist/modules/account_backend/screens/tax-form.d.ts.map +1 -0
  188. package/dist/modules/account_backend/screens/tax-form.js +25 -0
  189. package/dist/modules/account_backend/screens/tax-form.js.map +1 -0
  190. package/dist/modules/account_backend/screens/taxes-list.d.ts +55 -0
  191. package/dist/modules/account_backend/screens/taxes-list.d.ts.map +1 -0
  192. package/dist/modules/account_backend/screens/taxes-list.js +83 -0
  193. package/dist/modules/account_backend/screens/taxes-list.js.map +1 -0
  194. package/dist/modules/account_backend/screens/trial-balance.d.ts +19 -0
  195. package/dist/modules/account_backend/screens/trial-balance.d.ts.map +1 -0
  196. package/dist/modules/account_backend/screens/trial-balance.js +75 -0
  197. package/dist/modules/account_backend/screens/trial-balance.js.map +1 -0
  198. package/dist/modules/account_backend/screens/vendor-bill-form.d.ts +13 -0
  199. package/dist/modules/account_backend/screens/vendor-bill-form.d.ts.map +1 -0
  200. package/dist/modules/account_backend/screens/vendor-bill-form.js +20 -0
  201. package/dist/modules/account_backend/screens/vendor-bill-form.js.map +1 -0
  202. package/dist/modules/account_backend/screens/vendor-bills-list.d.ts +62 -0
  203. package/dist/modules/account_backend/screens/vendor-bills-list.d.ts.map +1 -0
  204. package/dist/modules/account_backend/screens/vendor-bills-list.js +84 -0
  205. package/dist/modules/account_backend/screens/vendor-bills-list.js.map +1 -0
  206. package/dist/modules/account_mail_backend/index.d.ts.map +1 -1
  207. package/dist/modules/account_mail_backend/index.js +0 -1
  208. package/dist/modules/account_mail_backend/index.js.map +1 -1
  209. package/dist/modules/account_partner/index.js +0 -2
  210. package/dist/modules/account_partner/index.js.map +1 -1
  211. package/dist/modules/account_partner_backend/index.d.ts +1 -1
  212. package/dist/modules/account_partner_backend/index.d.ts.map +1 -1
  213. package/dist/modules/account_partner_backend/index.js +2 -3
  214. package/dist/modules/account_partner_backend/index.js.map +1 -1
  215. package/dist/modules/account_partner_backend/routes.d.ts.map +1 -1
  216. package/dist/modules/account_partner_backend/routes.js +19 -25
  217. package/dist/modules/account_partner_backend/routes.js.map +1 -1
  218. package/dist/modules/account_partner_backend/screens/accounting-terms.d.ts +20 -0
  219. package/dist/modules/account_partner_backend/screens/accounting-terms.d.ts.map +1 -0
  220. package/dist/modules/account_partner_backend/screens/accounting-terms.js +63 -0
  221. package/dist/modules/account_partner_backend/screens/accounting-terms.js.map +1 -0
  222. package/dist/modules/account_partner_backend/screens/index.d.ts +2 -0
  223. package/dist/modules/account_partner_backend/screens/index.d.ts.map +1 -0
  224. package/dist/modules/account_partner_backend/screens/index.js +2 -0
  225. package/dist/modules/account_partner_backend/screens/index.js.map +1 -0
  226. package/dist/modules/account_staff_channel/channel-routes.d.ts +2 -0
  227. package/dist/modules/account_staff_channel/channel-routes.d.ts.map +1 -0
  228. package/dist/modules/account_staff_channel/channel-routes.js +787 -0
  229. package/dist/modules/account_staff_channel/channel-routes.js.map +1 -0
  230. package/dist/modules/account_staff_channel/functions.d.ts.map +1 -0
  231. package/dist/modules/account_staff_channel/functions.js +143 -0
  232. package/dist/modules/account_staff_channel/functions.js.map +1 -0
  233. package/dist/modules/account_staff_channel/index.d.ts +5 -0
  234. package/dist/modules/account_staff_channel/index.d.ts.map +1 -0
  235. package/dist/modules/account_staff_channel/index.js +42 -0
  236. package/dist/modules/account_staff_channel/index.js.map +1 -0
  237. package/dist/modules/account_staff_channel/models.d.ts.map +1 -0
  238. package/dist/modules/account_staff_channel/models.js +30 -0
  239. package/dist/modules/account_staff_channel/models.js.map +1 -0
  240. package/dist/modules/activity/index.d.ts.map +1 -1
  241. package/dist/modules/activity/index.js +0 -1
  242. package/dist/modules/activity/index.js.map +1 -1
  243. package/dist/modules/activity_backend/index.d.ts +1 -1
  244. package/dist/modules/activity_backend/index.d.ts.map +1 -1
  245. package/dist/modules/activity_backend/index.js +3 -12
  246. package/dist/modules/activity_backend/index.js.map +1 -1
  247. package/dist/modules/activity_backend/routes.d.ts.map +1 -1
  248. package/dist/modules/activity_backend/routes.js +36 -22
  249. package/dist/modules/activity_backend/routes.js.map +1 -1
  250. package/dist/modules/activity_backend/screens/activities-list.d.ts +15 -0
  251. package/dist/modules/activity_backend/screens/activities-list.d.ts.map +1 -0
  252. package/dist/modules/activity_backend/screens/activities-list.js +40 -0
  253. package/dist/modules/activity_backend/screens/activities-list.js.map +1 -0
  254. package/dist/modules/activity_backend/screens/index.d.ts +2 -0
  255. package/dist/modules/activity_backend/screens/index.d.ts.map +1 -0
  256. package/dist/modules/activity_backend/screens/index.js +2 -0
  257. package/dist/modules/activity_backend/screens/index.js.map +1 -0
  258. package/dist/modules/address/data/VN/NOTICE.md +1 -1
  259. package/dist/modules/address/index.d.ts.map +1 -1
  260. package/dist/modules/address/index.js +0 -1
  261. package/dist/modules/address/index.js.map +1 -1
  262. package/dist/modules/address_backend/index.d.ts +1 -1
  263. package/dist/modules/address_backend/index.d.ts.map +1 -1
  264. package/dist/modules/address_backend/index.js +1 -3
  265. package/dist/modules/address_backend/index.js.map +1 -1
  266. package/dist/modules/address_backend/routes.d.ts.map +1 -1
  267. package/dist/modules/address_backend/routes.js +20 -27
  268. package/dist/modules/address_backend/routes.js.map +1 -1
  269. package/dist/modules/address_backend/screens/catalogs-list.d.ts +14 -0
  270. package/dist/modules/address_backend/screens/catalogs-list.d.ts.map +1 -0
  271. package/dist/modules/address_backend/screens/catalogs-list.js +38 -0
  272. package/dist/modules/address_backend/screens/catalogs-list.js.map +1 -0
  273. package/dist/modules/address_backend/screens/country-browser.d.ts +12 -0
  274. package/dist/modules/address_backend/screens/country-browser.d.ts.map +1 -0
  275. package/dist/modules/address_backend/screens/country-browser.js +74 -0
  276. package/dist/modules/address_backend/screens/country-browser.js.map +1 -0
  277. package/dist/modules/address_backend/screens/index.d.ts +4 -0
  278. package/dist/modules/address_backend/screens/index.d.ts.map +1 -0
  279. package/dist/modules/address_backend/screens/index.js +3 -0
  280. package/dist/modules/address_backend/screens/index.js.map +1 -0
  281. package/dist/modules/address_backend/screens/types.d.ts +20 -0
  282. package/dist/modules/address_backend/screens/types.d.ts.map +1 -0
  283. package/dist/modules/address_backend/screens/types.js.map +1 -0
  284. package/dist/modules/attendance/channel-routes.d.ts +2 -0
  285. package/dist/modules/attendance/channel-routes.d.ts.map +1 -0
  286. package/dist/modules/attendance/channel-routes.js +234 -0
  287. package/dist/modules/attendance/channel-routes.js.map +1 -0
  288. package/dist/modules/attendance/functions.d.ts.map +1 -1
  289. package/dist/modules/attendance/functions.js +171 -22
  290. package/dist/modules/attendance/functions.js.map +1 -1
  291. package/dist/modules/attendance/index.d.ts.map +1 -1
  292. package/dist/modules/attendance/index.js +4 -2
  293. package/dist/modules/attendance/index.js.map +1 -1
  294. package/dist/modules/attendance/messages.d.ts +6 -0
  295. package/dist/modules/attendance/messages.d.ts.map +1 -1
  296. package/dist/modules/attendance/messages.js +6 -0
  297. package/dist/modules/attendance/messages.js.map +1 -1
  298. package/dist/modules/attendance/models.d.ts.map +1 -1
  299. package/dist/modules/attendance/models.js +1 -0
  300. package/dist/modules/attendance/models.js.map +1 -1
  301. package/dist/modules/attendance_backend/index.d.ts +3 -1
  302. package/dist/modules/attendance_backend/index.d.ts.map +1 -1
  303. package/dist/modules/attendance_backend/index.js +65 -4
  304. package/dist/modules/attendance_backend/index.js.map +1 -1
  305. package/dist/modules/attendance_backend/routes.d.ts.map +1 -1
  306. package/dist/modules/attendance_backend/routes.js +240 -53
  307. package/dist/modules/attendance_backend/routes.js.map +1 -1
  308. package/dist/modules/attendance_backend/screens/credentials.d.ts +32 -0
  309. package/dist/modules/attendance_backend/screens/credentials.d.ts.map +1 -0
  310. package/dist/modules/attendance_backend/screens/credentials.js +84 -0
  311. package/dist/modules/attendance_backend/screens/credentials.js.map +1 -0
  312. package/dist/modules/attendance_backend/screens/index.d.ts +4 -0
  313. package/dist/modules/attendance_backend/screens/index.d.ts.map +1 -0
  314. package/dist/modules/attendance_backend/screens/index.js +4 -0
  315. package/dist/modules/attendance_backend/screens/index.js.map +1 -0
  316. package/dist/modules/attendance_backend/screens/my-work.d.ts +35 -0
  317. package/dist/modules/attendance_backend/screens/my-work.d.ts.map +1 -0
  318. package/dist/modules/attendance_backend/screens/my-work.js +189 -0
  319. package/dist/modules/attendance_backend/screens/my-work.js.map +1 -0
  320. package/dist/modules/attendance_backend/screens/period.d.ts +22 -0
  321. package/dist/modules/attendance_backend/screens/period.d.ts.map +1 -0
  322. package/dist/modules/attendance_backend/screens/period.js +85 -0
  323. package/dist/modules/attendance_backend/screens/period.js.map +1 -0
  324. package/dist/modules/attendance_backend/screens.d.ts +0 -4
  325. package/dist/modules/attendance_backend/screens.d.ts.map +1 -1
  326. package/dist/modules/attendance_backend/screens.js +1 -209
  327. package/dist/modules/attendance_backend/screens.js.map +1 -1
  328. package/dist/modules/backend/catalogue.d.ts.map +1 -1
  329. package/dist/modules/backend/catalogue.js +53 -115
  330. package/dist/modules/backend/catalogue.js.map +1 -1
  331. package/dist/modules/backend/chart.d.ts +42 -0
  332. package/dist/modules/backend/chart.d.ts.map +1 -0
  333. package/dist/modules/backend/chart.js +39 -0
  334. package/dist/modules/backend/chart.js.map +1 -0
  335. package/dist/modules/backend/design/HANDOFF.md +118 -38
  336. package/dist/modules/backend/design/auth.css +463 -0
  337. package/dist/modules/backend/design/brand/logo-dark.png +0 -0
  338. package/dist/modules/backend/design/brand/logo-light.png +0 -0
  339. package/dist/modules/backend/design/charts.css +229 -0
  340. package/dist/modules/backend/design/client/chart.d.mts +31 -0
  341. package/dist/modules/backend/design/client/chart.d.mts.map +1 -0
  342. package/dist/modules/backend/design/client/chart.mjs +23 -0
  343. package/dist/modules/backend/design/client/chart.mjs.map +7 -0
  344. package/dist/modules/backend/design/client/relation-select.d.mts +6 -1
  345. package/dist/modules/backend/design/client/relation-select.d.mts.map +1 -1
  346. package/dist/modules/backend/design/client/relation-select.mjs +2 -7
  347. package/dist/modules/backend/design/client/relation-select.mjs.map +7 -1
  348. package/dist/modules/backend/design/client/table-selection.d.mts +7 -0
  349. package/dist/modules/backend/design/client/table-selection.d.mts.map +1 -0
  350. package/dist/modules/backend/design/client/table-selection.mjs +2 -0
  351. package/dist/modules/backend/design/client/table-selection.mjs.map +7 -0
  352. package/dist/modules/backend/design/content.css +766 -0
  353. package/dist/modules/backend/design/controls.css +451 -0
  354. package/dist/modules/backend/design/design-system.css +2 -0
  355. package/dist/modules/backend/design/forms.css +1134 -0
  356. package/dist/modules/backend/design/foundation.css +423 -0
  357. package/dist/modules/backend/design/lists.css +1462 -0
  358. package/dist/modules/backend/design/record.css +526 -0
  359. package/dist/modules/backend/design/responsive.css +331 -0
  360. package/dist/modules/backend/design/tokens.css +317 -92
  361. package/dist/modules/backend/index.d.ts +12 -5
  362. package/dist/modules/backend/index.d.ts.map +1 -1
  363. package/dist/modules/backend/index.js +32 -15
  364. package/dist/modules/backend/index.js.map +1 -1
  365. package/dist/modules/backend/islands.d.ts.map +1 -1
  366. package/dist/modules/backend/islands.js +22 -4
  367. package/dist/modules/backend/islands.js.map +1 -1
  368. package/dist/modules/backend/joints.d.ts +1 -1
  369. package/dist/modules/backend/joints.d.ts.map +1 -1
  370. package/dist/modules/backend/joints.js +14 -6
  371. package/dist/modules/backend/joints.js.map +1 -1
  372. package/dist/modules/backend/list-search.d.ts +33 -0
  373. package/dist/modules/backend/list-search.d.ts.map +1 -0
  374. package/dist/modules/backend/list-search.js +232 -0
  375. package/dist/modules/backend/list-search.js.map +1 -0
  376. package/dist/modules/backend/menus.d.ts.map +1 -1
  377. package/dist/modules/backend/menus.js +3 -12
  378. package/dist/modules/backend/menus.js.map +1 -1
  379. package/dist/modules/backend/messages.d.ts +1 -1
  380. package/dist/modules/backend/messages.d.ts.map +1 -1
  381. package/dist/modules/backend/messages.js +48 -35
  382. package/dist/modules/backend/messages.js.map +1 -1
  383. package/dist/modules/backend/paging.d.ts +1 -1
  384. package/dist/modules/backend/paging.d.ts.map +1 -1
  385. package/dist/modules/backend/paging.js +1 -1
  386. package/dist/modules/backend/paging.js.map +1 -1
  387. package/dist/modules/backend/relation-select.d.ts +2 -57
  388. package/dist/modules/backend/relation-select.d.ts.map +1 -1
  389. package/dist/modules/backend/relation-select.js +2 -0
  390. package/dist/modules/backend/relation-select.js.map +1 -1
  391. package/dist/modules/backend/routes.d.ts +1 -8
  392. package/dist/modules/backend/routes.d.ts.map +1 -1
  393. package/dist/modules/backend/routes.js +36 -111
  394. package/dist/modules/backend/routes.js.map +1 -1
  395. package/dist/modules/backend/screen.d.ts +130 -0
  396. package/dist/modules/backend/screen.d.ts.map +1 -0
  397. package/dist/modules/backend/screen.js +205 -0
  398. package/dist/modules/backend/screen.js.map +1 -0
  399. package/dist/modules/backend/screens.d.ts +11 -14
  400. package/dist/modules/backend/screens.d.ts.map +1 -1
  401. package/dist/modules/backend/screens.js +13 -70
  402. package/dist/modules/backend/screens.js.map +1 -1
  403. package/dist/modules/business_report_staff_channel/channel-routes.d.ts +2 -0
  404. package/dist/modules/business_report_staff_channel/channel-routes.d.ts.map +1 -0
  405. package/dist/modules/business_report_staff_channel/channel-routes.js +438 -0
  406. package/dist/modules/business_report_staff_channel/channel-routes.js.map +1 -0
  407. package/dist/modules/business_report_staff_channel/index.d.ts +5 -0
  408. package/dist/modules/business_report_staff_channel/index.d.ts.map +1 -0
  409. package/dist/modules/business_report_staff_channel/index.js +18 -0
  410. package/dist/modules/business_report_staff_channel/index.js.map +1 -0
  411. package/dist/modules/calendar/index.d.ts.map +1 -1
  412. package/dist/modules/calendar/index.js +0 -1
  413. package/dist/modules/calendar/index.js.map +1 -1
  414. package/dist/modules/calendar/recurrence.d.ts.map +1 -1
  415. package/dist/modules/calendar/recurrence.js +3 -11
  416. package/dist/modules/calendar/recurrence.js.map +1 -1
  417. package/dist/modules/calendar_activity/index.d.ts.map +1 -1
  418. package/dist/modules/calendar_activity/index.js +0 -2
  419. package/dist/modules/calendar_activity/index.js.map +1 -1
  420. package/dist/modules/calendar_backend/index.d.ts +1 -1
  421. package/dist/modules/calendar_backend/index.d.ts.map +1 -1
  422. package/dist/modules/calendar_backend/index.js +1 -3
  423. package/dist/modules/calendar_backend/index.js.map +1 -1
  424. package/dist/modules/calendar_backend/routes.d.ts.map +1 -1
  425. package/dist/modules/calendar_backend/routes.js +10 -22
  426. package/dist/modules/calendar_backend/routes.js.map +1 -1
  427. package/dist/modules/calendar_backend/screens/calendar.d.ts +5 -0
  428. package/dist/modules/calendar_backend/screens/calendar.d.ts.map +1 -0
  429. package/dist/modules/calendar_backend/screens/calendar.js +10 -0
  430. package/dist/modules/calendar_backend/screens/calendar.js.map +1 -0
  431. package/dist/modules/calendar_backend/screens/index.d.ts +2 -0
  432. package/dist/modules/calendar_backend/screens/index.d.ts.map +1 -0
  433. package/dist/modules/calendar_backend/screens/index.js +2 -0
  434. package/dist/modules/calendar_backend/screens/index.js.map +1 -0
  435. package/dist/modules/calendar_mail_transport/index.d.ts.map +1 -1
  436. package/dist/modules/calendar_mail_transport/index.js +0 -2
  437. package/dist/modules/calendar_mail_transport/index.js.map +1 -1
  438. package/dist/modules/channel_api/core.d.ts +253 -0
  439. package/dist/modules/channel_api/core.d.ts.map +1 -0
  440. package/dist/modules/channel_api/core.js +587 -0
  441. package/dist/modules/channel_api/core.js.map +1 -0
  442. package/dist/modules/channel_api/customer.d.ts +21 -0
  443. package/dist/modules/channel_api/customer.d.ts.map +1 -0
  444. package/dist/modules/channel_api/customer.js +368 -0
  445. package/dist/modules/channel_api/customer.js.map +1 -0
  446. package/dist/modules/channel_api/index.d.ts +6 -0
  447. package/dist/modules/channel_api/index.d.ts.map +1 -0
  448. package/dist/modules/channel_api/index.js +66 -0
  449. package/dist/modules/channel_api/index.js.map +1 -0
  450. package/dist/modules/channel_api/openapi.d.ts +17 -0
  451. package/dist/modules/channel_api/openapi.d.ts.map +1 -0
  452. package/dist/modules/channel_api/openapi.js +105 -0
  453. package/dist/modules/channel_api/openapi.js.map +1 -0
  454. package/dist/modules/channel_api/staff.d.ts +7 -0
  455. package/dist/modules/channel_api/staff.d.ts.map +1 -0
  456. package/dist/modules/channel_api/staff.js +209 -0
  457. package/dist/modules/channel_api/staff.js.map +1 -0
  458. package/dist/modules/company/functions.d.ts.map +1 -1
  459. package/dist/modules/company/functions.js +93 -12
  460. package/dist/modules/company/functions.js.map +1 -1
  461. package/dist/modules/company/index.js +3 -3
  462. package/dist/modules/company/index.js.map +1 -1
  463. package/dist/modules/company/messages.d.ts +8 -0
  464. package/dist/modules/company/messages.d.ts.map +1 -1
  465. package/dist/modules/company/messages.js +8 -0
  466. package/dist/modules/company/messages.js.map +1 -1
  467. package/dist/modules/company/models.d.ts +2 -2
  468. package/dist/modules/company/models.d.ts.map +1 -1
  469. package/dist/modules/company/models.js +12 -2
  470. package/dist/modules/company/models.js.map +1 -1
  471. package/dist/modules/company_backend/index.d.ts +2 -1
  472. package/dist/modules/company_backend/index.d.ts.map +1 -1
  473. package/dist/modules/company_backend/index.js +25 -4
  474. package/dist/modules/company_backend/index.js.map +1 -1
  475. package/dist/modules/company_backend/routes.d.ts.map +1 -1
  476. package/dist/modules/company_backend/routes.js +314 -96
  477. package/dist/modules/company_backend/routes.js.map +1 -1
  478. package/dist/modules/company_backend/screens/branch-form.d.ts +18 -0
  479. package/dist/modules/company_backend/screens/branch-form.d.ts.map +1 -0
  480. package/dist/modules/company_backend/screens/branch-form.js +63 -0
  481. package/dist/modules/company_backend/screens/branch-form.js.map +1 -0
  482. package/dist/modules/company_backend/screens/companies-list.d.ts +18 -0
  483. package/dist/modules/company_backend/screens/companies-list.d.ts.map +1 -0
  484. package/dist/modules/company_backend/screens/companies-list.js +49 -0
  485. package/dist/modules/company_backend/screens/companies-list.js.map +1 -0
  486. package/dist/modules/company_backend/screens/company-form.d.ts +25 -0
  487. package/dist/modules/company_backend/screens/company-form.d.ts.map +1 -0
  488. package/dist/modules/company_backend/screens/company-form.js +159 -0
  489. package/dist/modules/company_backend/screens/company-form.js.map +1 -0
  490. package/dist/modules/company_backend/screens/context.d.ts +30 -0
  491. package/dist/modules/company_backend/screens/context.d.ts.map +1 -0
  492. package/dist/modules/company_backend/screens/context.js +48 -0
  493. package/dist/modules/company_backend/screens/context.js.map +1 -0
  494. package/dist/modules/company_backend/screens/hierarchy.d.ts +16 -0
  495. package/dist/modules/company_backend/screens/hierarchy.d.ts.map +1 -0
  496. package/dist/modules/company_backend/screens/hierarchy.js +41 -0
  497. package/dist/modules/company_backend/screens/hierarchy.js.map +1 -0
  498. package/dist/modules/company_backend/screens/index.d.ts +7 -0
  499. package/dist/modules/company_backend/screens/index.d.ts.map +1 -0
  500. package/dist/modules/company_backend/screens/index.js +6 -0
  501. package/dist/modules/company_backend/screens/index.js.map +1 -0
  502. package/dist/modules/company_backend/screens/types.d.ts +22 -0
  503. package/dist/modules/company_backend/screens/types.d.ts.map +1 -0
  504. package/dist/modules/company_backend/screens/types.js +2 -0
  505. package/dist/modules/company_backend/screens/types.js.map +1 -0
  506. package/dist/modules/crm/functions.d.ts +1 -1
  507. package/dist/modules/crm/functions.d.ts.map +1 -1
  508. package/dist/modules/crm/functions.js +534 -75
  509. package/dist/modules/crm/functions.js.map +1 -1
  510. package/dist/modules/crm/index.d.ts +2 -1
  511. package/dist/modules/crm/index.d.ts.map +1 -1
  512. package/dist/modules/crm/index.js +3 -4
  513. package/dist/modules/crm/index.js.map +1 -1
  514. package/dist/modules/crm/jobs.d.ts +10 -0
  515. package/dist/modules/crm/jobs.d.ts.map +1 -1
  516. package/dist/modules/crm/jobs.js +50 -1
  517. package/dist/modules/crm/jobs.js.map +1 -1
  518. package/dist/modules/crm/messages.d.ts +14 -1
  519. package/dist/modules/crm/messages.d.ts.map +1 -1
  520. package/dist/modules/crm/messages.js +26 -0
  521. package/dist/modules/crm/messages.js.map +1 -1
  522. package/dist/modules/crm/models.d.ts.map +1 -1
  523. package/dist/modules/crm/models.js +25 -0
  524. package/dist/modules/crm/models.js.map +1 -1
  525. package/dist/modules/crm/operations.d.ts +110 -1
  526. package/dist/modules/crm/operations.d.ts.map +1 -1
  527. package/dist/modules/crm/operations.js +612 -84
  528. package/dist/modules/crm/operations.js.map +1 -1
  529. package/dist/modules/crm_backend/client/crm-kanban-view.d.mts.map +1 -1
  530. package/dist/modules/crm_backend/client/crm-kanban-view.mjs +132 -32
  531. package/dist/modules/crm_backend/client/crm-kanban-view.mjs.map +1 -1
  532. package/dist/modules/crm_backend/client/crm.css +398 -63
  533. package/dist/modules/crm_backend/index.d.ts.map +1 -1
  534. package/dist/modules/crm_backend/index.js +12 -4
  535. package/dist/modules/crm_backend/index.js.map +1 -1
  536. package/dist/modules/crm_backend/messages.d.ts +212 -0
  537. package/dist/modules/crm_backend/messages.d.ts.map +1 -1
  538. package/dist/modules/crm_backend/messages.js +212 -0
  539. package/dist/modules/crm_backend/messages.js.map +1 -1
  540. package/dist/modules/crm_backend/relation-control.d.ts +51 -0
  541. package/dist/modules/crm_backend/relation-control.d.ts.map +1 -0
  542. package/dist/modules/crm_backend/relation-control.js +107 -0
  543. package/dist/modules/crm_backend/relation-control.js.map +1 -0
  544. package/dist/modules/crm_backend/routes.d.ts.map +1 -1
  545. package/dist/modules/crm_backend/routes.js +1068 -260
  546. package/dist/modules/crm_backend/routes.js.map +1 -1
  547. package/dist/modules/crm_backend/screens/activity-planner.d.ts +22 -0
  548. package/dist/modules/crm_backend/screens/activity-planner.d.ts.map +1 -0
  549. package/dist/modules/crm_backend/screens/activity-planner.js +159 -0
  550. package/dist/modules/crm_backend/screens/activity-planner.js.map +1 -0
  551. package/dist/modules/crm_backend/screens/case-create.d.ts +15 -0
  552. package/dist/modules/crm_backend/screens/case-create.d.ts.map +1 -0
  553. package/dist/modules/crm_backend/screens/case-create.js +19 -0
  554. package/dist/modules/crm_backend/screens/case-create.js.map +1 -0
  555. package/dist/modules/crm_backend/screens/case-detail.d.ts +46 -0
  556. package/dist/modules/crm_backend/screens/case-detail.d.ts.map +1 -0
  557. package/dist/modules/crm_backend/screens/case-detail.js +506 -0
  558. package/dist/modules/crm_backend/screens/case-detail.js.map +1 -0
  559. package/dist/modules/crm_backend/screens/cases-list.d.ts +16 -0
  560. package/dist/modules/crm_backend/screens/cases-list.d.ts.map +1 -0
  561. package/dist/modules/crm_backend/screens/cases-list.js +86 -0
  562. package/dist/modules/crm_backend/screens/cases-list.js.map +1 -0
  563. package/dist/modules/crm_backend/screens/configuration.d.ts +28 -0
  564. package/dist/modules/crm_backend/screens/configuration.d.ts.map +1 -0
  565. package/dist/modules/crm_backend/screens/configuration.js +115 -0
  566. package/dist/modules/crm_backend/screens/configuration.js.map +1 -0
  567. package/dist/modules/crm_backend/screens/index.d.ts +14 -0
  568. package/dist/modules/crm_backend/screens/index.d.ts.map +1 -0
  569. package/dist/modules/crm_backend/screens/index.js +8 -0
  570. package/dist/modules/crm_backend/screens/index.js.map +1 -0
  571. package/dist/modules/crm_backend/screens/leaderboard.d.ts +12 -0
  572. package/dist/modules/crm_backend/screens/leaderboard.d.ts.map +1 -0
  573. package/dist/modules/crm_backend/screens/leaderboard.js +89 -0
  574. package/dist/modules/crm_backend/screens/leaderboard.js.map +1 -0
  575. package/dist/modules/crm_backend/screens/pipeline.d.ts +21 -0
  576. package/dist/modules/crm_backend/screens/pipeline.d.ts.map +1 -0
  577. package/dist/modules/crm_backend/screens/pipeline.js +22 -0
  578. package/dist/modules/crm_backend/screens/pipeline.js.map +1 -0
  579. package/dist/modules/crm_sale/index.d.ts.map +1 -1
  580. package/dist/modules/crm_sale/index.js +3 -4
  581. package/dist/modules/crm_sale/index.js.map +1 -1
  582. package/dist/modules/crm_sale/messages.d.ts +3 -1
  583. package/dist/modules/crm_sale/messages.d.ts.map +1 -1
  584. package/dist/modules/crm_sale/messages.js +4 -0
  585. package/dist/modules/crm_sale/messages.js.map +1 -1
  586. package/dist/modules/crm_sale/sale-functions.d.ts +8 -1
  587. package/dist/modules/crm_sale/sale-functions.d.ts.map +1 -1
  588. package/dist/modules/crm_sale/sale-functions.js +184 -55
  589. package/dist/modules/crm_sale/sale-functions.js.map +1 -1
  590. package/dist/modules/crm_staff_channel/channel-routes.d.ts +2 -0
  591. package/dist/modules/crm_staff_channel/channel-routes.d.ts.map +1 -0
  592. package/dist/modules/crm_staff_channel/channel-routes.js +788 -0
  593. package/dist/modules/crm_staff_channel/channel-routes.js.map +1 -0
  594. package/dist/modules/crm_staff_channel/index.d.ts +5 -0
  595. package/dist/modules/crm_staff_channel/index.d.ts.map +1 -0
  596. package/dist/modules/crm_staff_channel/index.js +30 -0
  597. package/dist/modules/crm_staff_channel/index.js.map +1 -0
  598. package/dist/modules/crm_website/functions.d.ts.map +1 -1
  599. package/dist/modules/crm_website/functions.js +89 -10
  600. package/dist/modules/crm_website/functions.js.map +1 -1
  601. package/dist/modules/crm_website/index.js +1 -2
  602. package/dist/modules/crm_website/index.js.map +1 -1
  603. package/dist/modules/crm_website/messages.d.ts +4 -1
  604. package/dist/modules/crm_website/messages.d.ts.map +1 -1
  605. package/dist/modules/crm_website/messages.js +6 -0
  606. package/dist/modules/crm_website/messages.js.map +1 -1
  607. package/dist/modules/crm_website/models.d.ts.map +1 -1
  608. package/dist/modules/crm_website/models.js +18 -0
  609. package/dist/modules/crm_website/models.js.map +1 -1
  610. package/dist/modules/crm_website/routes.d.ts.map +1 -1
  611. package/dist/modules/crm_website/routes.js +44 -12
  612. package/dist/modules/crm_website/routes.js.map +1 -1
  613. package/dist/modules/crm_website/screens.d.ts +7 -1
  614. package/dist/modules/crm_website/screens.d.ts.map +1 -1
  615. package/dist/modules/crm_website/screens.js +13 -8
  616. package/dist/modules/crm_website/screens.js.map +1 -1
  617. package/dist/modules/flow/functions.d.ts +3 -0
  618. package/dist/modules/flow/functions.d.ts.map +1 -0
  619. package/dist/modules/flow/functions.js +1876 -0
  620. package/dist/modules/flow/functions.js.map +1 -0
  621. package/dist/modules/flow/index.d.ts +12 -0
  622. package/dist/modules/flow/index.d.ts.map +1 -0
  623. package/dist/modules/flow/index.js +30 -0
  624. package/dist/modules/flow/index.js.map +1 -0
  625. package/dist/modules/flow/jobs.d.ts +3 -0
  626. package/dist/modules/flow/jobs.d.ts.map +1 -0
  627. package/dist/modules/flow/jobs.js +136 -0
  628. package/dist/modules/flow/jobs.js.map +1 -0
  629. package/dist/modules/flow/membership.d.ts +72 -0
  630. package/dist/modules/flow/membership.d.ts.map +1 -0
  631. package/dist/modules/flow/membership.js +176 -0
  632. package/dist/modules/flow/membership.js.map +1 -0
  633. package/dist/modules/flow/messages.d.ts +79 -0
  634. package/dist/modules/flow/messages.d.ts.map +1 -0
  635. package/dist/modules/flow/messages.js +152 -0
  636. package/dist/modules/flow/messages.js.map +1 -0
  637. package/dist/modules/flow/models.d.ts +3 -0
  638. package/dist/modules/flow/models.d.ts.map +1 -0
  639. package/dist/modules/flow/models.js +453 -0
  640. package/dist/modules/flow/models.js.map +1 -0
  641. package/dist/modules/flow/operations.d.ts +408 -0
  642. package/dist/modules/flow/operations.d.ts.map +1 -0
  643. package/dist/modules/flow/operations.js +1665 -0
  644. package/dist/modules/flow/operations.js.map +1 -0
  645. package/dist/modules/flow/pages.d.ts +146 -0
  646. package/dist/modules/flow/pages.d.ts.map +1 -0
  647. package/dist/modules/flow/pages.js +394 -0
  648. package/dist/modules/flow/pages.js.map +1 -0
  649. package/dist/modules/flow/projects.d.ts +41 -0
  650. package/dist/modules/flow/projects.d.ts.map +1 -0
  651. package/dist/modules/flow/projects.js +74 -0
  652. package/dist/modules/flow/projects.js.map +1 -0
  653. package/dist/modules/flow/search.d.ts +57 -0
  654. package/dist/modules/flow/search.d.ts.map +1 -0
  655. package/dist/modules/flow/search.js +110 -0
  656. package/dist/modules/flow/search.js.map +1 -0
  657. package/dist/modules/flow/types.d.ts +17 -0
  658. package/dist/modules/flow/types.d.ts.map +1 -0
  659. package/dist/modules/flow/types.js +13 -0
  660. package/dist/modules/flow/types.js.map +1 -0
  661. package/dist/modules/flow_backend/functions.d.ts +3 -0
  662. package/dist/modules/flow_backend/functions.d.ts.map +1 -0
  663. package/dist/modules/flow_backend/functions.js +162 -0
  664. package/dist/modules/flow_backend/functions.js.map +1 -0
  665. package/dist/modules/flow_backend/index.d.ts +3 -0
  666. package/dist/modules/flow_backend/index.d.ts.map +1 -0
  667. package/dist/modules/flow_backend/index.js +96 -0
  668. package/dist/modules/flow_backend/index.js.map +1 -0
  669. package/dist/modules/flow_backend/islands.d.ts +3 -0
  670. package/dist/modules/flow_backend/islands.d.ts.map +1 -0
  671. package/dist/modules/flow_backend/islands.js +31 -0
  672. package/dist/modules/flow_backend/islands.js.map +1 -0
  673. package/dist/modules/flow_backend/messages.d.ts +248 -0
  674. package/dist/modules/flow_backend/messages.d.ts.map +1 -0
  675. package/dist/modules/flow_backend/messages.js +470 -0
  676. package/dist/modules/flow_backend/messages.js.map +1 -0
  677. package/dist/modules/flow_backend/relation-control.d.ts +53 -0
  678. package/dist/modules/flow_backend/relation-control.d.ts.map +1 -0
  679. package/dist/modules/flow_backend/relation-control.js +106 -0
  680. package/dist/modules/flow_backend/relation-control.js.map +1 -0
  681. package/dist/modules/flow_backend/routes.d.ts +3 -0
  682. package/dist/modules/flow_backend/routes.d.ts.map +1 -0
  683. package/dist/modules/flow_backend/routes.js +2519 -0
  684. package/dist/modules/flow_backend/routes.js.map +1 -0
  685. package/dist/modules/flow_backend/screens/all-epics.d.ts +19 -0
  686. package/dist/modules/flow_backend/screens/all-epics.d.ts.map +1 -0
  687. package/dist/modules/flow_backend/screens/all-epics.js +59 -0
  688. package/dist/modules/flow_backend/screens/all-epics.js.map +1 -0
  689. package/dist/modules/flow_backend/screens/all-pages.d.ts +19 -0
  690. package/dist/modules/flow_backend/screens/all-pages.d.ts.map +1 -0
  691. package/dist/modules/flow_backend/screens/all-pages.js +65 -0
  692. package/dist/modules/flow_backend/screens/all-pages.js.map +1 -0
  693. package/dist/modules/flow_backend/screens/board.d.ts +5 -0
  694. package/dist/modules/flow_backend/screens/board.d.ts.map +1 -0
  695. package/dist/modules/flow_backend/screens/board.js +7 -0
  696. package/dist/modules/flow_backend/screens/board.js.map +1 -0
  697. package/dist/modules/flow_backend/screens/epic-detail.d.ts +22 -0
  698. package/dist/modules/flow_backend/screens/epic-detail.d.ts.map +1 -0
  699. package/dist/modules/flow_backend/screens/epic-detail.js +41 -0
  700. package/dist/modules/flow_backend/screens/epic-detail.js.map +1 -0
  701. package/dist/modules/flow_backend/screens/gantt.d.ts +21 -0
  702. package/dist/modules/flow_backend/screens/gantt.d.ts.map +1 -0
  703. package/dist/modules/flow_backend/screens/gantt.js +42 -0
  704. package/dist/modules/flow_backend/screens/gantt.js.map +1 -0
  705. package/dist/modules/flow_backend/screens/index.d.ts +29 -0
  706. package/dist/modules/flow_backend/screens/index.d.ts.map +1 -0
  707. package/dist/modules/flow_backend/screens/index.js +23 -0
  708. package/dist/modules/flow_backend/screens/index.js.map +1 -0
  709. package/dist/modules/flow_backend/screens/issue-detail.d.ts +38 -0
  710. package/dist/modules/flow_backend/screens/issue-detail.d.ts.map +1 -0
  711. package/dist/modules/flow_backend/screens/issue-detail.js +336 -0
  712. package/dist/modules/flow_backend/screens/issue-detail.js.map +1 -0
  713. package/dist/modules/flow_backend/screens/issues.d.ts +34 -0
  714. package/dist/modules/flow_backend/screens/issues.d.ts.map +1 -0
  715. package/dist/modules/flow_backend/screens/issues.js +118 -0
  716. package/dist/modules/flow_backend/screens/issues.js.map +1 -0
  717. package/dist/modules/flow_backend/screens/map.d.ts +13 -0
  718. package/dist/modules/flow_backend/screens/map.d.ts.map +1 -0
  719. package/dist/modules/flow_backend/screens/map.js +16 -0
  720. package/dist/modules/flow_backend/screens/map.js.map +1 -0
  721. package/dist/modules/flow_backend/screens/my-work.d.ts +42 -0
  722. package/dist/modules/flow_backend/screens/my-work.d.ts.map +1 -0
  723. package/dist/modules/flow_backend/screens/my-work.js +157 -0
  724. package/dist/modules/flow_backend/screens/my-work.js.map +1 -0
  725. package/dist/modules/flow_backend/screens/nav.d.ts +3 -0
  726. package/dist/modules/flow_backend/screens/nav.d.ts.map +1 -0
  727. package/dist/modules/flow_backend/screens/nav.js +79 -0
  728. package/dist/modules/flow_backend/screens/nav.js.map +1 -0
  729. package/dist/modules/flow_backend/screens/page-detail.d.ts +31 -0
  730. package/dist/modules/flow_backend/screens/page-detail.d.ts.map +1 -0
  731. package/dist/modules/flow_backend/screens/page-detail.js +113 -0
  732. package/dist/modules/flow_backend/screens/page-detail.js.map +1 -0
  733. package/dist/modules/flow_backend/screens/project-create.d.ts +26 -0
  734. package/dist/modules/flow_backend/screens/project-create.d.ts.map +1 -0
  735. package/dist/modules/flow_backend/screens/project-create.js +56 -0
  736. package/dist/modules/flow_backend/screens/project-create.js.map +1 -0
  737. package/dist/modules/flow_backend/screens/project-epics.d.ts +33 -0
  738. package/dist/modules/flow_backend/screens/project-epics.d.ts.map +1 -0
  739. package/dist/modules/flow_backend/screens/project-epics.js +90 -0
  740. package/dist/modules/flow_backend/screens/project-epics.js.map +1 -0
  741. package/dist/modules/flow_backend/screens/project-pages.d.ts +34 -0
  742. package/dist/modules/flow_backend/screens/project-pages.d.ts.map +1 -0
  743. package/dist/modules/flow_backend/screens/project-pages.js +66 -0
  744. package/dist/modules/flow_backend/screens/project-pages.js.map +1 -0
  745. package/dist/modules/flow_backend/screens/project-settings.d.ts +69 -0
  746. package/dist/modules/flow_backend/screens/project-settings.d.ts.map +1 -0
  747. package/dist/modules/flow_backend/screens/project-settings.js +248 -0
  748. package/dist/modules/flow_backend/screens/project-settings.js.map +1 -0
  749. package/dist/modules/flow_backend/screens/projects-list.d.ts +30 -0
  750. package/dist/modules/flow_backend/screens/projects-list.d.ts.map +1 -0
  751. package/dist/modules/flow_backend/screens/projects-list.js +121 -0
  752. package/dist/modules/flow_backend/screens/projects-list.js.map +1 -0
  753. package/dist/modules/flow_backend/screens/shared.d.ts +28 -0
  754. package/dist/modules/flow_backend/screens/shared.d.ts.map +1 -0
  755. package/dist/modules/flow_backend/screens/shared.js +46 -0
  756. package/dist/modules/flow_backend/screens/shared.js.map +1 -0
  757. package/dist/modules/flow_backend/screens/sprints.d.ts +33 -0
  758. package/dist/modules/flow_backend/screens/sprints.d.ts.map +1 -0
  759. package/dist/modules/flow_backend/screens/sprints.js +159 -0
  760. package/dist/modules/flow_backend/screens/sprints.js.map +1 -0
  761. package/dist/modules/flow_staff_channel/channel-routes.d.ts +2 -0
  762. package/dist/modules/flow_staff_channel/channel-routes.d.ts.map +1 -0
  763. package/dist/modules/flow_staff_channel/channel-routes.js +444 -0
  764. package/dist/modules/flow_staff_channel/channel-routes.js.map +1 -0
  765. package/dist/modules/flow_staff_channel/index.d.ts +5 -0
  766. package/dist/modules/flow_staff_channel/index.d.ts.map +1 -0
  767. package/dist/modules/flow_staff_channel/index.js +30 -0
  768. package/dist/modules/flow_staff_channel/index.js.map +1 -0
  769. package/dist/modules/hospitality_billing/functions.d.ts +18 -0
  770. package/dist/modules/hospitality_billing/functions.d.ts.map +1 -0
  771. package/dist/modules/hospitality_billing/functions.js +426 -0
  772. package/dist/modules/hospitality_billing/functions.js.map +1 -0
  773. package/dist/modules/hospitality_billing/index.d.ts +3 -0
  774. package/dist/modules/hospitality_billing/index.d.ts.map +1 -0
  775. package/dist/modules/hospitality_billing/index.js +25 -0
  776. package/dist/modules/hospitality_billing/index.js.map +1 -0
  777. package/dist/modules/hospitality_billing/jobs.d.ts +17 -0
  778. package/dist/modules/hospitality_billing/jobs.d.ts.map +1 -0
  779. package/dist/modules/hospitality_billing/jobs.js +83 -0
  780. package/dist/modules/hospitality_billing/jobs.js.map +1 -0
  781. package/dist/modules/hospitality_billing/menus.d.ts +9 -0
  782. package/dist/modules/hospitality_billing/menus.d.ts.map +1 -0
  783. package/dist/modules/hospitality_billing/menus.js +25 -0
  784. package/dist/modules/hospitality_billing/menus.js.map +1 -0
  785. package/dist/modules/hospitality_billing/messages.d.ts +3 -0
  786. package/dist/modules/hospitality_billing/messages.d.ts.map +1 -0
  787. package/dist/modules/hospitality_billing/messages.js +163 -0
  788. package/dist/modules/hospitality_billing/messages.js.map +1 -0
  789. package/dist/modules/hospitality_billing/models.d.ts +3 -0
  790. package/dist/modules/hospitality_billing/models.d.ts.map +1 -0
  791. package/dist/modules/hospitality_billing/models.js +65 -0
  792. package/dist/modules/hospitality_billing/models.js.map +1 -0
  793. package/dist/modules/hospitality_billing/routes.d.ts +3 -0
  794. package/dist/modules/hospitality_billing/routes.d.ts.map +1 -0
  795. package/dist/modules/hospitality_billing/routes.js +189 -0
  796. package/dist/modules/hospitality_billing/routes.js.map +1 -0
  797. package/dist/modules/hospitality_billing/screens/billing.d.ts +3 -0
  798. package/dist/modules/hospitality_billing/screens/billing.d.ts.map +1 -0
  799. package/dist/modules/hospitality_billing/screens/billing.js +20 -0
  800. package/dist/modules/hospitality_billing/screens/billing.js.map +1 -0
  801. package/dist/modules/hospitality_billing/screens/charge-rules.d.ts +12 -0
  802. package/dist/modules/hospitality_billing/screens/charge-rules.d.ts.map +1 -0
  803. package/dist/modules/hospitality_billing/screens/charge-rules.js +86 -0
  804. package/dist/modules/hospitality_billing/screens/charge-rules.js.map +1 -0
  805. package/dist/modules/hospitality_billing/screens/index.d.ts +4 -0
  806. package/dist/modules/hospitality_billing/screens/index.d.ts.map +1 -0
  807. package/dist/modules/hospitality_billing/screens/index.js +4 -0
  808. package/dist/modules/hospitality_billing/screens/index.js.map +1 -0
  809. package/dist/modules/hospitality_billing/screens/page-frame.d.ts +14 -0
  810. package/dist/modules/hospitality_billing/screens/page-frame.d.ts.map +1 -0
  811. package/dist/modules/hospitality_billing/screens/page-frame.js +6 -0
  812. package/dist/modules/hospitality_billing/screens/page-frame.js.map +1 -0
  813. package/dist/modules/hospitality_billing/screens/shared.d.ts +64 -0
  814. package/dist/modules/hospitality_billing/screens/shared.d.ts.map +1 -0
  815. package/dist/modules/hospitality_billing/screens/shared.js +117 -0
  816. package/dist/modules/hospitality_billing/screens/shared.js.map +1 -0
  817. package/dist/modules/hospitality_core/calendar.d.ts.map +1 -1
  818. package/dist/modules/hospitality_core/calendar.js +2 -1
  819. package/dist/modules/hospitality_core/calendar.js.map +1 -1
  820. package/dist/modules/hospitality_core/functions.d.ts.map +1 -1
  821. package/dist/modules/hospitality_core/functions.js +114 -14
  822. package/dist/modules/hospitality_core/functions.js.map +1 -1
  823. package/dist/modules/hospitality_core/index.d.ts +2 -2
  824. package/dist/modules/hospitality_core/index.d.ts.map +1 -1
  825. package/dist/modules/hospitality_core/index.js +3 -2
  826. package/dist/modules/hospitality_core/index.js.map +1 -1
  827. package/dist/modules/hospitality_core/inventory.d.ts +53 -4
  828. package/dist/modules/hospitality_core/inventory.d.ts.map +1 -1
  829. package/dist/modules/hospitality_core/inventory.js +121 -14
  830. package/dist/modules/hospitality_core/inventory.js.map +1 -1
  831. package/dist/modules/hospitality_core/menus.d.ts.map +1 -1
  832. package/dist/modules/hospitality_core/menus.js +31 -0
  833. package/dist/modules/hospitality_core/menus.js.map +1 -1
  834. package/dist/modules/hospitality_core/messages.d.ts.map +1 -1
  835. package/dist/modules/hospitality_core/messages.js +383 -183
  836. package/dist/modules/hospitality_core/messages.js.map +1 -1
  837. package/dist/modules/hospitality_core/models.d.ts +1 -1
  838. package/dist/modules/hospitality_core/models.d.ts.map +1 -1
  839. package/dist/modules/hospitality_core/models.js +47 -2
  840. package/dist/modules/hospitality_core/models.js.map +1 -1
  841. package/dist/modules/hospitality_core/night-audit.d.ts +1 -0
  842. package/dist/modules/hospitality_core/night-audit.d.ts.map +1 -1
  843. package/dist/modules/hospitality_core/night-audit.js +39 -1
  844. package/dist/modules/hospitality_core/night-audit.js.map +1 -1
  845. package/dist/modules/hospitality_core/online-booking.d.ts +5 -0
  846. package/dist/modules/hospitality_core/online-booking.d.ts.map +1 -0
  847. package/dist/modules/hospitality_core/online-booking.js +775 -0
  848. package/dist/modules/hospitality_core/online-booking.js.map +1 -0
  849. package/dist/modules/hospitality_core/operations.d.ts +21 -1
  850. package/dist/modules/hospitality_core/operations.d.ts.map +1 -1
  851. package/dist/modules/hospitality_core/operations.js +432 -67
  852. package/dist/modules/hospitality_core/operations.js.map +1 -1
  853. package/dist/modules/hospitality_core/routes.d.ts.map +1 -1
  854. package/dist/modules/hospitality_core/routes.js +503 -106
  855. package/dist/modules/hospitality_core/routes.js.map +1 -1
  856. package/dist/modules/hospitality_core/screens/amenities.d.ts +10 -0
  857. package/dist/modules/hospitality_core/screens/amenities.d.ts.map +1 -0
  858. package/dist/modules/hospitality_core/screens/amenities.js +65 -0
  859. package/dist/modules/hospitality_core/screens/amenities.js.map +1 -0
  860. package/dist/modules/hospitality_core/screens/building-detail.d.ts +3 -0
  861. package/dist/modules/hospitality_core/screens/building-detail.d.ts.map +1 -0
  862. package/dist/modules/hospitality_core/screens/building-detail.js +69 -0
  863. package/dist/modules/hospitality_core/screens/building-detail.js.map +1 -0
  864. package/dist/modules/hospitality_core/screens/cleaning-task-detail.d.ts +7 -0
  865. package/dist/modules/hospitality_core/screens/cleaning-task-detail.d.ts.map +1 -0
  866. package/dist/modules/hospitality_core/screens/cleaning-task-detail.js +109 -0
  867. package/dist/modules/hospitality_core/screens/cleaning-task-detail.js.map +1 -0
  868. package/dist/modules/hospitality_core/screens/cleaning-tasks.d.ts +20 -0
  869. package/dist/modules/hospitality_core/screens/cleaning-tasks.d.ts.map +1 -0
  870. package/dist/modules/hospitality_core/screens/cleaning-tasks.js +139 -0
  871. package/dist/modules/hospitality_core/screens/cleaning-tasks.js.map +1 -0
  872. package/dist/modules/hospitality_core/screens/content.d.ts +3 -0
  873. package/dist/modules/hospitality_core/screens/content.d.ts.map +1 -0
  874. package/dist/modules/hospitality_core/screens/content.js +114 -0
  875. package/dist/modules/hospitality_core/screens/content.js.map +1 -0
  876. package/dist/modules/hospitality_core/screens/floor-detail.d.ts +3 -0
  877. package/dist/modules/hospitality_core/screens/floor-detail.d.ts.map +1 -0
  878. package/dist/modules/hospitality_core/screens/floor-detail.js +74 -0
  879. package/dist/modules/hospitality_core/screens/floor-detail.js.map +1 -0
  880. package/dist/modules/hospitality_core/screens/folio-detail.d.ts +3 -0
  881. package/dist/modules/hospitality_core/screens/folio-detail.d.ts.map +1 -0
  882. package/dist/modules/hospitality_core/screens/folio-detail.js +142 -0
  883. package/dist/modules/hospitality_core/screens/folio-detail.js.map +1 -0
  884. package/dist/modules/hospitality_core/screens/folios.d.ts +3 -0
  885. package/dist/modules/hospitality_core/screens/folios.d.ts.map +1 -0
  886. package/dist/modules/hospitality_core/screens/folios.js +7 -0
  887. package/dist/modules/hospitality_core/screens/folios.js.map +1 -0
  888. package/dist/modules/hospitality_core/screens/front-desk.d.ts +35 -0
  889. package/dist/modules/hospitality_core/screens/front-desk.d.ts.map +1 -0
  890. package/dist/modules/hospitality_core/screens/front-desk.js +195 -0
  891. package/dist/modules/hospitality_core/screens/front-desk.js.map +1 -0
  892. package/dist/modules/hospitality_core/screens/housekeeping-room-detail.d.ts +3 -0
  893. package/dist/modules/hospitality_core/screens/housekeeping-room-detail.d.ts.map +1 -0
  894. package/dist/modules/hospitality_core/screens/housekeeping-room-detail.js +121 -0
  895. package/dist/modules/hospitality_core/screens/housekeeping-room-detail.js.map +1 -0
  896. package/dist/modules/hospitality_core/screens/housekeeping-rooms.d.ts +9 -0
  897. package/dist/modules/hospitality_core/screens/housekeeping-rooms.d.ts.map +1 -0
  898. package/dist/modules/hospitality_core/screens/housekeeping-rooms.js +54 -0
  899. package/dist/modules/hospitality_core/screens/housekeeping-rooms.js.map +1 -0
  900. package/dist/modules/hospitality_core/screens/index.d.ts +33 -0
  901. package/dist/modules/hospitality_core/screens/index.d.ts.map +1 -0
  902. package/dist/modules/hospitality_core/screens/index.js +33 -0
  903. package/dist/modules/hospitality_core/screens/index.js.map +1 -0
  904. package/dist/modules/hospitality_core/screens/inventory.d.ts +8 -0
  905. package/dist/modules/hospitality_core/screens/inventory.d.ts.map +1 -0
  906. package/dist/modules/hospitality_core/screens/inventory.js +122 -0
  907. package/dist/modules/hospitality_core/screens/inventory.js.map +1 -0
  908. package/dist/modules/hospitality_core/screens/new-property.d.ts +3 -0
  909. package/dist/modules/hospitality_core/screens/new-property.d.ts.map +1 -0
  910. package/dist/modules/hospitality_core/screens/new-property.js +8 -0
  911. package/dist/modules/hospitality_core/screens/new-property.js.map +1 -0
  912. package/dist/modules/hospitality_core/screens/new-room-type.d.ts +3 -0
  913. package/dist/modules/hospitality_core/screens/new-room-type.d.ts.map +1 -0
  914. package/dist/modules/hospitality_core/screens/new-room-type.js +8 -0
  915. package/dist/modules/hospitality_core/screens/new-room-type.js.map +1 -0
  916. package/dist/modules/hospitality_core/screens/new-room.d.ts +3 -0
  917. package/dist/modules/hospitality_core/screens/new-room.d.ts.map +1 -0
  918. package/dist/modules/hospitality_core/screens/new-room.js +8 -0
  919. package/dist/modules/hospitality_core/screens/new-room.js.map +1 -0
  920. package/dist/modules/hospitality_core/screens/night-audit.d.ts +10 -0
  921. package/dist/modules/hospitality_core/screens/night-audit.d.ts.map +1 -0
  922. package/dist/modules/hospitality_core/screens/night-audit.js +67 -0
  923. package/dist/modules/hospitality_core/screens/night-audit.js.map +1 -0
  924. package/dist/modules/hospitality_core/screens/page-frame.d.ts +15 -0
  925. package/dist/modules/hospitality_core/screens/page-frame.d.ts.map +1 -0
  926. package/dist/modules/hospitality_core/screens/page-frame.js +10 -0
  927. package/dist/modules/hospitality_core/screens/page-frame.js.map +1 -0
  928. package/dist/modules/hospitality_core/screens/policies.d.ts +10 -0
  929. package/dist/modules/hospitality_core/screens/policies.d.ts.map +1 -0
  930. package/dist/modules/hospitality_core/screens/policies.js +72 -0
  931. package/dist/modules/hospitality_core/screens/policies.js.map +1 -0
  932. package/dist/modules/hospitality_core/screens/properties.d.ts +7 -0
  933. package/dist/modules/hospitality_core/screens/properties.d.ts.map +1 -0
  934. package/dist/modules/hospitality_core/screens/properties.js +45 -0
  935. package/dist/modules/hospitality_core/screens/properties.js.map +1 -0
  936. package/dist/modules/hospitality_core/screens/property-detail.d.ts +3 -0
  937. package/dist/modules/hospitality_core/screens/property-detail.d.ts.map +1 -0
  938. package/dist/modules/hospitality_core/screens/property-detail.js +92 -0
  939. package/dist/modules/hospitality_core/screens/property-detail.js.map +1 -0
  940. package/dist/modules/hospitality_core/screens/rate-plans.d.ts +10 -0
  941. package/dist/modules/hospitality_core/screens/rate-plans.d.ts.map +1 -0
  942. package/dist/modules/hospitality_core/screens/rate-plans.js +123 -0
  943. package/dist/modules/hospitality_core/screens/rate-plans.js.map +1 -0
  944. package/dist/modules/hospitality_core/screens/reservation-detail.d.ts +11 -0
  945. package/dist/modules/hospitality_core/screens/reservation-detail.d.ts.map +1 -0
  946. package/dist/modules/hospitality_core/screens/reservation-detail.js +237 -0
  947. package/dist/modules/hospitality_core/screens/reservation-detail.js.map +1 -0
  948. package/dist/modules/hospitality_core/screens/reservations.d.ts +17 -0
  949. package/dist/modules/hospitality_core/screens/reservations.d.ts.map +1 -0
  950. package/dist/modules/hospitality_core/screens/reservations.js +166 -0
  951. package/dist/modules/hospitality_core/screens/reservations.js.map +1 -0
  952. package/dist/modules/hospitality_core/screens/room-detail.d.ts +3 -0
  953. package/dist/modules/hospitality_core/screens/room-detail.d.ts.map +1 -0
  954. package/dist/modules/hospitality_core/screens/room-detail.js +75 -0
  955. package/dist/modules/hospitality_core/screens/room-detail.js.map +1 -0
  956. package/dist/modules/hospitality_core/screens/room-type-detail.d.ts +3 -0
  957. package/dist/modules/hospitality_core/screens/room-type-detail.d.ts.map +1 -0
  958. package/dist/modules/hospitality_core/screens/room-type-detail.js +91 -0
  959. package/dist/modules/hospitality_core/screens/room-type-detail.js.map +1 -0
  960. package/dist/modules/hospitality_core/screens/room-types.d.ts +3 -0
  961. package/dist/modules/hospitality_core/screens/room-types.d.ts.map +1 -0
  962. package/dist/modules/hospitality_core/screens/room-types.js +61 -0
  963. package/dist/modules/hospitality_core/screens/room-types.js.map +1 -0
  964. package/dist/modules/hospitality_core/screens/rooms.d.ts +10 -0
  965. package/dist/modules/hospitality_core/screens/rooms.d.ts.map +1 -0
  966. package/dist/modules/hospitality_core/screens/rooms.js +150 -0
  967. package/dist/modules/hospitality_core/screens/rooms.js.map +1 -0
  968. package/dist/modules/hospitality_core/screens/services.d.ts +18 -0
  969. package/dist/modules/hospitality_core/screens/services.d.ts.map +1 -0
  970. package/dist/modules/hospitality_core/screens/services.js +196 -0
  971. package/dist/modules/hospitality_core/screens/services.js.map +1 -0
  972. package/dist/modules/hospitality_core/screens/shared.d.ts +777 -0
  973. package/dist/modules/hospitality_core/screens/shared.d.ts.map +1 -0
  974. package/dist/modules/hospitality_core/screens/shared.js +1586 -0
  975. package/dist/modules/hospitality_core/screens/shared.js.map +1 -0
  976. package/dist/modules/hospitality_core/screens/stay-detail.d.ts +3 -0
  977. package/dist/modules/hospitality_core/screens/stay-detail.d.ts.map +1 -0
  978. package/dist/modules/hospitality_core/screens/stay-detail.js +233 -0
  979. package/dist/modules/hospitality_core/screens/stay-detail.js.map +1 -0
  980. package/dist/modules/hospitality_core/screens/stay-notices.d.ts +9 -0
  981. package/dist/modules/hospitality_core/screens/stay-notices.d.ts.map +1 -0
  982. package/dist/modules/hospitality_core/screens/stay-notices.js +87 -0
  983. package/dist/modules/hospitality_core/screens/stay-notices.js.map +1 -0
  984. package/dist/modules/hospitality_core/screens/stays.d.ts +3 -0
  985. package/dist/modules/hospitality_core/screens/stays.d.ts.map +1 -0
  986. package/dist/modules/hospitality_core/screens/stays.js +7 -0
  987. package/dist/modules/hospitality_core/screens/stays.js.map +1 -0
  988. package/dist/modules/hospitality_core/screens/tape-chart.d.ts +7 -0
  989. package/dist/modules/hospitality_core/screens/tape-chart.d.ts.map +1 -0
  990. package/dist/modules/hospitality_core/screens/tape-chart.js +99 -0
  991. package/dist/modules/hospitality_core/screens/tape-chart.js.map +1 -0
  992. package/dist/modules/hospitality_core/services.d.ts.map +1 -1
  993. package/dist/modules/hospitality_core/services.js +133 -30
  994. package/dist/modules/hospitality_core/services.js.map +1 -1
  995. package/dist/modules/hospitality_core/stay-notices.js +2 -2
  996. package/dist/modules/hospitality_core/stay-notices.js.map +1 -1
  997. package/dist/modules/hospitality_core/types.d.ts +26 -5
  998. package/dist/modules/hospitality_core/types.d.ts.map +1 -1
  999. package/dist/modules/hospitality_core/types.js +47 -5
  1000. package/dist/modules/hospitality_core/types.js.map +1 -1
  1001. package/dist/modules/hospitality_staff_channel/channel-routes.d.ts +2 -0
  1002. package/dist/modules/hospitality_staff_channel/channel-routes.d.ts.map +1 -0
  1003. package/dist/modules/hospitality_staff_channel/channel-routes.js +1227 -0
  1004. package/dist/modules/hospitality_staff_channel/channel-routes.js.map +1 -0
  1005. package/dist/modules/hospitality_staff_channel/index.d.ts +5 -0
  1006. package/dist/modules/hospitality_staff_channel/index.d.ts.map +1 -0
  1007. package/dist/modules/hospitality_staff_channel/index.js +34 -0
  1008. package/dist/modules/hospitality_staff_channel/index.js.map +1 -0
  1009. package/dist/modules/hr/functions.d.ts.map +1 -1
  1010. package/dist/modules/hr/functions.js +108 -44
  1011. package/dist/modules/hr/functions.js.map +1 -1
  1012. package/dist/modules/hr/index.d.ts.map +1 -1
  1013. package/dist/modules/hr/index.js +0 -1
  1014. package/dist/modules/hr/index.js.map +1 -1
  1015. package/dist/modules/hr_backend/index.d.ts +2 -1
  1016. package/dist/modules/hr_backend/index.d.ts.map +1 -1
  1017. package/dist/modules/hr_backend/index.js +39 -7
  1018. package/dist/modules/hr_backend/index.js.map +1 -1
  1019. package/dist/modules/hr_backend/routes.d.ts.map +1 -1
  1020. package/dist/modules/hr_backend/routes.js +279 -42
  1021. package/dist/modules/hr_backend/routes.js.map +1 -1
  1022. package/dist/modules/hr_backend/screens/employee-form.d.ts +28 -0
  1023. package/dist/modules/hr_backend/screens/employee-form.d.ts.map +1 -0
  1024. package/dist/modules/hr_backend/screens/employee-form.js +110 -0
  1025. package/dist/modules/hr_backend/screens/employee-form.js.map +1 -0
  1026. package/dist/modules/hr_backend/screens/employees-list.d.ts +22 -0
  1027. package/dist/modules/hr_backend/screens/employees-list.d.ts.map +1 -0
  1028. package/dist/modules/hr_backend/screens/employees-list.js +53 -0
  1029. package/dist/modules/hr_backend/screens/employees-list.js.map +1 -0
  1030. package/dist/modules/hr_backend/screens/index.d.ts +5 -0
  1031. package/dist/modules/hr_backend/screens/index.d.ts.map +1 -0
  1032. package/dist/modules/hr_backend/screens/index.js +5 -0
  1033. package/dist/modules/hr_backend/screens/index.js.map +1 -0
  1034. package/dist/modules/hr_backend/screens/leaves-list.d.ts +22 -0
  1035. package/dist/modules/hr_backend/screens/leaves-list.d.ts.map +1 -0
  1036. package/dist/modules/hr_backend/screens/leaves-list.js +78 -0
  1037. package/dist/modules/hr_backend/screens/leaves-list.js.map +1 -0
  1038. package/dist/modules/hr_backend/screens/roster.d.ts +19 -0
  1039. package/dist/modules/hr_backend/screens/roster.d.ts.map +1 -0
  1040. package/dist/modules/hr_backend/screens/roster.js +83 -0
  1041. package/dist/modules/hr_backend/screens/roster.js.map +1 -0
  1042. package/dist/modules/inventory_staff_channel/channel-routes.d.ts +2 -0
  1043. package/dist/modules/inventory_staff_channel/channel-routes.d.ts.map +1 -0
  1044. package/dist/modules/inventory_staff_channel/channel-routes.js +724 -0
  1045. package/dist/modules/inventory_staff_channel/channel-routes.js.map +1 -0
  1046. package/dist/modules/inventory_staff_channel/index.d.ts +5 -0
  1047. package/dist/modules/inventory_staff_channel/index.d.ts.map +1 -0
  1048. package/dist/modules/inventory_staff_channel/index.js +38 -0
  1049. package/dist/modules/inventory_staff_channel/index.js.map +1 -0
  1050. package/dist/modules/livedoc/documents.d.ts +48 -0
  1051. package/dist/modules/livedoc/documents.d.ts.map +1 -0
  1052. package/dist/modules/livedoc/documents.js +99 -0
  1053. package/dist/modules/livedoc/documents.js.map +1 -0
  1054. package/dist/modules/livedoc/functions.d.ts +3 -0
  1055. package/dist/modules/livedoc/functions.d.ts.map +1 -0
  1056. package/dist/modules/livedoc/functions.js +47 -0
  1057. package/dist/modules/livedoc/functions.js.map +1 -0
  1058. package/dist/modules/livedoc/index.d.ts +22 -0
  1059. package/dist/modules/livedoc/index.d.ts.map +1 -0
  1060. package/dist/modules/livedoc/index.js +37 -0
  1061. package/dist/modules/livedoc/index.js.map +1 -0
  1062. package/dist/modules/livedoc/islands.d.ts +3 -0
  1063. package/dist/modules/livedoc/islands.d.ts.map +1 -0
  1064. package/dist/modules/livedoc/islands.js +22 -0
  1065. package/dist/modules/livedoc/islands.js.map +1 -0
  1066. package/dist/modules/livedoc/routes.d.ts +11 -0
  1067. package/dist/modules/livedoc/routes.d.ts.map +1 -0
  1068. package/dist/modules/livedoc/routes.js +232 -0
  1069. package/dist/modules/livedoc/routes.js.map +1 -0
  1070. package/dist/modules/livedoc/sync.d.ts +124 -0
  1071. package/dist/modules/livedoc/sync.d.ts.map +1 -0
  1072. package/dist/modules/livedoc/sync.js +218 -0
  1073. package/dist/modules/livedoc/sync.js.map +1 -0
  1074. package/dist/modules/loyalty/admin-functions.d.ts.map +1 -1
  1075. package/dist/modules/loyalty/admin-functions.js +42 -6
  1076. package/dist/modules/loyalty/admin-functions.js.map +1 -1
  1077. package/dist/modules/loyalty/engine.d.ts +1 -0
  1078. package/dist/modules/loyalty/engine.d.ts.map +1 -1
  1079. package/dist/modules/loyalty/engine.js +88 -28
  1080. package/dist/modules/loyalty/engine.js.map +1 -1
  1081. package/dist/modules/loyalty/index.d.ts.map +1 -1
  1082. package/dist/modules/loyalty/index.js +10 -2
  1083. package/dist/modules/loyalty/index.js.map +1 -1
  1084. package/dist/modules/loyalty/ledger.d.ts.map +1 -1
  1085. package/dist/modules/loyalty/ledger.js +11 -0
  1086. package/dist/modules/loyalty/ledger.js.map +1 -1
  1087. package/dist/modules/loyalty/membership-functions.d.ts.map +1 -1
  1088. package/dist/modules/loyalty/membership-functions.js +23 -7
  1089. package/dist/modules/loyalty/membership-functions.js.map +1 -1
  1090. package/dist/modules/loyalty/messages.d.ts +8 -0
  1091. package/dist/modules/loyalty/messages.d.ts.map +1 -1
  1092. package/dist/modules/loyalty/messages.js +8 -0
  1093. package/dist/modules/loyalty/messages.js.map +1 -1
  1094. package/dist/modules/loyalty/models.d.ts.map +1 -1
  1095. package/dist/modules/loyalty/models.js +20 -0
  1096. package/dist/modules/loyalty/models.js.map +1 -1
  1097. package/dist/modules/loyalty/order-functions.d.ts +16 -1
  1098. package/dist/modules/loyalty/order-functions.d.ts.map +1 -1
  1099. package/dist/modules/loyalty/order-functions.js +513 -291
  1100. package/dist/modules/loyalty/order-functions.js.map +1 -1
  1101. package/dist/modules/loyalty/stats.d.ts +17 -0
  1102. package/dist/modules/loyalty/stats.d.ts.map +1 -0
  1103. package/dist/modules/loyalty/stats.js +178 -0
  1104. package/dist/modules/loyalty/stats.js.map +1 -0
  1105. package/dist/modules/loyalty/stored-value.d.ts +42 -0
  1106. package/dist/modules/loyalty/stored-value.d.ts.map +1 -0
  1107. package/dist/modules/loyalty/stored-value.js +368 -0
  1108. package/dist/modules/loyalty/stored-value.js.map +1 -0
  1109. package/dist/modules/loyalty/types.d.ts +6 -4
  1110. package/dist/modules/loyalty/types.d.ts.map +1 -1
  1111. package/dist/modules/loyalty/types.js +1 -1
  1112. package/dist/modules/loyalty/types.js.map +1 -1
  1113. package/dist/modules/loyalty_backend/index.js +443 -172
  1114. package/dist/modules/loyalty_backend/index.js.map +1 -1
  1115. package/dist/modules/loyalty_backend/messages.d.ts +58 -1
  1116. package/dist/modules/loyalty_backend/messages.d.ts.map +1 -1
  1117. package/dist/modules/loyalty_backend/messages.js +114 -0
  1118. package/dist/modules/loyalty_backend/messages.js.map +1 -1
  1119. package/dist/modules/loyalty_backend/screens/index.d.ts +90 -0
  1120. package/dist/modules/loyalty_backend/screens/index.d.ts.map +1 -0
  1121. package/dist/modules/loyalty_backend/screens/index.js +912 -0
  1122. package/dist/modules/loyalty_backend/screens/index.js.map +1 -0
  1123. package/dist/modules/loyalty_backend/screens/page-frame.d.ts +14 -0
  1124. package/dist/modules/loyalty_backend/screens/page-frame.d.ts.map +1 -0
  1125. package/dist/modules/loyalty_backend/screens/page-frame.js +13 -0
  1126. package/dist/modules/loyalty_backend/screens/page-frame.js.map +1 -0
  1127. package/dist/modules/loyalty_pos/channel.d.ts +2 -0
  1128. package/dist/modules/loyalty_pos/channel.d.ts.map +1 -0
  1129. package/dist/modules/loyalty_pos/channel.js +270 -0
  1130. package/dist/modules/loyalty_pos/channel.js.map +1 -0
  1131. package/dist/modules/loyalty_pos/functions.d.ts +11 -17
  1132. package/dist/modules/loyalty_pos/functions.d.ts.map +1 -1
  1133. package/dist/modules/loyalty_pos/functions.js +454 -94
  1134. package/dist/modules/loyalty_pos/functions.js.map +1 -1
  1135. package/dist/modules/loyalty_pos/index.js +6 -16
  1136. package/dist/modules/loyalty_pos/index.js.map +1 -1
  1137. package/dist/modules/loyalty_pos/jobs.d.ts +3 -0
  1138. package/dist/modules/loyalty_pos/jobs.d.ts.map +1 -0
  1139. package/dist/modules/loyalty_pos/jobs.js +30 -0
  1140. package/dist/modules/loyalty_pos/jobs.js.map +1 -0
  1141. package/dist/modules/loyalty_sale/functions.d.ts +2 -2
  1142. package/dist/modules/loyalty_sale/functions.d.ts.map +1 -1
  1143. package/dist/modules/loyalty_sale/functions.js +53 -34
  1144. package/dist/modules/loyalty_sale/functions.js.map +1 -1
  1145. package/dist/modules/loyalty_sale/index.js +0 -2
  1146. package/dist/modules/loyalty_sale/index.js.map +1 -1
  1147. package/dist/modules/mail/functions.d.ts.map +1 -1
  1148. package/dist/modules/mail/functions.js +48 -6
  1149. package/dist/modules/mail/functions.js.map +1 -1
  1150. package/dist/modules/mail/index.d.ts.map +1 -1
  1151. package/dist/modules/mail/index.js +0 -1
  1152. package/dist/modules/mail/index.js.map +1 -1
  1153. package/dist/modules/mail/operations.d.ts +19 -0
  1154. package/dist/modules/mail/operations.d.ts.map +1 -1
  1155. package/dist/modules/mail/operations.js +69 -0
  1156. package/dist/modules/mail/operations.js.map +1 -1
  1157. package/dist/modules/mail_backend/index.d.ts +1 -1
  1158. package/dist/modules/mail_backend/index.d.ts.map +1 -1
  1159. package/dist/modules/mail_backend/index.js +5 -14
  1160. package/dist/modules/mail_backend/index.js.map +1 -1
  1161. package/dist/modules/mail_backend/islands.js +2 -2
  1162. package/dist/modules/mail_backend/islands.js.map +1 -1
  1163. package/dist/modules/mail_backend/routes.d.ts.map +1 -1
  1164. package/dist/modules/mail_backend/routes.js +25 -20
  1165. package/dist/modules/mail_backend/routes.js.map +1 -1
  1166. package/dist/modules/mail_backend/screens/inbox-list.d.ts +9 -0
  1167. package/dist/modules/mail_backend/screens/inbox-list.d.ts.map +1 -0
  1168. package/dist/modules/mail_backend/screens/inbox-list.js +13 -0
  1169. package/dist/modules/mail_backend/screens/inbox-list.js.map +1 -0
  1170. package/dist/modules/mail_backend/screens/index.d.ts +3 -0
  1171. package/dist/modules/mail_backend/screens/index.d.ts.map +1 -0
  1172. package/dist/modules/mail_backend/screens/index.js +2 -0
  1173. package/dist/modules/mail_backend/screens/index.js.map +1 -0
  1174. package/dist/modules/mail_inbound/index.d.ts.map +1 -1
  1175. package/dist/modules/mail_inbound/index.js +0 -1
  1176. package/dist/modules/mail_inbound/index.js.map +1 -1
  1177. package/dist/modules/mail_inbound_backend/index.d.ts +1 -1
  1178. package/dist/modules/mail_inbound_backend/index.d.ts.map +1 -1
  1179. package/dist/modules/mail_inbound_backend/index.js +3 -12
  1180. package/dist/modules/mail_inbound_backend/index.js.map +1 -1
  1181. package/dist/modules/mail_inbound_backend/routes.d.ts.map +1 -1
  1182. package/dist/modules/mail_inbound_backend/routes.js +6 -21
  1183. package/dist/modules/mail_inbound_backend/routes.js.map +1 -1
  1184. package/dist/modules/mail_inbound_backend/screens/inbound-list.d.ts +8 -0
  1185. package/dist/modules/mail_inbound_backend/screens/inbound-list.d.ts.map +1 -0
  1186. package/dist/modules/mail_inbound_backend/screens/inbound-list.js +20 -0
  1187. package/dist/modules/mail_inbound_backend/screens/inbound-list.js.map +1 -0
  1188. package/dist/modules/mail_inbound_backend/screens/index.d.ts +3 -0
  1189. package/dist/modules/mail_inbound_backend/screens/index.d.ts.map +1 -0
  1190. package/dist/modules/mail_inbound_backend/screens/index.js +2 -0
  1191. package/dist/modules/mail_inbound_backend/screens/index.js.map +1 -0
  1192. package/dist/modules/mail_staff_channel/channel-routes.d.ts +2 -0
  1193. package/dist/modules/mail_staff_channel/channel-routes.d.ts.map +1 -0
  1194. package/dist/modules/mail_staff_channel/channel-routes.js +183 -0
  1195. package/dist/modules/mail_staff_channel/channel-routes.js.map +1 -0
  1196. package/dist/modules/mail_staff_channel/index.d.ts +5 -0
  1197. package/dist/modules/mail_staff_channel/index.d.ts.map +1 -0
  1198. package/dist/modules/mail_staff_channel/index.js +28 -0
  1199. package/dist/modules/mail_staff_channel/index.js.map +1 -0
  1200. package/dist/modules/mail_transport/index.d.ts.map +1 -1
  1201. package/dist/modules/mail_transport/index.js +0 -1
  1202. package/dist/modules/mail_transport/index.js.map +1 -1
  1203. package/dist/modules/mail_transport_backend/index.d.ts +1 -1
  1204. package/dist/modules/mail_transport_backend/index.d.ts.map +1 -1
  1205. package/dist/modules/mail_transport_backend/index.js +3 -12
  1206. package/dist/modules/mail_transport_backend/index.js.map +1 -1
  1207. package/dist/modules/mail_transport_backend/routes.d.ts.map +1 -1
  1208. package/dist/modules/mail_transport_backend/routes.js +23 -22
  1209. package/dist/modules/mail_transport_backend/routes.js.map +1 -1
  1210. package/dist/modules/mail_transport_backend/screens/index.d.ts +3 -0
  1211. package/dist/modules/mail_transport_backend/screens/index.d.ts.map +1 -0
  1212. package/dist/modules/mail_transport_backend/screens/index.js +2 -0
  1213. package/dist/modules/mail_transport_backend/screens/index.js.map +1 -0
  1214. package/dist/modules/mail_transport_backend/screens/outbox-list.d.ts +9 -0
  1215. package/dist/modules/mail_transport_backend/screens/outbox-list.d.ts.map +1 -0
  1216. package/dist/modules/mail_transport_backend/screens/outbox-list.js +29 -0
  1217. package/dist/modules/mail_transport_backend/screens/outbox-list.js.map +1 -0
  1218. package/dist/modules/manufacturing/functions.d.ts +3 -0
  1219. package/dist/modules/manufacturing/functions.d.ts.map +1 -0
  1220. package/dist/modules/manufacturing/functions.js +912 -0
  1221. package/dist/modules/manufacturing/functions.js.map +1 -0
  1222. package/dist/modules/manufacturing/index.d.ts +6 -0
  1223. package/dist/modules/manufacturing/index.d.ts.map +1 -0
  1224. package/dist/modules/manufacturing/index.js +42 -0
  1225. package/dist/modules/manufacturing/index.js.map +1 -0
  1226. package/dist/modules/manufacturing/models.d.ts +8 -0
  1227. package/dist/modules/manufacturing/models.d.ts.map +1 -0
  1228. package/dist/modules/manufacturing/models.js +145 -0
  1229. package/dist/modules/manufacturing/models.js.map +1 -0
  1230. package/dist/modules/manufacturing/relations.d.ts.map +1 -0
  1231. package/dist/modules/manufacturing/relations.js +37 -0
  1232. package/dist/modules/manufacturing/relations.js.map +1 -0
  1233. package/dist/modules/manufacturing/types.d.ts +7 -0
  1234. package/dist/modules/manufacturing/types.d.ts.map +1 -0
  1235. package/dist/modules/manufacturing/types.js +11 -0
  1236. package/dist/modules/manufacturing/types.js.map +1 -0
  1237. package/dist/modules/manufacturing_backend/index.d.ts +5 -0
  1238. package/dist/modules/manufacturing_backend/index.d.ts.map +1 -0
  1239. package/dist/modules/manufacturing_backend/index.js +146 -0
  1240. package/dist/modules/manufacturing_backend/index.js.map +1 -0
  1241. package/dist/modules/manufacturing_backend/routes.d.ts +3 -0
  1242. package/dist/modules/manufacturing_backend/routes.d.ts.map +1 -0
  1243. package/dist/modules/manufacturing_backend/routes.js +477 -0
  1244. package/dist/modules/manufacturing_backend/routes.js.map +1 -0
  1245. package/dist/modules/manufacturing_backend/screens/bom-create.d.ts +15 -0
  1246. package/dist/modules/manufacturing_backend/screens/bom-create.d.ts.map +1 -0
  1247. package/dist/modules/manufacturing_backend/screens/bom-create.js +39 -0
  1248. package/dist/modules/manufacturing_backend/screens/bom-create.js.map +1 -0
  1249. package/dist/modules/manufacturing_backend/screens/boms-list.d.ts +18 -0
  1250. package/dist/modules/manufacturing_backend/screens/boms-list.d.ts.map +1 -0
  1251. package/dist/modules/manufacturing_backend/screens/boms-list.js +36 -0
  1252. package/dist/modules/manufacturing_backend/screens/boms-list.js.map +1 -0
  1253. package/dist/modules/manufacturing_backend/screens/index.d.ts +8 -0
  1254. package/dist/modules/manufacturing_backend/screens/index.d.ts.map +1 -0
  1255. package/dist/modules/manufacturing_backend/screens/index.js +8 -0
  1256. package/dist/modules/manufacturing_backend/screens/index.js.map +1 -0
  1257. package/dist/modules/manufacturing_backend/screens/order-create.d.ts +13 -0
  1258. package/dist/modules/manufacturing_backend/screens/order-create.d.ts.map +1 -0
  1259. package/dist/modules/manufacturing_backend/screens/order-create.js +20 -0
  1260. package/dist/modules/manufacturing_backend/screens/order-create.js.map +1 -0
  1261. package/dist/modules/manufacturing_backend/screens/order-execution.d.ts +7 -0
  1262. package/dist/modules/manufacturing_backend/screens/order-execution.d.ts.map +1 -0
  1263. package/dist/modules/manufacturing_backend/screens/order-execution.js +129 -0
  1264. package/dist/modules/manufacturing_backend/screens/order-execution.js.map +1 -0
  1265. package/dist/modules/manufacturing_backend/screens/orders-list.d.ts +21 -0
  1266. package/dist/modules/manufacturing_backend/screens/orders-list.d.ts.map +1 -0
  1267. package/dist/modules/manufacturing_backend/screens/orders-list.js +49 -0
  1268. package/dist/modules/manufacturing_backend/screens/orders-list.js.map +1 -0
  1269. package/dist/modules/manufacturing_backend/screens/work-center-form.d.ts +24 -0
  1270. package/dist/modules/manufacturing_backend/screens/work-center-form.d.ts.map +1 -0
  1271. package/dist/modules/manufacturing_backend/screens/work-center-form.js +80 -0
  1272. package/dist/modules/manufacturing_backend/screens/work-center-form.js.map +1 -0
  1273. package/dist/modules/manufacturing_backend/screens/work-centers-list.d.ts +23 -0
  1274. package/dist/modules/manufacturing_backend/screens/work-centers-list.d.ts.map +1 -0
  1275. package/dist/modules/manufacturing_backend/screens/work-centers-list.js +61 -0
  1276. package/dist/modules/manufacturing_backend/screens/work-centers-list.js.map +1 -0
  1277. package/dist/modules/oauth/index.d.ts.map +1 -1
  1278. package/dist/modules/oauth/index.js +0 -1
  1279. package/dist/modules/oauth/index.js.map +1 -1
  1280. package/dist/modules/oauth/models.d.ts.map +1 -1
  1281. package/dist/modules/oauth/models.js +2 -1
  1282. package/dist/modules/oauth/models.js.map +1 -1
  1283. package/dist/modules/oauth_backend/index.d.ts +1 -1
  1284. package/dist/modules/oauth_backend/index.d.ts.map +1 -1
  1285. package/dist/modules/oauth_backend/index.js +3 -5
  1286. package/dist/modules/oauth_backend/index.js.map +1 -1
  1287. package/dist/modules/oauth_backend/messages.d.ts +4 -0
  1288. package/dist/modules/oauth_backend/messages.d.ts.map +1 -1
  1289. package/dist/modules/oauth_backend/messages.js +4 -0
  1290. package/dist/modules/oauth_backend/messages.js.map +1 -1
  1291. package/dist/modules/oauth_backend/routes.d.ts.map +1 -1
  1292. package/dist/modules/oauth_backend/routes.js +28 -30
  1293. package/dist/modules/oauth_backend/routes.js.map +1 -1
  1294. package/dist/modules/oauth_backend/screens/index.d.ts +66 -0
  1295. package/dist/modules/oauth_backend/screens/index.d.ts.map +1 -0
  1296. package/dist/modules/oauth_backend/screens/index.js +306 -0
  1297. package/dist/modules/oauth_backend/screens/index.js.map +1 -0
  1298. package/dist/modules/partner/functions.d.ts.map +1 -1
  1299. package/dist/modules/partner/functions.js +74 -6
  1300. package/dist/modules/partner/functions.js.map +1 -1
  1301. package/dist/modules/partner/index.d.ts.map +1 -1
  1302. package/dist/modules/partner/index.js +0 -1
  1303. package/dist/modules/partner/index.js.map +1 -1
  1304. package/dist/modules/partner/models.d.ts +4 -4
  1305. package/dist/modules/partner/models.d.ts.map +1 -1
  1306. package/dist/modules/partner/models.js +9 -7
  1307. package/dist/modules/partner/models.js.map +1 -1
  1308. package/dist/modules/partner/types.d.ts +2 -2
  1309. package/dist/modules/partner/types.js +2 -2
  1310. package/dist/modules/partner_backend/client/address-view.mjs +5 -5
  1311. package/dist/modules/partner_backend/client/address-view.mjs.map +1 -1
  1312. package/dist/modules/partner_backend/client/address.css +22 -10
  1313. package/dist/modules/partner_backend/client/partner.css +116 -0
  1314. package/dist/modules/partner_backend/index.d.ts +1 -1
  1315. package/dist/modules/partner_backend/index.d.ts.map +1 -1
  1316. package/dist/modules/partner_backend/index.js +34 -4
  1317. package/dist/modules/partner_backend/index.js.map +1 -1
  1318. package/dist/modules/partner_backend/menus.js +2 -2
  1319. package/dist/modules/partner_backend/menus.js.map +1 -1
  1320. package/dist/modules/partner_backend/routes.d.ts +3 -1
  1321. package/dist/modules/partner_backend/routes.d.ts.map +1 -1
  1322. package/dist/modules/partner_backend/routes.js +236 -91
  1323. package/dist/modules/partner_backend/routes.js.map +1 -1
  1324. package/dist/modules/partner_backend/screens/form.d.ts +21 -0
  1325. package/dist/modules/partner_backend/screens/form.d.ts.map +1 -0
  1326. package/dist/modules/partner_backend/screens/form.js +101 -0
  1327. package/dist/modules/partner_backend/screens/form.js.map +1 -0
  1328. package/dist/modules/partner_backend/screens/index.d.ts +5 -0
  1329. package/dist/modules/partner_backend/screens/index.d.ts.map +1 -0
  1330. package/dist/modules/partner_backend/screens/index.js +4 -0
  1331. package/dist/modules/partner_backend/screens/index.js.map +1 -0
  1332. package/dist/modules/partner_backend/screens/list.d.ts +6 -0
  1333. package/dist/modules/partner_backend/screens/list.d.ts.map +1 -0
  1334. package/dist/modules/partner_backend/screens/list.js +94 -0
  1335. package/dist/modules/partner_backend/screens/list.js.map +1 -0
  1336. package/dist/modules/partner_backend/screens/new.d.ts +5 -0
  1337. package/dist/modules/partner_backend/screens/new.d.ts.map +1 -0
  1338. package/dist/modules/partner_backend/screens/new.js +58 -0
  1339. package/dist/modules/partner_backend/screens/new.js.map +1 -0
  1340. package/dist/modules/partner_backend/screens/types.d.ts +44 -0
  1341. package/dist/modules/partner_backend/screens/types.d.ts.map +1 -0
  1342. package/dist/modules/partner_backend/screens/types.js +2 -0
  1343. package/dist/modules/partner_backend/screens/types.js.map +1 -0
  1344. package/dist/modules/partner_mail_backend/index.d.ts +5 -0
  1345. package/dist/modules/partner_mail_backend/index.d.ts.map +1 -0
  1346. package/dist/modules/partner_mail_backend/index.js +29 -0
  1347. package/dist/modules/partner_mail_backend/index.js.map +1 -0
  1348. package/dist/modules/pos/functions.d.ts +18 -2
  1349. package/dist/modules/pos/functions.d.ts.map +1 -1
  1350. package/dist/modules/pos/functions.js +3279 -345
  1351. package/dist/modules/pos/functions.js.map +1 -1
  1352. package/dist/modules/pos/index.d.ts +2 -1
  1353. package/dist/modules/pos/index.d.ts.map +1 -1
  1354. package/dist/modules/pos/index.js +5 -5
  1355. package/dist/modules/pos/index.js.map +1 -1
  1356. package/dist/modules/pos/models.d.ts.map +1 -1
  1357. package/dist/modules/pos/models.js +189 -1
  1358. package/dist/modules/pos/models.js.map +1 -1
  1359. package/dist/modules/pos/relations.d.ts.map +1 -1
  1360. package/dist/modules/pos/relations.js +11 -0
  1361. package/dist/modules/pos/relations.js.map +1 -1
  1362. package/dist/modules/pos_backend/index.js +182 -154
  1363. package/dist/modules/pos_backend/index.js.map +1 -1
  1364. package/dist/modules/pos_backend/screens.d.ts +1 -0
  1365. package/dist/modules/pos_backend/screens.d.ts.map +1 -1
  1366. package/dist/modules/pos_backend/screens.js +28 -38
  1367. package/dist/modules/pos_backend/screens.js.map +1 -1
  1368. package/dist/modules/pos_channel/catalog.d.ts +27 -0
  1369. package/dist/modules/pos_channel/catalog.d.ts.map +1 -0
  1370. package/dist/modules/pos_channel/catalog.js +310 -0
  1371. package/dist/modules/pos_channel/catalog.js.map +1 -0
  1372. package/dist/modules/pos_channel/index.d.ts +7 -0
  1373. package/dist/modules/pos_channel/index.d.ts.map +1 -0
  1374. package/dist/modules/pos_channel/index.js +61 -0
  1375. package/dist/modules/pos_channel/index.js.map +1 -0
  1376. package/dist/modules/pos_channel/offline.d.ts +66 -0
  1377. package/dist/modules/pos_channel/offline.d.ts.map +1 -0
  1378. package/dist/modules/pos_channel/offline.js +16 -0
  1379. package/dist/modules/pos_channel/offline.js.map +1 -0
  1380. package/dist/modules/pos_channel/operations.d.ts +422 -0
  1381. package/dist/modules/pos_channel/operations.d.ts.map +1 -0
  1382. package/dist/modules/pos_channel/operations.js +1781 -0
  1383. package/dist/modules/pos_channel/operations.js.map +1 -0
  1384. package/dist/modules/pos_channel/sync.d.ts +6 -0
  1385. package/dist/modules/pos_channel/sync.d.ts.map +1 -0
  1386. package/dist/modules/pos_channel/sync.js +1161 -0
  1387. package/dist/modules/pos_channel/sync.js.map +1 -0
  1388. package/dist/modules/pricing/index.d.ts.map +1 -1
  1389. package/dist/modules/pricing/index.js +3 -4
  1390. package/dist/modules/pricing/index.js.map +1 -1
  1391. package/dist/modules/pricing_backend/index.js +135 -78
  1392. package/dist/modules/pricing_backend/index.js.map +1 -1
  1393. package/dist/modules/pricing_backend/screens/index.d.ts +5 -0
  1394. package/dist/modules/pricing_backend/screens/index.d.ts.map +1 -0
  1395. package/dist/modules/pricing_backend/screens/index.js +4 -0
  1396. package/dist/modules/pricing_backend/screens/index.js.map +1 -0
  1397. package/dist/modules/pricing_backend/screens/pricelist-create.d.ts +10 -0
  1398. package/dist/modules/pricing_backend/screens/pricelist-create.d.ts.map +1 -0
  1399. package/dist/modules/pricing_backend/screens/pricelist-create.js +30 -0
  1400. package/dist/modules/pricing_backend/screens/pricelist-create.js.map +1 -0
  1401. package/dist/modules/pricing_backend/screens/pricelist-detail.d.ts +15 -0
  1402. package/dist/modules/pricing_backend/screens/pricelist-detail.d.ts.map +1 -0
  1403. package/dist/modules/pricing_backend/screens/pricelist-detail.js +164 -0
  1404. package/dist/modules/pricing_backend/screens/pricelist-detail.js.map +1 -0
  1405. package/dist/modules/pricing_backend/screens/pricelists-list.d.ts +11 -0
  1406. package/dist/modules/pricing_backend/screens/pricelists-list.d.ts.map +1 -0
  1407. package/dist/modules/pricing_backend/screens/pricelists-list.js +27 -0
  1408. package/dist/modules/pricing_backend/screens/pricelists-list.js.map +1 -0
  1409. package/dist/modules/pricing_backend/screens/shared.d.ts +21 -0
  1410. package/dist/modules/pricing_backend/screens/shared.d.ts.map +1 -0
  1411. package/dist/modules/pricing_backend/screens/shared.js +3 -0
  1412. package/dist/modules/pricing_backend/screens/shared.js.map +1 -0
  1413. package/dist/modules/product/functions.d.ts.map +1 -1
  1414. package/dist/modules/product/functions.js +679 -50
  1415. package/dist/modules/product/functions.js.map +1 -1
  1416. package/dist/modules/product/index.d.ts +2 -0
  1417. package/dist/modules/product/index.d.ts.map +1 -1
  1418. package/dist/modules/product/index.js +2 -2
  1419. package/dist/modules/product/index.js.map +1 -1
  1420. package/dist/modules/product/models.d.ts +1 -1
  1421. package/dist/modules/product/models.d.ts.map +1 -1
  1422. package/dist/modules/product/models.js +27 -4
  1423. package/dist/modules/product/models.js.map +1 -1
  1424. package/dist/modules/product/relations.d.ts.map +1 -1
  1425. package/dist/modules/product/relations.js +4 -0
  1426. package/dist/modules/product/relations.js.map +1 -1
  1427. package/dist/modules/product/sellable.d.ts +26 -0
  1428. package/dist/modules/product/sellable.d.ts.map +1 -0
  1429. package/dist/modules/product/sellable.js +56 -0
  1430. package/dist/modules/product/sellable.js.map +1 -0
  1431. package/dist/modules/product/types.d.ts +2 -2
  1432. package/dist/modules/product/views.d.ts.map +1 -1
  1433. package/dist/modules/product/views.js +5 -1
  1434. package/dist/modules/product/views.js.map +1 -1
  1435. package/dist/modules/product_activity_backend/index.d.ts.map +1 -1
  1436. package/dist/modules/product_activity_backend/index.js +2 -3
  1437. package/dist/modules/product_activity_backend/index.js.map +1 -1
  1438. package/dist/modules/product_backend/client/media-upload-view.d.mts.map +1 -1
  1439. package/dist/modules/product_backend/client/media-upload-view.mjs +1 -0
  1440. package/dist/modules/product_backend/client/media-upload-view.mjs.map +1 -1
  1441. package/dist/modules/product_backend/client/product.css +964 -0
  1442. package/dist/modules/product_backend/index.d.ts +5 -6
  1443. package/dist/modules/product_backend/index.d.ts.map +1 -1
  1444. package/dist/modules/product_backend/index.js +203 -14
  1445. package/dist/modules/product_backend/index.js.map +1 -1
  1446. package/dist/modules/product_backend/menus.js +2 -2
  1447. package/dist/modules/product_backend/menus.js.map +1 -1
  1448. package/dist/modules/product_backend/relation-control.d.ts +85 -0
  1449. package/dist/modules/product_backend/relation-control.d.ts.map +1 -0
  1450. package/dist/modules/product_backend/relation-control.js +129 -0
  1451. package/dist/modules/product_backend/relation-control.js.map +1 -0
  1452. package/dist/modules/product_backend/routes.d.ts.map +1 -1
  1453. package/dist/modules/product_backend/routes.js +502 -196
  1454. package/dist/modules/product_backend/routes.js.map +1 -1
  1455. package/dist/modules/product_backend/screens/attributes.d.ts +7 -0
  1456. package/dist/modules/product_backend/screens/attributes.d.ts.map +1 -0
  1457. package/dist/modules/product_backend/screens/attributes.js +66 -0
  1458. package/dist/modules/product_backend/screens/attributes.js.map +1 -0
  1459. package/dist/modules/product_backend/screens/create.d.ts +16 -0
  1460. package/dist/modules/product_backend/screens/create.d.ts.map +1 -0
  1461. package/dist/modules/product_backend/screens/create.js +86 -0
  1462. package/dist/modules/product_backend/screens/create.js.map +1 -0
  1463. package/dist/modules/product_backend/screens/detail.d.ts +87 -0
  1464. package/dist/modules/product_backend/screens/detail.d.ts.map +1 -0
  1465. package/dist/modules/product_backend/screens/detail.js +381 -0
  1466. package/dist/modules/product_backend/screens/detail.js.map +1 -0
  1467. package/dist/modules/product_backend/screens/favorite.d.ts +6 -0
  1468. package/dist/modules/product_backend/screens/favorite.d.ts.map +1 -0
  1469. package/dist/modules/product_backend/screens/favorite.js +43 -0
  1470. package/dist/modules/product_backend/screens/favorite.js.map +1 -0
  1471. package/dist/modules/product_backend/screens/index.d.ts +10 -0
  1472. package/dist/modules/product_backend/screens/index.d.ts.map +1 -0
  1473. package/dist/modules/product_backend/screens/index.js +7 -0
  1474. package/dist/modules/product_backend/screens/index.js.map +1 -0
  1475. package/dist/modules/product_backend/screens/list.d.ts +54 -0
  1476. package/dist/modules/product_backend/screens/list.d.ts.map +1 -0
  1477. package/dist/modules/product_backend/screens/list.js +124 -0
  1478. package/dist/modules/product_backend/screens/list.js.map +1 -0
  1479. package/dist/modules/product_backend/screens/variant.d.ts +9 -0
  1480. package/dist/modules/product_backend/screens/variant.d.ts.map +1 -0
  1481. package/dist/modules/product_backend/screens/variant.js +113 -0
  1482. package/dist/modules/product_backend/screens/variant.js.map +1 -0
  1483. package/dist/modules/product_mail_backend/index.d.ts.map +1 -1
  1484. package/dist/modules/product_mail_backend/index.js +2 -3
  1485. package/dist/modules/product_mail_backend/index.js.map +1 -1
  1486. package/dist/modules/product_media/functions.d.ts.map +1 -1
  1487. package/dist/modules/product_media/functions.js +59 -6
  1488. package/dist/modules/product_media/functions.js.map +1 -1
  1489. package/dist/modules/product_media/index.js +0 -1
  1490. package/dist/modules/product_media/index.js.map +1 -1
  1491. package/dist/modules/product_variant_activity_backend/index.d.ts.map +1 -1
  1492. package/dist/modules/product_variant_activity_backend/index.js +2 -3
  1493. package/dist/modules/product_variant_activity_backend/index.js.map +1 -1
  1494. package/dist/modules/product_variant_mail_backend/index.d.ts.map +1 -1
  1495. package/dist/modules/product_variant_mail_backend/index.js +2 -3
  1496. package/dist/modules/product_variant_mail_backend/index.js.map +1 -1
  1497. package/dist/modules/purchase/functions.d.ts.map +1 -1
  1498. package/dist/modules/purchase/functions.js +852 -225
  1499. package/dist/modules/purchase/functions.js.map +1 -1
  1500. package/dist/modules/purchase/index.d.ts.map +1 -1
  1501. package/dist/modules/purchase/index.js +30 -5
  1502. package/dist/modules/purchase/index.js.map +1 -1
  1503. package/dist/modules/purchase/models.d.ts.map +1 -1
  1504. package/dist/modules/purchase/models.js +1 -0
  1505. package/dist/modules/purchase/models.js.map +1 -1
  1506. package/dist/modules/purchase/reports.d.ts +4 -0
  1507. package/dist/modules/purchase/reports.d.ts.map +1 -0
  1508. package/dist/modules/purchase/reports.js +86 -0
  1509. package/dist/modules/purchase/reports.js.map +1 -0
  1510. package/dist/modules/purchase_backend/index.js +513 -112
  1511. package/dist/modules/purchase_backend/index.js.map +1 -1
  1512. package/dist/modules/purchase_backend/screens/index.d.ts +10 -0
  1513. package/dist/modules/purchase_backend/screens/index.d.ts.map +1 -0
  1514. package/dist/modules/purchase_backend/screens/index.js +10 -0
  1515. package/dist/modules/purchase_backend/screens/index.js.map +1 -0
  1516. package/dist/modules/purchase_backend/screens/order-detail.d.ts +31 -0
  1517. package/dist/modules/purchase_backend/screens/order-detail.d.ts.map +1 -0
  1518. package/dist/modules/purchase_backend/screens/order-detail.js +204 -0
  1519. package/dist/modules/purchase_backend/screens/order-detail.js.map +1 -0
  1520. package/dist/modules/purchase_backend/screens/order-list-shared.d.ts +7 -0
  1521. package/dist/modules/purchase_backend/screens/order-list-shared.d.ts.map +1 -0
  1522. package/dist/modules/purchase_backend/screens/order-list-shared.js +58 -0
  1523. package/dist/modules/purchase_backend/screens/order-list-shared.js.map +1 -0
  1524. package/dist/modules/purchase_backend/screens/overview.d.ts +19 -0
  1525. package/dist/modules/purchase_backend/screens/overview.d.ts.map +1 -0
  1526. package/dist/modules/purchase_backend/screens/overview.js +52 -0
  1527. package/dist/modules/purchase_backend/screens/overview.js.map +1 -0
  1528. package/dist/modules/purchase_backend/screens/purchase-orders-list.d.ts +14 -0
  1529. package/dist/modules/purchase_backend/screens/purchase-orders-list.d.ts.map +1 -0
  1530. package/dist/modules/purchase_backend/screens/purchase-orders-list.js +26 -0
  1531. package/dist/modules/purchase_backend/screens/purchase-orders-list.js.map +1 -0
  1532. package/dist/modules/purchase_backend/screens/rfq-create.d.ts +16 -0
  1533. package/dist/modules/purchase_backend/screens/rfq-create.d.ts.map +1 -0
  1534. package/dist/modules/purchase_backend/screens/rfq-create.js +24 -0
  1535. package/dist/modules/purchase_backend/screens/rfq-create.js.map +1 -0
  1536. package/dist/modules/purchase_backend/screens/rfqs-list.d.ts +18 -0
  1537. package/dist/modules/purchase_backend/screens/rfqs-list.d.ts.map +1 -0
  1538. package/dist/modules/purchase_backend/screens/rfqs-list.js +28 -0
  1539. package/dist/modules/purchase_backend/screens/rfqs-list.js.map +1 -0
  1540. package/dist/modules/purchase_backend/screens/shared.d.ts +18 -0
  1541. package/dist/modules/purchase_backend/screens/shared.d.ts.map +1 -0
  1542. package/dist/modules/purchase_backend/screens/shared.js +30 -0
  1543. package/dist/modules/purchase_backend/screens/shared.js.map +1 -0
  1544. package/dist/modules/purchase_backend/screens/vendor-pricelist-create.d.ts +20 -0
  1545. package/dist/modules/purchase_backend/screens/vendor-pricelist-create.d.ts.map +1 -0
  1546. package/dist/modules/purchase_backend/screens/vendor-pricelist-create.js +25 -0
  1547. package/dist/modules/purchase_backend/screens/vendor-pricelist-create.js.map +1 -0
  1548. package/dist/modules/purchase_backend/screens/vendor-pricelists-list.d.ts +33 -0
  1549. package/dist/modules/purchase_backend/screens/vendor-pricelists-list.d.ts.map +1 -0
  1550. package/dist/modules/purchase_backend/screens/vendor-pricelists-list.js +73 -0
  1551. package/dist/modules/purchase_backend/screens/vendor-pricelists-list.js.map +1 -0
  1552. package/dist/modules/purchase_staff_channel/channel-routes.d.ts +2 -0
  1553. package/dist/modules/purchase_staff_channel/channel-routes.d.ts.map +1 -0
  1554. package/dist/modules/purchase_staff_channel/channel-routes.js +119 -0
  1555. package/dist/modules/purchase_staff_channel/channel-routes.js.map +1 -0
  1556. package/dist/modules/purchase_staff_channel/index.d.ts +8 -0
  1557. package/dist/modules/purchase_staff_channel/index.d.ts.map +1 -0
  1558. package/dist/modules/purchase_staff_channel/index.js +45 -0
  1559. package/dist/modules/purchase_staff_channel/index.js.map +1 -0
  1560. package/dist/modules/purchase_staff_channel/order-routes.d.ts +2 -0
  1561. package/dist/modules/purchase_staff_channel/order-routes.d.ts.map +1 -0
  1562. package/dist/modules/purchase_staff_channel/order-routes.js +754 -0
  1563. package/dist/modules/purchase_staff_channel/order-routes.js.map +1 -0
  1564. package/dist/modules/purchase_staff_channel/product-routes.d.ts +2 -0
  1565. package/dist/modules/purchase_staff_channel/product-routes.d.ts.map +1 -0
  1566. package/dist/modules/purchase_staff_channel/product-routes.js +183 -0
  1567. package/dist/modules/purchase_staff_channel/product-routes.js.map +1 -0
  1568. package/dist/modules/purchase_staff_channel/vendor-bill-routes.d.ts +2 -0
  1569. package/dist/modules/purchase_staff_channel/vendor-bill-routes.d.ts.map +1 -0
  1570. package/dist/modules/purchase_staff_channel/vendor-bill-routes.js +189 -0
  1571. package/dist/modules/purchase_staff_channel/vendor-bill-routes.js.map +1 -0
  1572. package/dist/modules/quality/functions.d.ts +3 -0
  1573. package/dist/modules/quality/functions.d.ts.map +1 -0
  1574. package/dist/modules/quality/functions.js +381 -0
  1575. package/dist/modules/quality/functions.js.map +1 -0
  1576. package/dist/modules/quality/index.d.ts +5 -0
  1577. package/dist/modules/quality/index.d.ts.map +1 -0
  1578. package/dist/modules/quality/index.js +19 -0
  1579. package/dist/modules/quality/index.js.map +1 -0
  1580. package/dist/modules/quality/models.d.ts +3 -0
  1581. package/dist/modules/quality/models.d.ts.map +1 -0
  1582. package/dist/modules/quality/models.js +91 -0
  1583. package/dist/modules/quality/models.js.map +1 -0
  1584. package/dist/modules/quality_staff_channel/channel-routes.d.ts +2 -0
  1585. package/dist/modules/quality_staff_channel/channel-routes.d.ts.map +1 -0
  1586. package/dist/modules/quality_staff_channel/channel-routes.js +495 -0
  1587. package/dist/modules/quality_staff_channel/channel-routes.js.map +1 -0
  1588. package/dist/modules/quality_staff_channel/index.d.ts +5 -0
  1589. package/dist/modules/quality_staff_channel/index.d.ts.map +1 -0
  1590. package/dist/modules/quality_staff_channel/index.js +30 -0
  1591. package/dist/modules/quality_staff_channel/index.js.map +1 -0
  1592. package/dist/modules/report/functions.d.ts +3 -0
  1593. package/dist/modules/report/functions.d.ts.map +1 -0
  1594. package/dist/modules/report/functions.js +197 -0
  1595. package/dist/modules/report/functions.js.map +1 -0
  1596. package/dist/modules/report/index.d.ts +3 -0
  1597. package/dist/modules/report/index.d.ts.map +1 -0
  1598. package/dist/modules/report/index.js +21 -0
  1599. package/dist/modules/report/index.js.map +1 -0
  1600. package/dist/modules/report/jobs.d.ts +3 -0
  1601. package/dist/modules/report/jobs.d.ts.map +1 -0
  1602. package/dist/modules/report/jobs.js +18 -0
  1603. package/dist/modules/report/jobs.js.map +1 -0
  1604. package/dist/modules/report/models.d.ts +3 -0
  1605. package/dist/modules/report/models.d.ts.map +1 -0
  1606. package/dist/modules/report/models.js +45 -0
  1607. package/dist/modules/report/models.js.map +1 -0
  1608. package/dist/modules/report/routes.d.ts +19 -0
  1609. package/dist/modules/report/routes.d.ts.map +1 -0
  1610. package/dist/modules/report/routes.js +138 -0
  1611. package/dist/modules/report/routes.js.map +1 -0
  1612. package/dist/modules/report_backend/index.d.ts +3 -0
  1613. package/dist/modules/report_backend/index.d.ts.map +1 -0
  1614. package/dist/modules/report_backend/index.js +67 -0
  1615. package/dist/modules/report_backend/index.js.map +1 -0
  1616. package/dist/modules/report_backend/routes.d.ts +10 -0
  1617. package/dist/modules/report_backend/routes.d.ts.map +1 -0
  1618. package/dist/modules/report_backend/routes.js +87 -0
  1619. package/dist/modules/report_backend/routes.js.map +1 -0
  1620. package/dist/modules/report_backend/screens/index.d.ts +13 -0
  1621. package/dist/modules/report_backend/screens/index.d.ts.map +1 -0
  1622. package/dist/modules/report_backend/screens/index.js +91 -0
  1623. package/dist/modules/report_backend/screens/index.js.map +1 -0
  1624. package/dist/modules/sale/functions.d.ts.map +1 -1
  1625. package/dist/modules/sale/functions.js +796 -238
  1626. package/dist/modules/sale/functions.js.map +1 -1
  1627. package/dist/modules/sale/index.d.ts.map +1 -1
  1628. package/dist/modules/sale/index.js +44 -5
  1629. package/dist/modules/sale/index.js.map +1 -1
  1630. package/dist/modules/sale/models.d.ts.map +1 -1
  1631. package/dist/modules/sale/models.js +47 -1
  1632. package/dist/modules/sale/models.js.map +1 -1
  1633. package/dist/modules/sale/relations.d.ts.map +1 -1
  1634. package/dist/modules/sale/relations.js +6 -0
  1635. package/dist/modules/sale/relations.js.map +1 -1
  1636. package/dist/modules/sale/reports.d.ts +4 -0
  1637. package/dist/modules/sale/reports.d.ts.map +1 -0
  1638. package/dist/modules/sale/reports.js +132 -0
  1639. package/dist/modules/sale/reports.js.map +1 -0
  1640. package/dist/modules/sale/scope.d.ts +31 -0
  1641. package/dist/modules/sale/scope.d.ts.map +1 -0
  1642. package/dist/modules/sale/scope.js +34 -0
  1643. package/dist/modules/sale/scope.js.map +1 -0
  1644. package/dist/modules/sale_activity_backend/index.d.ts.map +1 -1
  1645. package/dist/modules/sale_activity_backend/index.js +0 -1
  1646. package/dist/modules/sale_activity_backend/index.js.map +1 -1
  1647. package/dist/modules/sale_backend/index.js +338 -121
  1648. package/dist/modules/sale_backend/index.js.map +1 -1
  1649. package/dist/modules/sale_backend/screens/index.d.ts +9 -0
  1650. package/dist/modules/sale_backend/screens/index.d.ts.map +1 -0
  1651. package/dist/modules/sale_backend/screens/index.js +9 -0
  1652. package/dist/modules/sale_backend/screens/index.js.map +1 -0
  1653. package/dist/modules/sale_backend/screens/invoicing-policies-list.d.ts +14 -0
  1654. package/dist/modules/sale_backend/screens/invoicing-policies-list.d.ts.map +1 -0
  1655. package/dist/modules/sale_backend/screens/invoicing-policies-list.js +48 -0
  1656. package/dist/modules/sale_backend/screens/invoicing-policies-list.js.map +1 -0
  1657. package/dist/modules/sale_backend/screens/invoicing-policy-create.d.ts +14 -0
  1658. package/dist/modules/sale_backend/screens/invoicing-policy-create.d.ts.map +1 -0
  1659. package/dist/modules/sale_backend/screens/invoicing-policy-create.js +38 -0
  1660. package/dist/modules/sale_backend/screens/invoicing-policy-create.js.map +1 -0
  1661. package/dist/modules/sale_backend/screens/order-detail.d.ts +43 -0
  1662. package/dist/modules/sale_backend/screens/order-detail.d.ts.map +1 -0
  1663. package/dist/modules/sale_backend/screens/order-detail.js +226 -0
  1664. package/dist/modules/sale_backend/screens/order-detail.js.map +1 -0
  1665. package/dist/modules/sale_backend/screens/overview.d.ts +31 -0
  1666. package/dist/modules/sale_backend/screens/overview.d.ts.map +1 -0
  1667. package/dist/modules/sale_backend/screens/overview.js +73 -0
  1668. package/dist/modules/sale_backend/screens/overview.js.map +1 -0
  1669. package/dist/modules/sale_backend/screens/quotation-create.d.ts +13 -0
  1670. package/dist/modules/sale_backend/screens/quotation-create.d.ts.map +1 -0
  1671. package/dist/modules/sale_backend/screens/quotation-create.js +19 -0
  1672. package/dist/modules/sale_backend/screens/quotation-create.js.map +1 -0
  1673. package/dist/modules/sale_backend/screens/quotations-list.d.ts +25 -0
  1674. package/dist/modules/sale_backend/screens/quotations-list.d.ts.map +1 -0
  1675. package/dist/modules/sale_backend/screens/quotations-list.js +96 -0
  1676. package/dist/modules/sale_backend/screens/quotations-list.js.map +1 -0
  1677. package/dist/modules/sale_backend/screens/sales-orders-list.d.ts +25 -0
  1678. package/dist/modules/sale_backend/screens/sales-orders-list.d.ts.map +1 -0
  1679. package/dist/modules/sale_backend/screens/sales-orders-list.js +100 -0
  1680. package/dist/modules/sale_backend/screens/sales-orders-list.js.map +1 -0
  1681. package/dist/modules/sale_backend/screens/shared.d.ts +4 -0
  1682. package/dist/modules/sale_backend/screens/shared.d.ts.map +1 -0
  1683. package/dist/modules/sale_backend/screens/shared.js +4 -0
  1684. package/dist/modules/sale_backend/screens/shared.js.map +1 -0
  1685. package/dist/modules/sale_mail_backend/index.d.ts.map +1 -1
  1686. package/dist/modules/sale_mail_backend/index.js +0 -1
  1687. package/dist/modules/sale_mail_backend/index.js.map +1 -1
  1688. package/dist/modules/sale_staff_channel/channel-routes.d.ts +2 -0
  1689. package/dist/modules/sale_staff_channel/channel-routes.d.ts.map +1 -0
  1690. package/dist/modules/sale_staff_channel/channel-routes.js +296 -0
  1691. package/dist/modules/sale_staff_channel/channel-routes.js.map +1 -0
  1692. package/dist/modules/sale_staff_channel/index.d.ts +7 -0
  1693. package/dist/modules/sale_staff_channel/index.d.ts.map +1 -0
  1694. package/dist/modules/sale_staff_channel/index.js +44 -0
  1695. package/dist/modules/sale_staff_channel/index.js.map +1 -0
  1696. package/dist/modules/sale_staff_channel/order-routes.d.ts +2 -0
  1697. package/dist/modules/sale_staff_channel/order-routes.d.ts.map +1 -0
  1698. package/dist/modules/sale_staff_channel/order-routes.js +658 -0
  1699. package/dist/modules/sale_staff_channel/order-routes.js.map +1 -0
  1700. package/dist/modules/sale_staff_channel/product-routes.d.ts +2 -0
  1701. package/dist/modules/sale_staff_channel/product-routes.d.ts.map +1 -0
  1702. package/dist/modules/sale_staff_channel/product-routes.js +183 -0
  1703. package/dist/modules/sale_staff_channel/product-routes.js.map +1 -0
  1704. package/dist/modules/stock/functions.d.ts.map +1 -1
  1705. package/dist/modules/stock/functions.js +1239 -332
  1706. package/dist/modules/stock/functions.js.map +1 -1
  1707. package/dist/modules/stock/index.d.ts +2 -0
  1708. package/dist/modules/stock/index.d.ts.map +1 -1
  1709. package/dist/modules/stock/index.js +29 -6
  1710. package/dist/modules/stock/index.js.map +1 -1
  1711. package/dist/modules/stock/models.d.ts.map +1 -1
  1712. package/dist/modules/stock/models.js +1 -0
  1713. package/dist/modules/stock/models.js.map +1 -1
  1714. package/dist/modules/stock/reports.d.ts +4 -0
  1715. package/dist/modules/stock/reports.d.ts.map +1 -0
  1716. package/dist/modules/stock/reports.js +100 -0
  1717. package/dist/modules/stock/reports.js.map +1 -0
  1718. package/dist/modules/stock/routing.d.ts +1 -1
  1719. package/dist/modules/stock/routing.d.ts.map +1 -1
  1720. package/dist/modules/stock/routing.js +35 -30
  1721. package/dist/modules/stock/routing.js.map +1 -1
  1722. package/dist/modules/stock/scope.d.ts +23 -0
  1723. package/dist/modules/stock/scope.d.ts.map +1 -0
  1724. package/dist/modules/stock/scope.js +26 -0
  1725. package/dist/modules/stock/scope.js.map +1 -0
  1726. package/dist/modules/stock/units.d.ts +14 -0
  1727. package/dist/modules/stock/units.d.ts.map +1 -0
  1728. package/dist/modules/stock/units.js +50 -0
  1729. package/dist/modules/stock/units.js.map +1 -0
  1730. package/dist/modules/stock_activity_backend/index.d.ts.map +1 -1
  1731. package/dist/modules/stock_activity_backend/index.js +0 -1
  1732. package/dist/modules/stock_activity_backend/index.js.map +1 -1
  1733. package/dist/modules/stock_backend/client/editor-view.d.mts.map +1 -1
  1734. package/dist/modules/stock_backend/client/editor-view.mjs +12 -10
  1735. package/dist/modules/stock_backend/client/editor-view.mjs.map +1 -1
  1736. package/dist/modules/stock_backend/index.js +27 -20
  1737. package/dist/modules/stock_backend/index.js.map +1 -1
  1738. package/dist/modules/stock_backend/routes.d.ts.map +1 -1
  1739. package/dist/modules/stock_backend/routes.js +485 -232
  1740. package/dist/modules/stock_backend/routes.js.map +1 -1
  1741. package/dist/modules/stock_backend/screens/forecast.d.ts +28 -0
  1742. package/dist/modules/stock_backend/screens/forecast.d.ts.map +1 -0
  1743. package/dist/modules/stock_backend/screens/forecast.js +108 -0
  1744. package/dist/modules/stock_backend/screens/forecast.js.map +1 -0
  1745. package/dist/modules/stock_backend/screens/index.d.ts +22 -0
  1746. package/dist/modules/stock_backend/screens/index.d.ts.map +1 -0
  1747. package/dist/modules/stock_backend/screens/index.js +22 -0
  1748. package/dist/modules/stock_backend/screens/index.js.map +1 -0
  1749. package/dist/modules/stock_backend/screens/inventory.d.ts +27 -0
  1750. package/dist/modules/stock_backend/screens/inventory.d.ts.map +1 -0
  1751. package/dist/modules/stock_backend/screens/inventory.js +128 -0
  1752. package/dist/modules/stock_backend/screens/inventory.js.map +1 -0
  1753. package/dist/modules/stock_backend/screens/location-create.d.ts +15 -0
  1754. package/dist/modules/stock_backend/screens/location-create.d.ts.map +1 -0
  1755. package/dist/modules/stock_backend/screens/location-create.js +75 -0
  1756. package/dist/modules/stock_backend/screens/location-create.js.map +1 -0
  1757. package/dist/modules/stock_backend/screens/locations-list.d.ts +21 -0
  1758. package/dist/modules/stock_backend/screens/locations-list.d.ts.map +1 -0
  1759. package/dist/modules/stock_backend/screens/locations-list.js +62 -0
  1760. package/dist/modules/stock_backend/screens/locations-list.js.map +1 -0
  1761. package/dist/modules/stock_backend/screens/lot-create.d.ts +14 -0
  1762. package/dist/modules/stock_backend/screens/lot-create.d.ts.map +1 -0
  1763. package/dist/modules/stock_backend/screens/lot-create.js +60 -0
  1764. package/dist/modules/stock_backend/screens/lot-create.js.map +1 -0
  1765. package/dist/modules/stock_backend/screens/lot-detail.d.ts +30 -0
  1766. package/dist/modules/stock_backend/screens/lot-detail.d.ts.map +1 -0
  1767. package/dist/modules/stock_backend/screens/lot-detail.js +84 -0
  1768. package/dist/modules/stock_backend/screens/lot-detail.js.map +1 -0
  1769. package/dist/modules/stock_backend/screens/lots-list.d.ts +25 -0
  1770. package/dist/modules/stock_backend/screens/lots-list.d.ts.map +1 -0
  1771. package/dist/modules/stock_backend/screens/lots-list.js +54 -0
  1772. package/dist/modules/stock_backend/screens/lots-list.js.map +1 -0
  1773. package/dist/modules/stock_backend/screens/picking-type-create.d.ts +15 -0
  1774. package/dist/modules/stock_backend/screens/picking-type-create.d.ts.map +1 -0
  1775. package/dist/modules/stock_backend/screens/picking-type-create.js +89 -0
  1776. package/dist/modules/stock_backend/screens/picking-type-create.js.map +1 -0
  1777. package/dist/modules/stock_backend/screens/picking-types-list.d.ts +22 -0
  1778. package/dist/modules/stock_backend/screens/picking-types-list.d.ts.map +1 -0
  1779. package/dist/modules/stock_backend/screens/picking-types-list.js +80 -0
  1780. package/dist/modules/stock_backend/screens/picking-types-list.js.map +1 -0
  1781. package/dist/modules/stock_backend/screens/replenishment-create.d.ts +17 -0
  1782. package/dist/modules/stock_backend/screens/replenishment-create.d.ts.map +1 -0
  1783. package/dist/modules/stock_backend/screens/replenishment-create.js +74 -0
  1784. package/dist/modules/stock_backend/screens/replenishment-create.js.map +1 -0
  1785. package/dist/modules/stock_backend/screens/replenishment-list.d.ts +29 -0
  1786. package/dist/modules/stock_backend/screens/replenishment-list.d.ts.map +1 -0
  1787. package/dist/modules/stock_backend/screens/replenishment-list.js +84 -0
  1788. package/dist/modules/stock_backend/screens/replenishment-list.js.map +1 -0
  1789. package/dist/modules/stock_backend/screens/shared.d.ts +12 -0
  1790. package/dist/modules/stock_backend/screens/shared.d.ts.map +1 -0
  1791. package/dist/modules/stock_backend/screens/shared.js +29 -0
  1792. package/dist/modules/stock_backend/screens/shared.js.map +1 -0
  1793. package/dist/modules/stock_backend/screens/stock-route-create.d.ts +13 -0
  1794. package/dist/modules/stock_backend/screens/stock-route-create.d.ts.map +1 -0
  1795. package/dist/modules/stock_backend/screens/stock-route-create.js +52 -0
  1796. package/dist/modules/stock_backend/screens/stock-route-create.js.map +1 -0
  1797. package/dist/modules/stock_backend/screens/stock-route-detail.d.ts +30 -0
  1798. package/dist/modules/stock_backend/screens/stock-route-detail.d.ts.map +1 -0
  1799. package/dist/modules/stock_backend/screens/stock-route-detail.js +131 -0
  1800. package/dist/modules/stock_backend/screens/stock-route-detail.js.map +1 -0
  1801. package/dist/modules/stock_backend/screens/stock-routes-list.d.ts +22 -0
  1802. package/dist/modules/stock_backend/screens/stock-routes-list.d.ts.map +1 -0
  1803. package/dist/modules/stock_backend/screens/stock-routes-list.js +51 -0
  1804. package/dist/modules/stock_backend/screens/stock-routes-list.js.map +1 -0
  1805. package/dist/modules/stock_backend/screens/stock.d.ts +7 -0
  1806. package/dist/modules/stock_backend/screens/stock.d.ts.map +1 -0
  1807. package/dist/modules/stock_backend/screens/stock.js +13 -0
  1808. package/dist/modules/stock_backend/screens/stock.js.map +1 -0
  1809. package/dist/modules/stock_backend/screens/transfer-create.d.ts +13 -0
  1810. package/dist/modules/stock_backend/screens/transfer-create.d.ts.map +1 -0
  1811. package/dist/modules/stock_backend/screens/transfer-create.js +38 -0
  1812. package/dist/modules/stock_backend/screens/transfer-create.js.map +1 -0
  1813. package/dist/modules/stock_backend/screens/transfer-detail.d.ts +27 -0
  1814. package/dist/modules/stock_backend/screens/transfer-detail.d.ts.map +1 -0
  1815. package/dist/modules/stock_backend/screens/transfer-detail.js +91 -0
  1816. package/dist/modules/stock_backend/screens/transfer-detail.js.map +1 -0
  1817. package/dist/modules/stock_backend/screens/transfers-list.d.ts +25 -0
  1818. package/dist/modules/stock_backend/screens/transfers-list.d.ts.map +1 -0
  1819. package/dist/modules/stock_backend/screens/transfers-list.js +81 -0
  1820. package/dist/modules/stock_backend/screens/transfers-list.js.map +1 -0
  1821. package/dist/modules/stock_backend/screens/warehouse-create.d.ts +13 -0
  1822. package/dist/modules/stock_backend/screens/warehouse-create.d.ts.map +1 -0
  1823. package/dist/modules/stock_backend/screens/warehouse-create.js +79 -0
  1824. package/dist/modules/stock_backend/screens/warehouse-create.js.map +1 -0
  1825. package/dist/modules/stock_backend/screens/warehouses-list.d.ts +21 -0
  1826. package/dist/modules/stock_backend/screens/warehouses-list.d.ts.map +1 -0
  1827. package/dist/modules/stock_backend/screens/warehouses-list.js +60 -0
  1828. package/dist/modules/stock_backend/screens/warehouses-list.js.map +1 -0
  1829. package/dist/modules/stock_lot_activity_backend/index.d.ts.map +1 -1
  1830. package/dist/modules/stock_lot_activity_backend/index.js +0 -1
  1831. package/dist/modules/stock_lot_activity_backend/index.js.map +1 -1
  1832. package/dist/modules/stock_lot_mail_backend/index.d.ts.map +1 -1
  1833. package/dist/modules/stock_lot_mail_backend/index.js +0 -1
  1834. package/dist/modules/stock_lot_mail_backend/index.js.map +1 -1
  1835. package/dist/modules/stock_mail_backend/index.d.ts.map +1 -1
  1836. package/dist/modules/stock_mail_backend/index.js +0 -1
  1837. package/dist/modules/stock_mail_backend/index.js.map +1 -1
  1838. package/dist/modules/stock_mail_inbound/index.d.ts.map +1 -1
  1839. package/dist/modules/stock_mail_inbound/index.js +0 -2
  1840. package/dist/modules/stock_mail_inbound/index.js.map +1 -1
  1841. package/dist/modules/stock_staff_channel/channel-routes.d.ts +656 -0
  1842. package/dist/modules/stock_staff_channel/channel-routes.d.ts.map +1 -0
  1843. package/dist/modules/stock_staff_channel/channel-routes.js +445 -0
  1844. package/dist/modules/stock_staff_channel/channel-routes.js.map +1 -0
  1845. package/dist/modules/stock_staff_channel/functions.d.ts +3 -0
  1846. package/dist/modules/stock_staff_channel/functions.d.ts.map +1 -0
  1847. package/dist/modules/stock_staff_channel/functions.js +954 -0
  1848. package/dist/modules/stock_staff_channel/functions.js.map +1 -0
  1849. package/dist/modules/stock_staff_channel/index.d.ts +8 -0
  1850. package/dist/modules/stock_staff_channel/index.d.ts.map +1 -0
  1851. package/dist/modules/stock_staff_channel/index.js +37 -0
  1852. package/dist/modules/stock_staff_channel/index.js.map +1 -0
  1853. package/dist/modules/stock_staff_channel/models.d.ts +4 -0
  1854. package/dist/modules/stock_staff_channel/models.d.ts.map +1 -0
  1855. package/dist/modules/stock_staff_channel/models.js +119 -0
  1856. package/dist/modules/stock_staff_channel/models.js.map +1 -0
  1857. package/dist/modules/stock_staff_channel/operation-routes.d.ts +2 -0
  1858. package/dist/modules/stock_staff_channel/operation-routes.d.ts.map +1 -0
  1859. package/dist/modules/stock_staff_channel/operation-routes.js +1269 -0
  1860. package/dist/modules/stock_staff_channel/operation-routes.js.map +1 -0
  1861. package/dist/modules/storage/functions.d.ts.map +1 -1
  1862. package/dist/modules/storage/functions.js +18 -5
  1863. package/dist/modules/storage/functions.js.map +1 -1
  1864. package/dist/modules/storage/index.js +0 -1
  1865. package/dist/modules/storage/index.js.map +1 -1
  1866. package/dist/modules/storage/jobs.d.ts +21 -1
  1867. package/dist/modules/storage/jobs.d.ts.map +1 -1
  1868. package/dist/modules/storage/jobs.js +142 -2
  1869. package/dist/modules/storage/jobs.js.map +1 -1
  1870. package/dist/modules/storage/models.d.ts.map +1 -1
  1871. package/dist/modules/storage/models.js +2 -0
  1872. package/dist/modules/storage/models.js.map +1 -1
  1873. package/dist/modules/storage/policy.d.ts +5 -0
  1874. package/dist/modules/storage/policy.d.ts.map +1 -0
  1875. package/dist/modules/storage/policy.js +13 -0
  1876. package/dist/modules/storage/policy.js.map +1 -0
  1877. package/dist/modules/storage/routes.d.ts +1 -0
  1878. package/dist/modules/storage/routes.d.ts.map +1 -1
  1879. package/dist/modules/storage/routes.js +19 -15
  1880. package/dist/modules/storage/routes.js.map +1 -1
  1881. package/dist/modules/uom/convert.d.ts +1 -1
  1882. package/dist/modules/uom/convert.js +2 -2
  1883. package/dist/modules/uom/convert.js.map +1 -1
  1884. package/dist/modules/uom/functions.d.ts.map +1 -1
  1885. package/dist/modules/uom/functions.js +39 -4
  1886. package/dist/modules/uom/functions.js.map +1 -1
  1887. package/dist/modules/uom/index.d.ts.map +1 -1
  1888. package/dist/modules/uom/index.js +1 -2
  1889. package/dist/modules/uom/index.js.map +1 -1
  1890. package/dist/modules/uom/messages.js +2 -2
  1891. package/dist/modules/uom/messages.js.map +1 -1
  1892. package/dist/modules/uom/models.d.ts +1 -1
  1893. package/dist/modules/uom/models.d.ts.map +1 -1
  1894. package/dist/modules/uom/models.js +1 -1
  1895. package/dist/modules/uom/models.js.map +1 -1
  1896. package/dist/modules/user/authorization.d.ts +80 -0
  1897. package/dist/modules/user/authorization.d.ts.map +1 -0
  1898. package/dist/modules/user/authorization.js +1039 -0
  1899. package/dist/modules/user/authorization.js.map +1 -0
  1900. package/dist/modules/user/functions.d.ts.map +1 -1
  1901. package/dist/modules/user/functions.js +188 -32
  1902. package/dist/modules/user/functions.js.map +1 -1
  1903. package/dist/modules/user/index.d.ts +4 -1
  1904. package/dist/modules/user/index.d.ts.map +1 -1
  1905. package/dist/modules/user/index.js +2 -3
  1906. package/dist/modules/user/index.js.map +1 -1
  1907. package/dist/modules/user/login.d.ts +1 -27
  1908. package/dist/modules/user/login.d.ts.map +1 -1
  1909. package/dist/modules/user/login.js +5 -45
  1910. package/dist/modules/user/login.js.map +1 -1
  1911. package/dist/modules/user/messages.d.ts +6 -0
  1912. package/dist/modules/user/messages.d.ts.map +1 -1
  1913. package/dist/modules/user/messages.js +6 -0
  1914. package/dist/modules/user/messages.js.map +1 -1
  1915. package/dist/modules/user/models.d.ts +1 -1
  1916. package/dist/modules/user/models.d.ts.map +1 -1
  1917. package/dist/modules/user/models.js +73 -9
  1918. package/dist/modules/user/models.js.map +1 -1
  1919. package/dist/modules/user/relations.d.ts.map +1 -1
  1920. package/dist/modules/user/relations.js +6 -0
  1921. package/dist/modules/user/relations.js.map +1 -1
  1922. package/dist/modules/user/roles.d.ts +11 -1
  1923. package/dist/modules/user/roles.d.ts.map +1 -1
  1924. package/dist/modules/user/roles.js +402 -117
  1925. package/dist/modules/user/roles.js.map +1 -1
  1926. package/dist/modules/user/routes.js +1 -1
  1927. package/dist/modules/user/routes.js.map +1 -1
  1928. package/dist/modules/user_backend/index.d.ts +1 -1
  1929. package/dist/modules/user_backend/index.d.ts.map +1 -1
  1930. package/dist/modules/user_backend/index.js +1 -3
  1931. package/dist/modules/user_backend/index.js.map +1 -1
  1932. package/dist/modules/user_backend/messages.d.ts +60 -0
  1933. package/dist/modules/user_backend/messages.d.ts.map +1 -1
  1934. package/dist/modules/user_backend/messages.js +60 -0
  1935. package/dist/modules/user_backend/messages.js.map +1 -1
  1936. package/dist/modules/user_backend/routes.d.ts.map +1 -1
  1937. package/dist/modules/user_backend/routes.js +352 -69
  1938. package/dist/modules/user_backend/routes.js.map +1 -1
  1939. package/dist/modules/user_backend/screens/index.d.ts +11 -0
  1940. package/dist/modules/user_backend/screens/index.d.ts.map +1 -0
  1941. package/dist/modules/user_backend/screens/index.js +8 -0
  1942. package/dist/modules/user_backend/screens/index.js.map +1 -0
  1943. package/dist/modules/user_backend/screens/presets-form.d.ts +16 -0
  1944. package/dist/modules/user_backend/screens/presets-form.d.ts.map +1 -0
  1945. package/dist/modules/user_backend/screens/presets-form.js +37 -0
  1946. package/dist/modules/user_backend/screens/presets-form.js.map +1 -0
  1947. package/dist/modules/user_backend/screens/profile-form.d.ts +14 -0
  1948. package/dist/modules/user_backend/screens/profile-form.d.ts.map +1 -0
  1949. package/dist/modules/user_backend/screens/profile-form.js +37 -0
  1950. package/dist/modules/user_backend/screens/profile-form.js.map +1 -0
  1951. package/dist/modules/user_backend/screens/role-form.d.ts +21 -0
  1952. package/dist/modules/user_backend/screens/role-form.d.ts.map +1 -0
  1953. package/dist/modules/user_backend/screens/role-form.js +93 -0
  1954. package/dist/modules/user_backend/screens/role-form.js.map +1 -0
  1955. package/dist/modules/user_backend/screens/roles-list.d.ts +15 -0
  1956. package/dist/modules/user_backend/screens/roles-list.d.ts.map +1 -0
  1957. package/dist/modules/user_backend/screens/roles-list.js +48 -0
  1958. package/dist/modules/user_backend/screens/roles-list.js.map +1 -0
  1959. package/dist/modules/user_backend/screens/sessions.d.ts +5 -0
  1960. package/dist/modules/user_backend/screens/sessions.d.ts.map +1 -0
  1961. package/dist/modules/user_backend/screens/sessions.js +35 -0
  1962. package/dist/modules/user_backend/screens/sessions.js.map +1 -0
  1963. package/dist/modules/user_backend/screens/types.d.ts +68 -0
  1964. package/dist/modules/user_backend/screens/types.d.ts.map +1 -0
  1965. package/dist/modules/user_backend/screens/types.js +2 -0
  1966. package/dist/modules/user_backend/screens/types.js.map +1 -0
  1967. package/dist/modules/user_backend/screens/user-form.d.ts +55 -0
  1968. package/dist/modules/user_backend/screens/user-form.d.ts.map +1 -0
  1969. package/dist/modules/user_backend/screens/user-form.js +174 -0
  1970. package/dist/modules/user_backend/screens/user-form.js.map +1 -0
  1971. package/dist/modules/user_backend/screens/users-list.d.ts +17 -0
  1972. package/dist/modules/user_backend/screens/users-list.d.ts.map +1 -0
  1973. package/dist/modules/user_backend/screens/users-list.js +56 -0
  1974. package/dist/modules/user_backend/screens/users-list.js.map +1 -0
  1975. package/dist/modules/website/cms.d.ts +18 -1
  1976. package/dist/modules/website/cms.d.ts.map +1 -1
  1977. package/dist/modules/website/cms.js +373 -38
  1978. package/dist/modules/website/cms.js.map +1 -1
  1979. package/dist/modules/website/customer.d.ts.map +1 -1
  1980. package/dist/modules/website/customer.js +249 -1
  1981. package/dist/modules/website/customer.js.map +1 -1
  1982. package/dist/modules/website/index.d.ts.map +1 -1
  1983. package/dist/modules/website/index.js +26 -4
  1984. package/dist/modules/website/index.js.map +1 -1
  1985. package/dist/modules/website/models.d.ts.map +1 -1
  1986. package/dist/modules/website/models.js +101 -0
  1987. package/dist/modules/website/models.js.map +1 -1
  1988. package/dist/modules/website/paths.d.ts +31 -0
  1989. package/dist/modules/website/paths.d.ts.map +1 -0
  1990. package/dist/modules/website/paths.js +48 -0
  1991. package/dist/modules/website/paths.js.map +1 -0
  1992. package/dist/modules/website/publication.d.ts +3 -0
  1993. package/dist/modules/website/publication.d.ts.map +1 -0
  1994. package/dist/modules/website/publication.js +366 -0
  1995. package/dist/modules/website/publication.js.map +1 -0
  1996. package/dist/modules/website/renderable.d.ts +32 -0
  1997. package/dist/modules/website/renderable.d.ts.map +1 -0
  1998. package/dist/modules/website/renderable.js +59 -0
  1999. package/dist/modules/website/renderable.js.map +1 -0
  2000. package/dist/modules/website/sections.d.ts.map +1 -1
  2001. package/dist/modules/website/sections.js +13 -0
  2002. package/dist/modules/website/sections.js.map +1 -1
  2003. package/dist/modules/website_backend/csv.d.ts +23 -0
  2004. package/dist/modules/website_backend/csv.d.ts.map +1 -0
  2005. package/dist/modules/website_backend/csv.js +31 -0
  2006. package/dist/modules/website_backend/csv.js.map +1 -0
  2007. package/dist/modules/website_backend/index.js +260 -2
  2008. package/dist/modules/website_backend/index.js.map +1 -1
  2009. package/dist/modules/website_backend/menus.d.ts.map +1 -1
  2010. package/dist/modules/website_backend/menus.js +28 -6
  2011. package/dist/modules/website_backend/menus.js.map +1 -1
  2012. package/dist/modules/website_backend/routes.d.ts.map +1 -1
  2013. package/dist/modules/website_backend/routes.js +684 -126
  2014. package/dist/modules/website_backend/routes.js.map +1 -1
  2015. package/dist/modules/website_backend/screens/index.d.ts +333 -0
  2016. package/dist/modules/website_backend/screens/index.d.ts.map +1 -0
  2017. package/dist/modules/website_backend/screens/index.js +1332 -0
  2018. package/dist/modules/website_backend/screens/index.js.map +1 -0
  2019. package/dist/modules/website_backend/screens/page-frame.d.ts +14 -0
  2020. package/dist/modules/website_backend/screens/page-frame.d.ts.map +1 -0
  2021. package/dist/modules/website_backend/screens/page-frame.js +13 -0
  2022. package/dist/modules/website_backend/screens/page-frame.js.map +1 -0
  2023. package/dist/modules/website_form/audit.d.ts +27 -0
  2024. package/dist/modules/website_form/audit.d.ts.map +1 -0
  2025. package/dist/modules/website_form/audit.js +30 -0
  2026. package/dist/modules/website_form/audit.js.map +1 -0
  2027. package/dist/modules/website_form/functions.d.ts.map +1 -1
  2028. package/dist/modules/website_form/functions.js +416 -12
  2029. package/dist/modules/website_form/functions.js.map +1 -1
  2030. package/dist/modules/website_form/index.js +24 -2
  2031. package/dist/modules/website_form/index.js.map +1 -1
  2032. package/dist/modules/website_form/jobs.d.ts +11 -0
  2033. package/dist/modules/website_form/jobs.d.ts.map +1 -0
  2034. package/dist/modules/website_form/jobs.js +80 -0
  2035. package/dist/modules/website_form/jobs.js.map +1 -0
  2036. package/dist/modules/website_form/models.d.ts.map +1 -1
  2037. package/dist/modules/website_form/models.js +89 -0
  2038. package/dist/modules/website_form/models.js.map +1 -1
  2039. package/dist/modules/website_form/purge.d.ts +22 -0
  2040. package/dist/modules/website_form/purge.d.ts.map +1 -0
  2041. package/dist/modules/website_form/purge.js +59 -0
  2042. package/dist/modules/website_form/purge.js.map +1 -0
  2043. package/dist/modules/website_form/retention.d.ts +70 -0
  2044. package/dist/modules/website_form/retention.d.ts.map +1 -0
  2045. package/dist/modules/website_form/retention.js +145 -0
  2046. package/dist/modules/website_form/retention.js.map +1 -0
  2047. package/dist/modules/website_form/routes.d.ts.map +1 -1
  2048. package/dist/modules/website_form/routes.js +37 -3
  2049. package/dist/modules/website_form/routes.js.map +1 -1
  2050. package/dist/modules/website_form_mail/index.d.ts +36 -0
  2051. package/dist/modules/website_form_mail/index.d.ts.map +1 -0
  2052. package/dist/modules/website_form_mail/index.js +137 -0
  2053. package/dist/modules/website_form_mail/index.js.map +1 -0
  2054. package/dist/modules/website_hospitality/channel-routes.d.ts +2 -0
  2055. package/dist/modules/website_hospitality/channel-routes.d.ts.map +1 -0
  2056. package/dist/modules/website_hospitality/channel-routes.js +355 -0
  2057. package/dist/modules/website_hospitality/channel-routes.js.map +1 -0
  2058. package/dist/modules/website_hospitality/functions.d.ts.map +1 -1
  2059. package/dist/modules/website_hospitality/functions.js +27 -2
  2060. package/dist/modules/website_hospitality/functions.js.map +1 -1
  2061. package/dist/modules/website_hospitality/index.js +4 -3
  2062. package/dist/modules/website_hospitality/index.js.map +1 -1
  2063. package/dist/modules/website_hospitality/models.d.ts.map +1 -1
  2064. package/dist/modules/website_hospitality/models.js +2 -0
  2065. package/dist/modules/website_hospitality/models.js.map +1 -1
  2066. package/dist/modules/website_menu/functions.d.ts.map +1 -1
  2067. package/dist/modules/website_menu/functions.js +184 -9
  2068. package/dist/modules/website_menu/functions.js.map +1 -1
  2069. package/dist/modules/website_menu/index.js +6 -1
  2070. package/dist/modules/website_menu/index.js.map +1 -1
  2071. package/dist/modules/website_retail/channel-routes.d.ts +2 -0
  2072. package/dist/modules/website_retail/channel-routes.d.ts.map +1 -0
  2073. package/dist/modules/website_retail/channel-routes.js +305 -0
  2074. package/dist/modules/website_retail/channel-routes.js.map +1 -0
  2075. package/dist/modules/website_retail/functions.d.ts +14 -1
  2076. package/dist/modules/website_retail/functions.d.ts.map +1 -1
  2077. package/dist/modules/website_retail/functions.js +6 -6
  2078. package/dist/modules/website_retail/functions.js.map +1 -1
  2079. package/dist/modules/website_retail/index.js +24 -3
  2080. package/dist/modules/website_retail/index.js.map +1 -1
  2081. package/dist/modules/website_retail/models.d.ts.map +1 -1
  2082. package/dist/modules/website_retail/models.js +30 -0
  2083. package/dist/modules/website_retail/models.js.map +1 -1
  2084. package/dist/modules/website_retail/online.d.ts +3 -0
  2085. package/dist/modules/website_retail/online.d.ts.map +1 -0
  2086. package/dist/modules/website_retail/online.js +710 -0
  2087. package/dist/modules/website_retail/online.js.map +1 -0
  2088. package/dist/modules/website_search/client/search.d.mts +16 -2
  2089. package/dist/modules/website_search/client/search.d.mts.map +1 -1
  2090. package/dist/modules/website_search/client/search.mjs +112 -6
  2091. package/dist/modules/website_search/client/search.mjs.map +1 -1
  2092. package/dist/modules/website_search/functions.d.ts +3 -0
  2093. package/dist/modules/website_search/functions.d.ts.map +1 -0
  2094. package/dist/modules/website_search/functions.js +239 -0
  2095. package/dist/modules/website_search/functions.js.map +1 -0
  2096. package/dist/modules/website_search/index.js +4 -1
  2097. package/dist/modules/website_search/index.js.map +1 -1
  2098. package/dist/modules/website_search/islands.d.ts +6 -0
  2099. package/dist/modules/website_search/islands.d.ts.map +1 -1
  2100. package/dist/modules/website_search/islands.js +8 -2
  2101. package/dist/modules/website_search/islands.js.map +1 -1
  2102. package/dist/modules/website_search/models.d.ts +15 -0
  2103. package/dist/modules/website_search/models.d.ts.map +1 -0
  2104. package/dist/modules/website_search/models.js +58 -0
  2105. package/dist/modules/website_search/models.js.map +1 -0
  2106. package/dist/modules/website_seo/functions.d.ts +3 -0
  2107. package/dist/modules/website_seo/functions.d.ts.map +1 -0
  2108. package/dist/modules/website_seo/functions.js +164 -0
  2109. package/dist/modules/website_seo/functions.js.map +1 -0
  2110. package/dist/modules/website_seo/index.js +15 -5
  2111. package/dist/modules/website_seo/index.js.map +1 -1
  2112. package/dist/modules/website_seo/projection.d.ts +52 -0
  2113. package/dist/modules/website_seo/projection.d.ts.map +1 -0
  2114. package/dist/modules/website_seo/projection.js +129 -0
  2115. package/dist/modules/website_seo/projection.js.map +1 -0
  2116. package/dist/modules/website_seo/routes.d.ts +3 -0
  2117. package/dist/modules/website_seo/routes.d.ts.map +1 -0
  2118. package/dist/modules/website_seo/routes.js +56 -0
  2119. package/dist/modules/website_seo/routes.js.map +1 -0
  2120. package/dist/permission-catalogue.d.ts +5 -0
  2121. package/dist/permission-catalogue.d.ts.map +1 -0
  2122. package/dist/permission-catalogue.js +1505 -0
  2123. package/dist/permission-catalogue.js.map +1 -0
  2124. package/dist/scaffold/index.d.ts +2 -0
  2125. package/dist/scaffold/index.d.ts.map +1 -0
  2126. package/dist/scaffold/index.js +31 -0
  2127. package/dist/scaffold/index.js.map +1 -0
  2128. package/dist/scaffold/templates/README.md.tmpl +17 -0
  2129. package/dist/scaffold/templates/gitignore.tmpl +2 -0
  2130. package/dist/scaffold/templates/ket.workspace.mjs.tmpl +1 -0
  2131. package/dist/scaffold/templates/package.json.tmpl +15 -0
  2132. package/dist/themes/hospitality/templates/website.columns.ktl +4 -0
  2133. package/dist/themes/paper/templates/website.columns.ktl +4 -0
  2134. package/dist/ui/actions.d.ts +4 -0
  2135. package/dist/ui/actions.d.ts.map +1 -1
  2136. package/dist/ui/actions.js +1 -1
  2137. package/dist/ui/actions.js.map +1 -1
  2138. package/dist/ui/activity.d.ts +1 -1
  2139. package/dist/ui/activity.d.ts.map +1 -1
  2140. package/dist/ui/activity.js +3 -5
  2141. package/dist/ui/activity.js.map +1 -1
  2142. package/dist/ui/attachments.js +1 -1
  2143. package/dist/ui/attachments.js.map +1 -1
  2144. package/dist/ui/auth.d.ts +36 -0
  2145. package/dist/ui/auth.d.ts.map +1 -1
  2146. package/dist/ui/auth.js +55 -0
  2147. package/dist/ui/auth.js.map +1 -1
  2148. package/dist/ui/board-page.d.ts +6 -0
  2149. package/dist/ui/board-page.d.ts.map +1 -0
  2150. package/dist/ui/board-page.js +4 -0
  2151. package/dist/ui/board-page.js.map +1 -0
  2152. package/dist/ui/charts.d.ts +83 -0
  2153. package/dist/ui/charts.d.ts.map +1 -0
  2154. package/dist/ui/charts.js +105 -0
  2155. package/dist/ui/charts.js.map +1 -0
  2156. package/dist/ui/chrome.d.ts +37 -2
  2157. package/dist/ui/chrome.d.ts.map +1 -1
  2158. package/dist/ui/chrome.js +39 -5
  2159. package/dist/ui/chrome.js.map +1 -1
  2160. package/dist/ui/client/activity-view.mjs +7 -7
  2161. package/dist/ui/client/activity-view.mjs.map +1 -1
  2162. package/dist/ui/client/activity.css +6 -34
  2163. package/dist/ui/client/calendar-view.d.mts.map +1 -1
  2164. package/dist/ui/client/calendar-view.mjs +7 -6
  2165. package/dist/ui/client/calendar-view.mjs.map +1 -1
  2166. package/dist/ui/client/calendar.css +4 -14
  2167. package/dist/ui/client/chart-view.d.ts +51 -0
  2168. package/dist/ui/client/chart-view.d.ts.map +1 -0
  2169. package/dist/ui/client/chart-view.js +192 -0
  2170. package/dist/ui/client/chart-view.js.map +1 -0
  2171. package/dist/ui/client/flow-app.css +387 -0
  2172. package/dist/ui/client/flow-board-view.d.mts +8 -0
  2173. package/dist/ui/client/flow-board-view.d.mts.map +1 -0
  2174. package/dist/ui/client/flow-board-view.mjs +161 -0
  2175. package/dist/ui/client/flow-board-view.mjs.map +1 -0
  2176. package/dist/ui/client/flow-board.d.mts +3 -0
  2177. package/dist/ui/client/flow-board.d.mts.map +1 -0
  2178. package/dist/ui/client/flow-board.mjs +7 -0
  2179. package/dist/ui/client/flow-board.mjs.map +1 -0
  2180. package/dist/ui/client/flow-map-view.d.mts +2 -0
  2181. package/dist/ui/client/flow-map-view.d.mts.map +1 -0
  2182. package/dist/ui/client/flow-map-view.mjs +235 -0
  2183. package/dist/ui/client/flow-map-view.mjs.map +1 -0
  2184. package/dist/ui/client/flow-map.d.mts +3 -0
  2185. package/dist/ui/client/flow-map.d.mts.map +1 -0
  2186. package/dist/ui/client/flow-map.mjs +7 -0
  2187. package/dist/ui/client/flow-map.mjs.map +1 -0
  2188. package/dist/ui/client/live-doc-blocks.d.ts +19 -0
  2189. package/dist/ui/client/live-doc-blocks.d.ts.map +1 -0
  2190. package/dist/ui/client/live-doc-blocks.js +23 -0
  2191. package/dist/ui/client/live-doc-blocks.js.map +1 -0
  2192. package/dist/ui/client/live-doc-markdown.d.ts +18 -0
  2193. package/dist/ui/client/live-doc-markdown.d.ts.map +1 -0
  2194. package/dist/ui/client/live-doc-markdown.js +175 -0
  2195. package/dist/ui/client/live-doc-markdown.js.map +1 -0
  2196. package/dist/ui/client/live-doc-shell.d.ts +101 -0
  2197. package/dist/ui/client/live-doc-shell.d.ts.map +1 -0
  2198. package/dist/ui/client/live-doc-shell.js +251 -0
  2199. package/dist/ui/client/live-doc-shell.js.map +1 -0
  2200. package/dist/ui/client/live-doc-view.d.ts +33 -0
  2201. package/dist/ui/client/live-doc-view.d.ts.map +1 -0
  2202. package/dist/ui/client/live-doc-view.js +1237 -0
  2203. package/dist/ui/client/live-doc-view.js.map +1 -0
  2204. package/dist/ui/client/live-doc.css +243 -0
  2205. package/dist/ui/client/live-doc.d.mts +12 -0
  2206. package/dist/ui/client/live-doc.d.mts.map +1 -0
  2207. package/dist/ui/client/live-doc.mjs +11 -0
  2208. package/dist/ui/client/live-doc.mjs.map +7 -0
  2209. package/dist/ui/client/mail-bundle.d.mts +9 -0
  2210. package/dist/ui/client/mail-bundle.d.mts.map +1 -0
  2211. package/dist/ui/client/mail-bundle.mjs +50 -0
  2212. package/dist/ui/client/mail-bundle.mjs.map +7 -0
  2213. package/dist/ui/client/mail-entry.d.mts +11 -0
  2214. package/dist/ui/client/mail-entry.d.mts.map +1 -0
  2215. package/dist/ui/client/mail-entry.mjs +9 -0
  2216. package/dist/ui/client/mail-entry.mjs.map +1 -0
  2217. package/dist/ui/client/mail-view.d.mts.map +1 -1
  2218. package/dist/ui/client/mail-view.mjs +5 -3
  2219. package/dist/ui/client/mail-view.mjs.map +1 -1
  2220. package/dist/ui/client/mail.css +3 -3
  2221. package/dist/ui/client/relation-select-view.d.ts +77 -0
  2222. package/dist/ui/client/relation-select-view.d.ts.map +1 -0
  2223. package/dist/ui/client/relation-select-view.js +216 -0
  2224. package/dist/ui/client/relation-select-view.js.map +1 -0
  2225. package/dist/ui/client/table-selection-view.d.ts +4 -0
  2226. package/dist/ui/client/table-selection-view.d.ts.map +1 -0
  2227. package/dist/ui/client/table-selection-view.js +283 -0
  2228. package/dist/ui/client/table-selection-view.js.map +1 -0
  2229. package/dist/ui/dashboard-page.d.ts +6 -0
  2230. package/dist/ui/dashboard-page.d.ts.map +1 -0
  2231. package/dist/ui/dashboard-page.js +4 -0
  2232. package/dist/ui/dashboard-page.js.map +1 -0
  2233. package/dist/ui/data.d.ts +51 -1
  2234. package/dist/ui/data.d.ts.map +1 -1
  2235. package/dist/ui/data.js +87 -1
  2236. package/dist/ui/data.js.map +1 -1
  2237. package/dist/ui/date-picker.d.ts.map +1 -1
  2238. package/dist/ui/date-picker.js +2 -2
  2239. package/dist/ui/date-picker.js.map +1 -1
  2240. package/dist/ui/form-page.d.ts +6 -0
  2241. package/dist/ui/form-page.d.ts.map +1 -0
  2242. package/dist/ui/form-page.js +5 -0
  2243. package/dist/ui/form-page.js.map +1 -0
  2244. package/dist/ui/form.d.ts +4 -1
  2245. package/dist/ui/form.d.ts.map +1 -1
  2246. package/dist/ui/form.js +7 -5
  2247. package/dist/ui/form.js.map +1 -1
  2248. package/dist/ui/format.d.ts +13 -2
  2249. package/dist/ui/format.d.ts.map +1 -1
  2250. package/dist/ui/format.js +28 -7
  2251. package/dist/ui/format.js.map +1 -1
  2252. package/dist/ui/gantt.d.ts +52 -0
  2253. package/dist/ui/gantt.d.ts.map +1 -0
  2254. package/dist/ui/gantt.js +92 -0
  2255. package/dist/ui/gantt.js.map +1 -0
  2256. package/dist/ui/hooks.d.ts.map +1 -1
  2257. package/dist/ui/hooks.js +14 -0
  2258. package/dist/ui/hooks.js.map +1 -1
  2259. package/dist/ui/icons.d.ts.map +1 -1
  2260. package/dist/ui/icons.js +6 -1
  2261. package/dist/ui/icons.js.map +1 -1
  2262. package/dist/ui/index.d.ts +95 -14
  2263. package/dist/ui/index.d.ts.map +1 -1
  2264. package/dist/ui/index.js +78 -13
  2265. package/dist/ui/index.js.map +1 -1
  2266. package/dist/ui/layout.d.ts +43 -38
  2267. package/dist/ui/layout.d.ts.map +1 -1
  2268. package/dist/ui/layout.js +29 -37
  2269. package/dist/ui/layout.js.map +1 -1
  2270. package/dist/ui/list-page.d.ts +19 -0
  2271. package/dist/ui/list-page.d.ts.map +1 -0
  2272. package/dist/ui/list-page.js +21 -0
  2273. package/dist/ui/list-page.js.map +1 -0
  2274. package/dist/ui/media.d.ts.map +1 -1
  2275. package/dist/ui/media.js +1 -1
  2276. package/dist/ui/media.js.map +1 -1
  2277. package/dist/ui/modal.d.ts +26 -1
  2278. package/dist/ui/modal.d.ts.map +1 -1
  2279. package/dist/ui/modal.js +18 -2
  2280. package/dist/ui/modal.js.map +1 -1
  2281. package/dist/ui/nav.d.ts +21 -1
  2282. package/dist/ui/nav.d.ts.map +1 -1
  2283. package/dist/ui/nav.js +43 -8
  2284. package/dist/ui/nav.js.map +1 -1
  2285. package/dist/ui/navigation.d.ts +36 -2
  2286. package/dist/ui/navigation.d.ts.map +1 -1
  2287. package/dist/ui/navigation.js +60 -5
  2288. package/dist/ui/navigation.js.map +1 -1
  2289. package/dist/ui/partner.d.ts +18 -0
  2290. package/dist/ui/partner.d.ts.map +1 -0
  2291. package/dist/ui/partner.js +11 -0
  2292. package/dist/ui/partner.js.map +1 -0
  2293. package/dist/ui/primitives.d.ts +28 -10
  2294. package/dist/ui/primitives.d.ts.map +1 -1
  2295. package/dist/ui/primitives.js +21 -7
  2296. package/dist/ui/primitives.js.map +1 -1
  2297. package/dist/ui/product-media.d.ts +47 -0
  2298. package/dist/ui/product-media.d.ts.map +1 -0
  2299. package/dist/ui/product-media.js +67 -0
  2300. package/dist/ui/product-media.js.map +1 -0
  2301. package/dist/ui/product-variants.d.ts +68 -0
  2302. package/dist/ui/product-variants.d.ts.map +1 -0
  2303. package/dist/ui/product-variants.js +81 -0
  2304. package/dist/ui/product-variants.js.map +1 -0
  2305. package/dist/ui/record-detail.d.ts +70 -0
  2306. package/dist/ui/record-detail.d.ts.map +1 -0
  2307. package/dist/ui/record-detail.js +35 -0
  2308. package/dist/ui/record-detail.js.map +1 -0
  2309. package/dist/ui/record-page.d.ts +16 -0
  2310. package/dist/ui/record-page.d.ts.map +1 -0
  2311. package/dist/ui/record-page.js +13 -0
  2312. package/dist/ui/record-page.js.map +1 -0
  2313. package/dist/ui/record.d.ts +15 -3
  2314. package/dist/ui/record.d.ts.map +1 -1
  2315. package/dist/ui/record.js +6 -5
  2316. package/dist/ui/record.js.map +1 -1
  2317. package/dist/ui/surfaces.d.ts +30 -2
  2318. package/dist/ui/surfaces.d.ts.map +1 -1
  2319. package/dist/ui/surfaces.js +39 -2
  2320. package/dist/ui/surfaces.js.map +1 -1
  2321. package/dist/ui/table.d.ts +25 -2
  2322. package/dist/ui/table.d.ts.map +1 -1
  2323. package/dist/ui/table.js +10 -6
  2324. package/dist/ui/table.js.map +1 -1
  2325. package/dist/ui/timeframe.d.ts +39 -0
  2326. package/dist/ui/timeframe.d.ts.map +1 -0
  2327. package/dist/ui/timeframe.js +36 -0
  2328. package/dist/ui/timeframe.js.map +1 -0
  2329. package/dist/ui/workspace-page.d.ts +16 -0
  2330. package/dist/ui/workspace-page.d.ts.map +1 -0
  2331. package/dist/ui/workspace-page.js +15 -0
  2332. package/dist/ui/workspace-page.js.map +1 -0
  2333. package/package.json +16 -3
  2334. package/dist/modules/account/tt99.d.ts +0 -30
  2335. package/dist/modules/account/tt99.d.ts.map +0 -1
  2336. package/dist/modules/account/tt99.js +0 -1661
  2337. package/dist/modules/account/tt99.js.map +0 -1
  2338. package/dist/modules/account_backend/accounting-overview-screen.d.ts +0 -18
  2339. package/dist/modules/account_backend/accounting-overview-screen.d.ts.map +0 -1
  2340. package/dist/modules/account_backend/accounting-overview-screen.js +0 -104
  2341. package/dist/modules/account_backend/accounting-overview-screen.js.map +0 -1
  2342. package/dist/modules/account_backend/accounts-screen.d.ts +0 -13
  2343. package/dist/modules/account_backend/accounts-screen.d.ts.map +0 -1
  2344. package/dist/modules/account_backend/accounts-screen.js +0 -49
  2345. package/dist/modules/account_backend/accounts-screen.js.map +0 -1
  2346. package/dist/modules/account_backend/customer-invoices-screen.d.ts +0 -14
  2347. package/dist/modules/account_backend/customer-invoices-screen.d.ts.map +0 -1
  2348. package/dist/modules/account_backend/customer-invoices-screen.js +0 -63
  2349. package/dist/modules/account_backend/customer-invoices-screen.js.map +0 -1
  2350. package/dist/modules/account_backend/general-ledger-screen.d.ts +0 -13
  2351. package/dist/modules/account_backend/general-ledger-screen.d.ts.map +0 -1
  2352. package/dist/modules/account_backend/general-ledger-screen.js +0 -56
  2353. package/dist/modules/account_backend/general-ledger-screen.js.map +0 -1
  2354. package/dist/modules/account_backend/journal-entries-screen.d.ts +0 -14
  2355. package/dist/modules/account_backend/journal-entries-screen.d.ts.map +0 -1
  2356. package/dist/modules/account_backend/journal-entries-screen.js +0 -45
  2357. package/dist/modules/account_backend/journal-entries-screen.js.map +0 -1
  2358. package/dist/modules/account_backend/journals-screen.d.ts +0 -14
  2359. package/dist/modules/account_backend/journals-screen.d.ts.map +0 -1
  2360. package/dist/modules/account_backend/journals-screen.js +0 -53
  2361. package/dist/modules/account_backend/journals-screen.js.map +0 -1
  2362. package/dist/modules/account_backend/move-detail-screen.d.ts +0 -10
  2363. package/dist/modules/account_backend/move-detail-screen.d.ts.map +0 -1
  2364. package/dist/modules/account_backend/move-detail-screen.js +0 -100
  2365. package/dist/modules/account_backend/move-detail-screen.js.map +0 -1
  2366. package/dist/modules/account_backend/partner-ledger-screen.d.ts +0 -14
  2367. package/dist/modules/account_backend/partner-ledger-screen.d.ts.map +0 -1
  2368. package/dist/modules/account_backend/partner-ledger-screen.js +0 -69
  2369. package/dist/modules/account_backend/partner-ledger-screen.js.map +0 -1
  2370. package/dist/modules/account_backend/payment-terms-screen.d.ts +0 -14
  2371. package/dist/modules/account_backend/payment-terms-screen.d.ts.map +0 -1
  2372. package/dist/modules/account_backend/payment-terms-screen.js +0 -40
  2373. package/dist/modules/account_backend/payment-terms-screen.js.map +0 -1
  2374. package/dist/modules/account_backend/payments-screen.d.ts +0 -14
  2375. package/dist/modules/account_backend/payments-screen.d.ts.map +0 -1
  2376. package/dist/modules/account_backend/payments-screen.js +0 -54
  2377. package/dist/modules/account_backend/payments-screen.js.map +0 -1
  2378. package/dist/modules/account_backend/screens.d.ts +0 -7
  2379. package/dist/modules/account_backend/screens.d.ts.map +0 -1
  2380. package/dist/modules/account_backend/screens.js +0 -7
  2381. package/dist/modules/account_backend/screens.js.map +0 -1
  2382. package/dist/modules/account_backend/taxes-screen.d.ts +0 -15
  2383. package/dist/modules/account_backend/taxes-screen.d.ts.map +0 -1
  2384. package/dist/modules/account_backend/taxes-screen.js +0 -73
  2385. package/dist/modules/account_backend/taxes-screen.js.map +0 -1
  2386. package/dist/modules/account_backend/trial-balance-screen.d.ts +0 -13
  2387. package/dist/modules/account_backend/trial-balance-screen.d.ts.map +0 -1
  2388. package/dist/modules/account_backend/trial-balance-screen.js +0 -62
  2389. package/dist/modules/account_backend/trial-balance-screen.js.map +0 -1
  2390. package/dist/modules/account_backend/vendor-bills-screen.d.ts +0 -14
  2391. package/dist/modules/account_backend/vendor-bills-screen.d.ts.map +0 -1
  2392. package/dist/modules/account_backend/vendor-bills-screen.js +0 -59
  2393. package/dist/modules/account_backend/vendor-bills-screen.js.map +0 -1
  2394. package/dist/modules/account_partner_backend/screens.d.ts +0 -16
  2395. package/dist/modules/account_partner_backend/screens.d.ts.map +0 -1
  2396. package/dist/modules/account_partner_backend/screens.js +0 -26
  2397. package/dist/modules/account_partner_backend/screens.js.map +0 -1
  2398. package/dist/modules/activity_backend/screens.d.ts +0 -5
  2399. package/dist/modules/activity_backend/screens.d.ts.map +0 -1
  2400. package/dist/modules/activity_backend/screens.js +0 -52
  2401. package/dist/modules/activity_backend/screens.js.map +0 -1
  2402. package/dist/modules/address_backend/screens.d.ts +0 -31
  2403. package/dist/modules/address_backend/screens.d.ts.map +0 -1
  2404. package/dist/modules/address_backend/screens.js +0 -147
  2405. package/dist/modules/address_backend/screens.js.map +0 -1
  2406. package/dist/modules/backend/design/admin.css +0 -4229
  2407. package/dist/modules/backend/design/client/relation-select-view.d.mts +0 -5
  2408. package/dist/modules/backend/design/client/relation-select-view.d.mts.map +0 -1
  2409. package/dist/modules/backend/design/client/relation-select-view.mjs +0 -335
  2410. package/dist/modules/backend/design/client/relation-select-view.mjs.map +0 -1
  2411. package/dist/modules/calendar_backend/screens.d.ts +0 -5
  2412. package/dist/modules/calendar_backend/screens.d.ts.map +0 -1
  2413. package/dist/modules/calendar_backend/screens.js +0 -4
  2414. package/dist/modules/calendar_backend/screens.js.map +0 -1
  2415. package/dist/modules/company_backend/screens.d.ts +0 -62
  2416. package/dist/modules/company_backend/screens.d.ts.map +0 -1
  2417. package/dist/modules/company_backend/screens.js +0 -268
  2418. package/dist/modules/company_backend/screens.js.map +0 -1
  2419. package/dist/modules/crm_backend/list-search.d.ts +0 -21
  2420. package/dist/modules/crm_backend/list-search.d.ts.map +0 -1
  2421. package/dist/modules/crm_backend/list-search.js +0 -220
  2422. package/dist/modules/crm_backend/list-search.js.map +0 -1
  2423. package/dist/modules/crm_backend/screens.d.ts +0 -32
  2424. package/dist/modules/crm_backend/screens.d.ts.map +0 -1
  2425. package/dist/modules/crm_backend/screens.js +0 -405
  2426. package/dist/modules/crm_backend/screens.js.map +0 -1
  2427. package/dist/modules/hospitality_core/screens.d.ts +0 -773
  2428. package/dist/modules/hospitality_core/screens.d.ts.map +0 -1
  2429. package/dist/modules/hospitality_core/screens.js +0 -4152
  2430. package/dist/modules/hospitality_core/screens.js.map +0 -1
  2431. package/dist/modules/hr_backend/screens.d.ts +0 -9
  2432. package/dist/modules/hr_backend/screens.d.ts.map +0 -1
  2433. package/dist/modules/hr_backend/screens.js +0 -144
  2434. package/dist/modules/hr_backend/screens.js.map +0 -1
  2435. package/dist/modules/loyalty_backend/screens.d.ts +0 -33
  2436. package/dist/modules/loyalty_backend/screens.d.ts.map +0 -1
  2437. package/dist/modules/loyalty_backend/screens.js +0 -562
  2438. package/dist/modules/loyalty_backend/screens.js.map +0 -1
  2439. package/dist/modules/mail_backend/screens.d.ts +0 -5
  2440. package/dist/modules/mail_backend/screens.d.ts.map +0 -1
  2441. package/dist/modules/mail_backend/screens.js +0 -11
  2442. package/dist/modules/mail_backend/screens.js.map +0 -1
  2443. package/dist/modules/mail_inbound_backend/screens.d.ts +0 -5
  2444. package/dist/modules/mail_inbound_backend/screens.d.ts.map +0 -1
  2445. package/dist/modules/mail_inbound_backend/screens.js +0 -25
  2446. package/dist/modules/mail_inbound_backend/screens.js.map +0 -1
  2447. package/dist/modules/mail_transport_backend/screens.d.ts +0 -5
  2448. package/dist/modules/mail_transport_backend/screens.d.ts.map +0 -1
  2449. package/dist/modules/mail_transport_backend/screens.js +0 -35
  2450. package/dist/modules/mail_transport_backend/screens.js.map +0 -1
  2451. package/dist/modules/oauth_backend/screens.d.ts +0 -66
  2452. package/dist/modules/oauth_backend/screens.d.ts.map +0 -1
  2453. package/dist/modules/oauth_backend/screens.js +0 -323
  2454. package/dist/modules/oauth_backend/screens.js.map +0 -1
  2455. package/dist/modules/odoo_collaboration_import/functions.d.ts.map +0 -1
  2456. package/dist/modules/odoo_collaboration_import/functions.js +0 -128
  2457. package/dist/modules/odoo_collaboration_import/functions.js.map +0 -1
  2458. package/dist/modules/odoo_collaboration_import/index.d.ts +0 -6
  2459. package/dist/modules/odoo_collaboration_import/index.d.ts.map +0 -1
  2460. package/dist/modules/odoo_collaboration_import/index.js +0 -31
  2461. package/dist/modules/odoo_collaboration_import/index.js.map +0 -1
  2462. package/dist/modules/odoo_collaboration_import/models.d.ts.map +0 -1
  2463. package/dist/modules/odoo_collaboration_import/models.js +0 -76
  2464. package/dist/modules/odoo_collaboration_import/models.js.map +0 -1
  2465. package/dist/modules/odoo_collaboration_import/operations.d.ts +0 -14
  2466. package/dist/modules/odoo_collaboration_import/operations.d.ts.map +0 -1
  2467. package/dist/modules/odoo_collaboration_import/operations.js +0 -1139
  2468. package/dist/modules/odoo_collaboration_import/operations.js.map +0 -1
  2469. package/dist/modules/odoo_collaboration_import/relations.d.ts.map +0 -1
  2470. package/dist/modules/odoo_collaboration_import/relations.js +0 -19
  2471. package/dist/modules/odoo_collaboration_import/relations.js.map +0 -1
  2472. package/dist/modules/odoo_collaboration_import/types.d.ts +0 -58
  2473. package/dist/modules/odoo_collaboration_import/types.d.ts.map +0 -1
  2474. package/dist/modules/odoo_collaboration_import/types.js.map +0 -1
  2475. package/dist/modules/partner_backend/screens.d.ts +0 -53
  2476. package/dist/modules/partner_backend/screens.d.ts.map +0 -1
  2477. package/dist/modules/partner_backend/screens.js +0 -169
  2478. package/dist/modules/partner_backend/screens.js.map +0 -1
  2479. package/dist/modules/pricing_backend/screens.d.ts +0 -13
  2480. package/dist/modules/pricing_backend/screens.d.ts.map +0 -1
  2481. package/dist/modules/pricing_backend/screens.js +0 -182
  2482. package/dist/modules/pricing_backend/screens.js.map +0 -1
  2483. package/dist/modules/product_backend/attributes-screen.d.ts +0 -7
  2484. package/dist/modules/product_backend/attributes-screen.d.ts.map +0 -1
  2485. package/dist/modules/product_backend/attributes-screen.js +0 -76
  2486. package/dist/modules/product_backend/attributes-screen.js.map +0 -1
  2487. package/dist/modules/product_backend/create-screen.d.ts +0 -12
  2488. package/dist/modules/product_backend/create-screen.d.ts.map +0 -1
  2489. package/dist/modules/product_backend/create-screen.js +0 -83
  2490. package/dist/modules/product_backend/create-screen.js.map +0 -1
  2491. package/dist/modules/product_backend/screens.d.ts +0 -68
  2492. package/dist/modules/product_backend/screens.d.ts.map +0 -1
  2493. package/dist/modules/product_backend/screens.js +0 -388
  2494. package/dist/modules/product_backend/screens.js.map +0 -1
  2495. package/dist/modules/purchase_backend/screens.d.ts +0 -29
  2496. package/dist/modules/purchase_backend/screens.d.ts.map +0 -1
  2497. package/dist/modules/purchase_backend/screens.js +0 -324
  2498. package/dist/modules/purchase_backend/screens.js.map +0 -1
  2499. package/dist/modules/sale_backend/invoicing-policies-screen.d.ts +0 -14
  2500. package/dist/modules/sale_backend/invoicing-policies-screen.d.ts.map +0 -1
  2501. package/dist/modules/sale_backend/invoicing-policies-screen.js +0 -36
  2502. package/dist/modules/sale_backend/invoicing-policies-screen.js.map +0 -1
  2503. package/dist/modules/sale_backend/order-detail-screen.d.ts +0 -18
  2504. package/dist/modules/sale_backend/order-detail-screen.d.ts.map +0 -1
  2505. package/dist/modules/sale_backend/order-detail-screen.js +0 -217
  2506. package/dist/modules/sale_backend/order-detail-screen.js.map +0 -1
  2507. package/dist/modules/sale_backend/quotations-screen.d.ts +0 -15
  2508. package/dist/modules/sale_backend/quotations-screen.d.ts.map +0 -1
  2509. package/dist/modules/sale_backend/quotations-screen.js +0 -64
  2510. package/dist/modules/sale_backend/quotations-screen.js.map +0 -1
  2511. package/dist/modules/sale_backend/sales-orders-screen.d.ts +0 -12
  2512. package/dist/modules/sale_backend/sales-orders-screen.d.ts.map +0 -1
  2513. package/dist/modules/sale_backend/sales-orders-screen.js +0 -65
  2514. package/dist/modules/sale_backend/sales-orders-screen.js.map +0 -1
  2515. package/dist/modules/sale_backend/screens.d.ts +0 -23
  2516. package/dist/modules/sale_backend/screens.d.ts.map +0 -1
  2517. package/dist/modules/sale_backend/screens.js +0 -275
  2518. package/dist/modules/sale_backend/screens.js.map +0 -1
  2519. package/dist/modules/stock_backend/forecast-screen.d.ts +0 -28
  2520. package/dist/modules/stock_backend/forecast-screen.d.ts.map +0 -1
  2521. package/dist/modules/stock_backend/forecast-screen.js +0 -108
  2522. package/dist/modules/stock_backend/forecast-screen.js.map +0 -1
  2523. package/dist/modules/stock_backend/inventory-screen.d.ts +0 -27
  2524. package/dist/modules/stock_backend/inventory-screen.d.ts.map +0 -1
  2525. package/dist/modules/stock_backend/inventory-screen.js +0 -141
  2526. package/dist/modules/stock_backend/inventory-screen.js.map +0 -1
  2527. package/dist/modules/stock_backend/locations-screen.d.ts +0 -18
  2528. package/dist/modules/stock_backend/locations-screen.d.ts.map +0 -1
  2529. package/dist/modules/stock_backend/locations-screen.js +0 -92
  2530. package/dist/modules/stock_backend/locations-screen.js.map +0 -1
  2531. package/dist/modules/stock_backend/lot-screen.d.ts +0 -30
  2532. package/dist/modules/stock_backend/lot-screen.d.ts.map +0 -1
  2533. package/dist/modules/stock_backend/lot-screen.js +0 -86
  2534. package/dist/modules/stock_backend/lot-screen.js.map +0 -1
  2535. package/dist/modules/stock_backend/lots-screen.d.ts +0 -21
  2536. package/dist/modules/stock_backend/lots-screen.d.ts.map +0 -1
  2537. package/dist/modules/stock_backend/lots-screen.js +0 -79
  2538. package/dist/modules/stock_backend/lots-screen.js.map +0 -1
  2539. package/dist/modules/stock_backend/picking-types-screen.d.ts +0 -21
  2540. package/dist/modules/stock_backend/picking-types-screen.d.ts.map +0 -1
  2541. package/dist/modules/stock_backend/picking-types-screen.js +0 -110
  2542. package/dist/modules/stock_backend/picking-types-screen.js.map +0 -1
  2543. package/dist/modules/stock_backend/replenishment-screen.d.ts +0 -29
  2544. package/dist/modules/stock_backend/replenishment-screen.d.ts.map +0 -1
  2545. package/dist/modules/stock_backend/replenishment-screen.js +0 -131
  2546. package/dist/modules/stock_backend/replenishment-screen.js.map +0 -1
  2547. package/dist/modules/stock_backend/screens.d.ts +0 -14
  2548. package/dist/modules/stock_backend/screens.d.ts.map +0 -1
  2549. package/dist/modules/stock_backend/screens.js +0 -40
  2550. package/dist/modules/stock_backend/screens.js.map +0 -1
  2551. package/dist/modules/stock_backend/stock-route-screen.d.ts +0 -30
  2552. package/dist/modules/stock_backend/stock-route-screen.d.ts.map +0 -1
  2553. package/dist/modules/stock_backend/stock-route-screen.js +0 -129
  2554. package/dist/modules/stock_backend/stock-route-screen.js.map +0 -1
  2555. package/dist/modules/stock_backend/stock-routes-screen.d.ts +0 -17
  2556. package/dist/modules/stock_backend/stock-routes-screen.d.ts.map +0 -1
  2557. package/dist/modules/stock_backend/stock-routes-screen.js +0 -60
  2558. package/dist/modules/stock_backend/stock-routes-screen.js.map +0 -1
  2559. package/dist/modules/stock_backend/transfer-screen.d.ts +0 -26
  2560. package/dist/modules/stock_backend/transfer-screen.d.ts.map +0 -1
  2561. package/dist/modules/stock_backend/transfer-screen.js +0 -95
  2562. package/dist/modules/stock_backend/transfer-screen.js.map +0 -1
  2563. package/dist/modules/stock_backend/transfers-screen.d.ts +0 -21
  2564. package/dist/modules/stock_backend/transfers-screen.d.ts.map +0 -1
  2565. package/dist/modules/stock_backend/transfers-screen.js +0 -88
  2566. package/dist/modules/stock_backend/transfers-screen.js.map +0 -1
  2567. package/dist/modules/stock_backend/warehouses-screen.d.ts +0 -17
  2568. package/dist/modules/stock_backend/warehouses-screen.d.ts.map +0 -1
  2569. package/dist/modules/stock_backend/warehouses-screen.js +0 -96
  2570. package/dist/modules/stock_backend/warehouses-screen.js.map +0 -1
  2571. package/dist/modules/user_backend/screens.d.ts +0 -70
  2572. package/dist/modules/user_backend/screens.d.ts.map +0 -1
  2573. package/dist/modules/user_backend/screens.js +0 -308
  2574. package/dist/modules/user_backend/screens.js.map +0 -1
  2575. package/dist/modules/website/customer-routes.d.ts +0 -3
  2576. package/dist/modules/website/customer-routes.d.ts.map +0 -1
  2577. package/dist/modules/website/customer-routes.js +0 -322
  2578. package/dist/modules/website/customer-routes.js.map +0 -1
  2579. package/dist/modules/website_backend/screens.d.ts +0 -114
  2580. package/dist/modules/website_backend/screens.d.ts.map +0 -1
  2581. package/dist/modules/website_backend/screens.js +0 -625
  2582. package/dist/modules/website_backend/screens.js.map +0 -1
  2583. package/dist/ui/client/mail.d.mts +0 -11
  2584. package/dist/ui/client/mail.d.mts.map +0 -1
  2585. package/dist/ui/client/mail.mjs +0 -10
  2586. package/dist/ui/client/mail.mjs.map +0 -1
  2587. /package/dist/modules/{odoo_collaboration_import → account_staff_channel}/functions.d.ts +0 -0
  2588. /package/dist/modules/{odoo_collaboration_import → account_staff_channel}/models.d.ts +0 -0
  2589. /package/dist/modules/{odoo_collaboration_import → address_backend/screens}/types.js +0 -0
  2590. /package/dist/modules/{odoo_collaboration_import → manufacturing}/relations.d.ts +0 -0
@@ -1,57 +1,511 @@
1
- import { randomUUID } from 'node:crypto';
1
+ import { createHash, randomUUID } from 'node:crypto';
2
2
  import { defineModule, text } from '@ketvietlab/ketjs';
3
- import { backendPage, formatMoney } from '../../ui/index.js';
3
+ import { formatMoney, modalWorkspace } from '../../ui/index.js';
4
4
  import { readForm, seeOther } from '../backend/forms.js';
5
- import { viewerOf } from '../backend/routes.js';
6
- import { ACCOUNT_TYPES, JOURNAL_TYPES, PARTNER_TYPES, PAYMENT_TERM_DELAY_TYPES, PAYMENT_TERM_VALUES, PAYMENT_TYPES, TAX_AMOUNT_TYPES, TAX_USES, } from '../account/functions.js';
7
- import { optionsOf } from './screens.js';
8
- import { accountingOverviewScreen } from './accounting-overview-screen.js';
9
- import { accountsScreen } from './accounts-screen.js';
10
- import { customerInvoicesScreen } from './customer-invoices-screen.js';
11
- import { journalsScreen } from './journals-screen.js';
12
- import { generalLedgerScreen } from './general-ledger-screen.js';
13
- import { moveDetailScreen } from './move-detail-screen.js';
14
- import { journalEntriesScreen } from './journal-entries-screen.js';
15
- import { paymentsScreen } from './payments-screen.js';
16
- import { paymentTermsScreen } from './payment-terms-screen.js';
17
- import { partnerLedgerScreen } from './partner-ledger-screen.js';
18
- import { taxesScreen } from './taxes-screen.js';
19
- import { trialBalanceScreen } from './trial-balance-screen.js';
20
- import { vendorBillsScreen } from './vendor-bills-screen.js';
21
- const frame = async (ctx, url, req) => ({
22
- navigation: req.headers['x-ket-navigation'] === 'fragment-v1',
23
- viewer: await viewerOf(ctx, url, req),
24
- menu: await ctx.menu(url, req),
25
- extras: {
26
- 'nav.items': await ctx.joint(url, req, 'backend:nav.items', { active: url.pathname }),
27
- 'topbar.end': await ctx.joint(url, req, 'backend:topbar.end'),
5
+ import { accountOptions, accountRelationControl } from './relation-control.js';
6
+ import { partnerRelationControl } from '../partner_backend/relation-control.js';
7
+ import { ACCOUNT_TYPES, JOURNAL_TYPES, MOVE_STATES, PARTNER_TYPES, PAYMENT_STATES, PAYMENT_TERM_DELAY_TYPES, PAYMENT_TERM_VALUES, PAYMENT_TYPES, TAX_AMOUNT_TYPES, TAX_USES, } from '../account/functions.js';
8
+ import { addDecimals } from '../account/money.js';
9
+ import { accountDefaultsScreen, accountingBooksScreen, accountFormModal, accountingOverviewScreen, accountsListScreen, customerInvoiceFormScreen, customerInvoicesListScreen, generalLedgerScreen, journalEntriesListScreen, journalEntryCreateModal, journalFormModal, journalsListScreen, labelOf, moveDetailScreen, moveTitle, optionsOf, paymentFormScreen, paymentsListScreen, partnerLedgerScreen, openingBalanceDetailScreen, openingBalanceImportScreen, openingBalancesListScreen, paymentTermFormModal, paymentTermLineFormModal, paymentTermsListScreen, taxFormScreen, taxesListScreen, trialBalanceScreen, periodCloseDetailScreen, periodClosesListScreen, vendorBillFormScreen, vendorBillsListScreen, } from './screens/index.js';
10
+ import { adminPage, choices, localeQuery, optional, printGroup, selectionLabel } from '../backend/screen.js';
11
+ import { PAGE_SIZE, pageOf, pager, searchOf, withParam } from '../backend/paging.js';
12
+ import { overviewCharts, periodOf, yearsOf } from './overview.js';
13
+ const crossSite = (req) => {
14
+ const origin = req.headers.origin;
15
+ if (!origin)
16
+ return false;
17
+ try {
18
+ return new URL(origin).host !== String(req.headers.host ?? '');
19
+ }
20
+ catch {
21
+ return true;
22
+ }
23
+ };
24
+ /** How many rows an admin list renders before the reader has to narrow it down. */
25
+ const LIST_PAGE = 200;
26
+ const succeeded = (result) => result.ok === true;
27
+ const rejection = (result, _, form) => {
28
+ const errors = (result?.errors ?? []).map((error) => ({
29
+ field: error.field,
30
+ text: error.code ? _(error.code, error.params) : (error.message ?? _('account_backend.error.invalid')),
31
+ }));
32
+ return {
33
+ messages: errors.length ? errors.map((error) => error.text) : [_('account_backend.error.invalid')],
34
+ fields: Object.fromEntries(errors.filter((error) => error.field).map((error) => [String(error.field), error.text])),
35
+ values: form,
36
+ };
37
+ };
38
+ /** Apply a rejection to the form that produced it: the reason inline, the value back. */
39
+ const restore = (fields, rejected) => rejected
40
+ ? fields.map((field) => ({
41
+ ...field,
42
+ error: rejected.fields[field.name] ?? null,
43
+ // A form body omits an unchecked box entirely, so absence is the value.
44
+ value: field.type === 'checkbox'
45
+ ? rejected.values[field.name] === '1'
46
+ : (rejected.values[field.name] ?? ''),
47
+ }))
48
+ : fields;
49
+ /**
50
+ * The state a configuration form should show: what the user just submitted when it
51
+ * was refused, the record being corrected when one is open, the defaults otherwise.
52
+ */
53
+ const formState = (fields, row, rejected) => rejected ? restore(fields, rejected) : prefill(fields, row);
54
+ const currencyOf = (companies, shell) => companies.find((company) => company.id === shell.viewer?.company)?.currency;
55
+ /**
56
+ * A configuration list is also its own editor. `?edit=<id>` prefills the create
57
+ * form with that row and posts back to the same id, so a mistyped account code or
58
+ * a changed tax rate is a correction rather than a second row nobody can remove.
59
+ */
60
+ const editingId = (url) => url.searchParams.get('edit') ?? '';
61
+ const editTarget = (rows, url) => {
62
+ const id = editingId(url);
63
+ return id ? (rows.find((row) => String(row.id) === id) ?? null) : null;
64
+ };
65
+ /** The milestone a payment-term screen is correcting, found across every term's lines. */
66
+ const termLineTarget = (terms, url) => {
67
+ const id = url.searchParams.get('editLine') ?? '';
68
+ if (!id)
69
+ return null;
70
+ for (const term of terms)
71
+ for (const line of term.lines ?? [])
72
+ if (String(line.id) === id)
73
+ return line;
74
+ return null;
75
+ };
76
+ const paymentTermListPath = (url) => {
77
+ const target = new URL(url);
78
+ target.pathname = '/admin/accounting/terms';
79
+ for (const key of ['create', 'edit', 'line', 'editLine', 'invalid', 'returnTo'])
80
+ target.searchParams.delete(key);
81
+ return `${target.pathname}${target.search}`;
82
+ };
83
+ const paymentTermModalPath = (url, edit) => {
84
+ const target = new URL(paymentTermListPath(url), 'http://ket.local');
85
+ if (edit !== undefined && edit !== null && String(edit))
86
+ target.searchParams.set('edit', String(edit));
87
+ else
88
+ target.searchParams.set('create', '1');
89
+ return `${target.pathname}${target.search}`;
90
+ };
91
+ const paymentTermLineModalPath = (url, edit) => {
92
+ const target = new URL(paymentTermListPath(url), 'http://ket.local');
93
+ if (edit !== undefined && edit !== null && String(edit))
94
+ target.searchParams.set('editLine', String(edit));
95
+ else
96
+ target.searchParams.set('line', '1');
97
+ return `${target.pathname}${target.search}`;
98
+ };
99
+ const journalEntryListPath = (url) => {
100
+ const target = new URL(url);
101
+ target.pathname = '/admin/accounting/entries';
102
+ for (const key of ['create', 'invalid', 'returnTo'])
103
+ target.searchParams.delete(key);
104
+ return `${target.pathname}${target.search}`;
105
+ };
106
+ const journalEntryModalPath = (url) => {
107
+ const target = new URL(journalEntryListPath(url), 'http://ket.local');
108
+ target.searchParams.set('create', '1');
109
+ return `${target.pathname}${target.search}`;
110
+ };
111
+ const CUSTOMER_INVOICE_TYPES = ['out_invoice', 'out_refund', 'out_receipt'];
112
+ const customerInvoiceListPath = (url) => {
113
+ const target = new URL(url);
114
+ target.pathname = '/admin/accounting/customer-invoices';
115
+ for (const key of ['create', 'invalid', 'returnTo'])
116
+ target.searchParams.delete(key);
117
+ return `${target.pathname}${target.search}`;
118
+ };
119
+ const safeCustomerInvoiceReturnTo = (url) => {
120
+ const fallback = `/admin/accounting/customer-invoices${localeQuery(url)}`;
121
+ const raw = url.searchParams.get('returnTo');
122
+ if (!raw)
123
+ return fallback;
124
+ const candidate = new URL(raw, 'http://ket.local');
125
+ return candidate.origin === 'http://ket.local' &&
126
+ candidate.pathname === '/admin/accounting/customer-invoices'
127
+ ? `${candidate.pathname}${candidate.search}`
128
+ : fallback;
129
+ };
130
+ const customerInvoiceFormPath = (url, returnTo) => {
131
+ const target = new URL('/admin/accounting/customer-invoices/new', url);
132
+ target.search = '';
133
+ const lang = url.searchParams.get('lang');
134
+ if (lang)
135
+ target.searchParams.set('lang', lang);
136
+ target.searchParams.set('returnTo', returnTo);
137
+ return `${target.pathname}${target.search}`;
138
+ };
139
+ const VENDOR_BILL_TYPES = ['in_invoice', 'in_refund', 'in_receipt'];
140
+ const vendorBillListPath = (url) => {
141
+ const target = new URL(url);
142
+ target.pathname = '/admin/accounting/vendor-bills';
143
+ for (const key of ['create', 'invalid', 'returnTo'])
144
+ target.searchParams.delete(key);
145
+ return `${target.pathname}${target.search}`;
146
+ };
147
+ const safeVendorBillReturnTo = (url) => {
148
+ const fallback = `/admin/accounting/vendor-bills${localeQuery(url)}`;
149
+ const raw = url.searchParams.get('returnTo');
150
+ if (!raw)
151
+ return fallback;
152
+ const candidate = new URL(raw, 'http://ket.local');
153
+ return candidate.origin === 'http://ket.local' && candidate.pathname === '/admin/accounting/vendor-bills'
154
+ ? `${candidate.pathname}${candidate.search}`
155
+ : fallback;
156
+ };
157
+ const vendorBillFormPath = (url, returnTo) => {
158
+ const target = new URL('/admin/accounting/vendor-bills/new', url);
159
+ target.search = '';
160
+ const lang = url.searchParams.get('lang');
161
+ if (lang)
162
+ target.searchParams.set('lang', lang);
163
+ target.searchParams.set('returnTo', returnTo);
164
+ return `${target.pathname}${target.search}`;
165
+ };
166
+ const paymentListPath = (url) => {
167
+ const target = new URL(url);
168
+ target.pathname = '/admin/accounting/payments';
169
+ for (const key of ['create', 'invalid', 'returnTo'])
170
+ target.searchParams.delete(key);
171
+ return `${target.pathname}${target.search}`;
172
+ };
173
+ const safePaymentReturnTo = (url) => {
174
+ const fallback = `/admin/accounting/payments${localeQuery(url)}`;
175
+ const raw = url.searchParams.get('returnTo');
176
+ if (!raw)
177
+ return fallback;
178
+ const candidate = new URL(raw, 'http://ket.local');
179
+ return candidate.origin === 'http://ket.local' && candidate.pathname === '/admin/accounting/payments'
180
+ ? `${candidate.pathname}${candidate.search}`
181
+ : fallback;
182
+ };
183
+ const paymentFormPath = (url, returnTo) => {
184
+ const target = new URL('/admin/accounting/payments/new', url);
185
+ target.search = '';
186
+ const lang = url.searchParams.get('lang');
187
+ if (lang)
188
+ target.searchParams.set('lang', lang);
189
+ target.searchParams.set('returnTo', returnTo);
190
+ return `${target.pathname}${target.search}`;
191
+ };
192
+ const paymentTermSummary = (rows) => ({
193
+ total: rows.length,
194
+ configured: rows.filter((row) => Array.isArray(row.lines) && row.lines.length > 0).length,
195
+ lines: rows.reduce((total, row) => total + (Array.isArray(row.lines) ? row.lines.length : 0), 0),
196
+ });
197
+ /** The value a field should show: what the row holds when editing, the default otherwise. */
198
+ const prefill = (fields, row) => row
199
+ ? fields.map((field) => {
200
+ const held = row[field.name];
201
+ if (held === undefined)
202
+ return field;
203
+ if (field.type === 'checkbox')
204
+ return { ...field, value: held === true };
205
+ return { ...field, value: held === null ? '' : String(held) };
206
+ })
207
+ : fields;
208
+ /** The id a config POST writes to: the edited row, or a fresh one. */
209
+ const targetId = (url) => editingId(url) || randomUUID();
210
+ /**
211
+ * The account name in the reader's language.
212
+ *
213
+ * A bundled chart carries the statutory name in both languages; anything the
214
+ * company added itself has only the one it was typed in.
215
+ */
216
+ const accountName = (_, account) => String((_.locale.startsWith('en') && account.nameEn) || account.name);
217
+ const accountListPath = (url) => {
218
+ const target = new URL(url);
219
+ target.pathname = '/admin/accounting/accounts';
220
+ for (const key of ['create', 'edit', 'invalid', 'returnTo'])
221
+ target.searchParams.delete(key);
222
+ return `${target.pathname}${target.search}`;
223
+ };
224
+ const accountModalPath = (url, edit, invalid = false) => {
225
+ const target = new URL(accountListPath(url), 'http://ket.local');
226
+ if (edit)
227
+ target.searchParams.set('edit', String(edit));
228
+ else
229
+ target.searchParams.set('create', '1');
230
+ if (invalid)
231
+ target.searchParams.set('invalid', '1');
232
+ return `${target.pathname}${target.search}`;
233
+ };
234
+ const safeAccountReturnTo = (url) => {
235
+ const fallback = `/admin/accounting/accounts${localeQuery(url)}`;
236
+ const raw = url.searchParams.get('returnTo');
237
+ if (!raw)
238
+ return fallback;
239
+ const candidate = new URL(raw, 'http://ket.local');
240
+ return candidate.origin === 'http://ket.local' && candidate.pathname === '/admin/accounting/accounts'
241
+ ? `${candidate.pathname}${candidate.search}`
242
+ : fallback;
243
+ };
244
+ const accountSummary = (rows) => {
245
+ const count = (prefixes) => rows.filter((row) => prefixes.some((prefix) => String(row.accountType).startsWith(prefix))).length;
246
+ return {
247
+ total: rows.length,
248
+ asset: count(['asset']),
249
+ liability: count(['liability', 'equity']),
250
+ profit: count(['income', 'expense']),
251
+ };
252
+ };
253
+ const accountGroups = (_, url, rows, grouped) => {
254
+ if (!grouped)
255
+ return undefined;
256
+ const groups = new Map();
257
+ for (const row of rows) {
258
+ const type = String(row.accountType);
259
+ groups.set(type, [...(groups.get(type) ?? []), row]);
260
+ }
261
+ return [...groups.entries()].map(([type, groupRows]) => ({
262
+ id: `type:${type}`,
263
+ label: labelOf(_, 'accountType', type),
264
+ count: groupRows.length,
265
+ depth: 0,
266
+ open: true,
267
+ href: withParam(url, 'group', null),
268
+ rows: groupRows,
269
+ }));
270
+ };
271
+ const saveAccount = async (ctx, url, req, form) => ctx.call('account.saveAccount', {
272
+ id: targetId(url),
273
+ code: form.code ?? '',
274
+ name: form.name ?? '',
275
+ accountType: form.accountType ?? '',
276
+ reconcile: form.reconcile === '1',
277
+ active: form.active === '1',
278
+ }, url, req);
279
+ const accountFields = (_, editing, rejected) => formState([
280
+ { name: 'code', label: _('account_backend.field.code'), required: true },
281
+ {
282
+ name: 'name',
283
+ label: _('account_backend.field.name'),
284
+ required: true,
285
+ // A bundled account reads under its English name in an English session,
286
+ // so say which name this field is editing.
287
+ help: editing?.nameEn ? `${_('account_backend.field.nameEn')}: ${String(editing.nameEn)}` : undefined,
28
288
  },
289
+ {
290
+ name: 'accountType',
291
+ label: _('account_backend.field.accountType'),
292
+ type: 'select',
293
+ options: optionsOf(_, 'accountType', ACCOUNT_TYPES),
294
+ },
295
+ { name: 'reconcile', label: _('account_backend.field.reconcile'), type: 'checkbox' },
296
+ {
297
+ name: 'active',
298
+ label: _('account_backend.field.active'),
299
+ type: 'checkbox',
300
+ value: true,
301
+ help: _('account_backend.field.activeHint'),
302
+ },
303
+ ], editing, rejected);
304
+ const journalListPath = (url) => {
305
+ const target = new URL(url);
306
+ target.pathname = '/admin/accounting/journals';
307
+ for (const key of ['create', 'edit', 'invalid', 'returnTo'])
308
+ target.searchParams.delete(key);
309
+ return `${target.pathname}${target.search}`;
310
+ };
311
+ const journalModalPath = (url, edit, invalid = false) => {
312
+ const target = new URL(journalListPath(url), 'http://ket.local');
313
+ if (edit)
314
+ target.searchParams.set('edit', String(edit));
315
+ else
316
+ target.searchParams.set('create', '1');
317
+ if (invalid)
318
+ target.searchParams.set('invalid', '1');
319
+ return `${target.pathname}${target.search}`;
320
+ };
321
+ const safeJournalReturnTo = (url) => {
322
+ const fallback = `/admin/accounting/journals${localeQuery(url)}`;
323
+ const raw = url.searchParams.get('returnTo');
324
+ if (!raw)
325
+ return fallback;
326
+ const candidate = new URL(raw, 'http://ket.local');
327
+ return candidate.origin === 'http://ket.local' && candidate.pathname === '/admin/accounting/journals'
328
+ ? `${candidate.pathname}${candidate.search}`
329
+ : fallback;
330
+ };
331
+ const journalSummary = (rows) => ({
332
+ total: rows.length,
333
+ sale: rows.filter((row) => row.type === 'sale').length,
334
+ purchase: rows.filter((row) => row.type === 'purchase').length,
335
+ liquidity: rows.filter((row) => ['bank', 'cash'].includes(String(row.type))).length,
29
336
  });
30
- const document = async (ctx, url, req, title, body, translateTitle = true) => {
31
- const lang = ctx.localeOf(url, req);
32
- const _ = ctx.translate(lang);
33
- return backendPage(ctx, req, {
34
- lang,
35
- title: translateTitle ? _(title) : title,
36
- body: await body(lang, _, await frame(ctx, url, req)),
37
- });
337
+ const saveJournal = async (ctx, url, req, form) => ctx.call('account.saveJournal', {
338
+ id: targetId(url),
339
+ name: form.name ?? '',
340
+ code: form.code ?? '',
341
+ type: form.type ?? '',
342
+ ...optional(form, 'defaultAccountId'),
343
+ active: form.active === '1',
344
+ }, url, req);
345
+ const journalFields = async (ctx, url, req, _, accounts, editing, rejected) => formState([
346
+ { name: 'name', label: _('account_backend.field.name'), required: true },
347
+ { name: 'code', label: _('account_backend.field.code'), required: true },
348
+ {
349
+ name: 'type',
350
+ label: _('account_backend.field.type'),
351
+ type: 'select',
352
+ options: optionsOf(_, 'journalType', JOURNAL_TYPES),
353
+ },
354
+ {
355
+ name: 'defaultAccountId',
356
+ label: _('account_backend.field.defaultAccountId'),
357
+ type: 'select',
358
+ options: accountChoices(_, accounts, true),
359
+ control: await accountRelationControl(ctx, url, req, _, {
360
+ id: 'journal-default-account',
361
+ name: 'defaultAccountId',
362
+ label: _('account_backend.field.defaultAccountId'),
363
+ accounts: accountOptions(accounts),
364
+ allowEmpty: true,
365
+ }),
366
+ },
367
+ {
368
+ name: 'active',
369
+ label: _('account_backend.field.active'),
370
+ type: 'checkbox',
371
+ value: true,
372
+ help: _('account_backend.field.activeHint'),
373
+ },
374
+ ], editing, rejected);
375
+ const taxListPath = (url) => {
376
+ const target = new URL(url);
377
+ target.pathname = '/admin/accounting/taxes';
378
+ for (const key of ['edit', 'invalid', 'returnTo'])
379
+ target.searchParams.delete(key);
380
+ return `${target.pathname}${target.search}`;
38
381
  };
39
- const resultRedirect = (result, ok, fail = ok) => result.ok
40
- ? seeOther(ok)
41
- : seeOther(`${fail}${fail.includes('?') ? '&' : '?'}invalid=1`);
42
- const optional = (form, name) => (form[name] ? { [name]: form[name] } : {});
43
- const localeSuffix = (url) => {
382
+ const safeTaxReturnTo = (url) => {
383
+ const fallback = `/admin/accounting/taxes${localeQuery(url)}`;
384
+ const raw = url.searchParams.get('returnTo');
385
+ if (!raw)
386
+ return fallback;
387
+ const candidate = new URL(raw, 'http://ket.local');
388
+ return candidate.origin === 'http://ket.local' && candidate.pathname === '/admin/accounting/taxes'
389
+ ? `${candidate.pathname}${candidate.search}`
390
+ : fallback;
391
+ };
392
+ const taxFormPath = (url, returnTo, edit) => {
393
+ const target = new URL('/admin/accounting/taxes/new', url);
394
+ target.search = '';
44
395
  const lang = url.searchParams.get('lang');
45
- return lang ? `?lang=${encodeURIComponent(lang)}` : '';
396
+ if (lang)
397
+ target.searchParams.set('lang', lang);
398
+ target.searchParams.set('returnTo', returnTo);
399
+ if (edit)
400
+ target.searchParams.set('edit', String(edit));
401
+ return `${target.pathname}${target.search}`;
46
402
  };
47
- const choices = (rows, empty = false) => [
403
+ const taxSummary = (rows) => ({
404
+ total: rows.length,
405
+ sale: rows.filter((row) => row.typeTaxUse === 'sale').length,
406
+ purchase: rows.filter((row) => row.typeTaxUse === 'purchase').length,
407
+ included: rows.filter((row) => row.priceInclude).length,
408
+ });
409
+ const saveTax = async (ctx, url, req, form) => ctx.call('account.saveTax', {
410
+ id: targetId(url),
411
+ name: form.name ?? '',
412
+ ...optional(form, 'description'),
413
+ typeTaxUse: form.typeTaxUse ?? 'sale',
414
+ ...optional(form, 'taxScope'),
415
+ amountType: form.amountType ?? 'percent',
416
+ amount: form.amount || '0',
417
+ priceInclude: form.priceInclude === '1',
418
+ includeBaseAmount: form.includeBaseAmount === '1',
419
+ ...optional(form, 'accountId'),
420
+ sequence: Number(form.sequence || 10),
421
+ active: form.active === '1',
422
+ }, url, req);
423
+ const taxFields = async (ctx, url, req, _, accounts, editing, rejected) => formState([
424
+ { name: 'name', label: _('account_backend.field.name'), required: true },
425
+ { name: 'description', label: _('account_backend.field.description') },
426
+ {
427
+ name: 'typeTaxUse',
428
+ label: _('account_backend.field.typeTaxUse'),
429
+ type: 'select',
430
+ options: optionsOf(_, 'taxUse', TAX_USES),
431
+ },
432
+ {
433
+ name: 'amountType',
434
+ label: _('account_backend.field.amountType'),
435
+ type: 'select',
436
+ options: optionsOf(_, 'taxAmountType', TAX_AMOUNT_TYPES),
437
+ },
438
+ {
439
+ name: 'amount',
440
+ label: _('account_backend.field.amount'),
441
+ type: 'decimal',
442
+ value: 0,
443
+ required: true,
444
+ },
445
+ {
446
+ name: 'accountId',
447
+ label: _('account_backend.field.accountId'),
448
+ type: 'select',
449
+ options: accountChoices(_, accounts, true),
450
+ control: await accountRelationControl(ctx, url, req, _, {
451
+ id: 'tax-account',
452
+ name: 'accountId',
453
+ label: _('account_backend.field.accountId'),
454
+ accounts: accountOptions(accounts),
455
+ allowEmpty: true,
456
+ }),
457
+ },
458
+ { name: 'priceInclude', label: _('account_backend.field.priceInclude'), type: 'checkbox' },
459
+ {
460
+ name: 'includeBaseAmount',
461
+ label: _('account_backend.field.includeBaseAmount'),
462
+ type: 'checkbox',
463
+ help: _('account_backend.field.includeBaseAmountHint'),
464
+ },
465
+ {
466
+ name: 'sequence',
467
+ label: _('account_backend.field.sequence'),
468
+ type: 'number',
469
+ value: 10,
470
+ help: _('account_backend.field.sequenceHint'),
471
+ },
472
+ {
473
+ name: 'active',
474
+ label: _('account_backend.field.active'),
475
+ type: 'checkbox',
476
+ value: true,
477
+ help: _('account_backend.field.activeHint'),
478
+ },
479
+ ], editing, rejected);
480
+ const accountChoices = (_, rows, empty = false) => [
48
481
  ...(empty ? [{ value: '', label: '—' }] : []),
49
- ...rows.map((row) => ({
50
- value: String(row.id),
51
- label: `${String(row.code ?? '')}${row.code ? ' · ' : ''}${String(row.name)}`,
52
- })),
482
+ ...rows.map((row) => ({ value: String(row.id), label: `${String(row.code)} · ${accountName(_, row)}` })),
53
483
  ];
54
- const currencyOf = (companies, shell) => companies.find((company) => company.id === shell.viewer?.company)?.currency;
484
+ const accountLabel = (_, rows, id) => {
485
+ const held = rows.find((row) => String(row.id) === String(id));
486
+ return held ? `${String(held.code)} · ${accountName(_, held)}` : String(id ?? '');
487
+ };
488
+ /** Add the searchable account picker without losing the value restored by formState. */
489
+ const accountRelationFields = async (ctx, url, req, _, scope, fields, relations) => Promise.all(fields.map(async (field) => {
490
+ const relation = relations[field.name];
491
+ if (!relation)
492
+ return field;
493
+ return {
494
+ ...field,
495
+ control: await accountRelationControl(ctx, url, req, _, {
496
+ id: `${scope}:${field.name}`,
497
+ name: field.name,
498
+ label: field.label,
499
+ value: field.value === undefined || field.value === null ? '' : String(field.value),
500
+ accounts: accountOptions(relation.accounts),
501
+ accountTypes: relation.accountTypes,
502
+ allowEmpty: true,
503
+ }),
504
+ };
505
+ }));
506
+ /** The control accounts a payment can settle: receivables and payables, nothing else. */
507
+ const CONTROL_TYPES = ['asset_receivable', 'liability_payable'];
508
+ const controlAccounts = (rows) => rows.filter((row) => CONTROL_TYPES.includes(String(row.accountType)));
55
509
  const common = async (ctx, url, req) => {
56
510
  await ctx.call('account.initializeCompany', {}, url, req);
57
511
  const [accounts, journals, taxes, terms, partners, companies, templates, units] = (await Promise.all([
@@ -76,12 +530,116 @@ const common = async (ctx, url, req) => {
76
530
  units,
77
531
  };
78
532
  };
79
- const moveFields = (_, data, types) => [
533
+ const paymentFields = async (ctx, url, req, _, data, openItems, rejected) => {
534
+ const values = rejected?.values ?? {};
535
+ const keepRow = (rows, id, fallback) => id && !rows.some((row) => String(row.id) === id) ? [fallback, ...rows] : rows;
536
+ const partners = keepRow(data.partners, values.partnerId ?? '', {
537
+ id: values.partnerId,
538
+ name: values.partnerId,
539
+ });
540
+ const liquidityJournals = keepRow(data.journals.filter((journal) => ['bank', 'cash'].includes(String(journal.type))), values.journalId ?? '', { id: values.journalId, name: values.journalId });
541
+ const settleable = controlAccounts(data.accounts);
542
+ const selectedAccount = data.accounts.find((account) => String(account.id) === String(values.destinationAccountId ?? ''));
543
+ const destinationAccounts = keepRow(settleable, values.destinationAccountId ?? '', {
544
+ id: values.destinationAccountId,
545
+ code: values.destinationAccountId,
546
+ name: selectedAccount ? accountName(_, selectedAccount) : values.destinationAccountId,
547
+ accountType: selectedAccount?.accountType ?? '',
548
+ });
549
+ const reconciliationItems = keepRow(openItems, values.reconcileLineId ?? '', {
550
+ id: values.reconcileLineId,
551
+ });
552
+ const fields = [
553
+ { name: 'name', label: _('account_backend.field.name'), required: true },
554
+ {
555
+ name: 'paymentType',
556
+ label: _('account_backend.field.paymentType'),
557
+ type: 'select',
558
+ options: optionsOf(_, 'paymentType', PAYMENT_TYPES),
559
+ },
560
+ {
561
+ name: 'partnerType',
562
+ label: _('account_backend.field.partnerType'),
563
+ type: 'select',
564
+ options: optionsOf(_, 'partnerType', PARTNER_TYPES),
565
+ },
566
+ {
567
+ name: 'partnerId',
568
+ label: _('account_backend.field.partnerId'),
569
+ type: 'select',
570
+ options: choices(partners, true),
571
+ control: await partnerRelationControl(ctx, url, req, _, {
572
+ id: 'payment-partner',
573
+ partners: partners,
574
+ fieldLabel: _('account_backend.field.partnerId'),
575
+ title: _('account_backend.relation.partners'),
576
+ allowEmpty: true,
577
+ value: values.partnerId,
578
+ }),
579
+ },
580
+ {
581
+ name: 'journalId',
582
+ label: _('account_backend.field.journalId'),
583
+ type: 'select',
584
+ options: choices(liquidityJournals),
585
+ required: true,
586
+ },
587
+ {
588
+ name: 'destinationAccountId',
589
+ label: _('account_backend.field.destinationAccountId'),
590
+ type: 'select',
591
+ options: accountChoices(_, destinationAccounts),
592
+ required: true,
593
+ help: _('account_backend.field.destinationAccountIdHint'),
594
+ control: await accountRelationControl(ctx, url, req, _, {
595
+ id: 'payment-destination-account',
596
+ name: 'destinationAccountId',
597
+ label: _('account_backend.field.destinationAccountId'),
598
+ value: values.destinationAccountId,
599
+ accounts: accountOptions(destinationAccounts),
600
+ accountTypes: CONTROL_TYPES,
601
+ required: true,
602
+ }),
603
+ },
604
+ {
605
+ name: 'amount',
606
+ label: _('account_backend.field.paymentAmount'),
607
+ type: 'decimal',
608
+ value: 0,
609
+ required: true,
610
+ },
611
+ { name: 'date', label: _('account_backend.field.date'), type: 'date' },
612
+ { name: 'memo', label: _('account_backend.field.memo') },
613
+ { name: 'paymentReference', label: _('account_backend.field.paymentReference') },
614
+ {
615
+ name: 'reconcileLineId',
616
+ label: _('account_backend.field.reconcileLineId'),
617
+ type: 'select',
618
+ options: [
619
+ { value: '', label: '—' },
620
+ ...reconciliationItems.map((line) => ({
621
+ value: String(line.id),
622
+ label: line.accountId == null
623
+ ? String(line.move?.name ?? line.moveId ?? line.id)
624
+ : `${String(line.move?.name ?? line.moveId)} · ${accountLabel(_, data.accounts, line.accountId)} · ${formatMoney(_, line.amountResidual, line.move?.currency)}`,
625
+ })),
626
+ ],
627
+ },
628
+ ];
629
+ return restore(fields, rejected);
630
+ };
631
+ const moveFields = async (ctx, url, req, _, data, types, partnerValue) => [
80
632
  {
81
633
  name: 'journalId',
82
634
  label: _('account_backend.field.journalId'),
83
635
  type: 'select',
84
- options: choices(data.journals),
636
+ // A manual entry belongs in the general journal. Offering the journals in
637
+ // insertion order made "bank" the default, which put every hand-written entry
638
+ // into the bank sequence.
639
+ options: choices([
640
+ ...data.journals.filter((journal) => journal.type === 'general'),
641
+ ...data.journals.filter((journal) => journal.type !== 'general'),
642
+ ]),
85
643
  required: true,
86
644
  },
87
645
  {
@@ -97,9 +655,17 @@ const moveFields = (_, data, types) => [
97
655
  label: _('account_backend.field.partnerId'),
98
656
  type: 'select',
99
657
  options: choices(data.partners, true),
658
+ control: await partnerRelationControl(ctx, url, req, _, {
659
+ id: 'move-partner',
660
+ partners: data.partners,
661
+ fieldLabel: _('account_backend.field.partnerId'),
662
+ title: _('account_backend.relation.partners'),
663
+ allowEmpty: true,
664
+ value: partnerValue,
665
+ }),
100
666
  },
101
667
  ];
102
- const invoiceFields = (_, data, types) => {
668
+ const invoiceFields = async (ctx, url, req, _, data, types, values) => {
103
669
  const customer = types.every((type) => type.startsWith('out_'));
104
670
  const journals = data.journals.filter((journal) => journal.type === (customer ? 'sale' : 'purchase'));
105
671
  const lineTypes = customer
@@ -131,6 +697,14 @@ const invoiceFields = (_, data, types) => {
131
697
  label: _('account_backend.field.partnerId'),
132
698
  type: 'select',
133
699
  options: choices(data.partners),
700
+ control: await partnerRelationControl(ctx, url, req, _, {
701
+ id: 'invoice-partner',
702
+ partners: data.partners,
703
+ fieldLabel: _('account_backend.field.partnerId'),
704
+ title: _('account_backend.relation.partners'),
705
+ required: true,
706
+ value: values?.partnerId,
707
+ }),
134
708
  required: true,
135
709
  },
136
710
  { name: 'invoiceDate', label: _('account_backend.field.invoiceDate'), type: 'date' },
@@ -169,37 +743,82 @@ const invoiceFields = (_, data, types) => {
169
743
  required: true,
170
744
  },
171
745
  { name: 'discount', label: _('account_backend.field.discount'), type: 'decimal', value: 0 },
746
+ // Both accounts are answers the configuration already has: the product's
747
+ // category or the company default decides the first, the partner or the
748
+ // company default the second. The field stays, because an unusual document
749
+ // still needs to be able to say otherwise — it just no longer has to.
172
750
  {
173
751
  name: 'lineAccountId',
174
752
  label: _('account_backend.field.lineAccountId'),
175
753
  type: 'select',
176
- options: choices(lineAccounts),
177
- required: true,
754
+ options: accountChoices(_, lineAccounts, true),
755
+ help: _('account_backend.field.lineAccountIdHint'),
756
+ control: await accountRelationControl(ctx, url, req, _, {
757
+ id: `invoice-line-account:${types.join('-')}`,
758
+ name: 'lineAccountId',
759
+ label: _('account_backend.field.lineAccountId'),
760
+ accounts: accountOptions(lineAccounts),
761
+ accountTypes: customer ? ['income*'] : ['expense*'],
762
+ allowEmpty: true,
763
+ value: values?.lineAccountId,
764
+ }),
178
765
  },
179
766
  {
180
767
  name: 'counterpartAccountId',
181
768
  label: _('account_backend.field.counterpartAccountId'),
182
769
  type: 'select',
183
- options: choices(counterpartAccounts),
184
- required: true,
770
+ options: accountChoices(_, counterpartAccounts, true),
771
+ help: _('account_backend.field.counterpartAccountIdHint'),
772
+ control: await accountRelationControl(ctx, url, req, _, {
773
+ id: `invoice-counterpart:${types.join('-')}`,
774
+ name: 'counterpartAccountId',
775
+ label: _('account_backend.field.counterpartAccountId'),
776
+ accounts: accountOptions(counterpartAccounts),
777
+ accountTypes: [customer ? 'asset_receivable' : 'liability_payable'],
778
+ allowEmpty: true,
779
+ value: values?.counterpartAccountId,
780
+ }),
185
781
  },
186
782
  { name: 'taxId', label: _('account_backend.field.taxId'), type: 'select', options: choices(taxes, true) },
783
+ {
784
+ // Import duty and import VAT are two taxes on one line: the duty carries
785
+ // `includeBaseAmount`, so the VAT is computed on the base plus the duty.
786
+ name: 'secondTaxId',
787
+ label: _('account_backend.field.secondTaxId'),
788
+ type: 'select',
789
+ options: choices(taxes, true),
790
+ help: _('account_backend.field.secondTaxIdHint'),
791
+ },
187
792
  {
188
793
  name: 'taxAccountId',
189
794
  label: _('account_backend.field.taxAccountId'),
190
795
  type: 'select',
191
- options: choices(data.accounts, true),
796
+ options: accountChoices(_, data.accounts, true),
797
+ control: await accountRelationControl(ctx, url, req, _, {
798
+ id: `invoice-tax-account:${types.join('-')}`,
799
+ name: 'taxAccountId',
800
+ label: _('account_backend.field.taxAccountId'),
801
+ accounts: accountOptions(data.accounts),
802
+ allowEmpty: true,
803
+ value: values?.taxAccountId,
804
+ }),
805
+ help: _('account_backend.field.taxAccountIdHint'),
192
806
  },
193
807
  ];
194
808
  };
195
- const createInvoice = async (ctx, url, req, redirect) => {
809
+ const createInvoice = async (ctx, url, req) => {
196
810
  const form = await readForm(req);
811
+ // The taxes apply in their configured sequence, not in the order the two
812
+ // selects happen to sit on the page.
813
+ const taxIds = [form.taxId, form.secondTaxId].filter((id, at, all) => Boolean(id) && all.indexOf(id) === at);
814
+ const id = form.id || randomUUID();
197
815
  const result = await ctx.call('account.createInvoice', {
198
- id: randomUUID(),
816
+ id,
199
817
  journalId: form.journalId ?? '',
200
818
  moveType: form.moveType ?? '',
201
819
  partnerId: form.partnerId ?? '',
202
820
  ...optional(form, 'invoiceDate'),
821
+ ...(form.invoiceDate ? { accountingDate: form.invoiceDate, documentDate: form.invoiceDate } : {}),
203
822
  ...optional(form, 'paymentTermId'),
204
823
  ...optional(form, 'ref'),
205
824
  description: form.description ?? '',
@@ -208,54 +827,157 @@ const createInvoice = async (ctx, url, req, redirect) => {
208
827
  quantity: form.quantity || '1',
209
828
  priceUnit: form.priceUnit || '0',
210
829
  discount: form.discount || '0',
211
- lineAccountId: form.lineAccountId ?? '',
212
- counterpartAccountId: form.counterpartAccountId ?? '',
213
- ...optional(form, 'taxId'),
830
+ // Left blank, the domain resolves them from the category, the partner and
831
+ // the company defaults — so blank must arrive as absent, not as ''.
832
+ ...optional(form, 'lineAccountId'),
833
+ ...optional(form, 'counterpartAccountId'),
834
+ ...(taxIds.length ? { taxIds } : {}),
214
835
  ...optional(form, 'taxAccountId'),
215
836
  }, url, req);
216
- return resultRedirect(result, redirect);
837
+ if (!succeeded(result))
838
+ return { rejected: rejection(result, ctx.translate(ctx.localeOf(url, req)), { ...form, id }) };
839
+ // A new invoice is a draft that still has to be posted, so the reader goes to it
840
+ // rather than back to a list where it is one unnamed row among many.
841
+ const opened = `${encodeURIComponent(id)}${localeQuery(url)}`;
842
+ return {
843
+ done: seeOther(String(form.moveType ?? '').startsWith('out_')
844
+ ? `/admin/accounting/customer-invoices/${opened}`
845
+ : `/admin/accounting/vendor-bills/${opened}`),
846
+ };
217
847
  };
218
- const accountMoveRoute = (ctx) => async (url, req, params) => {
848
+ const submitPayment = async (ctx, url, req) => {
849
+ const form = await readForm(req);
850
+ // The action marker belongs to the new form. Missing remains the legacy
851
+ // collection POST; a named foreign action must never register money.
852
+ if (form.action && form.action !== 'register')
853
+ return { done: text('invalid payment action', { status: 400 }) };
854
+ const id = form.id || randomUUID();
855
+ const result = await ctx.call('account.registerPayment', {
856
+ id,
857
+ name: form.name ?? '',
858
+ paymentType: form.paymentType ?? 'inbound',
859
+ partnerType: form.partnerType ?? 'customer',
860
+ ...optional(form, 'partnerId'),
861
+ journalId: form.journalId ?? '',
862
+ destinationAccountId: form.destinationAccountId ?? '',
863
+ amount: form.amount || '0',
864
+ ...optional(form, 'date'),
865
+ ...(form.date ? { accountingDate: form.date, documentDate: form.date } : {}),
866
+ ...optional(form, 'memo'),
867
+ ...optional(form, 'paymentReference'),
868
+ ...optional(form, 'reconcileLineId'),
869
+ }, url, req);
870
+ if (succeeded(result))
871
+ return { done: seeOther(safePaymentReturnTo(url)) };
872
+ return {
873
+ rejected: rejection(result, ctx.translate(ctx.localeOf(url, req)), { ...form, id }),
874
+ };
875
+ };
876
+ const moveFamily = (move) => CUSTOMER_INVOICE_TYPES.includes(String(move.moveType))
877
+ ? 'customer'
878
+ : VENDOR_BILL_TYPES.includes(String(move.moveType))
879
+ ? 'vendor'
880
+ : 'entry';
881
+ const canonicalMovePath = (move, url) => {
882
+ const family = moveFamily(move);
883
+ const collection = family === 'customer'
884
+ ? '/admin/accounting/customer-invoices'
885
+ : family === 'vendor'
886
+ ? '/admin/accounting/vendor-bills'
887
+ : '/admin/accounting/entries';
888
+ return `${collection}/${encodeURIComponent(String(move.id))}${localeQuery(url)}`;
889
+ };
890
+ const accountMoveRoute = (family) => (ctx) => async (url, req, params) => {
891
+ if (req.method !== 'GET' && req.method !== 'POST')
892
+ return text('GET or POST', { status: 405 });
893
+ if (req.method === 'POST' && crossSite(req))
894
+ return text('Forbidden', { status: 403 });
895
+ let move = (await ctx.call('account.getMove', { id: params.id }, url, req));
896
+ if (!move)
897
+ return text(ctx.translate(ctx.localeOf(url, req))('account_backend.move.notFound'), { status: 404 });
898
+ if (moveFamily(move) !== family)
899
+ return seeOther(canonicalMovePath(move, url));
900
+ let rejected;
219
901
  if (req.method === 'POST') {
220
902
  const form = await readForm(req);
221
903
  const result = form.action === 'post'
222
- ? await ctx.call('account.postMove', { id: params.id }, url, req)
904
+ ? await ctx.call('account.postMove', {
905
+ id: params.id,
906
+ ...(form.expectedRevision ? { expectedRevision: Number(form.expectedRevision) } : {}),
907
+ }, url, req)
223
908
  : form.action === 'cancel'
224
- ? await ctx.call('account.cancelMove', { id: params.id }, url, req)
225
- : await ctx.call('account.addMoveLine', {
226
- id: randomUUID(),
227
- moveId: params.id,
228
- name: form.name ?? '',
229
- accountId: form.accountId ?? '',
230
- ...optional(form, 'partnerId'),
231
- debit: form.debit || '0',
232
- credit: form.credit || '0',
233
- }, url, req);
234
- return resultRedirect(result, `${url.pathname}${localeSuffix(url)}`);
909
+ ? await ctx.call('account.cancelMove', {
910
+ id: params.id,
911
+ ...(form.expectedRevision ? { expectedRevision: Number(form.expectedRevision) } : {}),
912
+ }, url, req)
913
+ : form.action === 'reverse'
914
+ ? await ctx.call('account.reverseMove', { id: params.id, reversalId: form.reversalId || randomUUID() }, url, req)
915
+ : form.action === 'add-line'
916
+ ? await ctx.call('account.addMoveLine', {
917
+ id: form.lineId || randomUUID(),
918
+ moveId: params.id,
919
+ name: form.name ?? '',
920
+ accountId: form.accountId ?? '',
921
+ ...optional(form, 'partnerId'),
922
+ debit: form.debit || '0',
923
+ credit: form.credit || '0',
924
+ }, url, req)
925
+ : null;
926
+ if (!result)
927
+ return text('invalid action', { status: 400 });
928
+ if (succeeded(result))
929
+ // A reversal is a journal entry of its own, so the user lands on it rather
930
+ // than on the document they just corrected.
931
+ return seeOther(form.action === 'reverse'
932
+ ? `/admin/accounting/entries/${encodeURIComponent(String(result.reversalId))}${localeQuery(url)}`
933
+ : `${url.pathname}${localeQuery(url)}`);
934
+ rejected = rejection(result, ctx.translate(ctx.localeOf(url, req)), form);
935
+ move = (await ctx.call('account.getMove', { id: params.id }, url, req));
936
+ if (!move)
937
+ return text(ctx.translate(ctx.localeOf(url, req))('account_backend.move.notFound'), { status: 404 });
235
938
  }
236
- if (req.method !== 'GET')
237
- return text('GET or POST', { status: 405 });
238
- const [move, accounts] = (await Promise.all([
239
- ctx.call('account.getMove', { id: params.id }, url, req),
240
- ctx.call('account.listAccounts', {}, url, req),
241
- ]));
242
- if (!move)
243
- return text(ctx.translate(ctx.localeOf(url, req))('account_backend.move.notFound'), { status: 404 });
939
+ const accounts = (await ctx.call('account.listAccounts', {}, url, req));
244
940
  const lang = ctx.localeOf(url, req);
245
941
  const collaboration = await ctx.joint(url, req, 'account_backend:move.collaboration', {
246
942
  resModel: 'account.Move',
247
943
  resId: String(move.id),
248
944
  lang,
249
945
  });
250
- return document(ctx, url, req, String(move.name), (_, tr, shell) => moveDetailScreen(tr, move, move.lines ?? [], shell, choices(accounts), `${url.pathname}${localeSuffix(url)}`, collaboration), false);
946
+ const wanted = move.moveType === 'out_invoice'
947
+ ? 'account.customerInvoice'
948
+ : move.moveType === 'in_invoice'
949
+ ? 'account.vendorBill'
950
+ : null;
951
+ const printable = (await ctx.reportsOf(url, req, 'account.Move')).filter((report) => report.id === wanted);
952
+ return adminPage(ctx, url, req, {
953
+ // A draft has no journal number, so `name` is still its raw id — not a
954
+ // browser-tab title.
955
+ title: moveTitle(ctx.translate(lang), move),
956
+ translate: false,
957
+ body: (_, frame) => moveDetailScreen(_, {
958
+ move,
959
+ lines: move.lines ?? [],
960
+ frame,
961
+ accountOptions: accountChoices(_, accounts),
962
+ action: `${url.pathname}${localeQuery(url)}`,
963
+ collaboration,
964
+ printActions: printGroup(_, printable, String(move.id), url.search),
965
+ rejected,
966
+ lineId: rejected?.values.lineId || randomUUID(),
967
+ reversalId: rejected?.values.reversalId || randomUUID(),
968
+ }),
969
+ });
251
970
  };
252
971
  const MESSAGES = { vi: {}, en: {} };
253
972
  export default defineModule({
254
973
  name: 'account_backend',
255
- version: '0.1.0',
974
+ // 0.4.0: accounting screens exchange civil dates with the ledger and keep
975
+ // visible control totals in exact decimal text.
976
+ // 0.3.0: a refused form says which rule it broke and keeps what was typed;
977
+ // pickers only offer values the ledger accepts; dashboard cards count the lists
978
+ // they open; payment-term milestones are visible and editable.
979
+ version: '0.4.0',
256
980
  depends: ['account', 'backend'],
257
- install: 'auto',
258
- app: true,
259
981
  joints: {
260
982
  'move.collaboration': {
261
983
  props: { resModel: 'text', resId: 'id', lang: 'text' },
@@ -266,7 +988,7 @@ export default defineModule({
266
988
  summary: 'Giao diện sổ cái, hoá đơn, thanh toán và báo cáo.',
267
989
  category: 'Tài chính',
268
990
  menus: {
269
- accounting: { label: 'menu.app', icon: 'banknote', sequence: 30 },
991
+ accounting: { label: 'menu.app', icon: 'banknote', sequence: 26 },
270
992
  'accounting.dashboard': {
271
993
  parent: 'accounting',
272
994
  label: 'menu.dashboard',
@@ -278,72 +1000,111 @@ export default defineModule({
278
1000
  'accounting.customerInvoices': {
279
1001
  parent: 'accounting.customers',
280
1002
  label: 'menu.customerInvoices',
281
- path: '/admin/customer-invoices',
1003
+ path: '/admin/accounting/customer-invoices',
282
1004
  needs: 'account.listMoves',
1005
+ sequence: 10,
283
1006
  },
284
1007
  'accounting.vendors': { parent: 'accounting', label: 'menu.vendors', sequence: 20 },
285
1008
  'accounting.vendorBills': {
286
1009
  parent: 'accounting.vendors',
287
1010
  label: 'menu.vendorBills',
288
- path: '/admin/vendor-bills',
1011
+ path: '/admin/accounting/vendor-bills',
289
1012
  needs: 'account.listMoves',
1013
+ sequence: 10,
290
1014
  },
291
1015
  'accounting.operations': { parent: 'accounting', label: 'menu.operations', sequence: 30 },
292
1016
  'accounting.entries': {
293
1017
  parent: 'accounting.operations',
294
1018
  label: 'menu.entries',
295
- path: '/admin/journal-entries',
1019
+ path: '/admin/accounting/entries',
296
1020
  needs: 'account.listMoves',
1021
+ sequence: 10,
297
1022
  },
298
1023
  'accounting.payments': {
299
1024
  parent: 'accounting.operations',
300
1025
  label: 'menu.payments',
301
- path: '/admin/payments',
1026
+ path: '/admin/accounting/payments',
302
1027
  needs: 'account.listPayments',
1028
+ sequence: 20,
303
1029
  },
304
1030
  'accounting.reporting': { parent: 'accounting', label: 'menu.reporting', sequence: 40 },
305
1031
  'accounting.trialBalance': {
306
1032
  parent: 'accounting.reporting',
307
1033
  label: 'menu.trialBalance',
308
- path: '/admin/trial-balance',
1034
+ path: '/admin/accounting/trial-balance',
309
1035
  needs: 'account.trialBalance',
1036
+ sequence: 10,
310
1037
  },
311
1038
  'accounting.generalLedger': {
312
1039
  parent: 'accounting.reporting',
313
1040
  label: 'menu.generalLedger',
314
- path: '/admin/general-ledger',
1041
+ path: '/admin/accounting/general-ledger',
315
1042
  needs: 'account.generalLedger',
1043
+ sequence: 20,
316
1044
  },
317
1045
  'accounting.partnerStatement': {
318
1046
  parent: 'accounting.reporting',
319
1047
  label: 'menu.partnerStatement',
320
- path: '/admin/partner-statement',
1048
+ path: '/admin/accounting/partner-statement',
321
1049
  needs: 'account.partnerStatement',
1050
+ sequence: 30,
1051
+ },
1052
+ 'accounting.books': {
1053
+ parent: 'accounting.reporting',
1054
+ label: 'menu.books',
1055
+ path: '/admin/accounting/books',
1056
+ needs: 'account.accountingBook',
1057
+ sequence: 40,
1058
+ },
1059
+ 'accounting.periodCloses': {
1060
+ parent: 'accounting.operations',
1061
+ label: 'menu.periodCloses',
1062
+ path: '/admin/accounting/period-closes',
1063
+ needs: 'account.listClosePeriods',
1064
+ sequence: 30,
1065
+ },
1066
+ 'accounting.openingBalances': {
1067
+ parent: 'accounting.configuration',
1068
+ label: 'menu.openingBalances',
1069
+ path: '/admin/accounting/opening-balances',
1070
+ needs: 'account.listOpeningBatches',
1071
+ sequence: 5,
322
1072
  },
323
1073
  'accounting.configuration': { parent: 'accounting', label: 'menu.configuration', sequence: 50 },
324
1074
  'accounting.accounts': {
325
1075
  parent: 'accounting.configuration',
326
1076
  label: 'menu.accounts',
327
- path: '/admin/accounts',
1077
+ path: '/admin/accounting/accounts',
328
1078
  needs: 'account.listAccounts',
1079
+ sequence: 10,
329
1080
  },
330
1081
  'accounting.journals': {
331
1082
  parent: 'accounting.configuration',
332
1083
  label: 'menu.journals',
333
- path: '/admin/journals',
1084
+ path: '/admin/accounting/journals',
334
1085
  needs: 'account.listJournals',
1086
+ sequence: 20,
335
1087
  },
336
1088
  'accounting.taxes': {
337
1089
  parent: 'accounting.configuration',
338
1090
  label: 'menu.taxes',
339
- path: '/admin/taxes',
1091
+ path: '/admin/accounting/taxes',
340
1092
  needs: 'account.listTaxes',
1093
+ sequence: 30,
341
1094
  },
342
1095
  'accounting.terms': {
343
1096
  parent: 'accounting.configuration',
344
1097
  label: 'menu.paymentTerms',
345
- path: '/admin/payment-terms',
1098
+ path: '/admin/accounting/terms',
346
1099
  needs: 'account.listPaymentTerms',
1100
+ sequence: 40,
1101
+ },
1102
+ 'accounting.defaults': {
1103
+ parent: 'accounting.configuration',
1104
+ label: 'menu.defaults',
1105
+ path: '/admin/accounting/defaults',
1106
+ needs: 'account.getDefaults',
1107
+ sequence: 50,
347
1108
  },
348
1109
  },
349
1110
  routes: {
@@ -351,178 +1112,634 @@ export default defineModule({
351
1112
  if (req.method !== 'GET')
352
1113
  return text('GET', { status: 405 });
353
1114
  await ctx.call('account.initializeCompany', {}, url, req);
354
- const [accounts, journals, moves, setup] = (await Promise.all([
355
- ctx.call('account.listAccounts', {}, url, req),
356
- ctx.call('account.listJournals', {}, url, req),
357
- ctx.call('account.listMoves', {}, url, req),
358
- ctx.call('account.getSetup', {}, url, req),
359
- ]));
360
- return document(ctx, url, req, 'account_backend.dashboard.title', (_, tr, shell) => accountingOverviewScreen(tr, {
361
- counts: {
362
- accounts: accounts.length,
363
- journals: journals.length,
364
- draft: moves.filter((move) => move.state === 'draft').length,
365
- posted: moves.filter((move) => move.state === 'posted').length,
366
- unpaid: moves.filter((move) => move.paymentState === 'not_paid').length,
1115
+ const [requestScope, companies] = await Promise.all([
1116
+ ctx.scopeOf(url, req),
1117
+ ctx.call('company.listCompanies', {}, url, req),
1118
+ ]);
1119
+ const accountingTimezone = String(companies.find((company) => String(company.id) === String(requestScope.company))
1120
+ ?.accountingTimezone ?? 'Asia/Ho_Chi_Minh');
1121
+ const period = periodOf(url, new Date(), accountingTimezone);
1122
+ const read = async (name, args) => (await ctx.call(name, args, url, req));
1123
+ // Nine reads, one round of latency. A balance is as at a date and a
1124
+ // result is over a window, so they are separate calls rather than one
1125
+ // "dashboard" function: the same split the trial balance and the general
1126
+ // ledger already make, and the reason narrowing the filter cannot make
1127
+ // total assets shrink.
1128
+ const [current, previous, position, opening, timeline, openItems, cashFlow, setup, oldest] = await Promise.all([
1129
+ read('account.performance', { dateFrom: period.from, dateTo: period.to }),
1130
+ read('account.performance', { dateFrom: period.previousFrom, dateTo: period.previousTo }),
1131
+ read('account.position', { asOf: period.to }),
1132
+ read('account.position', { asOf: period.previousTo }),
1133
+ read('account.revenueTimeline', { dateFrom: period.from, dateTo: period.to }),
1134
+ read('account.openItemSummary', { asOf: period.to, partnerLimit: 5 }),
1135
+ read('account.cashFlow', { dateFrom: period.from, dateTo: period.to }),
1136
+ read('account.getSetup', {}),
1137
+ // The oldest posted move, and only that one: the year chips offer
1138
+ // the years the ledger actually covers, and asking the database for
1139
+ // the earliest date is cheaper than every year deriving from a scan.
1140
+ ctx.call('account.listMoves', { state: 'posted', order: 'asc', limit: 1 }, url, req),
1141
+ ]);
1142
+ // The comparison line has to be bucketed the way this one was, or the
1143
+ // two are not comparable: a previous window one day shorter would
1144
+ // otherwise pick days where this picked months and draw a shape that
1145
+ // shares an axis with nothing.
1146
+ const previousTimeline = await read('account.revenueTimeline', {
1147
+ dateFrom: period.previousFrom,
1148
+ dateTo: period.previousTo,
1149
+ granularity: String(timeline.granularity ?? 'day'),
1150
+ });
1151
+ return adminPage(ctx, url, req, {
1152
+ title: 'account_backend.overview.title',
1153
+ body: async (_, frame) => {
1154
+ const currency = currencyOf(companies, frame);
1155
+ const charts = await overviewCharts(ctx, url, req, _, {
1156
+ currency,
1157
+ current,
1158
+ timeline,
1159
+ previousTimeline,
1160
+ });
1161
+ return accountingOverviewScreen(_, {
1162
+ frame,
1163
+ action: '/admin/accounting',
1164
+ preset: period.preset,
1165
+ years: yearsOf(String(oldest[0]?.accountingDate ?? oldest[0]?.date ?? ''), new Date(), accountingTimezone),
1166
+ presetHref: (name) => {
1167
+ const target = new URL('/admin/accounting', url);
1168
+ target.searchParams.set('period', name);
1169
+ const lang = url.searchParams.get('lang');
1170
+ if (lang)
1171
+ target.searchParams.set('lang', lang);
1172
+ return `${target.pathname}${target.search}`;
1173
+ },
1174
+ // The language rides as a hidden field: a GET form discards the
1175
+ // query string its action carried, which silently sent a reader
1176
+ // filtering in Vietnamese back to the negotiated locale.
1177
+ hidden: url.searchParams.get('lang')
1178
+ ? { lang: String(url.searchParams.get('lang')) }
1179
+ : undefined,
1180
+ fields: [
1181
+ { name: 'dateFrom', label: _('account_backend.field.dateFrom'), value: period.fromDay },
1182
+ { name: 'dateTo', label: _('account_backend.field.dateTo'), value: period.toDay },
1183
+ ],
1184
+ current,
1185
+ previous,
1186
+ position,
1187
+ opening,
1188
+ openItems,
1189
+ cashFlow,
1190
+ revenue: charts.revenue,
1191
+ mix: charts.mix,
1192
+ currency,
1193
+ standard: String(setup.standard),
1194
+ ledgerHref: (accountId) => {
1195
+ const target = new URL('/admin/accounting/general-ledger', url);
1196
+ target.searchParams.set('accountId', accountId);
1197
+ target.searchParams.set('dateFrom', period.from);
1198
+ target.searchParams.set('dateTo', period.to);
1199
+ const lang = url.searchParams.get('lang');
1200
+ if (lang)
1201
+ target.searchParams.set('lang', lang);
1202
+ return `${target.pathname}${target.search}`;
1203
+ },
1204
+ partnerHref: (partnerId) => {
1205
+ const target = new URL('/admin/accounting/partner-statement', url);
1206
+ target.searchParams.set('partnerId', partnerId);
1207
+ target.searchParams.set('dateFrom', period.fromDay);
1208
+ target.searchParams.set('dateTo', period.toDay);
1209
+ const lang = url.searchParams.get('lang');
1210
+ if (lang)
1211
+ target.searchParams.set('lang', lang);
1212
+ return `${target.pathname}${target.search}`;
1213
+ },
1214
+ });
367
1215
  },
368
- frame: shell,
369
- locale: localeSuffix(url),
370
- standard: String(setup.standard),
371
- }));
1216
+ });
372
1217
  },
373
- '/admin/accounts': (ctx) => async (url, req) => {
1218
+ '/admin/accounting/accounts': (ctx) => async (url, req) => {
1219
+ let rejected;
374
1220
  if (req.method === 'POST') {
1221
+ if (crossSite(req))
1222
+ return text('Forbidden', { status: 403 });
375
1223
  const form = await readForm(req);
376
- return resultRedirect(await ctx.call('account.saveAccount', {
377
- id: randomUUID(),
378
- code: form.code ?? '',
379
- name: form.name ?? '',
380
- accountType: form.accountType ?? '',
381
- reconcile: form.reconcile === '1',
382
- active: true,
383
- }, url, req), `/admin/accounts${localeSuffix(url)}`);
1224
+ const result = await saveAccount(ctx, url, req, form);
1225
+ if (succeeded(result))
1226
+ return seeOther(accountListPath(url));
1227
+ rejected = rejection(result, ctx.translate(ctx.localeOf(url, req)), form);
384
1228
  }
385
- if (req.method !== 'GET')
1229
+ else if (req.method !== 'GET')
386
1230
  return text('GET or POST', { status: 405 });
387
- const rows = (await ctx.call('account.listAccounts', {}, url, req));
388
- return document(ctx, url, req, 'account_backend.accounts.title', (_, tr, shell) => accountsScreen(tr, {
389
- frame: shell,
390
- action: `/admin/accounts${localeSuffix(url)}`,
391
- rows,
392
- errors: url.searchParams.get('invalid') === '1' ? [tr('account_backend.error.invalid')] : undefined,
393
- fields: [
394
- { name: 'code', label: tr('account_backend.field.code'), required: true },
395
- { name: 'name', label: tr('account_backend.field.name'), required: true },
396
- {
397
- name: 'accountType',
398
- label: tr('account_backend.field.accountType'),
399
- type: 'select',
400
- options: optionsOf(tr, 'accountType', ACCOUNT_TYPES),
401
- },
402
- { name: 'reconcile', label: tr('account_backend.field.reconcile'), type: 'checkbox' },
403
- ],
404
- }));
1231
+ const all = (await ctx.call('account.listAccounts', { includeArchived: true }, url, req));
1232
+ const editing = editTarget(all, url);
1233
+ const returnTo = accountListPath(url);
1234
+ const modalOpen = req.method === 'POST' || url.searchParams.get('create') === '1' || Boolean(editingId(url));
1235
+ const formPath = accountModalPath(url, editing?.id ?? editingId(url));
1236
+ const page = pageOf(url);
1237
+ const search = searchOf(url);
1238
+ const status = ['active', 'archived'].includes(String(url.searchParams.get('status')))
1239
+ ? url.searchParams.get('status')
1240
+ : null;
1241
+ const family = ['asset', 'liability', 'profit'].includes(String(url.searchParams.get('family')))
1242
+ ? url.searchParams.get('family')
1243
+ : null;
1244
+ const grouped = url.searchParams.get('group') === 'type';
1245
+ const needle = search?.toLocaleLowerCase();
1246
+ const translate = needle ? ctx.translate(ctx.localeOf(url, req)) : null;
1247
+ const matching = all.filter((row) => {
1248
+ const active = row.active === true;
1249
+ if (status === 'active' && !active)
1250
+ return false;
1251
+ if (status === 'archived' && active)
1252
+ return false;
1253
+ const type = String(row.accountType);
1254
+ if (family === 'asset' && !type.startsWith('asset'))
1255
+ return false;
1256
+ if (family === 'liability' && !['liability', 'equity'].some((prefix) => type.startsWith(prefix)))
1257
+ return false;
1258
+ if (family === 'profit' && !['income', 'expense'].some((prefix) => type.startsWith(prefix)))
1259
+ return false;
1260
+ return (!needle ||
1261
+ `${String(row.code)} ${accountName(translate, row)}`.toLocaleLowerCase().includes(needle));
1262
+ });
1263
+ const rows = grouped ? matching : matching.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);
1264
+ return adminPage(ctx, url, req, {
1265
+ title: 'account_backend.accounts.title',
1266
+ body: (_, frame) => {
1267
+ const workspace = accountsListScreen(_, {
1268
+ frame: {
1269
+ ...frame,
1270
+ chrome: {
1271
+ search: {
1272
+ name: 'q',
1273
+ value: search ?? '',
1274
+ placeholder: _('account_backend.accounts.title'),
1275
+ keep: {
1276
+ ...(status ? { status } : {}),
1277
+ ...(family ? { family } : {}),
1278
+ ...(grouped ? { group: 'type' } : {}),
1279
+ ...(url.searchParams.get('lang') ? { lang: String(url.searchParams.get('lang')) } : {}),
1280
+ },
1281
+ facets: [
1282
+ ...(status
1283
+ ? [
1284
+ {
1285
+ label: status === 'active'
1286
+ ? _('account_backend.active')
1287
+ : _('account_backend.archived'),
1288
+ without: withParam(url, 'status', null),
1289
+ },
1290
+ ]
1291
+ : []),
1292
+ ...(family
1293
+ ? [
1294
+ {
1295
+ label: _(`account_backend.account.summary.${family}`),
1296
+ without: withParam(url, 'family', null),
1297
+ },
1298
+ ]
1299
+ : []),
1300
+ ...(grouped
1301
+ ? [
1302
+ {
1303
+ label: `${_('backend.chrome.groupBy')}: ${_('account_backend.field.accountType')}`,
1304
+ without: withParam(url, 'group', null),
1305
+ },
1306
+ ]
1307
+ : []),
1308
+ ],
1309
+ menus: [
1310
+ {
1311
+ id: 'filters',
1312
+ label: _('backend.chrome.filters'),
1313
+ items: [
1314
+ {
1315
+ id: 'status:active',
1316
+ label: _('account_backend.active'),
1317
+ path: withParam(url, 'status', status === 'active' ? null : 'active'),
1318
+ active: status === 'active',
1319
+ },
1320
+ {
1321
+ id: 'status:archived',
1322
+ label: _('account_backend.archived'),
1323
+ path: withParam(url, 'status', status === 'archived' ? null : 'archived'),
1324
+ active: status === 'archived',
1325
+ },
1326
+ ...['asset', 'liability', 'profit'].map((value) => ({
1327
+ id: `family:${value}`,
1328
+ label: _(`account_backend.account.summary.${value}`),
1329
+ path: withParam(url, 'family', family === value ? null : value),
1330
+ active: family === value,
1331
+ })),
1332
+ ],
1333
+ },
1334
+ {
1335
+ id: 'group',
1336
+ label: _('backend.chrome.groupBy'),
1337
+ items: [
1338
+ {
1339
+ id: 'group:type',
1340
+ label: _('account_backend.field.accountType'),
1341
+ path: withParam(url, 'group', grouped ? null : 'type'),
1342
+ active: grouped,
1343
+ },
1344
+ ],
1345
+ },
1346
+ ],
1347
+ },
1348
+ pager: grouped ? null : pager(url, page, rows.length, matching.length),
1349
+ },
1350
+ },
1351
+ rows,
1352
+ createHref: accountModalPath(url),
1353
+ rowHref: (row) => accountModalPath(url, row.id),
1354
+ displayName: (row) => accountName(_, row),
1355
+ summary: accountSummary(all),
1356
+ table: { groups: accountGroups(_, url, matching, grouped) },
1357
+ });
1358
+ if (!modalOpen)
1359
+ return workspace;
1360
+ return modalWorkspace(workspace, accountFormModal(_, {
1361
+ frame,
1362
+ action: formPath,
1363
+ cancelHref: returnTo,
1364
+ editing,
1365
+ displayName: (row) => accountName(_, row),
1366
+ errors: rejected?.messages ??
1367
+ (url.searchParams.get('invalid') === '1'
1368
+ ? [_('account_backend.error.invalid')]
1369
+ : undefined),
1370
+ fields: accountFields(_, editing, rejected),
1371
+ }));
1372
+ },
1373
+ });
405
1374
  },
406
- '/admin/journals': (ctx) => async (url, req) => {
407
- const data = await common(ctx, url, req);
1375
+ '/admin/accounting/accounts/new': (ctx) => async (url, req) => {
408
1376
  if (req.method === 'POST') {
1377
+ if (crossSite(req))
1378
+ return text('Forbidden', { status: 403 });
409
1379
  const form = await readForm(req);
410
- return resultRedirect(await ctx.call('account.saveJournal', {
411
- id: randomUUID(),
412
- name: form.name ?? '',
413
- code: form.code ?? '',
414
- type: form.type ?? '',
415
- ...optional(form, 'defaultAccountId'),
416
- active: true,
417
- }, url, req), `/admin/journals${localeSuffix(url)}`);
1380
+ const result = await saveAccount(ctx, url, req, form);
1381
+ if (succeeded(result))
1382
+ return seeOther(safeAccountReturnTo(url));
1383
+ return seeOther(accountModalPath(url, editingId(url), true));
418
1384
  }
419
- if (req.method !== 'GET')
1385
+ else if (req.method !== 'GET')
420
1386
  return text('GET or POST', { status: 405 });
421
- return document(ctx, url, req, 'account_backend.journals.title', (_, tr, shell) => journalsScreen(tr, {
422
- frame: shell,
423
- action: `/admin/journals${localeSuffix(url)}`,
424
- rows: data.journals,
425
- accounts: data.accounts,
426
- errors: url.searchParams.get('invalid') === '1' ? [tr('account_backend.error.invalid')] : undefined,
427
- fields: [
428
- { name: 'name', label: tr('account_backend.field.name'), required: true },
429
- { name: 'code', label: tr('account_backend.field.code'), required: true },
430
- {
431
- name: 'type',
432
- label: tr('account_backend.field.type'),
433
- type: 'select',
434
- options: optionsOf(tr, 'journalType', JOURNAL_TYPES),
435
- },
436
- {
437
- name: 'defaultAccountId',
438
- label: tr('account_backend.field.defaultAccountId'),
439
- type: 'select',
440
- options: choices(data.accounts, true),
441
- },
442
- ],
443
- }));
1387
+ return seeOther(accountModalPath(url, editingId(url), url.searchParams.get('invalid') === '1'));
444
1388
  },
445
- '/admin/taxes': (ctx) => async (url, req) => {
446
- const data = await common(ctx, url, req);
1389
+ '/admin/accounting/journals': (ctx) => async (url, req) => {
1390
+ let rejected;
447
1391
  if (req.method === 'POST') {
1392
+ if (crossSite(req))
1393
+ return text('Forbidden', { status: 403 });
448
1394
  const form = await readForm(req);
449
- return resultRedirect(await ctx.call('account.saveTax', {
450
- id: randomUUID(),
451
- name: form.name ?? '',
452
- ...optional(form, 'description'),
453
- typeTaxUse: form.typeTaxUse ?? 'sale',
454
- ...optional(form, 'taxScope'),
455
- amountType: form.amountType ?? 'percent',
456
- amount: form.amount || '0',
457
- priceInclude: form.priceInclude === '1',
458
- includeBaseAmount: form.includeBaseAmount === '1',
459
- ...optional(form, 'accountId'),
460
- sequence: Number(form.sequence || 10),
461
- active: true,
462
- }, url, req), `/admin/taxes${localeSuffix(url)}`);
1395
+ const result = await saveJournal(ctx, url, req, form);
1396
+ if (succeeded(result))
1397
+ return seeOther(journalListPath(url));
1398
+ rejected = rejection(result, ctx.translate(ctx.localeOf(url, req)), form);
463
1399
  }
464
- if (req.method !== 'GET')
1400
+ else if (req.method !== 'GET')
465
1401
  return text('GET or POST', { status: 405 });
466
- return document(ctx, url, req, 'account_backend.taxes.title', (_, tr, shell) => {
467
- const currency = currencyOf(data.companies, shell);
468
- return taxesScreen(tr, {
469
- frame: shell,
470
- action: `/admin/taxes${localeSuffix(url)}`,
471
- rows: data.taxes,
472
- accounts: data.accounts,
473
- currency,
474
- errors: url.searchParams.get('invalid') === '1' ? [tr('account_backend.error.invalid')] : undefined,
475
- fields: [
476
- { name: 'name', label: tr('account_backend.field.name'), required: true },
477
- { name: 'description', label: tr('account_backend.field.description') },
478
- {
479
- name: 'typeTaxUse',
480
- label: tr('account_backend.field.typeTaxUse'),
481
- type: 'select',
482
- options: optionsOf(tr, 'taxUse', TAX_USES),
483
- },
484
- {
485
- name: 'taxScope',
486
- label: tr('account_backend.field.taxScope'),
487
- type: 'select',
488
- options: [{ value: '', label: '—' }, ...optionsOf(tr, 'taxScope', ['service', 'consu'])],
489
- },
490
- {
491
- name: 'amountType',
492
- label: tr('account_backend.field.amountType'),
493
- type: 'select',
494
- options: optionsOf(tr, 'taxAmountType', TAX_AMOUNT_TYPES),
495
- },
496
- {
497
- name: 'amount',
498
- label: tr('account_backend.field.amount'),
499
- type: 'decimal',
500
- value: 0,
501
- required: true,
502
- },
503
- {
504
- name: 'accountId',
505
- label: tr('account_backend.field.accountId'),
506
- type: 'select',
507
- options: choices(data.accounts, true),
508
- },
509
- { name: 'priceInclude', label: tr('account_backend.field.priceInclude'), type: 'checkbox' },
510
- {
511
- name: 'includeBaseAmount',
512
- label: tr('account_backend.field.includeBaseAmount'),
513
- type: 'checkbox',
1402
+ const data = await common(ctx, url, req);
1403
+ const all = (await ctx.call('account.listJournals', { includeArchived: true }, url, req));
1404
+ const editing = editTarget(all, url);
1405
+ const returnTo = journalListPath(url);
1406
+ const modalOpen = req.method === 'POST' || url.searchParams.get('create') === '1' || Boolean(editingId(url));
1407
+ const formPath = journalModalPath(url, editing?.id ?? editingId(url));
1408
+ const page = pageOf(url);
1409
+ const search = searchOf(url);
1410
+ const status = ['active', 'archived'].includes(String(url.searchParams.get('status')))
1411
+ ? url.searchParams.get('status')
1412
+ : null;
1413
+ const type = JOURNAL_TYPES.includes(String(url.searchParams.get('type')))
1414
+ ? url.searchParams.get('type')
1415
+ : null;
1416
+ const needle = search?.toLocaleLowerCase();
1417
+ const matching = all.filter((row) => {
1418
+ const active = row.active === true;
1419
+ if (status === 'active' && !active)
1420
+ return false;
1421
+ if (status === 'archived' && active)
1422
+ return false;
1423
+ if (type && row.type !== type)
1424
+ return false;
1425
+ return !needle || `${String(row.code)} ${String(row.name)}`.toLocaleLowerCase().includes(needle);
1426
+ });
1427
+ const journals = matching.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);
1428
+ return adminPage(ctx, url, req, {
1429
+ title: 'account_backend.journals.title',
1430
+ body: async (_, frame) => {
1431
+ const workspace = journalsListScreen(_, {
1432
+ frame: {
1433
+ ...frame,
1434
+ chrome: {
1435
+ search: {
1436
+ name: 'q',
1437
+ value: search ?? '',
1438
+ placeholder: _('account_backend.journals.title'),
1439
+ keep: {
1440
+ ...(status ? { status } : {}),
1441
+ ...(type ? { type } : {}),
1442
+ ...(url.searchParams.get('lang') ? { lang: String(url.searchParams.get('lang')) } : {}),
1443
+ },
1444
+ facets: [
1445
+ ...(status
1446
+ ? [
1447
+ {
1448
+ label: status === 'active'
1449
+ ? _('account_backend.active')
1450
+ : _('account_backend.archived'),
1451
+ without: withParam(url, 'status', null),
1452
+ },
1453
+ ]
1454
+ : []),
1455
+ ...(type
1456
+ ? [
1457
+ {
1458
+ label: labelOf(_, 'journalType', type),
1459
+ without: withParam(url, 'type', null),
1460
+ },
1461
+ ]
1462
+ : []),
1463
+ ],
1464
+ menus: [
1465
+ {
1466
+ id: 'filters',
1467
+ label: _('backend.chrome.filters'),
1468
+ items: [
1469
+ {
1470
+ id: 'status:active',
1471
+ label: _('account_backend.active'),
1472
+ path: withParam(url, 'status', status === 'active' ? null : 'active'),
1473
+ active: status === 'active',
1474
+ },
1475
+ {
1476
+ id: 'status:archived',
1477
+ label: _('account_backend.archived'),
1478
+ path: withParam(url, 'status', status === 'archived' ? null : 'archived'),
1479
+ active: status === 'archived',
1480
+ },
1481
+ ...JOURNAL_TYPES.map((value) => ({
1482
+ id: `type:${value}`,
1483
+ label: labelOf(_, 'journalType', value),
1484
+ path: withParam(url, 'type', type === value ? null : value),
1485
+ active: type === value,
1486
+ })),
1487
+ ],
1488
+ },
1489
+ ],
1490
+ },
1491
+ pager: pager(url, page, journals.length, matching.length),
1492
+ },
514
1493
  },
515
- { name: 'sequence', label: tr('account_backend.field.sequence'), type: 'number', value: 10 },
516
- ],
1494
+ rows: journals,
1495
+ accounts: data.accounts,
1496
+ createHref: journalModalPath(url),
1497
+ rowHref: (row) => journalModalPath(url, row.id),
1498
+ displayAccountName: (row) => accountName(_, row),
1499
+ summary: journalSummary(all),
1500
+ });
1501
+ if (!modalOpen)
1502
+ return workspace;
1503
+ return modalWorkspace(workspace, journalFormModal(_, {
1504
+ frame,
1505
+ action: formPath,
1506
+ cancelHref: returnTo,
1507
+ editing,
1508
+ errors: rejected?.messages ??
1509
+ (url.searchParams.get('invalid') === '1'
1510
+ ? [_('account_backend.error.invalid')]
1511
+ : undefined),
1512
+ fields: await journalFields(ctx, url, req, _, data.accounts, editing, rejected),
1513
+ }));
1514
+ },
1515
+ });
1516
+ },
1517
+ '/admin/accounting/journals/new': (ctx) => async (url, req) => {
1518
+ if (req.method === 'POST') {
1519
+ if (crossSite(req))
1520
+ return text('Forbidden', { status: 403 });
1521
+ const form = await readForm(req);
1522
+ const result = await saveJournal(ctx, url, req, form);
1523
+ if (succeeded(result))
1524
+ return seeOther(safeJournalReturnTo(url));
1525
+ return seeOther(journalModalPath(url, editingId(url), true));
1526
+ }
1527
+ else if (req.method !== 'GET')
1528
+ return text('GET or POST', { status: 405 });
1529
+ return seeOther(journalModalPath(url, editingId(url), url.searchParams.get('invalid') === '1'));
1530
+ },
1531
+ '/admin/accounting/taxes': (ctx) => async (url, req) => {
1532
+ let rejected;
1533
+ if (req.method === 'POST') {
1534
+ if (crossSite(req))
1535
+ return text('Forbidden', { status: 403 });
1536
+ const form = await readForm(req);
1537
+ const result = await saveTax(ctx, url, req, form);
1538
+ if (succeeded(result))
1539
+ return seeOther(taxListPath(url));
1540
+ rejected = rejection(result, ctx.translate(ctx.localeOf(url, req)), form);
1541
+ }
1542
+ else if (req.method !== 'GET')
1543
+ return text('GET or POST', { status: 405 });
1544
+ const data = await common(ctx, url, req);
1545
+ const all = (await ctx.call('account.listTaxes', { includeArchived: true }, url, req));
1546
+ const editing = editTarget(all, url);
1547
+ const returnTo = taxListPath(url);
1548
+ const formPath = taxFormPath(url, returnTo, editing?.id ?? editingId(url));
1549
+ if (req.method === 'POST' || editingId(url)) {
1550
+ if (req.method === 'GET')
1551
+ return seeOther(formPath);
1552
+ return adminPage(ctx, url, req, {
1553
+ title: editing ? 'account_backend.tax.edit.title' : 'account_backend.tax.create.title',
1554
+ body: async (_, frame) => taxFormScreen(_, {
1555
+ frame,
1556
+ action: formPath,
1557
+ cancelHref: returnTo,
1558
+ editing,
1559
+ errors: rejected?.messages,
1560
+ fields: await taxFields(ctx, url, req, _, data.accounts, editing, rejected),
1561
+ }),
517
1562
  });
1563
+ }
1564
+ const page = pageOf(url);
1565
+ const search = searchOf(url);
1566
+ const status = ['active', 'archived'].includes(String(url.searchParams.get('status')))
1567
+ ? url.searchParams.get('status')
1568
+ : null;
1569
+ const use = TAX_USES.includes(String(url.searchParams.get('use')))
1570
+ ? url.searchParams.get('use')
1571
+ : null;
1572
+ const computation = TAX_AMOUNT_TYPES.includes(String(url.searchParams.get('computation')))
1573
+ ? url.searchParams.get('computation')
1574
+ : null;
1575
+ const included = url.searchParams.get('included') === '1';
1576
+ const needle = search?.toLocaleLowerCase();
1577
+ const matching = all.filter((row) => {
1578
+ const active = row.active === true;
1579
+ if (status === 'active' && !active)
1580
+ return false;
1581
+ if (status === 'archived' && active)
1582
+ return false;
1583
+ if (use && row.typeTaxUse !== use)
1584
+ return false;
1585
+ if (computation && row.amountType !== computation)
1586
+ return false;
1587
+ if (included && row.priceInclude !== true)
1588
+ return false;
1589
+ return (!needle ||
1590
+ `${String(row.name)} ${String(row.description ?? '')} ${String(row.amount)}`
1591
+ .toLocaleLowerCase()
1592
+ .includes(needle));
1593
+ });
1594
+ const taxes = matching.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);
1595
+ return adminPage(ctx, url, req, {
1596
+ title: 'account_backend.taxes.title',
1597
+ body: (_, frame) => taxesListScreen(_, {
1598
+ frame: {
1599
+ ...frame,
1600
+ chrome: {
1601
+ search: {
1602
+ name: 'q',
1603
+ value: search ?? '',
1604
+ placeholder: _('account_backend.taxes.title'),
1605
+ keep: {
1606
+ ...(status ? { status } : {}),
1607
+ ...(use ? { use } : {}),
1608
+ ...(computation ? { computation } : {}),
1609
+ ...(included ? { included: '1' } : {}),
1610
+ ...(url.searchParams.get('lang') ? { lang: String(url.searchParams.get('lang')) } : {}),
1611
+ },
1612
+ facets: [
1613
+ ...(status
1614
+ ? [
1615
+ {
1616
+ label: status === 'active'
1617
+ ? _('account_backend.active')
1618
+ : _('account_backend.archived'),
1619
+ without: withParam(url, 'status', null),
1620
+ },
1621
+ ]
1622
+ : []),
1623
+ ...(use
1624
+ ? [
1625
+ {
1626
+ label: labelOf(_, 'taxUse', use),
1627
+ without: withParam(url, 'use', null),
1628
+ },
1629
+ ]
1630
+ : []),
1631
+ ...(computation
1632
+ ? [
1633
+ {
1634
+ label: labelOf(_, 'taxAmountType', computation),
1635
+ without: withParam(url, 'computation', null),
1636
+ },
1637
+ ]
1638
+ : []),
1639
+ ...(included
1640
+ ? [
1641
+ {
1642
+ label: _('account_backend.tax.summary.included'),
1643
+ without: withParam(url, 'included', null),
1644
+ },
1645
+ ]
1646
+ : []),
1647
+ ],
1648
+ menus: [
1649
+ {
1650
+ id: 'filters',
1651
+ label: _('backend.chrome.filters'),
1652
+ items: [
1653
+ {
1654
+ id: 'status:active',
1655
+ label: _('account_backend.active'),
1656
+ path: withParam(url, 'status', status === 'active' ? null : 'active'),
1657
+ active: status === 'active',
1658
+ },
1659
+ {
1660
+ id: 'status:archived',
1661
+ label: _('account_backend.archived'),
1662
+ path: withParam(url, 'status', status === 'archived' ? null : 'archived'),
1663
+ active: status === 'archived',
1664
+ },
1665
+ ...TAX_USES.map((value) => ({
1666
+ id: `use:${value}`,
1667
+ label: labelOf(_, 'taxUse', value),
1668
+ path: withParam(url, 'use', use === value ? null : value),
1669
+ active: use === value,
1670
+ })),
1671
+ ...TAX_AMOUNT_TYPES.map((value) => ({
1672
+ id: `computation:${value}`,
1673
+ label: labelOf(_, 'taxAmountType', value),
1674
+ path: withParam(url, 'computation', computation === value ? null : value),
1675
+ active: computation === value,
1676
+ })),
1677
+ {
1678
+ id: 'included',
1679
+ label: _('account_backend.tax.summary.included'),
1680
+ path: withParam(url, 'included', included ? null : '1'),
1681
+ active: included,
1682
+ },
1683
+ ],
1684
+ },
1685
+ ],
1686
+ },
1687
+ pager: pager(url, page, taxes.length, matching.length),
1688
+ },
1689
+ },
1690
+ rows: taxes,
1691
+ accounts: data.accounts,
1692
+ currency: currencyOf(data.companies, frame),
1693
+ createHref: taxFormPath(url, returnTo),
1694
+ rowHref: (row) => taxFormPath(url, returnTo, row.id),
1695
+ summary: taxSummary(all),
1696
+ }),
1697
+ });
1698
+ },
1699
+ '/admin/accounting/taxes/new': (ctx) => async (url, req) => {
1700
+ let rejected;
1701
+ if (req.method === 'POST') {
1702
+ if (crossSite(req))
1703
+ return text('Forbidden', { status: 403 });
1704
+ const form = await readForm(req);
1705
+ const result = await saveTax(ctx, url, req, form);
1706
+ if (succeeded(result))
1707
+ return seeOther(safeTaxReturnTo(url));
1708
+ rejected = rejection(result, ctx.translate(ctx.localeOf(url, req)), form);
1709
+ }
1710
+ else if (req.method !== 'GET')
1711
+ return text('GET or POST', { status: 405 });
1712
+ const data = await common(ctx, url, req);
1713
+ const taxes = (await ctx.call('account.listTaxes', { includeArchived: true }, url, req));
1714
+ const editing = editTarget(taxes, url);
1715
+ const returnTo = safeTaxReturnTo(url);
1716
+ const formPath = taxFormPath(url, returnTo, editing?.id ?? editingId(url));
1717
+ return adminPage(ctx, url, req, {
1718
+ title: editing ? 'account_backend.tax.edit.title' : 'account_backend.tax.create.title',
1719
+ body: async (_, frame) => taxFormScreen(_, {
1720
+ frame,
1721
+ action: formPath,
1722
+ cancelHref: returnTo,
1723
+ editing,
1724
+ errors: rejected?.messages,
1725
+ fields: await taxFields(ctx, url, req, _, data.accounts, editing, rejected),
1726
+ }),
518
1727
  });
519
1728
  },
520
- '/admin/payment-terms': (ctx) => async (url, req) => {
1729
+ '/admin/accounting/terms': (ctx) => async (url, req) => {
1730
+ // Two forms post here, so a refusal has to land on the one that caused it.
1731
+ let rejected;
1732
+ let rejectedLine;
1733
+ let submittedLine = false;
521
1734
  if (req.method === 'POST') {
1735
+ if (crossSite(req))
1736
+ return text('Forbidden', { status: 403 });
522
1737
  const form = await readForm(req);
523
- const result = form.action === 'line'
1738
+ const line = form.action === 'line';
1739
+ submittedLine = line;
1740
+ const result = line
524
1741
  ? await ctx.call('account.savePaymentTermLine', {
525
- id: randomUUID(),
1742
+ id: url.searchParams.get('editLine') || randomUUID(),
526
1743
  paymentId: form.paymentId ?? '',
527
1744
  value: form.value ?? 'percent',
528
1745
  valueAmount: form.valueAmount || '100',
@@ -531,312 +1748,1550 @@ export default defineModule({
531
1748
  ...(form.daysNextMonth ? { daysNextMonth: Number(form.daysNextMonth) } : {}),
532
1749
  sequence: Number(form.sequence || 10),
533
1750
  }, url, req)
534
- : await ctx.call('account.savePaymentTerm', { id: randomUUID(), name: form.name ?? '', ...optional(form, 'note'), active: true }, url, req);
535
- return resultRedirect(result, `/admin/payment-terms${localeSuffix(url)}`);
1751
+ : await ctx.call('account.savePaymentTerm', {
1752
+ id: targetId(url),
1753
+ name: form.name ?? '',
1754
+ ...optional(form, 'note'),
1755
+ active: form.active === '1',
1756
+ }, url, req);
1757
+ if (succeeded(result))
1758
+ return seeOther(paymentTermListPath(url));
1759
+ const failure = rejection(result, ctx.translate(ctx.localeOf(url, req)), form);
1760
+ if (line)
1761
+ rejectedLine = failure;
1762
+ else
1763
+ rejected = failure;
536
1764
  }
537
- if (req.method !== 'GET')
1765
+ else if (req.method !== 'GET')
538
1766
  return text('GET or POST', { status: 405 });
539
- const rows = (await ctx.call('account.listPaymentTerms', {}, url, req));
540
- return document(ctx, url, req, 'account_backend.terms.title', (_, tr, shell) => paymentTermsScreen(tr, {
541
- frame: shell,
542
- action: `/admin/payment-terms${localeSuffix(url)}`,
543
- rows,
544
- errors: url.searchParams.get('invalid') === '1' ? [tr('account_backend.error.invalid')] : undefined,
545
- termFields: [
546
- { name: 'name', label: tr('account_backend.field.name'), required: true },
547
- { name: 'note', label: tr('account_backend.field.note'), type: 'textarea', span: 'full' },
548
- ],
549
- lineFields: rows.length
550
- ? [
551
- {
552
- name: 'paymentId',
553
- label: tr('account_backend.field.paymentTermId'),
554
- type: 'select',
555
- options: choices(rows),
556
- required: true,
1767
+ const rows = (await ctx.call('account.listPaymentTerms', { includeArchived: true }, url, req));
1768
+ const editing = editTarget(rows, url);
1769
+ const editingLine = termLineTarget(rows, url);
1770
+ const returnTo = paymentTermListPath(url);
1771
+ const lineModalOpen = submittedLine || url.searchParams.get('line') === '1' || Boolean(url.searchParams.get('editLine'));
1772
+ const termModalOpen = !lineModalOpen &&
1773
+ (req.method === 'POST' || url.searchParams.get('create') === '1' || Boolean(editingId(url)));
1774
+ const page = pageOf(url);
1775
+ const search = searchOf(url);
1776
+ const status = ['active', 'archived'].includes(String(url.searchParams.get('status')))
1777
+ ? url.searchParams.get('status')
1778
+ : null;
1779
+ const needle = search?.toLocaleLowerCase();
1780
+ const matching = rows.filter((row) => {
1781
+ const active = row.active === true;
1782
+ if (status === 'active' && !active)
1783
+ return false;
1784
+ if (status === 'archived' && active)
1785
+ return false;
1786
+ return (!needle || `${String(row.name)} ${String(row.note ?? '')}`.toLocaleLowerCase().includes(needle));
1787
+ });
1788
+ const listed = matching.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);
1789
+ return adminPage(ctx, url, req, {
1790
+ title: 'account_backend.terms.title',
1791
+ body: (_, frame) => {
1792
+ const workspace = paymentTermsListScreen(_, {
1793
+ frame: {
1794
+ ...frame,
1795
+ chrome: {
1796
+ search: {
1797
+ name: 'q',
1798
+ value: search ?? '',
1799
+ placeholder: _('account_backend.terms.title'),
1800
+ keep: {
1801
+ ...(status ? { status } : {}),
1802
+ ...(url.searchParams.get('lang') ? { lang: String(url.searchParams.get('lang')) } : {}),
1803
+ },
1804
+ facets: status
1805
+ ? [
1806
+ {
1807
+ label: status === 'active'
1808
+ ? _('account_backend.active')
1809
+ : _('account_backend.archived'),
1810
+ without: withParam(url, 'status', null),
1811
+ },
1812
+ ]
1813
+ : [],
1814
+ menus: [
1815
+ {
1816
+ id: 'filters',
1817
+ label: _('backend.chrome.filters'),
1818
+ items: [
1819
+ {
1820
+ id: 'status:active',
1821
+ label: _('account_backend.active'),
1822
+ path: withParam(url, 'status', status === 'active' ? null : 'active'),
1823
+ active: status === 'active',
1824
+ },
1825
+ {
1826
+ id: 'status:archived',
1827
+ label: _('account_backend.archived'),
1828
+ path: withParam(url, 'status', status === 'archived' ? null : 'archived'),
1829
+ active: status === 'archived',
1830
+ },
1831
+ ],
1832
+ },
1833
+ ],
1834
+ },
1835
+ pager: pager(url, page, listed.length, matching.length),
1836
+ },
557
1837
  },
1838
+ rows: listed,
1839
+ createHref: paymentTermModalPath(url),
1840
+ lineCreateHref: rows.length ? paymentTermLineModalPath(url) : undefined,
1841
+ rowHref: (row) => paymentTermModalPath(url, row.id),
1842
+ lineHref: (line) => paymentTermLineModalPath(url, line.id),
1843
+ delayLabel: (line) => selectionLabel(_, 'account_backend', 'paymentTermDelay', line.delayType),
1844
+ valueLabel: (line) => selectionLabel(_, 'account_backend', 'paymentTermValue', line.value),
1845
+ summary: paymentTermSummary(rows),
1846
+ });
1847
+ if (lineModalOpen && rows.length)
1848
+ return modalWorkspace(workspace, paymentTermLineFormModal(_, {
1849
+ frame,
1850
+ action: paymentTermLineModalPath(url, editingLine?.id ?? url.searchParams.get('editLine')),
1851
+ cancelHref: returnTo,
1852
+ editing: editingLine,
1853
+ errors: rejectedLine?.messages,
1854
+ fields: formState([
1855
+ {
1856
+ name: 'paymentId',
1857
+ label: _('account_backend.field.paymentTermId'),
1858
+ type: 'select',
1859
+ options: choices(rows),
1860
+ required: true,
1861
+ },
1862
+ {
1863
+ name: 'value',
1864
+ label: _('account_backend.field.termValue'),
1865
+ type: 'select',
1866
+ options: optionsOf(_, 'paymentTermValue', PAYMENT_TERM_VALUES),
1867
+ },
1868
+ {
1869
+ name: 'valueAmount',
1870
+ label: _('account_backend.field.valueAmount'),
1871
+ type: 'decimal',
1872
+ value: 100,
1873
+ required: true,
1874
+ },
1875
+ {
1876
+ name: 'delayType',
1877
+ label: _('account_backend.field.delayType'),
1878
+ type: 'select',
1879
+ options: optionsOf(_, 'paymentTermDelay', PAYMENT_TERM_DELAY_TYPES),
1880
+ },
1881
+ {
1882
+ name: 'nbDays',
1883
+ label: _('account_backend.field.nbDays'),
1884
+ type: 'number',
1885
+ value: 0,
1886
+ required: true,
1887
+ },
1888
+ {
1889
+ name: 'daysNextMonth',
1890
+ label: _('account_backend.field.daysNextMonth'),
1891
+ type: 'number',
1892
+ help: _('account_backend.field.daysNextMonthHint'),
1893
+ },
1894
+ {
1895
+ name: 'sequence',
1896
+ label: _('account_backend.field.sequence'),
1897
+ type: 'number',
1898
+ value: 10,
1899
+ },
1900
+ ], editingLine, rejectedLine),
1901
+ }));
1902
+ if (!termModalOpen)
1903
+ return workspace;
1904
+ return modalWorkspace(workspace, paymentTermFormModal(_, {
1905
+ frame,
1906
+ action: paymentTermModalPath(url, editing?.id ?? editingId(url)),
1907
+ cancelHref: returnTo,
1908
+ editing,
1909
+ errors: rejected?.messages,
1910
+ fields: formState([
1911
+ { name: 'name', label: _('account_backend.field.name'), required: true },
1912
+ { name: 'note', label: _('account_backend.field.note'), type: 'textarea', span: 'full' },
1913
+ {
1914
+ name: 'active',
1915
+ label: _('account_backend.field.active'),
1916
+ type: 'checkbox',
1917
+ value: true,
1918
+ help: _('account_backend.field.activeHint'),
1919
+ },
1920
+ ], editing, rejected),
1921
+ }));
1922
+ },
1923
+ });
1924
+ },
1925
+ '/admin/accounting/defaults': (ctx) => async (url, req) => {
1926
+ let rejected;
1927
+ let rejectedCategory;
1928
+ if (req.method === 'POST') {
1929
+ if (crossSite(req))
1930
+ return text('Forbidden', { status: 403 });
1931
+ const form = await readForm(req);
1932
+ const category = form.action === 'category';
1933
+ const result = category
1934
+ ? await ctx.call('account.saveCategoryAccount', {
1935
+ categoryId: form.categoryId ?? '',
1936
+ ...optional(form, 'incomeAccountId'),
1937
+ ...optional(form, 'expenseAccountId'),
1938
+ }, url, req)
1939
+ : await ctx.call('account.saveDefaults', {
1940
+ ...optional(form, 'incomeAccountId'),
1941
+ ...optional(form, 'expenseAccountId'),
1942
+ ...optional(form, 'receivableAccountId'),
1943
+ ...optional(form, 'payableAccountId'),
1944
+ }, url, req);
1945
+ if (succeeded(result))
1946
+ return seeOther(`/admin/accounting/defaults${localeQuery(url)}`);
1947
+ const failure = rejection(result, ctx.translate(ctx.localeOf(url, req)), form);
1948
+ if (category)
1949
+ rejectedCategory = failure;
1950
+ else
1951
+ rejected = failure;
1952
+ }
1953
+ else if (req.method !== 'GET')
1954
+ return text('GET or POST', { status: 405 });
1955
+ const data = await common(ctx, url, req);
1956
+ const [defaults, rows, categories] = (await Promise.all([
1957
+ ctx.call('account.getDefaults', {}, url, req),
1958
+ ctx.call('account.listCategoryAccounts', {}, url, req),
1959
+ ctx.call('product.listCategories', {}, url, req),
1960
+ ]));
1961
+ const editingCategory = (() => {
1962
+ const id = url.searchParams.get('editCategory') ?? '';
1963
+ return id ? (rows.find((row) => String(row.categoryId) === id) ?? null) : null;
1964
+ })();
1965
+ const income = data.accounts.filter((row) => ['income', 'income_other'].includes(String(row.accountType)));
1966
+ const expense = data.accounts.filter((row) => ['expense', 'expense_other', 'expense_depreciation', 'expense_direct_cost'].includes(String(row.accountType)));
1967
+ const receivable = data.accounts.filter((row) => row.accountType === 'asset_receivable');
1968
+ const payable = data.accounts.filter((row) => row.accountType === 'liability_payable');
1969
+ const categoryTarget = (id) => {
1970
+ const target = new URL('/admin/accounting/defaults', url);
1971
+ const lang = url.searchParams.get('lang');
1972
+ if (lang)
1973
+ target.searchParams.set('lang', lang);
1974
+ if (id)
1975
+ target.searchParams.set('editCategory', String(id));
1976
+ return `${target.pathname}${target.search}`;
1977
+ };
1978
+ return adminPage(ctx, url, req, {
1979
+ title: 'account_backend.defaults.title',
1980
+ body: async (_, frame) => {
1981
+ const defaultsFields = await accountRelationFields(ctx, url, req, _, 'account-defaults', formState([
558
1982
  {
559
- name: 'value',
560
- label: tr('account_backend.field.termValue'),
1983
+ name: 'incomeAccountId',
1984
+ label: _('account_backend.field.incomeAccountId'),
561
1985
  type: 'select',
562
- options: optionsOf(tr, 'paymentTermValue', PAYMENT_TERM_VALUES),
1986
+ options: accountChoices(_, income, true),
1987
+ help: _('account_backend.field.incomeAccountIdHint'),
563
1988
  },
564
1989
  {
565
- name: 'valueAmount',
566
- label: tr('account_backend.field.valueAmount'),
567
- type: 'decimal',
568
- value: 100,
569
- required: true,
570
- },
571
- {
572
- name: 'delayType',
573
- label: tr('account_backend.field.delayType'),
1990
+ name: 'expenseAccountId',
1991
+ label: _('account_backend.field.expenseAccountId'),
574
1992
  type: 'select',
575
- options: optionsOf(tr, 'paymentTermDelay', PAYMENT_TERM_DELAY_TYPES),
1993
+ options: accountChoices(_, expense, true),
1994
+ help: _('account_backend.field.expenseAccountIdHint'),
576
1995
  },
577
1996
  {
578
- name: 'nbDays',
579
- label: tr('account_backend.field.nbDays'),
580
- type: 'number',
581
- value: 0,
582
- required: true,
1997
+ name: 'receivableAccountId',
1998
+ label: _('account_backend.field.receivableAccountId'),
1999
+ type: 'select',
2000
+ options: accountChoices(_, receivable, true),
2001
+ help: _('account_backend.field.receivableAccountIdHint'),
583
2002
  },
584
2003
  {
585
- name: 'daysNextMonth',
586
- label: tr('account_backend.field.daysNextMonth'),
587
- type: 'number',
2004
+ name: 'payableAccountId',
2005
+ label: _('account_backend.field.payableAccountId'),
2006
+ type: 'select',
2007
+ options: accountChoices(_, payable, true),
2008
+ help: _('account_backend.field.payableAccountIdHint'),
588
2009
  },
589
- {
590
- name: 'sequence',
591
- label: tr('account_backend.field.sequence'),
592
- type: 'number',
593
- value: 10,
2010
+ ], defaults, rejected), {
2011
+ incomeAccountId: { accounts: income, accountTypes: ['income', 'income_other'] },
2012
+ expenseAccountId: {
2013
+ accounts: expense,
2014
+ accountTypes: ['expense', 'expense_other', 'expense_depreciation', 'expense_direct_cost'],
594
2015
  },
595
- ]
596
- : undefined,
597
- }));
2016
+ receivableAccountId: { accounts: receivable, accountTypes: ['asset_receivable'] },
2017
+ payableAccountId: { accounts: payable, accountTypes: ['liability_payable'] },
2018
+ });
2019
+ const categoryFields = categories.length
2020
+ ? await accountRelationFields(ctx, url, req, _, 'account-category-defaults', formState([
2021
+ {
2022
+ name: 'categoryId',
2023
+ label: _('account_backend.field.categoryId'),
2024
+ type: 'select',
2025
+ options: choices(categories),
2026
+ required: true,
2027
+ },
2028
+ {
2029
+ name: 'incomeAccountId',
2030
+ label: _('account_backend.field.incomeAccountId'),
2031
+ type: 'select',
2032
+ options: accountChoices(_, income, true),
2033
+ },
2034
+ {
2035
+ name: 'expenseAccountId',
2036
+ label: _('account_backend.field.expenseAccountId'),
2037
+ type: 'select',
2038
+ options: accountChoices(_, expense, true),
2039
+ },
2040
+ ], editingCategory, rejectedCategory), {
2041
+ incomeAccountId: { accounts: income, accountTypes: ['income', 'income_other'] },
2042
+ expenseAccountId: {
2043
+ accounts: expense,
2044
+ accountTypes: [
2045
+ 'expense',
2046
+ 'expense_other',
2047
+ 'expense_depreciation',
2048
+ 'expense_direct_cost',
2049
+ ],
2050
+ },
2051
+ })
2052
+ : undefined;
2053
+ return accountDefaultsScreen(_, {
2054
+ frame: frame,
2055
+ action: `/admin/accounting/defaults${localeQuery(url)}`,
2056
+ categoryAction: categoryTarget(url.searchParams.get('editCategory')),
2057
+ rows,
2058
+ accountLabel: (id) => accountLabel(_, data.accounts, id),
2059
+ editing: editingCategory,
2060
+ categorySubmit: editingCategory
2061
+ ? _('account_backend.action.save')
2062
+ : _('account_backend.action.create'),
2063
+ categoryHref: (row) => categoryTarget(row.categoryId),
2064
+ cancelHref: `/admin/accounting/defaults${localeQuery(url)}`,
2065
+ errors: rejected?.messages,
2066
+ categoryErrors: rejectedCategory?.messages,
2067
+ defaultsFields,
2068
+ categoryFields,
2069
+ });
2070
+ },
2071
+ });
598
2072
  },
599
- '/admin/journal-entries': (ctx) => async (url, req) => {
2073
+ '/admin/accounting/entries': (ctx) => async (url, req) => {
600
2074
  const data = await common(ctx, url, req);
2075
+ let rejected;
2076
+ let idempotencyKey = '';
601
2077
  if (req.method === 'POST') {
2078
+ if (crossSite(req))
2079
+ return text('Forbidden', { status: 403 });
602
2080
  const form = await readForm(req);
603
- return resultRedirect(await ctx.call('account.createMove', {
604
- id: randomUUID(),
2081
+ const id = form.id || randomUUID();
2082
+ idempotencyKey = id;
2083
+ const result = await ctx.call('account.createMove', {
2084
+ id,
605
2085
  journalId: form.journalId ?? '',
606
2086
  moveType: form.moveType || 'entry',
607
2087
  ...optional(form, 'date'),
2088
+ ...(form.date ? { accountingDate: form.date, documentDate: form.date } : {}),
608
2089
  ...optional(form, 'ref'),
609
2090
  ...optional(form, 'partnerId'),
610
- }, url, req), `/admin/journal-entries${localeSuffix(url)}`);
2091
+ }, url, req);
2092
+ // A new entry is empty, so the only useful next step is opening it to add
2093
+ // its lines. Landing back on the list left the reader to find it again.
2094
+ if (succeeded(result))
2095
+ return seeOther(`/admin/accounting/entries/${encodeURIComponent(id)}${localeQuery(url)}`);
2096
+ rejected = rejection(result, ctx.translate(ctx.localeOf(url, req)), form);
611
2097
  }
612
- if (req.method !== 'GET')
2098
+ else if (req.method !== 'GET')
613
2099
  return text('GET or POST', { status: 405 });
614
- const state = url.searchParams.get('state');
615
- const rows = (await ctx.call('account.listMoves', { moveType: 'entry', ...(state ? { state } : {}) }, url, req));
616
- return document(ctx, url, req, 'account_backend.entries.title', (_, tr, shell) => journalEntriesScreen(tr, {
617
- frame: shell,
618
- action: `/admin/journal-entries${localeSuffix(url)}`,
619
- fields: moveFields(tr, data, ['entry']),
620
- rows,
621
- locale: localeSuffix(url),
622
- errors: url.searchParams.get('invalid') === '1' ? [tr('account_backend.error.invalid')] : undefined,
623
- }));
2100
+ const all = (await ctx.call('account.listMoves', { moveType: 'entry', limit: LIST_PAGE }, url, req));
2101
+ const state = MOVE_STATES.includes(String(url.searchParams.get('state')))
2102
+ ? url.searchParams.get('state')
2103
+ : null;
2104
+ const page = pageOf(url);
2105
+ const search = searchOf(url);
2106
+ const needle = search?.toLocaleLowerCase();
2107
+ const matching = all.filter((row) => {
2108
+ if (state && row.state !== state)
2109
+ return false;
2110
+ return (!needle ||
2111
+ `${String(row.name ?? '')} ${String(row.ref ?? '')} ${String(row.accountingDate ?? row.date ?? '')} ${String(row.partnerId ?? '')}`
2112
+ .toLocaleLowerCase()
2113
+ .includes(needle));
2114
+ });
2115
+ const rows = matching.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);
2116
+ const returnTo = journalEntryListPath(url);
2117
+ const modalOpen = req.method === 'POST' || url.searchParams.get('create') === '1';
2118
+ if (modalOpen && !idempotencyKey)
2119
+ idempotencyKey = randomUUID();
2120
+ return adminPage(ctx, url, req, {
2121
+ title: 'account_backend.entries.title',
2122
+ body: async (_, frame) => {
2123
+ const workspace = journalEntriesListScreen(_, {
2124
+ frame: {
2125
+ ...frame,
2126
+ chrome: {
2127
+ search: {
2128
+ name: 'q',
2129
+ value: search ?? '',
2130
+ placeholder: _('account_backend.entries.title'),
2131
+ keep: {
2132
+ ...(state ? { state } : {}),
2133
+ ...(url.searchParams.get('lang') ? { lang: String(url.searchParams.get('lang')) } : {}),
2134
+ },
2135
+ facets: state
2136
+ ? [{ label: labelOf(_, 'moveState', state), without: withParam(url, 'state', null) }]
2137
+ : [],
2138
+ menus: [
2139
+ {
2140
+ id: 'filters',
2141
+ label: _('backend.chrome.filters'),
2142
+ items: MOVE_STATES.map((value) => ({
2143
+ id: `state:${value}`,
2144
+ label: labelOf(_, 'moveState', value),
2145
+ path: withParam(url, 'state', state === value ? null : value),
2146
+ active: state === value,
2147
+ })),
2148
+ },
2149
+ ],
2150
+ },
2151
+ pager: pager(url, page, rows.length, matching.length),
2152
+ },
2153
+ },
2154
+ rows,
2155
+ createHref: journalEntryModalPath(url),
2156
+ rowHref: (row) => `/admin/accounting/entries/${encodeURIComponent(String(row.id))}${localeQuery(url)}`,
2157
+ summary: {
2158
+ total: all.length,
2159
+ draft: all.filter((row) => row.state === 'draft').length,
2160
+ posted: all.filter((row) => row.state === 'posted').length,
2161
+ },
2162
+ });
2163
+ if (!modalOpen)
2164
+ return workspace;
2165
+ return modalWorkspace(workspace, journalEntryCreateModal(_, {
2166
+ frame,
2167
+ action: journalEntryModalPath(url),
2168
+ cancelHref: returnTo,
2169
+ idempotencyKey,
2170
+ fields: restore(await moveFields(ctx, url, req, _, data, ['entry'], rejected?.values.partnerId), rejected),
2171
+ errors: rejected?.messages,
2172
+ }));
2173
+ },
2174
+ });
624
2175
  },
625
- '/admin/customer-invoices': (ctx) => async (url, req) => {
2176
+ '/admin/accounting/customer-invoices': (ctx) => async (url, req) => {
2177
+ let rejected;
2178
+ if (req.method === 'POST') {
2179
+ if (crossSite(req))
2180
+ return text('Forbidden', { status: 403 });
2181
+ const outcome = await createInvoice(ctx, url, req);
2182
+ if ('done' in outcome)
2183
+ return outcome.done;
2184
+ rejected = outcome.rejected;
2185
+ }
2186
+ else if (req.method !== 'GET')
2187
+ return text('GET or POST', { status: 405 });
626
2188
  const data = await common(ctx, url, req);
627
- if (req.method === 'POST')
628
- return createInvoice(ctx, url, req, `/admin/customer-invoices${localeSuffix(url)}`);
629
- if (req.method !== 'GET')
2189
+ if (rejected)
2190
+ return adminPage(ctx, url, req, {
2191
+ title: 'account_backend.customerInvoice.create.title',
2192
+ body: async (_, frame) => customerInvoiceFormScreen(_, {
2193
+ frame,
2194
+ action: customerInvoiceListPath(url),
2195
+ cancelHref: customerInvoiceListPath(url),
2196
+ idempotencyKey: rejected.values.id ?? randomUUID(),
2197
+ fields: restore(await invoiceFields(ctx, url, req, _, data, CUSTOMER_INVOICE_TYPES, rejected.values), rejected),
2198
+ errors: rejected.messages,
2199
+ }),
2200
+ });
2201
+ const all = (await ctx.call('account.listMoves', { moveTypes: CUSTOMER_INVOICE_TYPES, limit: LIST_PAGE }, url, req));
2202
+ const state = MOVE_STATES.includes(String(url.searchParams.get('state')))
2203
+ ? url.searchParams.get('state')
2204
+ : null;
2205
+ const payment = PAYMENT_STATES.includes(String(url.searchParams.get('payment')))
2206
+ ? url.searchParams.get('payment')
2207
+ : null;
2208
+ const type = CUSTOMER_INVOICE_TYPES.includes(String(url.searchParams.get('type')))
2209
+ ? url.searchParams.get('type')
2210
+ : null;
2211
+ const page = pageOf(url);
2212
+ const search = searchOf(url);
2213
+ const partnerLabels = new Map(data.partners.map((partner) => [String(partner.id), String(partner.name)]));
2214
+ const needle = search?.toLocaleLowerCase();
2215
+ const matching = all.filter((row) => {
2216
+ if (state && row.state !== state)
2217
+ return false;
2218
+ if (payment && row.paymentState !== payment)
2219
+ return false;
2220
+ if (type && row.moveType !== type)
2221
+ return false;
2222
+ return (!needle ||
2223
+ `${String(row.name ?? '')} ${String(row.ref ?? '')} ${String(row.accountingDate ?? row.date ?? '')} ${partnerLabels.get(String(row.partnerId)) ?? ''}`
2224
+ .toLocaleLowerCase()
2225
+ .includes(needle));
2226
+ });
2227
+ const rows = matching.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);
2228
+ const returnTo = customerInvoiceListPath(url);
2229
+ return adminPage(ctx, url, req, {
2230
+ title: 'account_backend.customerInvoices.title',
2231
+ body: (_, frame) => customerInvoicesListScreen(_, {
2232
+ frame: {
2233
+ ...frame,
2234
+ chrome: {
2235
+ search: {
2236
+ name: 'q',
2237
+ value: search ?? '',
2238
+ placeholder: _('account_backend.customerInvoices.title'),
2239
+ keep: {
2240
+ ...(state ? { state } : {}),
2241
+ ...(payment ? { payment } : {}),
2242
+ ...(type ? { type } : {}),
2243
+ ...(url.searchParams.get('lang') ? { lang: String(url.searchParams.get('lang')) } : {}),
2244
+ },
2245
+ facets: [
2246
+ ...(state
2247
+ ? [{ label: labelOf(_, 'moveState', state), without: withParam(url, 'state', null) }]
2248
+ : []),
2249
+ ...(payment
2250
+ ? [
2251
+ {
2252
+ label: labelOf(_, 'paymentState', payment),
2253
+ without: withParam(url, 'payment', null),
2254
+ },
2255
+ ]
2256
+ : []),
2257
+ ...(type
2258
+ ? [{ label: labelOf(_, 'moveType', type), without: withParam(url, 'type', null) }]
2259
+ : []),
2260
+ ],
2261
+ menus: [
2262
+ {
2263
+ id: 'filters',
2264
+ label: _('backend.chrome.filters'),
2265
+ items: [
2266
+ ...MOVE_STATES.map((value) => ({
2267
+ id: `state:${value}`,
2268
+ label: labelOf(_, 'moveState', value),
2269
+ path: withParam(url, 'state', state === value ? null : value),
2270
+ active: state === value,
2271
+ })),
2272
+ ...PAYMENT_STATES.map((value) => ({
2273
+ id: `payment:${value}`,
2274
+ label: labelOf(_, 'paymentState', value),
2275
+ path: withParam(url, 'payment', payment === value ? null : value),
2276
+ active: payment === value,
2277
+ })),
2278
+ ...CUSTOMER_INVOICE_TYPES.map((value) => ({
2279
+ id: `type:${value}`,
2280
+ label: labelOf(_, 'moveType', value),
2281
+ path: withParam(url, 'type', type === value ? null : value),
2282
+ active: type === value,
2283
+ })),
2284
+ ],
2285
+ },
2286
+ ],
2287
+ },
2288
+ pager: pager(url, page, rows.length, matching.length),
2289
+ },
2290
+ },
2291
+ rows,
2292
+ createHref: customerInvoiceFormPath(url, returnTo),
2293
+ rowHref: (row) => `/admin/accounting/customer-invoices/${encodeURIComponent(String(row.id))}${localeQuery(url)}`,
2294
+ partnerLabel: (row) => partnerLabels.get(String(row.partnerId)) ?? '—',
2295
+ summary: {
2296
+ total: all.length,
2297
+ draft: all.filter((row) => row.state === 'draft').length,
2298
+ posted: all.filter((row) => row.state === 'posted').length,
2299
+ unpaid: all.filter((row) => row.paymentState === 'not_paid').length,
2300
+ },
2301
+ }),
2302
+ });
2303
+ },
2304
+ '/admin/accounting/customer-invoices/new': (ctx) => async (url, req) => {
2305
+ let rejected;
2306
+ if (req.method === 'POST') {
2307
+ if (crossSite(req))
2308
+ return text('Forbidden', { status: 403 });
2309
+ const outcome = await createInvoice(ctx, url, req);
2310
+ if ('done' in outcome)
2311
+ return outcome.done;
2312
+ rejected = outcome.rejected;
2313
+ }
2314
+ else if (req.method !== 'GET')
630
2315
  return text('GET or POST', { status: 405 });
631
- const all = (await ctx.call('account.listMoves', {}, url, req));
632
- const rows = all.filter((move) => ['out_invoice', 'out_refund', 'out_receipt'].includes(String(move.moveType)));
633
- return document(ctx, url, req, 'account_backend.customerInvoices.title', (_, tr, shell) => customerInvoicesScreen(tr, {
634
- frame: shell,
635
- action: `/admin/customer-invoices${localeSuffix(url)}`,
636
- fields: invoiceFields(tr, data, ['out_invoice', 'out_refund', 'out_receipt']),
637
- rows,
638
- locale: localeSuffix(url),
639
- errors: url.searchParams.get('invalid') === '1' ? [tr('account_backend.error.invalid')] : undefined,
640
- }));
2316
+ const data = await common(ctx, url, req);
2317
+ const returnTo = safeCustomerInvoiceReturnTo(url);
2318
+ return adminPage(ctx, url, req, {
2319
+ title: 'account_backend.customerInvoice.create.title',
2320
+ body: async (_, frame) => customerInvoiceFormScreen(_, {
2321
+ frame,
2322
+ action: customerInvoiceFormPath(url, returnTo),
2323
+ cancelHref: returnTo,
2324
+ idempotencyKey: rejected?.values.id ?? randomUUID(),
2325
+ fields: restore(await invoiceFields(ctx, url, req, _, data, CUSTOMER_INVOICE_TYPES, rejected?.values), rejected),
2326
+ errors: rejected?.messages,
2327
+ }),
2328
+ });
641
2329
  },
642
- '/admin/vendor-bills': (ctx) => async (url, req) => {
2330
+ '/admin/accounting/vendor-bills': (ctx) => async (url, req) => {
2331
+ let rejected;
2332
+ if (req.method === 'POST') {
2333
+ if (crossSite(req))
2334
+ return text('Forbidden', { status: 403 });
2335
+ const outcome = await createInvoice(ctx, url, req);
2336
+ if ('done' in outcome)
2337
+ return outcome.done;
2338
+ rejected = outcome.rejected;
2339
+ }
2340
+ else if (req.method !== 'GET')
2341
+ return text('GET or POST', { status: 405 });
643
2342
  const data = await common(ctx, url, req);
644
- if (req.method === 'POST')
645
- return createInvoice(ctx, url, req, `/admin/vendor-bills${localeSuffix(url)}`);
646
- if (req.method !== 'GET')
2343
+ if (rejected)
2344
+ return adminPage(ctx, url, req, {
2345
+ title: 'account_backend.vendorBill.create.title',
2346
+ body: async (_, frame) => vendorBillFormScreen(_, {
2347
+ frame,
2348
+ action: vendorBillListPath(url),
2349
+ cancelHref: vendorBillListPath(url),
2350
+ idempotencyKey: rejected.values.id ?? randomUUID(),
2351
+ fields: restore(await invoiceFields(ctx, url, req, _, data, VENDOR_BILL_TYPES, rejected.values), rejected),
2352
+ errors: rejected.messages,
2353
+ }),
2354
+ });
2355
+ const all = (await ctx.call('account.listMoves', { moveTypes: VENDOR_BILL_TYPES, limit: LIST_PAGE }, url, req));
2356
+ const state = MOVE_STATES.includes(String(url.searchParams.get('state')))
2357
+ ? url.searchParams.get('state')
2358
+ : null;
2359
+ const payment = PAYMENT_STATES.includes(String(url.searchParams.get('payment')))
2360
+ ? url.searchParams.get('payment')
2361
+ : null;
2362
+ const type = VENDOR_BILL_TYPES.includes(String(url.searchParams.get('type')))
2363
+ ? url.searchParams.get('type')
2364
+ : null;
2365
+ const page = pageOf(url);
2366
+ const search = searchOf(url);
2367
+ const partnerLabels = new Map(data.partners.map((partner) => [String(partner.id), String(partner.name)]));
2368
+ const needle = search?.toLocaleLowerCase();
2369
+ const matching = all.filter((row) => {
2370
+ if (state && row.state !== state)
2371
+ return false;
2372
+ if (payment && row.paymentState !== payment)
2373
+ return false;
2374
+ if (type && row.moveType !== type)
2375
+ return false;
2376
+ return (!needle ||
2377
+ `${String(row.name ?? '')} ${String(row.ref ?? '')} ${String(row.accountingDate ?? row.date ?? '')} ${partnerLabels.get(String(row.partnerId)) ?? ''}`
2378
+ .toLocaleLowerCase()
2379
+ .includes(needle));
2380
+ });
2381
+ const rows = matching.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);
2382
+ const returnTo = vendorBillListPath(url);
2383
+ return adminPage(ctx, url, req, {
2384
+ title: 'account_backend.vendorBills.title',
2385
+ body: (_, frame) => vendorBillsListScreen(_, {
2386
+ frame: {
2387
+ ...frame,
2388
+ chrome: {
2389
+ search: {
2390
+ name: 'q',
2391
+ value: search ?? '',
2392
+ placeholder: _('account_backend.vendorBills.title'),
2393
+ keep: {
2394
+ ...(state ? { state } : {}),
2395
+ ...(payment ? { payment } : {}),
2396
+ ...(type ? { type } : {}),
2397
+ ...(url.searchParams.get('lang') ? { lang: String(url.searchParams.get('lang')) } : {}),
2398
+ },
2399
+ facets: [
2400
+ ...(state
2401
+ ? [{ label: labelOf(_, 'moveState', state), without: withParam(url, 'state', null) }]
2402
+ : []),
2403
+ ...(payment
2404
+ ? [
2405
+ {
2406
+ label: labelOf(_, 'paymentState', payment),
2407
+ without: withParam(url, 'payment', null),
2408
+ },
2409
+ ]
2410
+ : []),
2411
+ ...(type
2412
+ ? [{ label: labelOf(_, 'moveType', type), without: withParam(url, 'type', null) }]
2413
+ : []),
2414
+ ],
2415
+ menus: [
2416
+ {
2417
+ id: 'filters',
2418
+ label: _('backend.chrome.filters'),
2419
+ items: [
2420
+ ...MOVE_STATES.map((value) => ({
2421
+ id: `state:${value}`,
2422
+ label: labelOf(_, 'moveState', value),
2423
+ path: withParam(url, 'state', state === value ? null : value),
2424
+ active: state === value,
2425
+ })),
2426
+ ...PAYMENT_STATES.map((value) => ({
2427
+ id: `payment:${value}`,
2428
+ label: labelOf(_, 'paymentState', value),
2429
+ path: withParam(url, 'payment', payment === value ? null : value),
2430
+ active: payment === value,
2431
+ })),
2432
+ ...VENDOR_BILL_TYPES.map((value) => ({
2433
+ id: `type:${value}`,
2434
+ label: labelOf(_, 'moveType', value),
2435
+ path: withParam(url, 'type', type === value ? null : value),
2436
+ active: type === value,
2437
+ })),
2438
+ ],
2439
+ },
2440
+ ],
2441
+ },
2442
+ pager: pager(url, page, rows.length, matching.length),
2443
+ },
2444
+ },
2445
+ rows,
2446
+ createHref: vendorBillFormPath(url, returnTo),
2447
+ rowHref: (row) => `/admin/accounting/vendor-bills/${encodeURIComponent(String(row.id))}${localeQuery(url)}`,
2448
+ partnerLabel: (row) => partnerLabels.get(String(row.partnerId)) ?? '—',
2449
+ summary: {
2450
+ total: all.length,
2451
+ draft: all.filter((row) => row.state === 'draft').length,
2452
+ posted: all.filter((row) => row.state === 'posted').length,
2453
+ unpaid: all.filter((row) => row.paymentState === 'not_paid').length,
2454
+ },
2455
+ }),
2456
+ });
2457
+ },
2458
+ '/admin/accounting/vendor-bills/new': (ctx) => async (url, req) => {
2459
+ let rejected;
2460
+ if (req.method === 'POST') {
2461
+ if (crossSite(req))
2462
+ return text('Forbidden', { status: 403 });
2463
+ const outcome = await createInvoice(ctx, url, req);
2464
+ if ('done' in outcome)
2465
+ return outcome.done;
2466
+ rejected = outcome.rejected;
2467
+ }
2468
+ else if (req.method !== 'GET')
647
2469
  return text('GET or POST', { status: 405 });
648
- const all = (await ctx.call('account.listMoves', {}, url, req));
649
- const rows = all.filter((move) => ['in_invoice', 'in_refund', 'in_receipt'].includes(String(move.moveType)));
650
- return document(ctx, url, req, 'account_backend.vendorBills.title', (_, tr, shell) => vendorBillsScreen(tr, {
651
- frame: shell,
652
- action: `/admin/vendor-bills${localeSuffix(url)}`,
653
- fields: invoiceFields(tr, data, ['in_invoice', 'in_refund', 'in_receipt']),
654
- rows,
655
- locale: localeSuffix(url),
656
- errors: url.searchParams.get('invalid') === '1' ? [tr('account_backend.error.invalid')] : undefined,
657
- }));
2470
+ const data = await common(ctx, url, req);
2471
+ const returnTo = safeVendorBillReturnTo(url);
2472
+ return adminPage(ctx, url, req, {
2473
+ title: 'account_backend.vendorBill.create.title',
2474
+ body: async (_, frame) => vendorBillFormScreen(_, {
2475
+ frame,
2476
+ action: vendorBillFormPath(url, returnTo),
2477
+ cancelHref: returnTo,
2478
+ idempotencyKey: rejected?.values.id ?? randomUUID(),
2479
+ fields: restore(await invoiceFields(ctx, url, req, _, data, VENDOR_BILL_TYPES, rejected?.values), rejected),
2480
+ errors: rejected?.messages,
2481
+ }),
2482
+ });
658
2483
  },
659
- '/admin/journal-entries/{id}': accountMoveRoute,
660
- '/admin/customer-invoices/{id}': accountMoveRoute,
661
- '/admin/vendor-bills/{id}': accountMoveRoute,
662
- '/admin/payments': (ctx) => async (url, req) => {
2484
+ '/admin/accounting/entries/{id}': accountMoveRoute('entry'),
2485
+ '/admin/accounting/customer-invoices/{id}': accountMoveRoute('customer'),
2486
+ '/admin/accounting/vendor-bills/{id}': accountMoveRoute('vendor'),
2487
+ '/admin/accounting/payments': (ctx) => async (url, req) => {
2488
+ let rejected;
2489
+ if (req.method === 'POST') {
2490
+ if (crossSite(req))
2491
+ return text('Forbidden', { status: 403 });
2492
+ const outcome = await submitPayment(ctx, url, req);
2493
+ if ('done' in outcome)
2494
+ return outcome.done;
2495
+ rejected = outcome.rejected;
2496
+ }
2497
+ else if (req.method !== 'GET')
2498
+ return text('GET or POST', { status: 405 });
663
2499
  const [data, openItems] = await Promise.all([
664
2500
  common(ctx, url, req),
665
- ctx.call('account.listOpenItems', {}, url, req),
2501
+ ctx.call('account.listOpenItems', { limit: LIST_PAGE }, url, req),
666
2502
  ]);
2503
+ // Legacy collection POSTs still render the new full form when refused.
2504
+ if (rejected)
2505
+ return adminPage(ctx, url, req, {
2506
+ title: 'account_backend.payment.create.title',
2507
+ body: async (_, frame) => paymentFormScreen(_, {
2508
+ frame,
2509
+ action: paymentListPath(url),
2510
+ cancelHref: paymentListPath(url),
2511
+ paymentId: rejected.values.id ?? randomUUID(),
2512
+ fields: await paymentFields(ctx, url, req, _, data, openItems, rejected),
2513
+ errors: rejected.messages,
2514
+ }),
2515
+ });
2516
+ const all = (await ctx.call('account.listPayments', { limit: LIST_PAGE }, url, req));
2517
+ const paymentType = PAYMENT_TYPES.includes(String(url.searchParams.get('type')))
2518
+ ? url.searchParams.get('type')
2519
+ : null;
2520
+ const partnerType = PARTNER_TYPES.includes(String(url.searchParams.get('partnerType')))
2521
+ ? url.searchParams.get('partnerType')
2522
+ : null;
2523
+ const state = PAYMENT_STATES.includes(String(url.searchParams.get('state')))
2524
+ ? url.searchParams.get('state')
2525
+ : null;
2526
+ const partnerId = url.searchParams.get('partnerId') || null;
2527
+ const page = pageOf(url);
2528
+ const search = searchOf(url);
2529
+ const partnerLabels = new Map(data.partners.map((partner) => [String(partner.id), String(partner.name)]));
2530
+ const needle = search?.toLocaleLowerCase();
2531
+ const matching = all.filter((row) => {
2532
+ if (paymentType && row.paymentType !== paymentType)
2533
+ return false;
2534
+ if (partnerType && row.partnerType !== partnerType)
2535
+ return false;
2536
+ if (state && row.state !== state)
2537
+ return false;
2538
+ if (partnerId && String(row.partnerId ?? '') !== partnerId)
2539
+ return false;
2540
+ return (!needle ||
2541
+ `${String(row.name ?? '')} ${String(row.accountingDate ?? row.date ?? '')} ${String(row.memo ?? '')} ${String(row.paymentReference ?? '')} ${partnerLabels.get(String(row.partnerId)) ?? ''}`
2542
+ .toLocaleLowerCase()
2543
+ .includes(needle));
2544
+ });
2545
+ const rows = matching.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);
2546
+ const returnTo = paymentListPath(url);
2547
+ return adminPage(ctx, url, req, {
2548
+ title: 'account_backend.payments.title',
2549
+ body: (_, frame) => paymentsListScreen(_, {
2550
+ frame: {
2551
+ ...frame,
2552
+ chrome: {
2553
+ search: {
2554
+ name: 'q',
2555
+ value: search ?? '',
2556
+ placeholder: _('account_backend.payments.title'),
2557
+ keep: {
2558
+ ...(paymentType ? { type: paymentType } : {}),
2559
+ ...(partnerType ? { partnerType } : {}),
2560
+ ...(state ? { state } : {}),
2561
+ ...(partnerId ? { partnerId } : {}),
2562
+ ...(url.searchParams.get('lang') ? { lang: String(url.searchParams.get('lang')) } : {}),
2563
+ },
2564
+ facets: [
2565
+ ...(paymentType
2566
+ ? [
2567
+ {
2568
+ label: labelOf(_, 'paymentType', paymentType),
2569
+ without: withParam(url, 'type', null),
2570
+ },
2571
+ ]
2572
+ : []),
2573
+ ...(partnerType
2574
+ ? [
2575
+ {
2576
+ label: labelOf(_, 'partnerType', partnerType),
2577
+ without: withParam(url, 'partnerType', null),
2578
+ },
2579
+ ]
2580
+ : []),
2581
+ ...(state
2582
+ ? [
2583
+ {
2584
+ label: labelOf(_, 'paymentStatus', state),
2585
+ without: withParam(url, 'state', null),
2586
+ },
2587
+ ]
2588
+ : []),
2589
+ ...(partnerId
2590
+ ? [
2591
+ {
2592
+ label: partnerLabels.get(partnerId) ?? partnerId,
2593
+ without: withParam(url, 'partnerId', null),
2594
+ },
2595
+ ]
2596
+ : []),
2597
+ ],
2598
+ menus: [
2599
+ {
2600
+ id: 'filters',
2601
+ label: _('backend.chrome.filters'),
2602
+ items: [
2603
+ ...PAYMENT_TYPES.map((value) => ({
2604
+ id: `type:${value}`,
2605
+ label: labelOf(_, 'paymentType', value),
2606
+ path: withParam(url, 'type', paymentType === value ? null : value),
2607
+ active: paymentType === value,
2608
+ })),
2609
+ ...PARTNER_TYPES.map((value) => ({
2610
+ id: `partnerType:${value}`,
2611
+ label: labelOf(_, 'partnerType', value),
2612
+ path: withParam(url, 'partnerType', partnerType === value ? null : value),
2613
+ active: partnerType === value,
2614
+ })),
2615
+ ...PAYMENT_STATES.map((value) => ({
2616
+ id: `state:${value}`,
2617
+ label: labelOf(_, 'paymentStatus', value),
2618
+ path: withParam(url, 'state', state === value ? null : value),
2619
+ active: state === value,
2620
+ })),
2621
+ ],
2622
+ },
2623
+ ],
2624
+ },
2625
+ pager: pager(url, page, rows.length, matching.length),
2626
+ },
2627
+ },
2628
+ rows,
2629
+ createHref: paymentFormPath(url, returnTo),
2630
+ rowHref: (row) => `/admin/accounting/entries/${encodeURIComponent(String(row.moveId))}${localeQuery(url)}`,
2631
+ partnerLabel: (row) => partnerLabels.get(String(row.partnerId)) ?? '—',
2632
+ summary: {
2633
+ total: all.length,
2634
+ inbound: all.filter((row) => row.paymentType === 'inbound').length,
2635
+ outbound: all.filter((row) => row.paymentType === 'outbound').length,
2636
+ open: openItems.length,
2637
+ },
2638
+ }),
2639
+ });
2640
+ },
2641
+ '/admin/accounting/payments/new': (ctx) => async (url, req) => {
2642
+ let rejected;
667
2643
  if (req.method === 'POST') {
668
- const form = await readForm(req);
669
- return resultRedirect(await ctx.call('account.registerPayment', {
670
- id: randomUUID(),
671
- name: form.name ?? '',
672
- paymentType: form.paymentType ?? 'inbound',
673
- partnerType: form.partnerType ?? 'customer',
674
- ...optional(form, 'partnerId'),
675
- journalId: form.journalId ?? '',
676
- destinationAccountId: form.destinationAccountId ?? '',
677
- amount: form.amount || '0',
678
- ...optional(form, 'date'),
679
- ...optional(form, 'memo'),
680
- ...optional(form, 'paymentReference'),
681
- ...optional(form, 'reconcileLineId'),
682
- }, url, req), `/admin/payments${localeSuffix(url)}`);
2644
+ if (crossSite(req))
2645
+ return text('Forbidden', { status: 403 });
2646
+ const outcome = await submitPayment(ctx, url, req);
2647
+ if ('done' in outcome)
2648
+ return outcome.done;
2649
+ rejected = outcome.rejected;
683
2650
  }
684
- if (req.method !== 'GET')
2651
+ else if (req.method !== 'GET')
685
2652
  return text('GET or POST', { status: 405 });
686
- const rows = (await ctx.call('account.listPayments', {}, url, req));
687
- return document(ctx, url, req, 'account_backend.payments.title', (_, tr, shell) => paymentsScreen(tr, {
688
- frame: shell,
689
- action: `/admin/payments${localeSuffix(url)}`,
690
- rows,
691
- openItems: openItems.length,
692
- errors: url.searchParams.get('invalid') === '1' ? [tr('account_backend.error.invalid')] : undefined,
693
- fields: [
694
- { name: 'name', label: tr('account_backend.field.name'), required: true },
695
- {
696
- name: 'paymentType',
697
- label: tr('account_backend.field.paymentType'),
698
- type: 'select',
699
- options: optionsOf(tr, 'paymentType', PAYMENT_TYPES),
700
- },
701
- {
702
- name: 'partnerType',
703
- label: tr('account_backend.field.partnerType'),
704
- type: 'select',
705
- options: optionsOf(tr, 'partnerType', PARTNER_TYPES),
706
- },
707
- {
708
- name: 'partnerId',
709
- label: tr('account_backend.field.partnerId'),
710
- type: 'select',
711
- options: choices(data.partners, true),
712
- },
713
- {
714
- name: 'journalId',
715
- label: tr('account_backend.field.journalId'),
716
- type: 'select',
717
- options: choices(data.journals.filter((journal) => ['bank', 'cash'].includes(String(journal.type)))),
718
- required: true,
719
- },
720
- {
721
- name: 'destinationAccountId',
722
- label: tr('account_backend.field.destinationAccountId'),
723
- type: 'select',
724
- options: choices(data.accounts),
725
- required: true,
726
- },
727
- {
728
- name: 'amount',
729
- label: tr('account_backend.field.amount'),
730
- type: 'decimal',
731
- value: 0,
732
- required: true,
733
- },
734
- { name: 'date', label: tr('account_backend.field.date'), type: 'date' },
735
- { name: 'memo', label: tr('account_backend.field.memo') },
736
- { name: 'paymentReference', label: tr('account_backend.field.paymentReference') },
737
- {
738
- name: 'reconcileLineId',
739
- label: tr('account_backend.field.reconcileLineId'),
740
- type: 'select',
741
- options: [
742
- { value: '', label: '—' },
743
- ...openItems.map((line) => ({
744
- value: String(line.id),
745
- label: `${String(line.move?.name ?? line.moveId)} · ${String(line.accountId)} · ${formatMoney(tr, line.amountResidual, line.move?.currency)}`,
746
- })),
747
- ],
748
- },
749
- ],
750
- }));
2653
+ const [data, openItems] = await Promise.all([
2654
+ common(ctx, url, req),
2655
+ ctx.call('account.listOpenItems', { limit: LIST_PAGE }, url, req),
2656
+ ]);
2657
+ const returnTo = safePaymentReturnTo(url);
2658
+ return adminPage(ctx, url, req, {
2659
+ title: 'account_backend.payment.create.title',
2660
+ body: async (_, frame) => paymentFormScreen(_, {
2661
+ frame,
2662
+ action: paymentFormPath(url, returnTo),
2663
+ cancelHref: returnTo,
2664
+ paymentId: rejected?.values.id ?? randomUUID(),
2665
+ fields: await paymentFields(ctx, url, req, _, data, openItems, rejected),
2666
+ errors: rejected?.messages,
2667
+ }),
2668
+ });
751
2669
  },
752
- '/admin/trial-balance': (ctx) => async (url, req) => {
2670
+ '/admin/accounting/trial-balance': (ctx) => async (url, req) => {
753
2671
  if (req.method !== 'GET')
754
2672
  return text('GET', { status: 405 });
755
2673
  const dateFrom = url.searchParams.get('dateFrom') ?? '', dateTo = url.searchParams.get('dateTo') ?? '';
2674
+ const inverted = Boolean(dateFrom && dateTo && dateFrom > dateTo);
756
2675
  const [rows, companies] = (await Promise.all([
757
- ctx.call('account.trialBalance', { ...(dateFrom ? { dateFrom } : {}), ...(dateTo ? { dateTo } : {}) }, url, req),
2676
+ inverted
2677
+ ? Promise.resolve([])
2678
+ : ctx.call('account.trialBalance', {
2679
+ ...(dateFrom ? { dateFrom } : {}),
2680
+ ...(dateTo ? { dateTo } : {}),
2681
+ }, url, req),
2682
+ ctx.call('company.listCompanies', {}, url, req),
2683
+ ]));
2684
+ rows.sort((a, b) => String(a.code ?? '').localeCompare(String(b.code ?? ''), undefined, { numeric: true }));
2685
+ return adminPage(ctx, url, req, {
2686
+ title: 'account_backend.trialBalance.title',
2687
+ body: (_, frame) => {
2688
+ const currency = currencyOf(companies, frame);
2689
+ return trialBalanceScreen(_, {
2690
+ frame: frame,
2691
+ action: '/admin/accounting/trial-balance',
2692
+ locale: url.searchParams.get('lang') ?? '',
2693
+ rows,
2694
+ currency,
2695
+ // The balance carries its own date window into the ledger, so the
2696
+ // rows opened are the ones that produced the number.
2697
+ ledgerHref: (row) => {
2698
+ const target = new URL('/admin/accounting/general-ledger', url);
2699
+ target.searchParams.set('accountId', String(row.accountId));
2700
+ if (dateFrom)
2701
+ target.searchParams.set('dateFrom', dateFrom);
2702
+ if (dateTo)
2703
+ target.searchParams.set('dateTo', dateTo);
2704
+ const lang = url.searchParams.get('lang');
2705
+ if (lang)
2706
+ target.searchParams.set('lang', lang);
2707
+ return `${target.pathname}${target.search}`;
2708
+ },
2709
+ fields: [
2710
+ {
2711
+ name: 'dateFrom',
2712
+ label: _('account_backend.field.dateFrom'),
2713
+ value: dateFrom,
2714
+ error: inverted ? _('account_backend.trial.filter.rangeError') : null,
2715
+ },
2716
+ {
2717
+ name: 'dateTo',
2718
+ label: _('account_backend.field.dateTo'),
2719
+ value: dateTo,
2720
+ error: inverted ? _('account_backend.trial.filter.rangeError') : null,
2721
+ },
2722
+ ],
2723
+ errors: inverted ? [_('account_backend.trial.filter.rangeError')] : undefined,
2724
+ });
2725
+ },
2726
+ });
2727
+ },
2728
+ '/admin/accounting/general-ledger': (ctx) => async (url, req) => {
2729
+ if (req.method !== 'GET')
2730
+ return text('GET', { status: 405 });
2731
+ const accountId = url.searchParams.get('accountId') ?? '', dateFrom = url.searchParams.get('dateFrom') ?? '', dateTo = url.searchParams.get('dateTo') ?? '', search = searchOf(url) ?? '', page = pageOf(url), inverted = Boolean(dateFrom && dateTo && dateFrom > dateTo);
2732
+ await ctx.call('account.initializeCompany', {}, url, req);
2733
+ const [accounts, companies, allRows] = (await Promise.all([
2734
+ ctx.call('account.listAccounts', {}, url, req),
2735
+ ctx.call('company.listCompanies', {}, url, req),
2736
+ inverted
2737
+ ? Promise.resolve([])
2738
+ : ctx.call('account.generalLedger', {
2739
+ ...(accountId ? { accountId } : {}),
2740
+ ...(dateFrom ? { dateFrom } : {}),
2741
+ ...(dateTo ? { dateTo } : {}),
2742
+ }, url, req),
2743
+ ]));
2744
+ return adminPage(ctx, url, req, {
2745
+ title: 'account_backend.generalLedger.title',
2746
+ body: async (_, frame) => {
2747
+ const unknownAccount = Boolean(accountId && !accounts.some((account) => String(account.id) === accountId));
2748
+ const unavailableAccount = {
2749
+ id: accountId,
2750
+ code: accountId,
2751
+ name: _('account_backend.ledger.filter.unavailableAccount'),
2752
+ nameEn: _('account_backend.ledger.filter.unavailableAccount'),
2753
+ };
2754
+ const filterAccounts = unknownAccount ? [unavailableAccount, ...accounts] : accounts;
2755
+ const needle = search.toLocaleLowerCase(ctx.localeOf(url, req));
2756
+ const matching = allRows.filter((row) => {
2757
+ if (!needle)
2758
+ return true;
2759
+ const move = (row.move ?? {});
2760
+ return [
2761
+ move.name,
2762
+ move.ref,
2763
+ move.accountingDate ?? move.date,
2764
+ row.name,
2765
+ row.accountId,
2766
+ accountLabel(_, accounts, row.accountId),
2767
+ ].some((value) => String(value ?? '')
2768
+ .toLocaleLowerCase(ctx.localeOf(url, req))
2769
+ .includes(needle));
2770
+ });
2771
+ const rows = matching.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);
2772
+ const errors = [
2773
+ ...(inverted ? [_('account_backend.trial.filter.rangeError')] : []),
2774
+ ...(unknownAccount ? [_('account_backend.ledger.filter.accountError')] : []),
2775
+ ];
2776
+ frame.chrome = {
2777
+ search: {
2778
+ name: 'q',
2779
+ value: search,
2780
+ placeholder: _('account_backend.ledger.search'),
2781
+ keep: {
2782
+ ...(accountId ? { accountId } : {}),
2783
+ ...(dateFrom ? { dateFrom } : {}),
2784
+ ...(dateTo ? { dateTo } : {}),
2785
+ ...(url.searchParams.get('lang') ? { lang: url.searchParams.get('lang') } : {}),
2786
+ },
2787
+ },
2788
+ pager: pager(url, page, rows.length, matching.length),
2789
+ };
2790
+ const currency = currencyOf(companies, frame);
2791
+ return generalLedgerScreen(_, {
2792
+ frame: frame,
2793
+ action: '/admin/accounting/general-ledger',
2794
+ rows,
2795
+ summary: {
2796
+ lines: matching.length,
2797
+ debit: matching.reduce((total, row) => addDecimals(total, row.debit ?? '0'), '0'),
2798
+ credit: matching.reduce((total, row) => addDecimals(total, row.credit ?? '0'), '0'),
2799
+ },
2800
+ currency,
2801
+ hidden: {
2802
+ ...(search ? { q: search } : {}),
2803
+ ...(url.searchParams.get('lang') ? { lang: url.searchParams.get('lang') } : {}),
2804
+ },
2805
+ errors: errors.length ? errors : undefined,
2806
+ accountLabel: (id) => accountLabel(_, accounts, id),
2807
+ entryHref: (row) => `/admin/accounting/entries/${encodeURIComponent(String(row.moveId))}${localeQuery(url)}`,
2808
+ fields: [
2809
+ {
2810
+ name: 'accountId',
2811
+ label: _('account_backend.field.accountId'),
2812
+ type: 'select',
2813
+ value: accountId,
2814
+ error: unknownAccount ? _('account_backend.ledger.filter.accountError') : null,
2815
+ options: accountChoices(_, filterAccounts, true),
2816
+ control: await accountRelationControl(ctx, url, req, _, {
2817
+ id: 'general-ledger-account',
2818
+ name: 'accountId',
2819
+ label: _('account_backend.field.accountId'),
2820
+ value: accountId,
2821
+ accounts: accountOptions(filterAccounts.map((account) => ({ ...account, name: accountName(_, account) }))),
2822
+ allowEmpty: true,
2823
+ }),
2824
+ },
2825
+ {
2826
+ name: 'dateFrom',
2827
+ label: _('account_backend.field.dateFrom'),
2828
+ type: 'date',
2829
+ value: dateFrom,
2830
+ error: inverted ? _('account_backend.trial.filter.rangeError') : null,
2831
+ },
2832
+ {
2833
+ name: 'dateTo',
2834
+ label: _('account_backend.field.dateTo'),
2835
+ type: 'date',
2836
+ value: dateTo,
2837
+ error: inverted ? _('account_backend.trial.filter.rangeError') : null,
2838
+ },
2839
+ ],
2840
+ });
2841
+ },
2842
+ });
2843
+ },
2844
+ '/admin/accounting/partner-statement': (ctx) => async (url, req) => {
2845
+ if (req.method !== 'GET')
2846
+ return text('GET', { status: 405 });
2847
+ const partnerId = url.searchParams.get('partnerId') ?? '', dateFrom = url.searchParams.get('dateFrom') ?? '', dateTo = url.searchParams.get('dateTo') ?? '', search = searchOf(url) ?? '', page = pageOf(url), inverted = Boolean(dateFrom && dateTo && dateFrom > dateTo);
2848
+ await ctx.call('account.initializeCompany', {}, url, req);
2849
+ const [accounts, companies, initialPartners, selectedPartners, allRows] = (await Promise.all([
2850
+ ctx.call('account.listAccounts', {}, url, req),
758
2851
  ctx.call('company.listCompanies', {}, url, req),
2852
+ ctx.call('partner.listPartners', { limit: PAGE_SIZE }, url, req),
2853
+ partnerId
2854
+ ? ctx.call('partner.listPartners', { ids: [partnerId], includeArchived: true }, url, req)
2855
+ : Promise.resolve([]),
2856
+ partnerId && !inverted
2857
+ ? ctx.call('account.partnerStatement', {
2858
+ partnerId,
2859
+ ...(dateFrom ? { dateFrom } : {}),
2860
+ ...(dateTo ? { dateTo } : {}),
2861
+ }, url, req)
2862
+ : Promise.resolve([]),
759
2863
  ]));
760
- return document(ctx, url, req, 'account_backend.trialBalance.title', (_, tr, shell) => {
761
- const currency = currencyOf(companies, shell);
762
- return trialBalanceScreen(tr, {
763
- frame: shell,
764
- action: `/admin/trial-balance${localeSuffix(url)}`,
2864
+ return adminPage(ctx, url, req, {
2865
+ title: 'account_backend.partnerStatement.title',
2866
+ body: async (_, frame) => {
2867
+ const companyPartners = new Set(companies.map((company) => String(company.partnerId)));
2868
+ const selectedPartner = selectedPartners.find((partner) => !companyPartners.has(String(partner.id)));
2869
+ const unknownPartner = Boolean(partnerId && !selectedPartner);
2870
+ const unavailablePartner = {
2871
+ id: partnerId,
2872
+ name: _('account_backend.partnerLedger.filter.unavailablePartner'),
2873
+ };
2874
+ const bundledPartners = [
2875
+ ...(selectedPartner ? [selectedPartner] : unknownPartner ? [unavailablePartner] : []),
2876
+ ...initialPartners.filter((partner) => !companyPartners.has(String(partner.id)) && String(partner.id) !== partnerId),
2877
+ ];
2878
+ const needle = search.toLocaleLowerCase(ctx.localeOf(url, req));
2879
+ const matching = allRows.filter((row) => {
2880
+ if (!needle)
2881
+ return true;
2882
+ const move = (row.move ?? {});
2883
+ return [
2884
+ move.name,
2885
+ move.ref,
2886
+ move.accountingDate ?? move.date,
2887
+ row.name,
2888
+ row.accountId,
2889
+ accountLabel(_, accounts, row.accountId),
2890
+ ].some((value) => String(value ?? '')
2891
+ .toLocaleLowerCase(ctx.localeOf(url, req))
2892
+ .includes(needle));
2893
+ });
2894
+ const rows = matching.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);
2895
+ const errors = [
2896
+ ...(inverted ? [_('account_backend.trial.filter.rangeError')] : []),
2897
+ ...(unknownPartner ? [_('account_backend.partnerLedger.filter.partnerError')] : []),
2898
+ ];
2899
+ frame.chrome = {
2900
+ search: {
2901
+ name: 'q',
2902
+ value: search,
2903
+ placeholder: _('account_backend.partnerLedger.search'),
2904
+ keep: {
2905
+ ...(partnerId ? { partnerId } : {}),
2906
+ ...(dateFrom ? { dateFrom } : {}),
2907
+ ...(dateTo ? { dateTo } : {}),
2908
+ ...(url.searchParams.get('lang') ? { lang: url.searchParams.get('lang') } : {}),
2909
+ },
2910
+ },
2911
+ pager: pager(url, page, rows.length, matching.length),
2912
+ };
2913
+ const currency = currencyOf(companies, frame);
2914
+ return partnerLedgerScreen(_, {
2915
+ frame: frame,
2916
+ action: '/admin/accounting/partner-statement',
2917
+ rows,
2918
+ summary: {
2919
+ debit: matching.reduce((total, row) => addDecimals(total, row.debit ?? '0'), '0'),
2920
+ credit: matching.reduce((total, row) => addDecimals(total, row.credit ?? '0'), '0'),
2921
+ residual: matching.reduce((total, row) => addDecimals(total, row.amountResidual ?? '0'), '0'),
2922
+ },
2923
+ currency,
2924
+ selected: Boolean(partnerId),
2925
+ hidden: {
2926
+ ...(search ? { q: search } : {}),
2927
+ ...(url.searchParams.get('lang') ? { lang: url.searchParams.get('lang') } : {}),
2928
+ },
2929
+ errors: errors.length ? errors : undefined,
2930
+ accountLabel: (id) => accountLabel(_, accounts, id),
2931
+ entryHref: (row) => `/admin/accounting/entries/${encodeURIComponent(String(row.moveId))}${localeQuery(url)}`,
2932
+ fields: [
2933
+ {
2934
+ name: 'partnerId',
2935
+ label: _('account_backend.field.partnerId'),
2936
+ type: 'select',
2937
+ value: partnerId,
2938
+ error: unknownPartner ? _('account_backend.partnerLedger.filter.partnerError') : null,
2939
+ options: choices(bundledPartners, true),
2940
+ control: await partnerRelationControl(ctx, url, req, _, {
2941
+ id: 'partner-statement-partner',
2942
+ name: 'partnerId',
2943
+ value: partnerId,
2944
+ partners: bundledPartners.map((partner) => ({
2945
+ id: String(partner.id),
2946
+ name: String(partner.name),
2947
+ ref: partner.ref ? String(partner.ref) : null,
2948
+ })),
2949
+ fieldLabel: _('account_backend.field.partnerId'),
2950
+ title: _('account_backend.relation.partners'),
2951
+ allowEmpty: true,
2952
+ excludeIds: [...companyPartners],
2953
+ }),
2954
+ },
2955
+ {
2956
+ name: 'dateFrom',
2957
+ label: _('account_backend.field.dateFrom'),
2958
+ type: 'date',
2959
+ value: dateFrom,
2960
+ error: inverted ? _('account_backend.trial.filter.rangeError') : null,
2961
+ },
2962
+ {
2963
+ name: 'dateTo',
2964
+ label: _('account_backend.field.dateTo'),
2965
+ type: 'date',
2966
+ value: dateTo,
2967
+ error: inverted ? _('account_backend.trial.filter.rangeError') : null,
2968
+ },
2969
+ ],
2970
+ });
2971
+ },
2972
+ });
2973
+ },
2974
+ '/admin/accounting/opening-balances': (ctx) => async (url, req) => {
2975
+ if (req.method !== 'GET')
2976
+ return text('GET', { status: 405 });
2977
+ const rows = (await ctx.call('account.listOpeningBatches', {}, url, req));
2978
+ return adminPage(ctx, url, req, {
2979
+ title: 'account_backend.opening.title',
2980
+ body: (_, frame) => openingBalancesListScreen(_, {
2981
+ frame,
765
2982
  rows,
766
- currency,
2983
+ createHref: `/admin/accounting/opening-balances/new${localeQuery(url)}`,
2984
+ rowHref: (row) => `/admin/accounting/opening-balances/${encodeURIComponent(String(row.id))}${localeQuery(url)}`,
2985
+ }),
2986
+ });
2987
+ },
2988
+ '/admin/accounting/opening-balances/new': (ctx) => async (url, req) => {
2989
+ let rejected;
2990
+ if (req.method === 'POST') {
2991
+ if (crossSite(req))
2992
+ return text('Forbidden', { status: 403 });
2993
+ const form = await readForm(req);
2994
+ let lines = [];
2995
+ try {
2996
+ lines = JSON.parse(form.lines || '[]');
2997
+ }
2998
+ catch {
2999
+ rejected = {
3000
+ messages: [ctx.translate(ctx.localeOf(url, req))('account_backend.opening.linesInvalid')],
3001
+ fields: {
3002
+ lines: ctx.translate(ctx.localeOf(url, req))('account_backend.opening.linesInvalid'),
3003
+ },
3004
+ values: form,
3005
+ };
3006
+ }
3007
+ if (!rejected) {
3008
+ const id = form.id || randomUUID();
3009
+ const sourceChecksum = createHash('sha256')
3010
+ .update(`${form.sourceName || 'manual'}\n${form.lines || '[]'}`)
3011
+ .digest('hex');
3012
+ const result = await ctx.call('account.prepareOpeningBatch', {
3013
+ id,
3014
+ accountingDate: form.accountingDate,
3015
+ journalId: form.journalId,
3016
+ sourceChecksum,
3017
+ controlDebit: form.controlDebit,
3018
+ controlCredit: form.controlCredit,
3019
+ lines,
3020
+ }, url, req);
3021
+ if (succeeded(result))
3022
+ return seeOther(`/admin/accounting/opening-balances/${encodeURIComponent(id)}${localeQuery(url)}`);
3023
+ rejected = rejection(result, ctx.translate(ctx.localeOf(url, req)), form);
3024
+ }
3025
+ }
3026
+ else if (req.method !== 'GET')
3027
+ return text('GET or POST', { status: 405 });
3028
+ const journals = (await ctx.call('account.listJournals', {}, url, req));
3029
+ const values = rejected?.values ?? {};
3030
+ return adminPage(ctx, url, req, {
3031
+ title: 'account_backend.opening.create',
3032
+ body: (_, frame) => openingBalanceImportScreen(_, {
3033
+ frame,
3034
+ action: `${url.pathname}${localeQuery(url)}`,
3035
+ cancelHref: `/admin/accounting/opening-balances${localeQuery(url)}`,
3036
+ errors: rejected?.messages,
767
3037
  fields: [
768
3038
  {
769
- name: 'dateFrom',
770
- label: tr('account_backend.field.dateFrom'),
3039
+ name: 'sourceName',
3040
+ label: _('account_backend.opening.sourceName'),
3041
+ value: values.sourceName ?? '',
3042
+ required: true,
3043
+ },
3044
+ {
3045
+ name: 'accountingDate',
3046
+ label: _('account_backend.field.accountingDate'),
771
3047
  type: 'date',
772
- value: dateFrom,
3048
+ value: values.accountingDate ?? '',
3049
+ required: true,
3050
+ },
3051
+ {
3052
+ name: 'journalId',
3053
+ label: _('account_backend.field.journalId'),
3054
+ type: 'select',
3055
+ value: values.journalId ?? '',
3056
+ required: true,
3057
+ options: choices(journals.filter((row) => row.type === 'general'), true),
3058
+ },
3059
+ {
3060
+ name: 'controlDebit',
3061
+ label: _('account_backend.opening.controlDebit'),
3062
+ type: 'decimal',
3063
+ step: '0.01',
3064
+ value: values.controlDebit ?? '',
3065
+ required: true,
3066
+ },
3067
+ {
3068
+ name: 'controlCredit',
3069
+ label: _('account_backend.opening.controlCredit'),
3070
+ type: 'decimal',
3071
+ step: '0.01',
3072
+ value: values.controlCredit ?? '',
3073
+ required: true,
3074
+ },
3075
+ {
3076
+ name: 'lines',
3077
+ label: _('account_backend.opening.linesJson'),
3078
+ type: 'textarea',
3079
+ span: 'full',
3080
+ value: values.lines ??
3081
+ '[\n {"sourceKey":"1","accountId":"...","description":"Số dư đầu kỳ","debit":"0.00","credit":"0.00"}\n]',
3082
+ required: true,
3083
+ error: rejected?.fields.lines,
3084
+ help: _('account_backend.opening.linesJsonHint'),
773
3085
  },
774
- { name: 'dateTo', label: tr('account_backend.field.dateTo'), type: 'date', value: dateTo },
775
3086
  ],
776
- });
3087
+ }),
777
3088
  });
778
3089
  },
779
- '/admin/general-ledger': (ctx) => async (url, req) => {
780
- if (req.method !== 'GET')
781
- return text('GET', { status: 405 });
782
- const data = await common(ctx, url, req), accountId = url.searchParams.get('accountId') ?? '', dateFrom = url.searchParams.get('dateFrom') ?? '', dateTo = url.searchParams.get('dateTo') ?? '';
783
- const rows = (await ctx.call('account.generalLedger', {
784
- ...(accountId ? { accountId } : {}),
785
- ...(dateFrom ? { dateFrom } : {}),
786
- ...(dateTo ? { dateTo } : {}),
787
- }, url, req));
788
- return document(ctx, url, req, 'account_backend.generalLedger.title', (_, tr, shell) => {
789
- const currency = currencyOf(data.companies, shell);
790
- return generalLedgerScreen(tr, {
791
- frame: shell,
792
- action: `/admin/general-ledger${localeSuffix(url)}`,
3090
+ '/admin/accounting/opening-balances/{id}': (ctx) => async (url, req, params) => {
3091
+ let errors;
3092
+ if (req.method === 'POST') {
3093
+ if (crossSite(req))
3094
+ return text('Forbidden', { status: 403 });
3095
+ const form = await readForm(req);
3096
+ const result = await ctx.call('account.postOpeningBatch', { id: params.id }, url, req);
3097
+ if (succeeded(result))
3098
+ return seeOther(`${url.pathname}${localeQuery(url)}`);
3099
+ errors = rejection(result, ctx.translate(ctx.localeOf(url, req)), form).messages;
3100
+ }
3101
+ else if (req.method !== 'GET')
3102
+ return text('GET or POST', { status: 405 });
3103
+ const [{ batch, lines }, companies] = (await Promise.all([
3104
+ ctx.call('account.getOpeningBatch', { id: params.id }, url, req),
3105
+ ctx.call('company.listCompanies', {}, url, req),
3106
+ ]));
3107
+ if (!batch)
3108
+ return text('Not found', { status: 404 });
3109
+ return adminPage(ctx, url, req, {
3110
+ title: 'account_backend.opening.batch',
3111
+ body: (_, frame) => openingBalanceDetailScreen(_, {
3112
+ frame,
3113
+ batch,
3114
+ lines,
3115
+ action: `${url.pathname}${localeQuery(url)}`,
3116
+ currency: currencyOf(companies, frame),
3117
+ entryHref: batch.moveId
3118
+ ? `/admin/accounting/entries/${encodeURIComponent(String(batch.moveId))}${localeQuery(url)}`
3119
+ : undefined,
3120
+ errors,
3121
+ }),
3122
+ });
3123
+ },
3124
+ '/admin/accounting/period-closes': (ctx) => async (url, req) => {
3125
+ let errors;
3126
+ if (req.method === 'POST') {
3127
+ if (crossSite(req))
3128
+ return text('Forbidden', { status: 403 });
3129
+ const form = await readForm(req);
3130
+ const result = await ctx.call('account.createClosePeriod', {
3131
+ id: form.id || randomUUID(),
3132
+ periodKey: form.periodKey,
3133
+ dateFrom: form.dateFrom,
3134
+ dateTo: form.dateTo,
3135
+ }, url, req);
3136
+ if (succeeded(result))
3137
+ return seeOther(`${url.pathname}${localeQuery(url)}`);
3138
+ errors = rejection(result, ctx.translate(ctx.localeOf(url, req)), form).messages;
3139
+ }
3140
+ else if (req.method !== 'GET')
3141
+ return text('GET or POST', { status: 405 });
3142
+ const rows = (await ctx.call('account.listClosePeriods', {}, url, req));
3143
+ return adminPage(ctx, url, req, {
3144
+ title: 'account_backend.close.title',
3145
+ body: (_, frame) => periodClosesListScreen(_, {
3146
+ frame,
793
3147
  rows,
794
- currency,
3148
+ action: `${url.pathname}${localeQuery(url)}`,
3149
+ errors,
795
3150
  fields: [
796
3151
  {
797
- name: 'accountId',
798
- label: tr('account_backend.field.accountId'),
799
- type: 'select',
800
- value: accountId,
801
- options: choices(data.accounts, true),
3152
+ name: 'periodKey',
3153
+ label: _('account_backend.close.period'),
3154
+ placeholder: '2026-08',
3155
+ required: true,
802
3156
  },
803
3157
  {
804
3158
  name: 'dateFrom',
805
- label: tr('account_backend.field.dateFrom'),
3159
+ label: _('account_backend.field.dateFrom'),
806
3160
  type: 'date',
807
- value: dateFrom,
3161
+ required: true,
808
3162
  },
809
- { name: 'dateTo', label: tr('account_backend.field.dateTo'), type: 'date', value: dateTo },
3163
+ { name: 'dateTo', label: _('account_backend.field.dateTo'), type: 'date', required: true },
810
3164
  ],
811
- });
3165
+ rowHref: (row) => `/admin/accounting/period-closes/${encodeURIComponent(String(row.id))}${localeQuery(url)}`,
3166
+ }),
812
3167
  });
813
3168
  },
814
- '/admin/partner-statement': (ctx) => async (url, req) => {
3169
+ '/admin/accounting/period-closes/{id}': (ctx) => async (url, req, params) => {
3170
+ let errors;
3171
+ if (req.method === 'POST') {
3172
+ if (crossSite(req))
3173
+ return text('Forbidden', { status: 403 });
3174
+ const form = await readForm(req);
3175
+ const name = form.action === 'refresh'
3176
+ ? 'account.refreshClosePeriod'
3177
+ : form.action === 'reopen'
3178
+ ? 'account.reopenClosePeriod'
3179
+ : 'account.closePeriod';
3180
+ const args = form.action === 'refresh'
3181
+ ? { id: params.id }
3182
+ : form.action === 'reopen'
3183
+ ? { id: params.id, expectedRevision: Number(form.expectedRevision), reason: form.reason }
3184
+ : {
3185
+ id: params.id,
3186
+ mode: form.mode || 'soft',
3187
+ expectedRevision: Number(form.expectedRevision),
3188
+ reason: form.reason,
3189
+ };
3190
+ const result = await ctx.call(name, args, url, req);
3191
+ if (succeeded(result))
3192
+ return seeOther(`${url.pathname}${localeQuery(url)}`);
3193
+ errors = rejection(result, ctx.translate(ctx.localeOf(url, req)), form).messages;
3194
+ }
3195
+ else if (req.method !== 'GET')
3196
+ return text('GET or POST', { status: 405 });
3197
+ const result = (await ctx.call('account.getClosePeriod', { id: params.id }, url, req));
3198
+ if (!result.period)
3199
+ return text('Not found', { status: 404 });
3200
+ return adminPage(ctx, url, req, {
3201
+ title: 'account_backend.close.title',
3202
+ body: (_, frame) => periodCloseDetailScreen(_, {
3203
+ frame,
3204
+ period: result.period,
3205
+ steps: result.steps,
3206
+ action: `${url.pathname}${localeQuery(url)}`,
3207
+ errors,
3208
+ }),
3209
+ });
3210
+ },
3211
+ '/admin/accounting/books': (ctx) => async (url, req) => {
815
3212
  if (req.method !== 'GET')
816
3213
  return text('GET', { status: 405 });
817
- const data = await common(ctx, url, req);
3214
+ const book = url.searchParams.get('book') ?? 'general_journal';
3215
+ const dateFrom = url.searchParams.get('dateFrom') ?? '';
3216
+ const dateTo = url.searchParams.get('dateTo') ?? '';
3217
+ const accountId = url.searchParams.get('accountId') ?? '';
3218
+ const journalId = url.searchParams.get('journalId') ?? '';
818
3219
  const partnerId = url.searchParams.get('partnerId') ?? '';
819
- const rows = partnerId
820
- ? (await ctx.call('account.partnerStatement', { partnerId }, url, req))
821
- : [];
822
- return document(ctx, url, req, 'account_backend.partnerStatement.title', (_, tr, shell) => {
823
- const currency = currencyOf(data.companies, shell);
824
- return partnerLedgerScreen(tr, {
825
- frame: shell,
826
- action: `/admin/partner-statement${localeSuffix(url)}`,
827
- rows,
828
- currency,
829
- selected: Boolean(partnerId),
3220
+ const [accounts, journals, companies, result] = (await Promise.all([
3221
+ ctx.call('account.listAccounts', {}, url, req),
3222
+ ctx.call('account.listJournals', {}, url, req),
3223
+ ctx.call('company.listCompanies', {}, url, req),
3224
+ dateFrom && dateTo
3225
+ ? ctx.call('account.accountingBook', {
3226
+ book,
3227
+ dateFrom,
3228
+ dateTo,
3229
+ ...(accountId ? { accountId } : {}),
3230
+ ...(journalId ? { journalId } : {}),
3231
+ ...(partnerId ? { partnerId } : {}),
3232
+ }, url, req)
3233
+ : Promise.resolve(null),
3234
+ ]));
3235
+ return adminPage(ctx, url, req, {
3236
+ title: 'account_backend.books.title',
3237
+ body: (_, frame) => accountingBooksScreen(_, {
3238
+ frame,
3239
+ action: url.pathname,
3240
+ result: result?.errors ? undefined : (result ?? undefined),
3241
+ currency: currencyOf(companies, frame),
3242
+ errors: result?.errors?.map((issue) => issue.code ? _(issue.code) : String(issue.message)),
3243
+ entryHref: (row) => `/admin/accounting/entries/${encodeURIComponent(String(row.moveId))}${localeQuery(url)}`,
830
3244
  fields: [
831
3245
  {
832
- name: 'partnerId',
833
- label: tr('account_backend.field.partnerId'),
3246
+ name: 'book',
3247
+ label: _('account_backend.books.book'),
834
3248
  type: 'select',
3249
+ value: book,
3250
+ options: [
3251
+ 'general_journal',
3252
+ 'general_ledger',
3253
+ 'account_detail',
3254
+ 'cash',
3255
+ 'bank',
3256
+ 'partner',
3257
+ ].map((value) => ({ value, label: _(`account_backend.books.${value}`) })),
3258
+ },
3259
+ {
3260
+ name: 'dateFrom',
3261
+ label: _('account_backend.field.dateFrom'),
3262
+ type: 'date',
3263
+ value: dateFrom,
3264
+ required: true,
3265
+ },
3266
+ {
3267
+ name: 'dateTo',
3268
+ label: _('account_backend.field.dateTo'),
3269
+ type: 'date',
3270
+ value: dateTo,
3271
+ required: true,
3272
+ },
3273
+ {
3274
+ name: 'accountId',
3275
+ label: _('account_backend.field.accountId'),
3276
+ type: 'select',
3277
+ value: accountId,
3278
+ options: choices(accounts, true),
3279
+ },
3280
+ {
3281
+ name: 'journalId',
3282
+ label: _('account_backend.field.journalId'),
3283
+ type: 'select',
3284
+ value: journalId,
3285
+ options: choices(journals, true),
3286
+ },
3287
+ {
3288
+ name: 'partnerId',
3289
+ label: _('account_backend.field.partnerId'),
835
3290
  value: partnerId,
836
- options: choices(data.partners, true),
3291
+ help: _('account_backend.books.partnerHint'),
837
3292
  },
838
3293
  ],
839
- });
3294
+ }),
840
3295
  });
841
3296
  },
842
3297
  },
@@ -864,6 +3319,157 @@ const vi = {
864
3319
  'menu.journals': 'Sổ nhật ký',
865
3320
  'menu.taxes': 'Thuế',
866
3321
  'menu.paymentTerms': 'Điều khoản thanh toán',
3322
+ 'menu.defaults': 'Tài khoản mặc định',
3323
+ 'menu.openingBalances': 'Số dư đầu kỳ',
3324
+ 'menu.periodCloses': 'Đóng kỳ',
3325
+ 'menu.books': 'Sổ kế toán',
3326
+ 'opening.title': 'Số dư đầu kỳ',
3327
+ 'opening.subtitle': 'Nhập, kiểm soát và ghi sổ số dư chuyển sang.',
3328
+ 'opening.create': 'Nhập số dư đầu kỳ',
3329
+ 'opening.createHint': 'Dán dữ liệu nguồn có mã dòng ổn định; hệ thống đối chiếu tổng Nợ/Có trước khi ghi.',
3330
+ 'opening.summary': 'Số đợt nhập',
3331
+ 'opening.empty': 'Chưa có số dư đầu kỳ',
3332
+ 'opening.emptyHint': 'Tạo đợt nhập đầu tiên khi chuẩn bị chuyển đổi dữ liệu.',
3333
+ 'opening.batch': 'Đợt số dư',
3334
+ 'opening.lines': 'Số dòng',
3335
+ 'opening.source': 'Checksum nguồn',
3336
+ 'opening.sourceName': 'Tên nguồn',
3337
+ 'opening.controlDebit': 'Tổng Nợ kiểm soát',
3338
+ 'opening.controlCredit': 'Tổng Có kiểm soát',
3339
+ 'opening.linesJson': 'Các dòng nguồn (JSON)',
3340
+ 'opening.linesJsonHint': 'Mỗi dòng cần sourceKey, accountId, description và đúng một số tiền debit hoặc credit.',
3341
+ 'opening.linesInvalid': 'JSON dòng nguồn không hợp lệ.',
3342
+ 'opening.validate': 'Kiểm tra dữ liệu',
3343
+ 'opening.control': 'Đối chiếu số dư',
3344
+ 'opening.controlHint': 'Mỗi dòng mở được về tài khoản và chứng từ nguồn.',
3345
+ 'opening.openEntry': 'Mở bút toán',
3346
+ 'opening.post': 'Ghi sổ số dư',
3347
+ 'opening.postHint': 'Sau khi ghi sổ, mọi chỉnh sửa phải thực hiện bằng bút toán đảo.',
3348
+ 'close.title': 'Đóng kỳ kế toán',
3349
+ 'close.subtitle': 'Checklist có bằng chứng, khóa mềm và khóa cứng theo kỳ.',
3350
+ 'close.summary': 'Số kỳ',
3351
+ 'close.create': 'Tạo kỳ đóng sổ',
3352
+ 'close.createHint': 'Kỳ chỉ đóng khi toàn bộ kiểm tra bắt buộc đã hoàn tất.',
3353
+ 'close.period': 'Kỳ',
3354
+ 'close.range': 'Khoảng ngày',
3355
+ 'close.blockers': 'Chặn',
3356
+ 'close.empty': 'Chưa có kỳ đóng sổ',
3357
+ 'close.emptyHint': 'Tạo kỳ đầu tiên để chạy checklist.',
3358
+ 'close.version': 'Phiên bản checklist',
3359
+ 'close.revision': 'Lần cập nhật',
3360
+ 'close.blocked': 'Chưa thể đóng kỳ',
3361
+ 'close.checklist': 'Checklist đóng kỳ',
3362
+ 'close.checklistHint': 'Mỗi bước giữ checksum bằng chứng để có thể kiểm toán lại.',
3363
+ 'close.refresh': 'Chạy lại kiểm tra',
3364
+ 'close.check': 'Kiểm tra',
3365
+ 'close.required': 'Bắt buộc',
3366
+ 'close.evidence': 'Bằng chứng',
3367
+ 'close.actions': 'Kiểm soát kỳ',
3368
+ 'close.actionsHint': 'Khóa mềm có thể mở lại với lý do; khóa cứng là vĩnh viễn.',
3369
+ 'close.soft': 'Khóa mềm',
3370
+ 'close.hard': 'Khóa cứng vĩnh viễn',
3371
+ 'close.reopen': 'Mở lại kỳ',
3372
+ 'close.check.draft_moves': 'Không còn bút toán nháp',
3373
+ 'close.check.trial_balance': 'Tổng Nợ bằng tổng Có',
3374
+ 'close.check.localization_evidence': 'Bằng chứng chuẩn kế toán đang dùng',
3375
+ 'close.check.bank_reconciled': 'Đối chiếu ngân hàng',
3376
+ 'close.check.inventory_closed': 'Đóng kho',
3377
+ 'close.check.assets_tied_out': 'Đối chiếu tài sản',
3378
+ 'books.title': 'Sổ kế toán',
3379
+ 'books.subtitle': 'Sổ trung lập quốc gia với số đầu kỳ, phát sinh và số cuối kỳ chính xác.',
3380
+ 'books.filter': 'Phạm vi sổ',
3381
+ 'books.filterHint': 'Chọn loại sổ, kỳ và chiều phân tích cần thiết.',
3382
+ 'books.result': 'Dòng sổ',
3383
+ 'books.resultHint': 'Mỗi dòng mở về bút toán đã tạo ra số liệu.',
3384
+ 'books.book': 'Loại sổ',
3385
+ 'books.opening': 'Đầu kỳ',
3386
+ 'books.closing': 'Cuối kỳ',
3387
+ 'books.running': 'Số dư lũy kế',
3388
+ 'books.partnerHint': 'Mã đối tác là bắt buộc với sổ đối tác.',
3389
+ 'books.general_journal': 'Sổ nhật ký chung',
3390
+ 'books.general_ledger': 'Sổ cái',
3391
+ 'books.account_detail': 'Sổ chi tiết tài khoản',
3392
+ 'books.cash': 'Sổ quỹ tiền mặt',
3393
+ 'books.bank': 'Sổ tiền gửi ngân hàng',
3394
+ 'books.partner': 'Sổ đối tác',
3395
+ 'wave1.state.validated': 'Đã kiểm tra',
3396
+ 'wave1.state.posted': 'Đã ghi sổ',
3397
+ 'wave1.state.open': 'Đang mở',
3398
+ 'wave1.state.soft_closed': 'Đã khóa mềm',
3399
+ 'wave1.state.hard_closed': 'Đã khóa cứng',
3400
+ 'wave1.state.reopened': 'Đã mở lại',
3401
+ 'wave1.state.complete': 'Hoàn tất',
3402
+ 'wave1.state.blocked': 'Bị chặn',
3403
+ 'wave1.state.pending': 'Chờ xử lý',
3404
+ 'field.accountingDate': 'Ngày hạch toán',
3405
+ 'field.reason': 'Lý do',
3406
+ 'defaults.title': 'Tài khoản mặc định',
3407
+ 'defaults.kicker': 'Cấu hình hạch toán',
3408
+ 'defaults.subtitle': 'Quyết định trước tài khoản cho hoá đơn, để chứng từ khỏi phải hỏi lại mỗi lần.',
3409
+ 'defaults.summary.categories': 'Nhóm đã cấu hình',
3410
+ 'defaults.company.title': 'Mặc định của công ty',
3411
+ 'defaults.company.hint': 'Dùng khi nhóm sản phẩm và đối tác không có cấu hình riêng.',
3412
+ 'defaults.category.title': 'Đặt tài khoản cho nhóm sản phẩm',
3413
+ 'defaults.category.edit.title': 'Sửa tài khoản của nhóm sản phẩm',
3414
+ 'defaults.category.hint': 'Nhóm sản phẩm quyết định tài khoản doanh thu và chi phí cho hàng thuộc nhóm đó.',
3415
+ 'defaults.categories.title': 'Nhóm sản phẩm đã cấu hình',
3416
+ 'defaults.categories.hint': 'Mở một dòng để sửa. Nhóm không có ở đây sẽ dùng mặc định của công ty.',
3417
+ 'defaults.categories.empty': 'Chưa nhóm nào có tài khoản riêng',
3418
+ 'defaults.categories.emptyHint': 'Mọi hàng hoá đang hạch toán theo mặc định của công ty.',
3419
+ 'overview.title': 'Tổng quan kế toán',
3420
+ 'overview.subtitle': 'Kết quả kinh doanh, tình hình tài chính và công nợ lấy thẳng từ sổ đã ghi.',
3421
+ 'overview.period': 'Kỳ báo cáo',
3422
+ 'overview.periodHint': 'Chọn một khoảng có sẵn, hoặc chọn năm rồi thu hẹp bằng ngày cụ thể. Số liệu kết quả tính trong kỳ; số dư tính đến ngày cuối kỳ. Kỳ so sánh là khoảng thời gian cùng độ dài liền trước.',
3423
+ 'overview.preset.today': 'Hôm nay',
3424
+ 'overview.preset.yesterday': 'Hôm qua',
3425
+ 'overview.preset.last7': '7 ngày qua',
3426
+ 'overview.preset.last14': '14 ngày qua',
3427
+ 'overview.preset.last30': '30 ngày qua',
3428
+ 'overview.preset.month': 'Tháng này',
3429
+ 'overview.preset.lastMonth': 'Tháng trước',
3430
+ 'overview.preset.last90': '90 ngày qua',
3431
+ 'overview.byYear': 'Theo năm',
3432
+ 'overview.custom': 'Thu hẹp trong năm',
3433
+ 'overview.headline': 'Chỉ số chính',
3434
+ 'overview.headlineHint': 'So với kỳ liền trước cùng độ dài.',
3435
+ 'overview.revenue': 'Doanh thu thuần',
3436
+ 'overview.profit': 'Lợi nhuận trước thuế',
3437
+ 'overview.cash': 'Tiền và tương đương tiền',
3438
+ 'overview.assets': 'Tổng tài sản',
3439
+ 'overview.liabilities': 'Tổng nợ phải trả',
3440
+ 'overview.versusPrevious': 'so với kỳ trước',
3441
+ 'overview.noComparison': 'chưa có kỳ so sánh',
3442
+ 'overview.previous': 'kỳ trước',
3443
+ 'overview.thisPeriod': 'Kỳ này',
3444
+ 'overview.lastPeriod': 'Kỳ trước',
3445
+ 'overview.revenueTrend': 'Doanh thu theo thời gian',
3446
+ 'overview.revenueTrendHint': 'Mỗi điểm là doanh thu phát sinh trong khoảng đó, không phải luỹ kế.',
3447
+ 'overview.mix': 'Cơ cấu doanh thu',
3448
+ 'overview.otherRevenue': 'Doanh thu khác',
3449
+ 'overview.expenses': 'Chi phí theo tài khoản',
3450
+ 'overview.totalExpense': 'Tổng chi phí',
3451
+ 'overview.grossMargin': 'Tỷ lệ lợi nhuận gộp',
3452
+ 'overview.receivable': 'Công nợ phải thu',
3453
+ 'overview.payable': 'Công nợ phải trả',
3454
+ 'overview.partner': 'Đối tác',
3455
+ 'overview.outstanding': 'Còn phải thanh toán',
3456
+ 'overview.notYetDue': 'Trong hạn',
3457
+ 'overview.overdue': 'Quá hạn',
3458
+ 'overview.cashFlow': 'Dòng tiền',
3459
+ 'overview.cashFlowHint': 'Tiền thực tế đi qua tài khoản tiền mặt và ngân hàng, phân loại theo tài khoản đối ứng.',
3460
+ 'overview.movement': 'Khoản mục',
3461
+ 'overview.cashSales': 'Tiền thu từ bán hàng',
3462
+ 'overview.cashPurchases': 'Tiền chi cho mua hàng',
3463
+ 'overview.cashOperating': 'Tiền chi phí hoạt động',
3464
+ 'overview.cashOther': 'Tiền thu chi khác',
3465
+ 'overview.cashNet': 'Lưu chuyển tiền thuần',
3466
+ 'overview.noRevenue': 'Kỳ này chưa có doanh thu ghi sổ.',
3467
+ 'overview.noExpense': 'Kỳ này chưa có chi phí ghi sổ.',
3468
+ 'overview.noReceivable': 'Không còn khoản phải thu nào đang mở.',
3469
+ 'overview.noPayable': 'Không còn khoản phải trả nào đang mở.',
3470
+ 'overview.unitBillion': ' tỷ',
3471
+ 'overview.unitMillion': ' tr',
3472
+ 'overview.unitThousand': ' ng',
867
3473
  'dashboard.title': 'Tổng quan kế toán',
868
3474
  'dashboard.kicker': 'Không gian tài chính',
869
3475
  'dashboard.subtitle': 'Theo dõi chứng từ, công nợ, báo cáo và cấu hình kế toán tại một nơi.',
@@ -883,13 +3489,13 @@ const vi = {
883
3489
  'dashboard.trialBalanceHint': 'Đối chiếu tổng phát sinh Nợ và Có theo tài khoản.',
884
3490
  'dashboard.generalLedgerHint': 'Xem chi tiết phát sinh trên từng tài khoản.',
885
3491
  'dashboard.partnerLedgerHint': 'Theo dõi công nợ phải thu, phải trả theo đối tác.',
886
- 'dashboard.accountsHint': 'Hệ thống tài khoản Việt Nam theo Thông 99/2025/TT-BTC.',
3492
+ 'dashboard.accountsHint': 'Hệ thống tài khoản đang được cấu hình cho công ty.',
887
3493
  'dashboard.journalsHint': 'Phân loại và đánh số chứng từ kế toán.',
888
3494
  'dashboard.taxesHint': 'Cấu hình phạm vi và cách tính thuế.',
889
3495
  'dashboard.paymentTermsHint': 'Lịch thanh toán dùng cho hoá đơn và công nợ.',
890
3496
  'accounts.title': 'Hệ thống tài khoản',
891
3497
  'account.kicker': 'Cấu hình sổ cái',
892
- 'account.subtitle': 'Quản lý hệ thống mã và loại tài khoản theo chuẩn Odoo 19.',
3498
+ 'account.subtitle': 'Quản lý hệ thống mã và loại tài khoản.',
893
3499
  'account.summary.total': 'Tổng tài khoản',
894
3500
  'account.summary.asset': 'Tài sản',
895
3501
  'account.summary.liability': 'Nợ và vốn',
@@ -902,7 +3508,7 @@ const vi = {
902
3508
  'account.emptyHint': 'Tạo tài khoản đầu tiên để cấu hình sổ cái.',
903
3509
  'journals.title': 'Sổ nhật ký',
904
3510
  'journal.kicker': 'Cấu hình ghi sổ',
905
- 'journal.subtitle': 'Tổ chức chứng từ theo loại sổ nhật ký chuẩn Odoo 19.',
3511
+ 'journal.subtitle': 'Tổ chức chứng từ theo loại sổ nhật ký.',
906
3512
  'journal.summary.total': 'Tổng sổ',
907
3513
  'journal.summary.sale': 'Bán hàng',
908
3514
  'journal.summary.purchase': 'Mua hàng',
@@ -915,7 +3521,7 @@ const vi = {
915
3521
  'journal.emptyHint': 'Tạo sổ đầu tiên để bắt đầu phân loại chứng từ.',
916
3522
  'taxes.title': 'Thuế',
917
3523
  'tax.kicker': 'Cấu hình thuế',
918
- 'tax.subtitle': 'Quản lý phạm vi và cách tính thuế theo selection code Odoo 19.',
3524
+ 'tax.subtitle': 'Quản lý phạm vi và cách tính thuế theo ổn định.',
919
3525
  'tax.summary.total': 'Tổng sắc thuế',
920
3526
  'tax.summary.sale': 'Bán hàng',
921
3527
  'tax.summary.purchase': 'Mua hàng',
@@ -928,13 +3534,18 @@ const vi = {
928
3534
  'tax.emptyHint': 'Tạo sắc thuế đầu tiên để áp dụng trên chứng từ.',
929
3535
  'terms.title': 'Điều khoản thanh toán',
930
3536
  'term.kicker': 'Lịch thanh toán',
931
- 'term.subtitle': 'Cấu hình các mốc đến hạn theo quy tắc Odoo 19.',
3537
+ 'term.subtitle': 'Cấu hình các mốc đến hạn thanh toán.',
932
3538
  'term.summary.total': 'Tổng điều khoản',
933
3539
  'term.summary.configured': 'Đã có mốc',
934
3540
  'term.summary.lines': 'Tổng số mốc',
935
3541
  'term.create.title': 'Tạo điều khoản thanh toán',
936
3542
  'term.create.hint': 'Đặt tên và ghi chú hiển thị trên chứng từ.',
937
3543
  'term.line.create.title': 'Thêm mốc đến hạn',
3544
+ 'term.line.edit.title': 'Sửa mốc đến hạn',
3545
+ 'term.milestones.title': 'Các mốc đã cấu hình',
3546
+ 'term.milestones.hint': 'Mở một mốc để sửa tỷ lệ, cách tính hạn và số ngày.',
3547
+ 'term.milestones.empty': 'Chưa có mốc nào',
3548
+ 'term.milestones.emptyHint': 'Một điều khoản chưa có mốc thì hoá đơn đến hạn ngay trong ngày lập.',
938
3549
  'term.line.create.hint': 'Phân bổ phần trăm hoặc số tiền và chọn cách tính ngày đến hạn.',
939
3550
  'term.list.title': 'Điều khoản hiện có',
940
3551
  'term.list.hint': 'Kiểm tra số mốc đến hạn và ghi chú của từng điều khoản.',
@@ -979,6 +3590,8 @@ const vi = {
979
3590
  'vendorBill.empty': 'Chưa có hoá đơn nhà cung cấp',
980
3591
  'vendorBill.emptyHint': 'Tạo hoá đơn đầu tiên để bắt đầu theo dõi công nợ phải trả.',
981
3592
  'error.invalid': 'Dữ liệu chưa hợp lệ. Kiểm tra các trường bắt buộc và thử lại.',
3593
+ 'relation.accounts': 'Hệ thống tài khoản',
3594
+ 'relation.partners': 'Danh bạ đối tác',
982
3595
  'payments.title': 'Thanh toán',
983
3596
  'payment.kicker': 'Ngân hàng và tiền mặt',
984
3597
  'payment.subtitle': 'Ghi nhận tiền thu, tiền chi và đối soát công nợ mở.',
@@ -1000,6 +3613,7 @@ const vi = {
1000
3613
  'trial.summary.balance': 'Chênh lệch',
1001
3614
  'trial.filter.title': 'Kỳ báo cáo',
1002
3615
  'trial.filter.hint': 'Để trống ngày để tính trên toàn bộ bút toán đã ghi sổ.',
3616
+ 'trial.filter.rangeError': 'Ngày kết thúc phải bằng hoặc sau ngày bắt đầu.',
1003
3617
  'trial.result.title': 'Số dư theo tài khoản',
1004
3618
  'trial.result.hint': 'Tổng Nợ và Có phải cân bằng trên toàn bộ hệ thống tài khoản.',
1005
3619
  'trial.empty': 'Không có số liệu trong kỳ',
@@ -1012,6 +3626,9 @@ const vi = {
1012
3626
  'ledger.summary.credit': 'Tổng Có',
1013
3627
  'ledger.filter.title': 'Bộ lọc sổ cái',
1014
3628
  'ledger.filter.hint': 'Chọn một tài khoản hoặc để trống để xem toàn bộ dòng đã ghi sổ.',
3629
+ 'ledger.filter.unavailableAccount': 'Tài khoản không còn khả dụng',
3630
+ 'ledger.filter.accountError': 'Tài khoản đã chọn không còn khả dụng. Hãy xóa bộ lọc tài khoản.',
3631
+ 'ledger.search': 'Tìm theo bút toán, tài khoản hoặc nội dung…',
1015
3632
  'ledger.result.title': 'Chi tiết phát sinh',
1016
3633
  'ledger.result.hint': 'Mỗi dòng liên kết phát sinh với bút toán và ngày ghi sổ.',
1017
3634
  'ledger.empty': 'Không có phát sinh phù hợp',
@@ -1024,6 +3641,9 @@ const vi = {
1024
3641
  'partnerLedger.summary.residual': 'Còn lại',
1025
3642
  'partnerLedger.filter.title': 'Chọn đối tác',
1026
3643
  'partnerLedger.filter.hint': 'Báo cáo chỉ bao gồm tài khoản phải thu và phải trả trên bút toán đã ghi sổ.',
3644
+ 'partnerLedger.filter.unavailablePartner': 'Đối tác không còn khả dụng',
3645
+ 'partnerLedger.filter.partnerError': 'Đối tác đã chọn không còn khả dụng. Hãy xóa bộ lọc đối tác.',
3646
+ 'partnerLedger.search': 'Tìm theo chứng từ, tài khoản hoặc nội dung…',
1027
3647
  'partnerLedger.result.title': 'Chi tiết công nợ',
1028
3648
  'partnerLedger.result.hint': 'Theo dõi chứng từ, phát sinh Nợ/Có và phần chưa đối soát.',
1029
3649
  'partnerLedger.select': 'Chưa chọn đối tác',
@@ -1034,18 +3654,33 @@ const vi = {
1034
3654
  'lines.add': 'Thêm dòng bút toán',
1035
3655
  'move.kicker': 'Chứng từ kế toán',
1036
3656
  'move.actions': 'Hành động trên chứng từ',
3657
+ 'move.refused': 'Không thực hiện được',
3658
+ 'move.draftTitle': 'Bút toán nháp',
1037
3659
  'move.collaboration': 'Trao đổi và hoạt động của chứng từ',
1038
3660
  'terms.lines': 'Số mốc thanh toán',
1039
3661
  'action.create': 'Tạo mới',
3662
+ 'action.save': 'Lưu thay đổi',
3663
+ 'action.cancelEdit': 'Thôi sửa',
1040
3664
  'action.createTerm': 'Tạo điều khoản',
1041
3665
  'action.addTermLine': 'Thêm mốc thanh toán',
1042
3666
  'action.addLine': 'Thêm dòng',
1043
3667
  'action.post': 'Ghi sổ',
1044
3668
  'action.cancel': 'Huỷ',
3669
+ 'action.reverse': 'Đảo bút toán',
1045
3670
  'action.registerPayment': 'Ghi nhận thanh toán',
1046
3671
  'action.calculate': 'Tính báo cáo',
3672
+ active: 'Đang dùng',
3673
+ archived: 'Đã lưu trữ',
3674
+ 'column.includeBaseAmount': 'Cộng vào cơ sở',
3675
+ 'account.edit.title': 'Sửa tài khoản',
3676
+ 'journal.edit.title': 'Sửa sổ nhật ký',
3677
+ 'tax.edit.title': 'Sửa thuế',
3678
+ 'term.edit.title': 'Sửa điều khoản thanh toán',
1047
3679
  'field.code': 'Mã',
1048
3680
  'field.name': 'Tên',
3681
+ 'field.nameEn': 'Tên tiếng Anh theo chế độ kế toán',
3682
+ 'field.active': 'Đang sử dụng',
3683
+ 'field.activeHint': 'Bỏ chọn để lưu trữ. Bản ghi đã lưu trữ không còn xuất hiện trong danh sách chọn.',
1049
3684
  'field.accountType': 'Loại tài khoản',
1050
3685
  'field.reconcile': 'Cho phép đối soát',
1051
3686
  'field.type': 'Loại',
@@ -1059,6 +3694,8 @@ const vi = {
1059
3694
  'field.paymentAmount': 'Số tiền',
1060
3695
  'field.priceInclude': 'Đã gồm trong giá',
1061
3696
  'field.includeBaseAmount': 'Cộng vào cơ sở tính thuế',
3697
+ 'field.includeBaseAmountHint': 'Số thuế này được cộng vào cơ sở tính của các thuế đứng sau nó. Dùng cho thuế nhập khẩu, khi thuế GTGT hàng nhập khẩu tính trên giá đã gồm thuế nhập khẩu.',
3698
+ 'field.sequenceHint': 'Thuế trên cùng một dòng được áp dụng theo thứ tự tăng dần của số này.',
1062
3699
  'field.note': 'Ghi chú',
1063
3700
  'field.journalId': 'Sổ nhật ký',
1064
3701
  'field.moveType': 'Loại chứng từ',
@@ -1081,11 +3718,26 @@ const vi = {
1081
3718
  'field.discount': 'Chiết khấu %',
1082
3719
  'field.lineAccountId': 'Tài khoản doanh thu / chi phí',
1083
3720
  'field.counterpartAccountId': 'Tài khoản phải thu / phải trả',
3721
+ 'field.lineAccountIdHint': 'Để trống để lấy theo nhóm sản phẩm, hoặc mặc định của công ty.',
3722
+ 'field.counterpartAccountIdHint': 'Để trống để lấy theo đối tác, hoặc mặc định của công ty.',
3723
+ 'field.categoryId': 'Nhóm sản phẩm',
3724
+ 'field.incomeAccountId': 'Tài khoản doanh thu',
3725
+ 'field.incomeAccountIdHint': 'Ghi có khi bán hàng, nếu nhóm sản phẩm không chỉ định khác.',
3726
+ 'field.expenseAccountId': 'Tài khoản chi phí',
3727
+ 'field.expenseAccountIdHint': 'Ghi nợ khi mua hàng, nếu nhóm sản phẩm không chỉ định khác.',
3728
+ 'field.receivableAccountId': 'Tài khoản phải thu',
3729
+ 'field.receivableAccountIdHint': 'Công nợ khách hàng, nếu đối tác không chỉ định khác.',
3730
+ 'field.payableAccountId': 'Tài khoản phải trả',
3731
+ 'field.payableAccountIdHint': 'Công nợ nhà cung cấp, nếu đối tác không chỉ định khác.',
1084
3732
  'field.taxId': 'Thuế',
3733
+ 'field.secondTaxId': 'Thuế thứ hai',
3734
+ 'field.secondTaxIdHint': 'Để trống nếu dòng chỉ chịu một loại thuế.',
1085
3735
  'field.taxAccountId': 'Tài khoản thuế',
3736
+ 'field.taxAccountIdHint': 'Chỉ dùng khi dòng có đúng một loại thuế. Với nhiều thuế, mỗi thuế hạch toán vào tài khoản đã cấu hình của nó.',
1086
3737
  'field.paymentType': 'Loại thanh toán',
1087
3738
  'field.partnerType': 'Loại đối tác',
1088
3739
  'field.destinationAccountId': 'Tài khoản đối ứng',
3740
+ 'field.destinationAccountIdHint': 'Tài khoản công nợ mà khoản thu/chi này tất toán: phải thu với khách hàng, phải trả với nhà cung cấp.',
1089
3741
  'field.memo': 'Nội dung',
1090
3742
  'field.paymentReference': 'Tham chiếu thanh toán',
1091
3743
  'field.reconcileLineId': 'Đối soát với khoản mở',
@@ -1094,6 +3746,7 @@ const vi = {
1094
3746
  'field.delayType': 'Cách tính hạn',
1095
3747
  'field.nbDays': 'Số ngày',
1096
3748
  'field.daysNextMonth': 'Ngày trong tháng sau',
3749
+ 'field.daysNextMonthHint': 'Chỉ dùng với cách tính “ngày cố định của tháng sau”.',
1097
3750
  'field.dateFrom': 'Từ ngày',
1098
3751
  'field.dateTo': 'Đến ngày',
1099
3752
  'field.balance': 'Số dư',
@@ -1126,6 +3779,60 @@ const en = {
1126
3779
  'menu.journals': 'Journals',
1127
3780
  'menu.taxes': 'Taxes',
1128
3781
  'menu.paymentTerms': 'Payment terms',
3782
+ 'overview.title': 'Accounting overview',
3783
+ 'overview.subtitle': 'Result, position, and what is still owed, read straight from the posted ledger.',
3784
+ 'overview.period': 'Reporting period',
3785
+ 'overview.periodHint': 'Pick a named window, or pick a year and narrow it to exact dates. Results are for the window; balances are as at its last day. The comparison is the window of equal length immediately before it.',
3786
+ 'overview.preset.today': 'Today',
3787
+ 'overview.preset.yesterday': 'Yesterday',
3788
+ 'overview.preset.last7': 'Last 7 days',
3789
+ 'overview.preset.last14': 'Last 14 days',
3790
+ 'overview.preset.last30': 'Last 30 days',
3791
+ 'overview.preset.month': 'This month',
3792
+ 'overview.preset.lastMonth': 'Last month',
3793
+ 'overview.preset.last90': 'Last 90 days',
3794
+ 'overview.byYear': 'By year',
3795
+ 'overview.custom': 'Narrow to exact dates',
3796
+ 'overview.headline': 'Headline figures',
3797
+ 'overview.headlineHint': 'Against the preceding window of equal length.',
3798
+ 'overview.revenue': 'Net revenue',
3799
+ 'overview.profit': 'Profit before tax',
3800
+ 'overview.cash': 'Cash and equivalents',
3801
+ 'overview.assets': 'Total assets',
3802
+ 'overview.liabilities': 'Total liabilities',
3803
+ 'overview.versusPrevious': 'against the previous period',
3804
+ 'overview.noComparison': 'no period to compare',
3805
+ 'overview.previous': 'previous',
3806
+ 'overview.thisPeriod': 'This period',
3807
+ 'overview.lastPeriod': 'Previous period',
3808
+ 'overview.revenueTrend': 'Revenue over time',
3809
+ 'overview.revenueTrendHint': 'Each point is what was earned in that bucket, not a running total.',
3810
+ 'overview.mix': 'Revenue mix',
3811
+ 'overview.otherRevenue': 'Other revenue',
3812
+ 'overview.expenses': 'Expenses by account',
3813
+ 'overview.totalExpense': 'Total expense',
3814
+ 'overview.grossMargin': 'Gross margin',
3815
+ 'overview.receivable': 'Receivables',
3816
+ 'overview.payable': 'Payables',
3817
+ 'overview.partner': 'Partner',
3818
+ 'overview.outstanding': 'Outstanding',
3819
+ 'overview.notYetDue': 'Not yet due',
3820
+ 'overview.overdue': 'Overdue',
3821
+ 'overview.cashFlow': 'Cash flow',
3822
+ 'overview.cashFlowHint': 'Money that actually moved through cash and bank accounts, filed by its counterpart.',
3823
+ 'overview.movement': 'Movement',
3824
+ 'overview.cashSales': 'Received from sales',
3825
+ 'overview.cashPurchases': 'Paid for purchases',
3826
+ 'overview.cashOperating': 'Paid for operating expenses',
3827
+ 'overview.cashOther': 'Other movements',
3828
+ 'overview.cashNet': 'Net cash movement',
3829
+ 'overview.noRevenue': 'No revenue was posted in this period.',
3830
+ 'overview.noExpense': 'No expense was posted in this period.',
3831
+ 'overview.noReceivable': 'Nothing is outstanding from customers.',
3832
+ 'overview.noPayable': 'Nothing is outstanding to suppliers.',
3833
+ 'overview.unitBillion': 'B',
3834
+ 'overview.unitMillion': 'M',
3835
+ 'overview.unitThousand': 'K',
1129
3836
  'dashboard.title': 'Accounting overview',
1130
3837
  'dashboard.kicker': 'Finance workspace',
1131
3838
  'dashboard.subtitle': 'Track documents, balances, reports, and accounting configuration in one place.',
@@ -1140,18 +3847,115 @@ const en = {
1140
3847
  'dashboard.configurationHint': 'Manage the foundations used when posting documents.',
1141
3848
  'dashboard.customerInvoicesHint': 'Sales invoices and outstanding customer balances.',
1142
3849
  'dashboard.vendorBillsHint': 'Purchase documents and supplier obligations.',
3850
+ 'menu.defaults': 'Default accounts',
3851
+ 'menu.openingBalances': 'Opening balances',
3852
+ 'menu.periodCloses': 'Period closes',
3853
+ 'menu.books': 'Accounting books',
3854
+ 'opening.title': 'Opening balances',
3855
+ 'opening.subtitle': 'Import, control, and post brought-forward balances.',
3856
+ 'opening.create': 'Import opening balances',
3857
+ 'opening.createHint': 'Paste source rows with stable keys; debit and credit controls are checked before posting.',
3858
+ 'opening.summary': 'Import batches',
3859
+ 'opening.empty': 'No opening balances yet',
3860
+ 'opening.emptyHint': 'Create the first import batch when preparing migration.',
3861
+ 'opening.batch': 'Opening batch',
3862
+ 'opening.lines': 'Lines',
3863
+ 'opening.source': 'Source checksum',
3864
+ 'opening.sourceName': 'Source name',
3865
+ 'opening.controlDebit': 'Control debit',
3866
+ 'opening.controlCredit': 'Control credit',
3867
+ 'opening.linesJson': 'Source rows (JSON)',
3868
+ 'opening.linesJsonHint': 'Each row needs sourceKey, accountId, description, and exactly one debit or credit amount.',
3869
+ 'opening.linesInvalid': 'The source-row JSON is invalid.',
3870
+ 'opening.validate': 'Validate data',
3871
+ 'opening.control': 'Balance control',
3872
+ 'opening.controlHint': 'Every row remains drillable to its account and source entry.',
3873
+ 'opening.openEntry': 'Open journal entry',
3874
+ 'opening.post': 'Post opening balances',
3875
+ 'opening.postHint': 'After posting, corrections use a reversal entry.',
3876
+ 'close.title': 'Accounting period close',
3877
+ 'close.subtitle': 'Evidence-backed checklist with soft and hard locks.',
3878
+ 'close.summary': 'Close periods',
3879
+ 'close.create': 'Create close period',
3880
+ 'close.createHint': 'A period closes only after all required checks pass.',
3881
+ 'close.period': 'Period',
3882
+ 'close.range': 'Date range',
3883
+ 'close.blockers': 'Blockers',
3884
+ 'close.empty': 'No close periods yet',
3885
+ 'close.emptyHint': 'Create the first period to run its checklist.',
3886
+ 'close.version': 'Checklist version',
3887
+ 'close.revision': 'Revision',
3888
+ 'close.blocked': 'Period cannot close yet',
3889
+ 'close.checklist': 'Close checklist',
3890
+ 'close.checklistHint': 'Every step retains an evidence checksum for later audit.',
3891
+ 'close.refresh': 'Refresh checks',
3892
+ 'close.check': 'Check',
3893
+ 'close.required': 'Required',
3894
+ 'close.evidence': 'Evidence',
3895
+ 'close.actions': 'Period control',
3896
+ 'close.actionsHint': 'A soft lock can reopen with a reason; a hard lock is permanent.',
3897
+ 'close.soft': 'Soft close',
3898
+ 'close.hard': 'Permanent hard close',
3899
+ 'close.reopen': 'Reopen period',
3900
+ 'close.check.draft_moves': 'No draft journal entries',
3901
+ 'close.check.trial_balance': 'Debits equal credits',
3902
+ 'close.check.localization_evidence': 'Installed-standard evidence',
3903
+ 'close.check.bank_reconciled': 'Bank reconciliation',
3904
+ 'close.check.inventory_closed': 'Inventory close',
3905
+ 'close.check.assets_tied_out': 'Asset tie-out',
3906
+ 'books.title': 'Accounting books',
3907
+ 'books.subtitle': 'Jurisdiction-neutral books with exact opening, movement, and closing controls.',
3908
+ 'books.filter': 'Book scope',
3909
+ 'books.filterHint': 'Choose the book, period, and required analysis dimensions.',
3910
+ 'books.result': 'Book rows',
3911
+ 'books.resultHint': 'Every row drills into the journal entry that produced it.',
3912
+ 'books.book': 'Book',
3913
+ 'books.opening': 'Opening',
3914
+ 'books.closing': 'Closing',
3915
+ 'books.running': 'Running balance',
3916
+ 'books.partnerHint': 'A partner id is required for the partner book.',
3917
+ 'books.general_journal': 'General journal',
3918
+ 'books.general_ledger': 'General ledger',
3919
+ 'books.account_detail': 'Account detail',
3920
+ 'books.cash': 'Cash book',
3921
+ 'books.bank': 'Bank book',
3922
+ 'books.partner': 'Partner book',
3923
+ 'wave1.state.validated': 'Validated',
3924
+ 'wave1.state.posted': 'Posted',
3925
+ 'wave1.state.open': 'Open',
3926
+ 'wave1.state.soft_closed': 'Soft closed',
3927
+ 'wave1.state.hard_closed': 'Hard closed',
3928
+ 'wave1.state.reopened': 'Reopened',
3929
+ 'wave1.state.complete': 'Complete',
3930
+ 'wave1.state.blocked': 'Blocked',
3931
+ 'wave1.state.pending': 'Pending',
3932
+ 'field.accountingDate': 'Accounting date',
3933
+ 'field.reason': 'Reason',
3934
+ 'defaults.title': 'Default accounts',
3935
+ 'defaults.kicker': 'Posting configuration',
3936
+ 'defaults.subtitle': 'Decide the accounts once, so a document stops asking on every line.',
3937
+ 'defaults.summary.categories': 'Configured categories',
3938
+ 'defaults.company.title': 'Company defaults',
3939
+ 'defaults.company.hint': 'Used when neither the product category nor the partner says otherwise.',
3940
+ 'defaults.category.title': 'Set the accounts for a product category',
3941
+ 'defaults.category.edit.title': 'Edit a product category',
3942
+ 'defaults.category.hint': 'A category decides the revenue and expense accounts for what it holds.',
3943
+ 'defaults.categories.title': 'Configured categories',
3944
+ 'defaults.categories.hint': 'Open a row to change it. A category absent here uses the company defaults.',
3945
+ 'defaults.categories.empty': 'No category has its own accounts yet',
3946
+ 'defaults.categories.emptyHint': 'Everything posts to the company defaults.',
1143
3947
  'dashboard.entriesHint': 'Draft and posted entries across accounting journals.',
1144
3948
  'dashboard.paymentsHint': 'Inbound, outbound, and reconciled payments.',
1145
3949
  'dashboard.trialBalanceHint': 'Compare total debit and credit movements by account.',
1146
3950
  'dashboard.generalLedgerHint': 'Inspect posted movements on an individual account.',
1147
3951
  'dashboard.partnerLedgerHint': 'Track receivable and payable balances by partner.',
1148
- 'dashboard.accountsHint': 'Vietnam chart of accounts under Circular 99/2025/TT-BTC.',
3952
+ 'dashboard.accountsHint': 'The chart of accounts configured for this company.',
1149
3953
  'dashboard.journalsHint': 'Classify and sequence accounting documents.',
1150
3954
  'dashboard.taxesHint': 'Configure tax scope and calculation methods.',
1151
3955
  'dashboard.paymentTermsHint': 'Payment schedules used by invoices and balances.',
1152
3956
  'accounts.title': 'Chart of accounts',
1153
3957
  'account.kicker': 'Ledger configuration',
1154
- 'account.subtitle': 'Manage account codes and Odoo 19 account types.',
3958
+ 'account.subtitle': 'Manage account codes and account types.',
1155
3959
  'account.summary.total': 'Total accounts',
1156
3960
  'account.summary.asset': 'Assets',
1157
3961
  'account.summary.liability': 'Liabilities & equity',
@@ -1164,7 +3968,7 @@ const en = {
1164
3968
  'account.emptyHint': 'Create the first account to configure the general ledger.',
1165
3969
  'journals.title': 'Journals',
1166
3970
  'journal.kicker': 'Posting configuration',
1167
- 'journal.subtitle': 'Organize documents with Odoo 19 journal types.',
3971
+ 'journal.subtitle': 'Organize documents with journal types.',
1168
3972
  'journal.summary.total': 'Total journals',
1169
3973
  'journal.summary.sale': 'Sales',
1170
3974
  'journal.summary.purchase': 'Purchases',
@@ -1177,7 +3981,7 @@ const en = {
1177
3981
  'journal.emptyHint': 'Create the first journal to start classifying documents.',
1178
3982
  'taxes.title': 'Taxes',
1179
3983
  'tax.kicker': 'Tax configuration',
1180
- 'tax.subtitle': 'Manage tax scope and computation with Odoo 19 selection codes.',
3984
+ 'tax.subtitle': 'Manage tax scope and computation with stable selection codes.',
1181
3985
  'tax.summary.total': 'Total taxes',
1182
3986
  'tax.summary.sale': 'Sales',
1183
3987
  'tax.summary.purchase': 'Purchases',
@@ -1190,13 +3994,18 @@ const en = {
1190
3994
  'tax.emptyHint': 'Create the first tax to apply it on documents.',
1191
3995
  'terms.title': 'Payment terms',
1192
3996
  'term.kicker': 'Payment schedule',
1193
- 'term.subtitle': 'Configure due milestones with Odoo 19 rules.',
3997
+ 'term.subtitle': 'Configure payment due milestones.',
1194
3998
  'term.summary.total': 'Total terms',
1195
3999
  'term.summary.configured': 'With milestones',
1196
4000
  'term.summary.lines': 'Total milestones',
1197
4001
  'term.create.title': 'Create a payment term',
1198
4002
  'term.create.hint': 'Set the name and note shown on documents.',
1199
4003
  'term.line.create.title': 'Add a due milestone',
4004
+ 'term.line.edit.title': 'Edit a due milestone',
4005
+ 'term.milestones.title': 'Configured milestones',
4006
+ 'term.milestones.hint': 'Open a milestone to change its share, due-date rule and number of days.',
4007
+ 'term.milestones.empty': 'No milestones yet',
4008
+ 'term.milestones.emptyHint': 'A term with no milestone makes its invoices due on the day they are issued.',
1200
4009
  'term.line.create.hint': 'Allocate a percentage or fixed amount and choose the due-date computation.',
1201
4010
  'term.list.title': 'Current payment terms',
1202
4011
  'term.list.hint': 'Review milestone counts and notes for every term.',
@@ -1241,6 +4050,8 @@ const en = {
1241
4050
  'vendorBill.empty': 'No vendor bills yet',
1242
4051
  'vendorBill.emptyHint': 'Create the first bill to start tracking accounts payable.',
1243
4052
  'error.invalid': 'The form is invalid. Check required fields and try again.',
4053
+ 'relation.accounts': 'Chart of accounts',
4054
+ 'relation.partners': 'Partner directory',
1244
4055
  'payments.title': 'Payments',
1245
4056
  'payment.kicker': 'Bank and cash',
1246
4057
  'payment.subtitle': 'Record receipts, disbursements, and reconciliation against open items.',
@@ -1262,6 +4073,7 @@ const en = {
1262
4073
  'trial.summary.balance': 'Difference',
1263
4074
  'trial.filter.title': 'Reporting period',
1264
4075
  'trial.filter.hint': 'Leave dates blank to calculate across all posted entries.',
4076
+ 'trial.filter.rangeError': 'The end date must be on or after the start date.',
1265
4077
  'trial.result.title': 'Balances by account',
1266
4078
  'trial.result.hint': 'Total debit and credit must balance across the chart of accounts.',
1267
4079
  'trial.empty': 'No figures for this period',
@@ -1274,6 +4086,9 @@ const en = {
1274
4086
  'ledger.summary.credit': 'Total credit',
1275
4087
  'ledger.filter.title': 'Ledger filters',
1276
4088
  'ledger.filter.hint': 'Choose an account or leave it blank to show all posted journal items.',
4089
+ 'ledger.filter.unavailableAccount': 'Account no longer available',
4090
+ 'ledger.filter.accountError': 'The selected account is no longer available. Clear the account filter.',
4091
+ 'ledger.search': 'Search entries, accounts, or descriptions…',
1277
4092
  'ledger.result.title': 'Account movements',
1278
4093
  'ledger.result.hint': 'Each item relates the movement to its journal entry and posting date.',
1279
4094
  'ledger.empty': 'No matching movements',
@@ -1286,6 +4101,9 @@ const en = {
1286
4101
  'partnerLedger.summary.residual': 'Residual',
1287
4102
  'partnerLedger.filter.title': 'Select a partner',
1288
4103
  'partnerLedger.filter.hint': 'The report includes only posted receivable and payable journal items.',
4104
+ 'partnerLedger.filter.unavailablePartner': 'Partner no longer available',
4105
+ 'partnerLedger.filter.partnerError': 'The selected partner is no longer available. Clear the partner filter.',
4106
+ 'partnerLedger.search': 'Search documents, accounts, or descriptions…',
1289
4107
  'partnerLedger.result.title': 'Partner movements',
1290
4108
  'partnerLedger.result.hint': 'Review documents, debit/credit movements, and unreconciled amounts.',
1291
4109
  'partnerLedger.select': 'No partner selected',
@@ -1296,18 +4114,33 @@ const en = {
1296
4114
  'lines.add': 'Add journal item',
1297
4115
  'move.kicker': 'Accounting document',
1298
4116
  'move.actions': 'Document actions',
4117
+ 'move.refused': 'That did not go through',
4118
+ 'move.draftTitle': 'Draft entry',
1299
4119
  'move.collaboration': 'Document conversation and activities',
1300
4120
  'terms.lines': 'Due milestones',
1301
4121
  'action.create': 'Create',
4122
+ 'action.save': 'Save changes',
4123
+ 'action.cancelEdit': 'Stop editing',
1302
4124
  'action.createTerm': 'Create term',
1303
4125
  'action.addTermLine': 'Add due milestone',
1304
4126
  'action.addLine': 'Add line',
1305
4127
  'action.post': 'Post',
1306
4128
  'action.cancel': 'Cancel',
4129
+ 'action.reverse': 'Reverse entry',
1307
4130
  'action.registerPayment': 'Register payment',
1308
4131
  'action.calculate': 'Calculate',
4132
+ active: 'Active',
4133
+ archived: 'Archived',
4134
+ 'account.edit.title': 'Edit account',
4135
+ 'column.includeBaseAmount': 'Affects base',
4136
+ 'journal.edit.title': 'Edit journal',
4137
+ 'tax.edit.title': 'Edit tax',
4138
+ 'term.edit.title': 'Edit payment term',
1309
4139
  'field.code': 'Code',
1310
4140
  'field.name': 'Name',
4141
+ 'field.nameEn': 'Statutory English name',
4142
+ 'field.active': 'In use',
4143
+ 'field.activeHint': 'Clear to archive. An archived record no longer appears in selection lists.',
1311
4144
  'field.accountType': 'Account type',
1312
4145
  'field.reconcile': 'Allow reconciliation',
1313
4146
  'field.type': 'Type',
@@ -1321,6 +4154,8 @@ const en = {
1321
4154
  'field.paymentAmount': 'Amount',
1322
4155
  'field.priceInclude': 'Included in price',
1323
4156
  'field.includeBaseAmount': 'Affects tax base',
4157
+ 'field.includeBaseAmountHint': 'This tax is added to the base every later tax is computed on. Import duty uses it, so import VAT applies to the price plus the duty.',
4158
+ 'field.sequenceHint': 'Taxes on one line apply in ascending order of this number.',
1324
4159
  'field.note': 'Note',
1325
4160
  'field.journalId': 'Journal',
1326
4161
  'field.moveType': 'Document type',
@@ -1344,11 +4179,26 @@ const en = {
1344
4179
  'field.lineAccountId': 'Income / expense account',
1345
4180
  'field.counterpartAccountId': 'Receivable / payable account',
1346
4181
  'field.taxId': 'Tax',
4182
+ 'field.secondTaxId': 'Second tax',
4183
+ 'field.secondTaxIdHint': 'Leave empty when the line carries a single tax.',
1347
4184
  'field.taxAccountId': 'Tax account',
4185
+ 'field.taxAccountIdHint': 'Only used when the line carries exactly one tax. With several, each tax posts to its own configured account.',
1348
4186
  'field.paymentType': 'Payment type',
1349
4187
  'field.partnerType': 'Partner type',
1350
4188
  'field.destinationAccountId': 'Counterpart account',
1351
4189
  'field.memo': 'Memo',
4190
+ 'field.destinationAccountIdHint': 'The control account this payment settles: a receivable for a customer, a payable for a supplier.',
4191
+ 'field.lineAccountIdHint': 'Leave empty to take it from the product category, or the company default.',
4192
+ 'field.counterpartAccountIdHint': 'Leave empty to take it from the partner, or the company default.',
4193
+ 'field.categoryId': 'Product category',
4194
+ 'field.incomeAccountId': 'Revenue account',
4195
+ 'field.incomeAccountIdHint': 'Credited on a sale, unless the product category says otherwise.',
4196
+ 'field.expenseAccountId': 'Expense account',
4197
+ 'field.expenseAccountIdHint': 'Debited on a purchase, unless the product category says otherwise.',
4198
+ 'field.receivableAccountId': 'Receivable account',
4199
+ 'field.receivableAccountIdHint': 'Customer balances, unless the partner says otherwise.',
4200
+ 'field.payableAccountId': 'Payable account',
4201
+ 'field.payableAccountIdHint': 'Supplier balances, unless the partner says otherwise.',
1352
4202
  'field.paymentReference': 'Payment reference',
1353
4203
  'field.reconcileLineId': 'Reconcile with open item',
1354
4204
  'field.termValue': 'Value type',
@@ -1357,6 +4207,7 @@ const en = {
1357
4207
  'field.nbDays': 'Days',
1358
4208
  'field.daysNextMonth': 'Day of next month',
1359
4209
  'field.dateFrom': 'Date from',
4210
+ 'field.daysNextMonthHint': 'Only used by the “fixed day of the next month” rule.',
1360
4211
  'field.dateTo': 'Date to',
1361
4212
  'field.balance': 'Balance',
1362
4213
  'field.entry': 'Entry',
@@ -1409,12 +4260,9 @@ const selection = {
1409
4260
  moveState: { draft: 'Draft', posted: 'Posted', cancel: 'Cancelled' },
1410
4261
  paymentState: {
1411
4262
  not_paid: 'Not Paid',
1412
- in_payment: 'In Payment',
1413
4263
  paid: 'Paid',
1414
4264
  partial: 'Partially Paid',
1415
4265
  reversed: 'Reversed',
1416
- blocked: 'Blocked',
1417
- invoicing_legacy: 'Invoicing App Legacy',
1418
4266
  },
1419
4267
  paymentType: { outbound: 'Send', inbound: 'Receive' },
1420
4268
  partnerType: { customer: 'Customer', supplier: 'Vendor' },
@@ -1482,12 +4330,9 @@ const viSelection = {
1482
4330
  moveState: { draft: 'Nháp', posted: 'Đã ghi sổ', cancel: 'Đã huỷ' },
1483
4331
  paymentState: {
1484
4332
  not_paid: 'Chưa thanh toán',
1485
- in_payment: 'Đang thanh toán',
1486
4333
  paid: 'Đã thanh toán',
1487
4334
  partial: 'Thanh toán một phần',
1488
4335
  reversed: 'Đã đảo',
1489
- blocked: 'Bị chặn',
1490
- invoicing_legacy: 'Kế thừa hệ thống cũ',
1491
4336
  },
1492
4337
  paymentType: { outbound: 'Gửi tiền', inbound: 'Nhận tiền' },
1493
4338
  partnerType: { customer: 'Khách hàng', supplier: 'Nhà cung cấp' },