shutro-erp 0.3.5 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (384) hide show
  1. package/dist/account_asset/.kosh/bindings.d.ts +22 -0
  2. package/dist/account_asset/.kosh/bindings.js +15 -0
  3. package/dist/account_asset/.kosh/schema.d.ts +1755 -0
  4. package/dist/account_asset/board.d.ts +61 -0
  5. package/dist/account_asset/board.js +86 -0
  6. package/dist/account_asset/books.d.ts +42 -0
  7. package/dist/account_asset/books.js +398 -0
  8. package/dist/account_asset/demo.d.ts +7 -0
  9. package/dist/account_asset/demo.js +72 -0
  10. package/dist/account_asset/index.d.ts +9 -0
  11. package/dist/account_asset/index.js +335 -0
  12. package/dist/account_asset/module.d.ts +7622 -0
  13. package/dist/account_asset/module.js +230 -0
  14. package/dist/account_budget/.kosh/bindings.d.ts +22 -0
  15. package/dist/account_budget/.kosh/bindings.js +15 -0
  16. package/dist/account_budget/.kosh/schema.d.ts +1767 -0
  17. package/dist/account_budget/budget.d.ts +5 -0
  18. package/dist/account_budget/budget.js +142 -0
  19. package/dist/account_budget/demo.d.ts +6 -0
  20. package/dist/account_budget/demo.js +30 -0
  21. package/dist/account_budget/index.d.ts +4 -0
  22. package/dist/account_budget/index.js +223 -0
  23. package/dist/account_budget/module.d.ts +13863 -0
  24. package/dist/account_budget/module.js +167 -0
  25. package/dist/account_portal/.kosh/bindings.js +1 -1
  26. package/dist/account_portal/.kosh/schema.d.ts +123 -4
  27. package/dist/account_portal/module.d.ts +146 -0
  28. package/dist/accounting/.kosh/bindings.js +1 -1
  29. package/dist/accounting/.kosh/schema.d.ts +123 -4
  30. package/dist/accounting/index.d.ts +1 -1
  31. package/dist/accounting/index.js +131 -3
  32. package/dist/accounting/module.d.ts +296 -0
  33. package/dist/accounting/module.js +32 -1
  34. package/dist/approvals/.kosh/bindings.d.ts +22 -0
  35. package/dist/approvals/.kosh/bindings.js +15 -0
  36. package/dist/approvals/.kosh/schema.d.ts +611 -0
  37. package/dist/approvals/index.d.ts +18 -0
  38. package/dist/approvals/index.js +302 -0
  39. package/dist/approvals/mails.d.ts +25 -0
  40. package/dist/approvals/mails.js +82 -0
  41. package/dist/approvals/module.d.ts +1 -0
  42. package/dist/approvals/module.js +12 -0
  43. package/dist/approvals/web/History.d.ts +4 -0
  44. package/dist/approvals/web/History.js +13 -0
  45. package/dist/approvals/web/Inbox.d.ts +9 -0
  46. package/dist/approvals/web/Inbox.js +114 -0
  47. package/dist/approvals/web/Mine.d.ts +7 -0
  48. package/dist/approvals/web/Mine.js +27 -0
  49. package/dist/approvals/web/index.d.ts +13 -0
  50. package/dist/approvals/web/index.js +22 -0
  51. package/dist/approvals/web/messages.d.ts +2 -0
  52. package/dist/approvals/web/messages.js +119 -0
  53. package/dist/approvals/web/shared.d.ts +59 -0
  54. package/dist/approvals/web/shared.js +46 -0
  55. package/dist/attendance/.kosh/bindings.d.ts +22 -0
  56. package/dist/attendance/.kosh/bindings.js +15 -0
  57. package/dist/attendance/.kosh/schema.d.ts +1048 -0
  58. package/dist/attendance/days.d.ts +96 -0
  59. package/dist/attendance/days.js +430 -0
  60. package/dist/attendance/demo.d.ts +7 -0
  61. package/dist/attendance/demo.js +58 -0
  62. package/dist/attendance/index.d.ts +4 -0
  63. package/dist/attendance/index.js +513 -0
  64. package/dist/attendance/module.d.ts +3969 -0
  65. package/dist/attendance/module.js +412 -0
  66. package/dist/attendance/routes.d.ts +16 -0
  67. package/dist/attendance/routes.js +266 -0
  68. package/dist/attendance/web/Check.d.ts +8 -0
  69. package/dist/attendance/web/Check.js +40 -0
  70. package/dist/attendance/web/Kiosk.d.ts +8 -0
  71. package/dist/attendance/web/Kiosk.js +62 -0
  72. package/dist/attendance/web/PinButton.d.ts +7 -0
  73. package/dist/attendance/web/PinButton.js +29 -0
  74. package/dist/attendance/web/index.d.ts +13 -0
  75. package/dist/attendance/web/index.js +22 -0
  76. package/dist/attendance/web/messages.d.ts +2 -0
  77. package/dist/attendance/web/messages.js +61 -0
  78. package/dist/cli/init.js +32 -0
  79. package/dist/cli/templates.d.ts +1 -1
  80. package/dist/cli/templates.js +89 -0
  81. package/dist/contacts/module.js +13 -2
  82. package/dist/crm/.kosh/bindings.js +1 -1
  83. package/dist/crm/.kosh/schema.d.ts +2 -1
  84. package/dist/crm/module.d.ts +2 -0
  85. package/dist/crm/module.js +2 -1
  86. package/dist/documents/.kosh/bindings.d.ts +22 -0
  87. package/dist/documents/.kosh/bindings.js +15 -0
  88. package/dist/documents/.kosh/schema.d.ts +862 -0
  89. package/dist/documents/demo.d.ts +6 -0
  90. package/dist/documents/demo.js +22 -0
  91. package/dist/documents/documents.d.ts +98 -0
  92. package/dist/documents/documents.js +318 -0
  93. package/dist/documents/index.d.ts +30 -0
  94. package/dist/documents/index.js +442 -0
  95. package/dist/documents/module.d.ts +2781 -0
  96. package/dist/documents/module.js +214 -0
  97. package/dist/documents/web/Versions.d.ts +7 -0
  98. package/dist/documents/web/Versions.js +45 -0
  99. package/dist/documents/web/index.d.ts +11 -0
  100. package/dist/documents/web/index.js +16 -0
  101. package/dist/documents/web/messages.d.ts +2 -0
  102. package/dist/documents/web/messages.js +21 -0
  103. package/dist/event_account/.kosh/bindings.js +1 -1
  104. package/dist/event_account/.kosh/schema.d.ts +123 -4
  105. package/dist/event_account/module.d.ts +146 -0
  106. package/dist/expense/.kosh/bindings.d.ts +22 -0
  107. package/dist/expense/.kosh/bindings.js +15 -0
  108. package/dist/expense/.kosh/schema.d.ts +1299 -0
  109. package/dist/expense/demo.d.ts +7 -0
  110. package/dist/expense/demo.js +69 -0
  111. package/dist/expense/index.d.ts +3 -0
  112. package/dist/expense/index.js +495 -0
  113. package/dist/expense/module.d.ts +4747 -0
  114. package/dist/expense/module.js +647 -0
  115. package/dist/expense_account/.kosh/bindings.d.ts +22 -0
  116. package/dist/expense_account/.kosh/bindings.js +15 -0
  117. package/dist/expense_account/.kosh/schema.d.ts +1936 -0
  118. package/dist/expense_account/index.d.ts +3 -0
  119. package/dist/expense_account/index.js +74 -0
  120. package/dist/expense_account/module.d.ts +9153 -0
  121. package/dist/expense_account/module.js +318 -0
  122. package/dist/helpdesk/.kosh/bindings.d.ts +22 -0
  123. package/dist/helpdesk/.kosh/bindings.js +15 -0
  124. package/dist/helpdesk/.kosh/schema.d.ts +885 -0
  125. package/dist/helpdesk/demo.d.ts +7 -0
  126. package/dist/helpdesk/demo.js +65 -0
  127. package/dist/helpdesk/hours.d.ts +17 -0
  128. package/dist/helpdesk/hours.js +94 -0
  129. package/dist/helpdesk/index.d.ts +10 -0
  130. package/dist/helpdesk/index.js +461 -0
  131. package/dist/helpdesk/module.d.ts +2940 -0
  132. package/dist/helpdesk/module.js +326 -0
  133. package/dist/helpdesk/routes.d.ts +12 -0
  134. package/dist/helpdesk/routes.js +132 -0
  135. package/dist/helpdesk/sla.d.ts +37 -0
  136. package/dist/helpdesk/sla.js +226 -0
  137. package/dist/hr/index.d.ts +1 -1
  138. package/dist/hr/index.js +1 -1
  139. package/dist/l10n_bd/.kosh/bindings.js +1 -1
  140. package/dist/l10n_bd/.kosh/schema.d.ts +123 -4
  141. package/dist/l10n_bd/module.d.ts +146 -0
  142. package/dist/l10n_bd_payroll/.kosh/bindings.d.ts +22 -0
  143. package/dist/l10n_bd_payroll/.kosh/bindings.js +15 -0
  144. package/dist/l10n_bd_payroll/.kosh/schema.d.ts +2312 -0
  145. package/dist/l10n_bd_payroll/data.d.ts +47 -0
  146. package/dist/l10n_bd_payroll/data.js +347 -0
  147. package/dist/l10n_bd_payroll/index.d.ts +4 -0
  148. package/dist/l10n_bd_payroll/index.js +24 -0
  149. package/dist/l10n_bd_payroll/module.d.ts +12932 -0
  150. package/dist/l10n_bd_payroll/module.js +86 -0
  151. package/dist/l10n_in/.kosh/bindings.js +1 -1
  152. package/dist/l10n_in/.kosh/schema.d.ts +123 -4
  153. package/dist/l10n_in/module.d.ts +147 -0
  154. package/dist/mail/inbound/handle.js +6 -1
  155. package/dist/maintenance_stock/.kosh/bindings.js +1 -1
  156. package/dist/maintenance_stock/.kosh/schema.d.ts +77 -2
  157. package/dist/maintenance_stock/module.d.ts +788 -66
  158. package/dist/modules-sdk/index.d.ts +1 -1
  159. package/dist/modules-sdk/manifest.d.ts +39 -2
  160. package/dist/mrp/.kosh/bindings.js +1 -1
  161. package/dist/mrp/.kosh/schema.d.ts +77 -2
  162. package/dist/mrp/index.d.ts +1 -1
  163. package/dist/mrp/index.js +2 -1
  164. package/dist/mrp/module.d.ts +781 -54
  165. package/dist/mrp/module.js +64 -2
  166. package/dist/mrp_account/.kosh/bindings.js +1 -1
  167. package/dist/mrp_account/.kosh/schema.d.ts +198 -5
  168. package/dist/mrp_account/module.d.ts +4852 -2541
  169. package/dist/payment/.kosh/bindings.js +1 -1
  170. package/dist/payment/.kosh/schema.d.ts +125 -5
  171. package/dist/payment/index.d.ts +41 -0
  172. package/dist/payment/index.js +131 -74
  173. package/dist/payment/module.d.ts +210 -6
  174. package/dist/payment/module.js +19 -3
  175. package/dist/payment/settle.js +10 -1
  176. package/dist/payroll/.kosh/bindings.d.ts +22 -0
  177. package/dist/payroll/.kosh/bindings.js +15 -0
  178. package/dist/payroll/.kosh/schema.d.ts +1390 -0
  179. package/dist/payroll/compute.d.ts +35 -0
  180. package/dist/payroll/compute.js +398 -0
  181. package/dist/payroll/demo.d.ts +55 -0
  182. package/dist/payroll/demo.js +121 -0
  183. package/dist/payroll/formula.d.ts +62 -0
  184. package/dist/payroll/formula.js +320 -0
  185. package/dist/payroll/index.d.ts +230 -0
  186. package/dist/payroll/index.js +713 -0
  187. package/dist/payroll/module.d.ts +9390 -0
  188. package/dist/payroll/module.js +606 -0
  189. package/dist/payroll/routes.d.ts +10 -0
  190. package/dist/payroll/routes.js +112 -0
  191. package/dist/payroll_account/.kosh/bindings.d.ts +22 -0
  192. package/dist/payroll_account/.kosh/bindings.js +15 -0
  193. package/dist/payroll_account/.kosh/schema.d.ts +2308 -0
  194. package/dist/payroll_account/index.d.ts +3 -0
  195. package/dist/payroll_account/index.js +40 -0
  196. package/dist/payroll_account/module.d.ts +12396 -0
  197. package/dist/payroll_account/module.js +256 -0
  198. package/dist/permissions/approvals.d.ts +131 -9
  199. package/dist/permissions/approvals.js +662 -57
  200. package/dist/permissions/index.d.ts +1 -1
  201. package/dist/permissions/index.js +2 -2
  202. package/dist/permissions/models.js +191 -12
  203. package/dist/permissions/routes.d.ts +6 -1
  204. package/dist/permissions/routes.js +37 -4
  205. package/dist/permissions/web/ApprovalPanel.d.ts +5 -4
  206. package/dist/permissions/web/ApprovalPanel.js +39 -13
  207. package/dist/permissions/web/index.d.ts +6 -4
  208. package/dist/permissions/web/index.js +13 -4
  209. package/dist/permissions/web/messages.d.ts +2 -0
  210. package/dist/permissions/web/messages.js +43 -0
  211. package/dist/portal/index.js +1 -1
  212. package/dist/pos/.kosh/bindings.js +1 -1
  213. package/dist/pos/.kosh/schema.d.ts +123 -4
  214. package/dist/pos/index.js +4 -0
  215. package/dist/pos/module.d.ts +147 -0
  216. package/dist/pos_stock/.kosh/bindings.js +1 -1
  217. package/dist/pos_stock/.kosh/schema.d.ts +198 -5
  218. package/dist/pos_stock/module.d.ts +914 -46
  219. package/dist/product/.kosh/bindings.js +1 -1
  220. package/dist/product/.kosh/schema.d.ts +2 -1
  221. package/dist/product/index.js +13 -0
  222. package/dist/product/module.d.ts +2 -0
  223. package/dist/product/module.js +2 -1
  224. package/dist/project/.kosh/bindings.js +1 -1
  225. package/dist/project/.kosh/schema.d.ts +672 -1
  226. package/dist/project/index.d.ts +3 -1
  227. package/dist/project/index.js +901 -14
  228. package/dist/project/module.d.ts +9892 -390
  229. package/dist/project/module.js +1530 -13
  230. package/dist/project/routes.d.ts +44 -0
  231. package/dist/project/routes.js +314 -0
  232. package/dist/project/schedule.d.ts +72 -0
  233. package/dist/project/schedule.js +192 -0
  234. package/dist/project/web/Refresh.d.ts +8 -0
  235. package/dist/project/web/Refresh.js +29 -0
  236. package/dist/project/web/Schedule.d.ts +9 -0
  237. package/dist/project/web/Schedule.js +93 -0
  238. package/dist/project/web/Structure.d.ts +8 -0
  239. package/dist/project/web/Structure.js +86 -0
  240. package/dist/project/web/Workload.d.ts +8 -0
  241. package/dist/project/web/Workload.js +43 -0
  242. package/dist/project/web/index.d.ts +14 -0
  243. package/dist/project/web/index.js +25 -0
  244. package/dist/project/web/messages.d.ts +2 -0
  245. package/dist/project/web/messages.js +85 -0
  246. package/dist/project_account/.kosh/bindings.d.ts +22 -0
  247. package/dist/project_account/.kosh/bindings.js +15 -0
  248. package/dist/project_account/.kosh/schema.d.ts +2241 -0
  249. package/dist/project_account/index.d.ts +3 -0
  250. package/dist/project_account/index.js +27 -0
  251. package/dist/project_account/module.d.ts +11539 -0
  252. package/dist/project_account/module.js +76 -0
  253. package/dist/project_portal/.kosh/bindings.js +1 -1
  254. package/dist/project_portal/.kosh/schema.d.ts +672 -1
  255. package/dist/project_portal/module.d.ts +4798 -129
  256. package/dist/project_purchase/.kosh/bindings.d.ts +22 -0
  257. package/dist/project_purchase/.kosh/bindings.js +15 -0
  258. package/dist/project_purchase/.kosh/schema.d.ts +2320 -0
  259. package/dist/project_purchase/index.d.ts +9 -0
  260. package/dist/project_purchase/index.js +22 -0
  261. package/dist/project_purchase/module.d.ts +25147 -0
  262. package/dist/project_purchase/module.js +56 -0
  263. package/dist/purchase/.kosh/bindings.js +1 -1
  264. package/dist/purchase/.kosh/schema.d.ts +97 -4
  265. package/dist/purchase/module.d.ts +13 -2
  266. package/dist/purchase/module.js +10 -1
  267. package/dist/purchase_account/.kosh/bindings.js +1 -1
  268. package/dist/purchase_account/.kosh/schema.d.ts +126 -6
  269. package/dist/purchase_account/index.js +1 -0
  270. package/dist/purchase_account/module.d.ts +176 -1
  271. package/dist/purchase_account/module.js +13 -2
  272. package/dist/purchase_portal/.kosh/bindings.js +1 -1
  273. package/dist/purchase_portal/.kosh/schema.d.ts +97 -4
  274. package/dist/purchase_portal/module.d.ts +6 -1
  275. package/dist/purchase_stock/.kosh/bindings.js +1 -1
  276. package/dist/purchase_stock/.kosh/schema.d.ts +174 -5
  277. package/dist/purchase_stock/index.d.ts +1 -1
  278. package/dist/purchase_stock/index.js +9 -2
  279. package/dist/purchase_stock/module.d.ts +840 -68
  280. package/dist/purchase_stock/module.js +242 -6
  281. package/dist/purchase_stock_account/.kosh/bindings.js +1 -1
  282. package/dist/purchase_stock_account/.kosh/schema.d.ts +203 -7
  283. package/dist/purchase_stock_account/module.d.ts +8163 -5514
  284. package/dist/purchase_stock_account/module.js +11 -5
  285. package/dist/recruitment/.kosh/bindings.js +1 -1
  286. package/dist/recruitment/.kosh/schema.d.ts +2 -1
  287. package/dist/recruitment/module.d.ts +2 -0
  288. package/dist/recruitment/module.js +2 -1
  289. package/dist/sale_account/.kosh/bindings.js +1 -1
  290. package/dist/sale_account/.kosh/schema.d.ts +123 -4
  291. package/dist/sale_account/module.d.ts +147 -0
  292. package/dist/sale_portal/.kosh/bindings.js +1 -1
  293. package/dist/sale_portal/.kosh/schema.d.ts +2 -1
  294. package/dist/sale_portal/module.d.ts +1 -0
  295. package/dist/sale_project/.kosh/bindings.js +1 -1
  296. package/dist/sale_project/.kosh/schema.d.ts +673 -1
  297. package/dist/sale_project/module.d.ts +4800 -129
  298. package/dist/sale_project/module.js +17 -1
  299. package/dist/sale_stock/.kosh/bindings.js +1 -1
  300. package/dist/sale_stock/.kosh/schema.d.ts +77 -2
  301. package/dist/sale_stock/module.d.ts +789 -66
  302. package/dist/sales/.kosh/bindings.js +1 -1
  303. package/dist/sales/.kosh/schema.d.ts +2 -1
  304. package/dist/sales/index.js +4 -0
  305. package/dist/sales/module.d.ts +1 -0
  306. package/dist/sign/.kosh/bindings.d.ts +22 -0
  307. package/dist/sign/.kosh/bindings.js +15 -0
  308. package/dist/sign/.kosh/schema.d.ts +990 -0
  309. package/dist/sign/index.d.ts +14 -0
  310. package/dist/sign/index.js +350 -0
  311. package/dist/sign/module.d.ts +4478 -0
  312. package/dist/sign/module.js +158 -0
  313. package/dist/sign/sign.d.ts +82 -0
  314. package/dist/sign/sign.js +474 -0
  315. package/dist/stock/.kosh/bindings.js +1 -1
  316. package/dist/stock/.kosh/schema.d.ts +77 -2
  317. package/dist/stock/demo.d.ts +2 -1
  318. package/dist/stock/demo.js +28 -1
  319. package/dist/stock/index.d.ts +2 -1
  320. package/dist/stock/index.js +233 -4
  321. package/dist/stock/module.d.ts +2363 -837
  322. package/dist/stock/module.js +569 -14
  323. package/dist/stock/replenish.d.ts +38 -0
  324. package/dist/stock/replenish.js +176 -0
  325. package/dist/stock/web/Replenishment.d.ts +8 -0
  326. package/dist/stock/web/Replenishment.js +84 -0
  327. package/dist/stock/web/index.d.ts +4 -2
  328. package/dist/stock/web/index.js +6 -2
  329. package/dist/stock/web/messages.js +52 -0
  330. package/dist/stock_account/.kosh/bindings.js +1 -1
  331. package/dist/stock_account/.kosh/schema.d.ts +198 -5
  332. package/dist/stock_account/index.js +10 -0
  333. package/dist/stock_account/module.d.ts +969 -101
  334. package/dist/trade_finance/index.js +2 -0
  335. package/dist/trade_finance/module.js +2 -0
  336. package/dist/trade_finance_account/.kosh/bindings.js +1 -1
  337. package/dist/trade_finance_account/.kosh/schema.d.ts +123 -4
  338. package/dist/trade_finance_account/index.js +1 -0
  339. package/dist/trade_finance_account/module.d.ts +146 -0
  340. package/dist/trade_finance_account/module.js +1 -0
  341. package/dist/trade_finance_purchase/.kosh/bindings.js +1 -1
  342. package/dist/trade_finance_purchase/.kosh/schema.d.ts +97 -4
  343. package/dist/trade_finance_purchase/module.d.ts +6 -1
  344. package/dist/trade_finance_sale/.kosh/bindings.js +1 -1
  345. package/dist/trade_finance_sale/.kosh/schema.d.ts +2 -1
  346. package/dist/trade_finance_sale/module.d.ts +1 -0
  347. package/dist/ui/app.js +24 -12
  348. package/dist/ui/components/AppIcon.js +8 -1
  349. package/dist/ui/i18n/messages.d.ts +4 -0
  350. package/dist/ui/i18n/messages.js +8 -0
  351. package/dist/ui/views/FormView.js +4 -2
  352. package/dist/ui/views/KanbanView.js +9 -1
  353. package/dist/ui/views/ListView.js +4 -2
  354. package/dist/ui/views/widgets.js +7 -1
  355. package/dist/website/index.js +1 -0
  356. package/dist/website/module.js +1 -0
  357. package/dist/website_crm/.kosh/bindings.js +1 -1
  358. package/dist/website_crm/.kosh/schema.d.ts +2 -1
  359. package/dist/website_crm/module.d.ts +1 -0
  360. package/dist/website_sale/.kosh/bindings.d.ts +22 -0
  361. package/dist/website_sale/.kosh/bindings.js +15 -0
  362. package/dist/website_sale/.kosh/schema.d.ts +2284 -0
  363. package/dist/website_sale/couriers.d.ts +50 -0
  364. package/dist/website_sale/couriers.js +59 -0
  365. package/dist/website_sale/demo.d.ts +7 -0
  366. package/dist/website_sale/demo.js +90 -0
  367. package/dist/website_sale/growth.d.ts +31 -0
  368. package/dist/website_sale/growth.js +163 -0
  369. package/dist/website_sale/index.d.ts +49 -0
  370. package/dist/website_sale/index.js +538 -0
  371. package/dist/website_sale/module.d.ts +22027 -0
  372. package/dist/website_sale/module.js +397 -0
  373. package/dist/website_sale/shipments.d.ts +16 -0
  374. package/dist/website_sale/shipments.js +113 -0
  375. package/dist/website_sale/shop.d.ts +81 -0
  376. package/dist/website_sale/shop.js +649 -0
  377. package/dist/website_sale_stock/.kosh/bindings.d.ts +22 -0
  378. package/dist/website_sale_stock/.kosh/bindings.js +15 -0
  379. package/dist/website_sale_stock/.kosh/schema.d.ts +2681 -0
  380. package/dist/website_sale_stock/index.d.ts +9 -0
  381. package/dist/website_sale_stock/index.js +20 -0
  382. package/dist/website_sale_stock/module.d.ts +24998 -0
  383. package/dist/website_sale_stock/module.js +28 -0
  384. package/package.json +83 -2
@@ -7,12 +7,16 @@
7
7
  import { contacts } from '../contacts/index.js';
8
8
  import { messaging } from '../messaging/index.js';
9
9
  import { defineModule } from '../modules-sdk/index.js';
10
+ import { permissions } from '../permissions/index.js';
10
11
  import { reporting } from '../reporting/index.js';
11
- import { action, calendar, form, gantt, kanban, list, pivot, search } from '../views/index.js';
12
+ import { action, calendar, form, gantt, hierarchy, kanban, list, pivot, search } from '../views/index.js';
12
13
  import { projectDemo, SUPPORT_PROJECT } from './demo.js';
13
- import { ProjectProject, ProjectTask, ProjectTaskStage, ProjectTimesheet, projectShutro, } from './module.js';
14
+ import { ProjectBudgetLine, ProjectChange, ProjectIssue, ProjectMember, ProjectPhase, ProjectPlan, ProjectProject, ProjectRisk, ProjectRole, ProjectStatusReport, ProjectTag, ProjectTask, ProjectTaskCategory, ProjectTaskLink, ProjectTaskStage, ProjectTimesheet, ProjectType, ProjectWorkPackage, projectShutro, } from './module.js';
15
+ import { registerProjectRoutes } from './routes.js';
14
16
  export { SUPPORT_PROJECT } from './demo.js';
15
- export { ProjectProject, ProjectTask, ProjectTaskStage, ProjectTimesheet, projectShutro, } from './module.js';
17
+ export { configureProjectChatter, HEALTH, judgeHealth, ProjectBudgetLine, ProjectChange, ProjectIssue, ProjectMember, ProjectPhase, ProjectPlan, ProjectProject, ProjectRisk, ProjectRole, ProjectStatusReport, ProjectTag, ProjectTask, ProjectTaskCategory, ProjectTaskLink, ProjectTaskStage, ProjectTimesheet, ProjectType, ProjectWorkPackage, peakAllocation, projectShutro, riskLevel, } from './module.js';
18
+ export { mondayOf, refreshProjects, shiftDate, workload } from './routes.js';
19
+ export { criticalPath, scheduleOf, slipMoves } from './schedule.js';
16
20
  export const project = defineModule({
17
21
  shutro: projectShutro,
18
22
  kosh: '^0.1.0',
@@ -39,6 +43,33 @@ export const project = defineModule({
39
43
  },
40
44
  ],
41
45
  },
46
+ {
47
+ key: 'health',
48
+ label: 'Health',
49
+ description: 'When a project shows at risk or off track: how far behind its schedule, how much of its budget used.',
50
+ keywords: 'health schedule behind budget risk off track',
51
+ scope: 'company',
52
+ editors: ['project.manager'],
53
+ fields: [
54
+ { key: 'projectHealthBehindRisk', min: 0 },
55
+ { key: 'projectHealthBehindOff', min: 0 },
56
+ { key: 'projectHealthCostRisk', min: 0 },
57
+ ],
58
+ },
59
+ {
60
+ key: 'plans',
61
+ label: 'Plans',
62
+ description: 'Whether a project starts only from an approved plan.',
63
+ keywords: 'plan approval require proposal budget',
64
+ scope: 'company',
65
+ editors: ['project.manager'],
66
+ fields: [
67
+ {
68
+ key: 'projectRequirePlan',
69
+ help: 'Projects inside a programme and projects made by sales orders need none of their own.',
70
+ },
71
+ ],
72
+ },
42
73
  ],
43
74
  },
44
75
  // support@<inbound domain>: a task in the support project (RFC 0006 §7.1), or the first project there is.
@@ -59,7 +90,60 @@ export const project = defineModule({
59
90
  },
60
91
  },
61
92
  ],
62
- depends: [contacts, messaging, reporting],
93
+ depends: [contacts, messaging, permissions, reporting],
94
+ routes: (context) => registerProjectRoutes(context),
95
+ // A plan is decided by its sponsor (a Projects manager when there is none), and a large one by a manager too.
96
+ approvals: [
97
+ {
98
+ name: 'Project plans',
99
+ model: 'project.plan',
100
+ onApproved: 'approve',
101
+ onRejected: 'reject',
102
+ onSentBack: 'redraft',
103
+ onWithdrawn: 'redraft',
104
+ levels: [
105
+ {
106
+ name: 'Sponsor',
107
+ condition: {},
108
+ approver: { field: 'sponsor' },
109
+ approverRole: 'project.manager',
110
+ },
111
+ {
112
+ name: 'Large budget',
113
+ condition: { estimatedBudget: { gt: '1000000' } },
114
+ approverRole: 'project.manager',
115
+ },
116
+ ],
117
+ },
118
+ // A change to a project's deadline or budget: its sponsor, then a Projects manager.
119
+ {
120
+ name: 'Project change requests',
121
+ model: 'project.change',
122
+ onApproved: 'approve',
123
+ onRejected: 'reject',
124
+ onSentBack: 'redraft',
125
+ onWithdrawn: 'redraft',
126
+ levels: [
127
+ {
128
+ name: 'Sponsor',
129
+ condition: {},
130
+ approver: { field: 'sponsor' },
131
+ approverRole: 'project.manager',
132
+ },
133
+ { name: 'Projects manager', condition: {}, approverRole: 'project.manager' },
134
+ ],
135
+ },
136
+ ],
137
+ events: [
138
+ { topic: 'project.change.applied', model: 'project.change', label: 'Change request applied' },
139
+ {
140
+ topic: 'project.status.report.sent',
141
+ model: 'project.status.report',
142
+ label: 'Status report sent',
143
+ },
144
+ { topic: 'project.plan.submitted', model: 'project.plan', label: 'Project plan submitted' },
145
+ { topic: 'project.plan.approved', model: 'project.plan', label: 'Project plan approved' },
146
+ ],
63
147
  app: {
64
148
  code: 'projects',
65
149
  label: 'Projects',
@@ -114,6 +198,34 @@ export const project = defineModule({
114
198
  filter: { 'stage.done': false },
115
199
  w: 3,
116
200
  },
201
+ {
202
+ id: 'projects_by_health',
203
+ title: 'Projects by health',
204
+ kind: 'chart',
205
+ model: 'project.project',
206
+ measure: 'count',
207
+ groupBy: 'health',
208
+ chart: 'pie',
209
+ w: 6,
210
+ },
211
+ {
212
+ id: 'plans_waiting',
213
+ title: 'Plans waiting for a decision',
214
+ kind: 'kpi',
215
+ model: 'project.plan',
216
+ measure: 'count',
217
+ filter: { state: 'submitted' },
218
+ w: 3,
219
+ },
220
+ {
221
+ id: 'phases_overdue',
222
+ title: 'Phases overdue',
223
+ kind: 'kpi',
224
+ model: 'project.phase',
225
+ measure: 'count',
226
+ filter: { late: true },
227
+ w: 3,
228
+ },
117
229
  {
118
230
  id: 'tasks_by_stage',
119
231
  title: 'Tasks by stage',
@@ -156,13 +268,56 @@ export const project = defineModule({
156
268
  ],
157
269
  },
158
270
  actions: {
271
+ 'projects.action_plans': action(ProjectPlan, {
272
+ label: 'Plans',
273
+ views: ['list', 'kanban', 'form'],
274
+ }),
159
275
  'projects.action_projects': action(ProjectProject, {
160
276
  label: 'Projects',
277
+ views: ['list', 'gantt', 'hierarchy', 'form'],
278
+ }),
279
+ 'projects.action_phases': action(ProjectPhase, {
280
+ label: 'Phases',
161
281
  views: ['list', 'gantt', 'form'],
162
282
  }),
283
+ 'projects.action_work_packages': action(ProjectWorkPackage, {
284
+ label: 'Work packages',
285
+ views: ['list', 'kanban', 'form'],
286
+ }),
287
+ 'projects.action_types': action(ProjectType, {
288
+ label: 'Project types',
289
+ views: ['list', 'form'],
290
+ }),
291
+ 'projects.action_roles': action(ProjectRole, { label: 'Roles', views: ['list', 'form'] }),
292
+ 'projects.action_members': action(ProjectMember, {
293
+ label: 'Team members',
294
+ views: ['list', 'form'],
295
+ }),
296
+ 'projects.action_workload': { type: 'client', page: 'projects.Workload', label: 'Workload' },
297
+ 'projects.action_risks': action(ProjectRisk, {
298
+ label: 'Risks',
299
+ views: ['list', 'kanban', 'form'],
300
+ }),
301
+ 'projects.action_issues': action(ProjectIssue, {
302
+ label: 'Issues',
303
+ views: ['list', 'kanban', 'form'],
304
+ }),
305
+ 'projects.action_changes': action(ProjectChange, {
306
+ label: 'Change requests',
307
+ views: ['list', 'form'],
308
+ }),
309
+ 'projects.action_reports': action(ProjectStatusReport, {
310
+ label: 'Status reports',
311
+ views: ['list', 'form'],
312
+ }),
313
+ 'projects.action_categories': action(ProjectTaskCategory, {
314
+ label: 'Task categories',
315
+ views: ['list', 'form'],
316
+ }),
317
+ 'projects.action_tags': action(ProjectTag, { label: 'Tags', views: ['list', 'form'] }),
163
318
  'projects.action_tasks': action(ProjectTask, {
164
319
  label: 'Tasks',
165
- views: ['kanban', 'list', 'form', 'calendar'],
320
+ views: ['kanban', 'list', 'form', 'calendar', 'gantt'],
166
321
  }),
167
322
  'projects.action_timesheets': action(ProjectTimesheet, {
168
323
  label: 'Timesheets',
@@ -175,6 +330,13 @@ export const project = defineModule({
175
330
  },
176
331
  menus: [
177
332
  { id: 'projects.root', label: 'Projects', app: 'projects' },
333
+ {
334
+ id: 'projects.plans',
335
+ parent: 'projects.root',
336
+ label: 'Plans',
337
+ action: 'projects.action_plans',
338
+ sequence: 0.5,
339
+ },
178
340
  {
179
341
  id: 'projects.projects',
180
342
  parent: 'projects.root',
@@ -182,6 +344,20 @@ export const project = defineModule({
182
344
  action: 'projects.action_projects',
183
345
  sequence: 1,
184
346
  },
347
+ {
348
+ id: 'projects.phases',
349
+ parent: 'projects.root',
350
+ label: 'Phases',
351
+ action: 'projects.action_phases',
352
+ sequence: 1.3,
353
+ },
354
+ {
355
+ id: 'projects.work_packages',
356
+ parent: 'projects.root',
357
+ label: 'Work packages',
358
+ action: 'projects.action_work_packages',
359
+ sequence: 1.6,
360
+ },
185
361
  {
186
362
  id: 'projects.tasks',
187
363
  parent: 'projects.root',
@@ -196,6 +372,35 @@ export const project = defineModule({
196
372
  action: 'projects.action_timesheets',
197
373
  sequence: 3,
198
374
  },
375
+ { id: 'projects.control', parent: 'projects.root', label: 'Control', sequence: 5 },
376
+ {
377
+ id: 'projects.risks',
378
+ parent: 'projects.control',
379
+ label: 'Risks',
380
+ action: 'projects.action_risks',
381
+ sequence: 1,
382
+ },
383
+ {
384
+ id: 'projects.issues',
385
+ parent: 'projects.control',
386
+ label: 'Issues',
387
+ action: 'projects.action_issues',
388
+ sequence: 2,
389
+ },
390
+ {
391
+ id: 'projects.changes',
392
+ parent: 'projects.control',
393
+ label: 'Change requests',
394
+ action: 'projects.action_changes',
395
+ sequence: 3,
396
+ },
397
+ {
398
+ id: 'projects.reports',
399
+ parent: 'projects.control',
400
+ label: 'Status reports',
401
+ action: 'projects.action_reports',
402
+ sequence: 4,
403
+ },
199
404
  { id: 'projects.configuration', parent: 'projects.root', label: 'Configuration', sequence: 9 },
200
405
  {
201
406
  id: 'projects.stages',
@@ -204,18 +409,63 @@ export const project = defineModule({
204
409
  action: 'projects.action_stages',
205
410
  sequence: 1,
206
411
  },
412
+ {
413
+ id: 'projects.workload',
414
+ parent: 'projects.root',
415
+ label: 'Workload',
416
+ action: 'projects.action_workload',
417
+ sequence: 2.5,
418
+ },
419
+ {
420
+ id: 'projects.roles',
421
+ parent: 'projects.configuration',
422
+ label: 'Roles',
423
+ action: 'projects.action_roles',
424
+ sequence: 1.5,
425
+ },
426
+ {
427
+ id: 'projects.types',
428
+ parent: 'projects.configuration',
429
+ label: 'Project types',
430
+ action: 'projects.action_types',
431
+ sequence: 2,
432
+ },
433
+ {
434
+ id: 'projects.categories',
435
+ parent: 'projects.configuration',
436
+ label: 'Task categories',
437
+ action: 'projects.action_categories',
438
+ sequence: 3,
439
+ },
440
+ {
441
+ id: 'projects.tags',
442
+ parent: 'projects.configuration',
443
+ label: 'Tags',
444
+ action: 'projects.action_tags',
445
+ sequence: 4,
446
+ },
207
447
  ],
208
448
  views: {
209
449
  'project.project.list': list(ProjectProject, {
210
450
  columns: [
451
+ 'code',
211
452
  'name',
453
+ 'type',
212
454
  'partner',
213
455
  'manager',
214
- 'dateEnd',
456
+ { field: 'priority', widget: 'badge' },
457
+ { field: 'riskLevel', widget: 'badge' },
458
+ { field: 'health', widget: 'badge' },
459
+ { field: 'progress', widget: 'progress' },
460
+ { field: 'dateEnd', widget: 'daysLeft' },
215
461
  { field: 'taskCount', sum: true },
216
462
  { field: 'hours', sum: true },
217
463
  ],
218
464
  defaultOrder: ['sequence asc', 'name asc'],
465
+ decorations: {
466
+ danger: { health: 'off_track' },
467
+ warning: { health: 'at_risk' },
468
+ },
219
469
  }),
220
470
  'project.project.form': form(ProjectProject, (k) => ({
221
471
  header: { buttons: [] },
@@ -244,17 +494,126 @@ export const project = defineModule({
244
494
  measure: { sum: 'hours' },
245
495
  action: 'projects.action_timesheets',
246
496
  },
497
+ {
498
+ id: 'project_phases',
499
+ label: 'Phases',
500
+ model: ProjectPhase,
501
+ where: { project: { $record: 'id' } },
502
+ action: 'projects.action_phases',
503
+ },
504
+ {
505
+ id: 'project_work_packages',
506
+ label: 'Work packages',
507
+ model: ProjectWorkPackage,
508
+ where: { project: { $record: 'id' } },
509
+ action: 'projects.action_work_packages',
510
+ },
511
+ {
512
+ id: 'project_risks',
513
+ label: 'Open risks',
514
+ model: ProjectRisk,
515
+ where: { project: { $record: 'id' }, status: { in: ['open', 'mitigating'] } },
516
+ action: 'projects.action_risks',
517
+ },
518
+ {
519
+ id: 'project_issues',
520
+ label: 'Open issues',
521
+ model: ProjectIssue,
522
+ where: { project: { $record: 'id' }, status: { in: ['open', 'in_progress'] } },
523
+ action: 'projects.action_issues',
524
+ },
525
+ {
526
+ id: 'project_changes',
527
+ label: 'Change requests',
528
+ model: ProjectChange,
529
+ where: { project: { $record: 'id' } },
530
+ action: 'projects.action_changes',
531
+ },
532
+ {
533
+ id: 'project_reports',
534
+ label: 'Status reports',
535
+ model: ProjectStatusReport,
536
+ where: { project: { $record: 'id' } },
537
+ action: 'projects.action_reports',
538
+ },
539
+ {
540
+ id: 'project_children',
541
+ label: 'Projects in it',
542
+ model: ProjectProject,
543
+ where: { parentProject: { $record: 'id' } },
544
+ action: 'projects.action_projects',
545
+ },
546
+ ]),
547
+ k.group('main', ['name', 'code', 'type', 'parentProject', 'plan', 'partner', 'location']),
548
+ k.group('people', ['manager', 'sponsor', 'owner', 'priority', 'riskLevel'], {
549
+ label: 'People and risk',
550
+ }),
551
+ k.group('dates', ['dateStart', 'dateEnd', 'progress', 'taskCount', 'hours']),
552
+ k.group('health_group', ['health', 'healthNotes', 'healthCheckedAt'], {
553
+ label: 'Health',
554
+ description: 'From the figures — schedule against time elapsed, late milestones, the budget used —, refreshed hourly.',
555
+ }),
556
+ k.group('health_override', ['healthComputed', 'healthOverride', 'healthReason'], {
557
+ label: 'Health set by hand',
558
+ description: 'The manager may override what the figures say, with the reason; it stays in the history.',
559
+ }),
560
+ k.group('money', ['budget', 'labourCost', 'bookedCost', 'committedCost', 'actualCost', 'variance'], {
561
+ label: 'Money',
562
+ description: 'Labour from timesheets at each member’s cost; booked and committed costs from Accounting and Purchase on the project’s cost centre.',
563
+ }),
564
+ k.component('refresh', 'projects.Refresh'),
565
+ k.lines('budgetLines', [
566
+ { field: 'name', id: 'budget_name' },
567
+ { field: 'category', id: 'budget_category' },
568
+ { field: 'phase', id: 'budget_phase' },
569
+ { field: 'workPackage', id: 'budget_wp' },
570
+ { field: 'planned', id: 'budget_planned', sum: true },
571
+ ]),
572
+ k.group('baseline', ['baselineStart', 'baselineEnd', 'baselineBudget', 'slipDays'], {
573
+ label: 'Baseline',
574
+ description: 'The dates and budget approved with the plan; the deadline is compared with them.',
575
+ }),
576
+ k.group('about', ['description', 'scope', 'assumptions', 'constraints'], {
577
+ columns: 1,
578
+ label: 'Scope',
579
+ }),
580
+ k.component('structure', 'projects.Structure'),
581
+ k.component('schedule', 'projects.Schedule'),
582
+ k.lines('members', [
583
+ { field: 'user', id: 'member_user' },
584
+ { field: 'role', id: 'member_role' },
585
+ { field: 'allocation', id: 'member_allocation' },
586
+ { field: 'hourlyCost', id: 'member_cost' },
587
+ { field: 'dateFrom', id: 'member_from' },
588
+ { field: 'dateTo', id: 'member_to' },
589
+ { field: 'overallocated', id: 'member_over' },
590
+ ]),
591
+ k.lines('phases', [
592
+ { field: 'sequence', id: 'phase_sequence' },
593
+ { field: 'name', id: 'phase_name' },
594
+ { field: 'manager', id: 'phase_manager' },
595
+ { field: 'dateStart', id: 'phase_start' },
596
+ { field: 'dateEnd', id: 'phase_end' },
597
+ { field: 'status', id: 'phase_status' },
598
+ { field: 'progress', id: 'phase_progress', widget: 'progress' },
599
+ ]),
600
+ k.lines('workPackages', [
601
+ { field: 'name', id: 'wp_name' },
602
+ { field: 'phase', id: 'wp_phase' },
603
+ { field: 'manager', id: 'wp_manager' },
604
+ { field: 'dateEnd', id: 'wp_end' },
605
+ { field: 'status', id: 'wp_status' },
606
+ { field: 'progress', id: 'wp_progress', widget: 'progress' },
247
607
  ]),
248
- k.group('main', ['name', 'partner', 'manager', 'sequence']),
249
- k.group('dates', ['dateStart', 'dateEnd', 'taskCount', 'hours']),
250
- k.group('about', ['description'], { columns: 1 }),
251
608
  k.lines('tasks', [
252
609
  { field: 'name', id: 'task_name' },
610
+ { field: 'phase', id: 'task_phase' },
253
611
  'stage',
254
612
  'assignee',
255
613
  'deadline',
256
614
  'plannedHours',
257
615
  'effectiveHours',
616
+ { field: 'progress', id: 'task_progress', widget: 'progress' },
258
617
  ]),
259
618
  ],
260
619
  chatter: true,
@@ -269,7 +628,9 @@ export const project = defineModule({
269
628
  footer: [
270
629
  { field: 'deadline', widget: 'daysLeft' },
271
630
  { field: 'priority', widget: 'priority' },
631
+ { field: 'tags', widget: 'tags' },
272
632
  ],
633
+ progress: 'progress',
273
634
  },
274
635
  }),
275
636
  // Projects on a timeline, from their start to their deadline.
@@ -283,8 +644,11 @@ export const project = defineModule({
283
644
  columns: [
284
645
  'name',
285
646
  'project',
647
+ 'phase',
648
+ 'workPackage',
286
649
  'stage',
287
650
  'assignee',
651
+ { field: 'progress', widget: 'progress' },
288
652
  { field: 'deadline', widget: 'daysLeft' },
289
653
  { field: 'priority', widget: 'priority' },
290
654
  { field: 'plannedHours', sum: true },
@@ -295,9 +659,34 @@ export const project = defineModule({
295
659
  'project.task.form': form(ProjectTask, (k) => ({
296
660
  header: { buttons: [] },
297
661
  sheet: [
298
- k.group('main', ['name', 'project', 'stage', 'assignee']),
299
- k.group('when', ['partner', 'priority', 'deadline', 'plannedHours', 'effectiveHours']),
662
+ k.group('main', ['name', 'project', 'phase', 'workPackage', 'parentTask', 'stage']),
663
+ k.group('people', ['assignee', 'assignees', 'category', 'tags', 'milestone', 'blocked']),
664
+ k.group('when', [
665
+ 'partner',
666
+ 'priority',
667
+ 'dateStart',
668
+ 'deadline',
669
+ 'plannedHours',
670
+ 'effectiveHours',
671
+ 'progress',
672
+ ]),
673
+ k.group('repeat', ['repeatEvery', 'repeatUnit', 'repeatUntil', 'nextTask'], {
674
+ label: 'Repeats',
675
+ description: 'Once done, the next one is made with its dates moved, until the date given.',
676
+ }),
677
+ k.group('task_baseline', ['baselineStart', 'baselineEnd'], { label: 'Baseline' }),
300
678
  k.group('about', ['description'], { columns: 1 }),
679
+ k.lines('subtasks', [
680
+ { field: 'name', id: 'sub_name' },
681
+ { field: 'assignee', id: 'sub_assignee' },
682
+ { field: 'deadline', id: 'sub_deadline' },
683
+ { field: 'plannedHours', id: 'sub_planned' },
684
+ { field: 'stage', id: 'sub_stage' },
685
+ ]),
686
+ k.lines('predecessors', [
687
+ { field: 'predecessor', id: 'dep_predecessor' },
688
+ { field: 'lag', id: 'dep_lag' },
689
+ ]),
301
690
  k.lines('timesheets', [
302
691
  'date',
303
692
  'user',
@@ -307,6 +696,14 @@ export const project = defineModule({
307
696
  ],
308
697
  chatter: true,
309
698
  })),
699
+ 'project.task.gantt': gantt(ProjectTask, {
700
+ dateStart: 'dateStart',
701
+ dateStop: 'deadline',
702
+ title: 'name',
703
+ groupBy: 'project',
704
+ progress: 'progress',
705
+ scale: 'week',
706
+ }),
310
707
  'project.task.calendar': calendar(ProjectTask, {
311
708
  dateStart: 'deadline',
312
709
  title: 'name',
@@ -331,6 +728,381 @@ export const project = defineModule({
331
728
  measures: [{ sum: 'hours' }],
332
729
  comparison: { field: 'date', mode: 'previous' },
333
730
  }),
731
+ 'project.risk.list': list(ProjectRisk, {
732
+ columns: [
733
+ 'project',
734
+ 'name',
735
+ 'category',
736
+ 'probability',
737
+ 'impact',
738
+ 'score',
739
+ { field: 'level', widget: 'badge' },
740
+ 'owner',
741
+ { field: 'dueDate', widget: 'daysLeft' },
742
+ { field: 'status', widget: 'badge' },
743
+ ],
744
+ decorations: {
745
+ danger: { level: 'critical' },
746
+ warning: { level: 'high' },
747
+ neutral: { status: 'closed' },
748
+ },
749
+ }),
750
+ 'project.risk.kanban': kanban(ProjectRisk, {
751
+ groupBy: 'level',
752
+ card: {
753
+ title: 'name',
754
+ subtitle: 'project',
755
+ avatar: 'owner',
756
+ footer: ['score', { field: 'status', widget: 'badge' }],
757
+ },
758
+ }),
759
+ 'project.risk.form': form(ProjectRisk, (k) => ({
760
+ sheet: [
761
+ k.group('main', ['name', 'project', 'category', 'owner', 'status', 'dueDate']),
762
+ k.group('assessment', ['probability', 'impact', 'score', 'level'], {
763
+ label: 'Assessment',
764
+ description: 'Probability and impact from 1 to 5; their product is the score.',
765
+ }),
766
+ k.group('response', ['description', 'mitigation', 'contingency'], {
767
+ columns: 1,
768
+ label: 'Response',
769
+ }),
770
+ ],
771
+ chatter: true,
772
+ })),
773
+ 'project.issue.list': list(ProjectIssue, {
774
+ columns: [
775
+ 'project',
776
+ 'name',
777
+ { field: 'severity', widget: 'badge' },
778
+ 'owner',
779
+ { field: 'dueDate', widget: 'daysLeft' },
780
+ { field: 'status', widget: 'badge' },
781
+ ],
782
+ decorations: { danger: { severity: 'critical' }, neutral: { status: 'closed' } },
783
+ }),
784
+ 'project.issue.kanban': kanban(ProjectIssue, {
785
+ groupBy: 'status',
786
+ card: {
787
+ title: 'name',
788
+ subtitle: 'project',
789
+ avatar: 'owner',
790
+ footer: [
791
+ { field: 'severity', widget: 'badge' },
792
+ { field: 'dueDate', widget: 'daysLeft' },
793
+ ],
794
+ },
795
+ }),
796
+ 'project.issue.form': form(ProjectIssue, (k) => ({
797
+ sheet: [
798
+ k.group('main', ['name', 'project', 'severity', 'status', 'risk']),
799
+ k.group('people', ['raisedBy', 'owner', 'dueDate']),
800
+ k.group('about', ['description', 'resolution'], { columns: 1 }),
801
+ ],
802
+ chatter: true,
803
+ })),
804
+ 'project.change.list': list(ProjectChange, {
805
+ columns: [
806
+ 'name',
807
+ 'project',
808
+ 'title',
809
+ 'requester',
810
+ 'newDateEnd',
811
+ 'newBudget',
812
+ { field: 'state', widget: 'badge' },
813
+ ],
814
+ decorations: { warning: { state: 'submitted' }, danger: { state: 'rejected' } },
815
+ }),
816
+ 'project.change.form': form(ProjectChange, (k) => ({
817
+ header: {
818
+ statusbar: 'state',
819
+ buttons: [
820
+ k.button('submit', { primary: true, label: 'Submit for approval' }),
821
+ k.button('redraft', { label: 'Set to draft' }),
822
+ k.button('cancel', { label: 'Cancel' }),
823
+ ],
824
+ },
825
+ sheet: [
826
+ k.group('main', ['title', 'name', 'project', 'requester', 'sponsor']),
827
+ k.component('approvals', 'approvals.Panel'),
828
+ k.group('asked', ['newDateEnd', 'newBudget'], {
829
+ label: 'What it asks for',
830
+ description: 'Once approved, the project’s deadline and baseline end move to the new deadline, and its baseline budget to the new budget.',
831
+ }),
832
+ k.group('why', ['reason', 'impact'], { columns: 1, label: 'Why' }),
833
+ k.group('before', ['previousDateEnd', 'previousBaselineEnd', 'previousBudget', 'appliedAt'], {
834
+ label: 'What it changed',
835
+ }),
836
+ ],
837
+ chatter: true,
838
+ })),
839
+ 'project.status.report.list': list(ProjectStatusReport, {
840
+ columns: [
841
+ 'project',
842
+ 'date',
843
+ 'author',
844
+ { field: 'health', widget: 'badge' },
845
+ { field: 'progress', widget: 'progress' },
846
+ { field: 'state', widget: 'badge' },
847
+ ],
848
+ decorations: { danger: { health: 'off_track' }, warning: { health: 'at_risk' } },
849
+ }),
850
+ 'project.status.report.form': form(ProjectStatusReport, (k) => ({
851
+ header: {
852
+ statusbar: 'state',
853
+ buttons: [
854
+ k.button('send', {
855
+ primary: true,
856
+ label: 'Send',
857
+ confirm: 'Send the report? It is posted on the project for its followers and its sponsor.',
858
+ }),
859
+ ],
860
+ },
861
+ sheet: [
862
+ k.group('main', ['project', 'date', 'author', 'sentAt']),
863
+ k.group('figures', ['health', 'progress'], {
864
+ label: 'Figures',
865
+ description: 'Filled in from the project when it is chosen.',
866
+ }),
867
+ k.group('report', ['done', 'next', 'risks'], { columns: 1, label: 'Report' }),
868
+ ],
869
+ })),
870
+ 'project.budget.line.list': list(ProjectBudgetLine, {
871
+ columns: [
872
+ 'project',
873
+ 'name',
874
+ 'category',
875
+ 'phase',
876
+ 'workPackage',
877
+ { field: 'planned', sum: true },
878
+ ],
879
+ }),
880
+ 'project.budget.line.form': form(ProjectBudgetLine, (k) => ({
881
+ sheet: [k.group('main', ['project', 'name', 'category', 'phase', 'workPackage', 'planned'])],
882
+ })),
883
+ 'project.role.list': list(ProjectRole, {
884
+ columns: ['sequence', 'code', 'name', 'defaultHourlyCost'],
885
+ inlineEdit: ['sequence', 'code', 'name', 'defaultHourlyCost'],
886
+ }),
887
+ 'project.role.form': form(ProjectRole, (k) => ({
888
+ sheet: [k.group('main', ['name', 'code', 'sequence', 'defaultHourlyCost'])],
889
+ })),
890
+ 'project.member.list': list(ProjectMember, {
891
+ columns: [
892
+ 'project',
893
+ 'user',
894
+ 'role',
895
+ 'allocation',
896
+ 'hourlyCost',
897
+ 'dateFrom',
898
+ 'dateTo',
899
+ 'overallocated',
900
+ ],
901
+ decorations: { danger: { overallocated: true } },
902
+ }),
903
+ 'project.member.form': form(ProjectMember, (k) => ({
904
+ sheet: [
905
+ k.group('main', ['project', 'user', 'role', 'allocation', 'overallocated']),
906
+ k.group('when', ['dateFrom', 'dateTo', 'hourlyCost']),
907
+ k.group('about', ['notes'], { columns: 1 }),
908
+ ],
909
+ })),
910
+ 'project.plan.list': list(ProjectPlan, {
911
+ columns: [
912
+ 'name',
913
+ 'title',
914
+ 'type',
915
+ 'manager',
916
+ 'sponsor',
917
+ 'dateStart',
918
+ 'dateEnd',
919
+ { field: 'estimatedBudget', sum: true },
920
+ { field: 'approvedBudget', sum: true },
921
+ { field: 'state', widget: 'badge' },
922
+ ],
923
+ decorations: {
924
+ warning: { state: 'submitted' },
925
+ danger: { state: 'rejected' },
926
+ neutral: { state: { in: ['completed', 'cancelled'] } },
927
+ },
928
+ }),
929
+ 'project.plan.kanban': kanban(ProjectPlan, {
930
+ groupBy: 'state',
931
+ card: {
932
+ title: 'title',
933
+ subtitle: 'name',
934
+ avatar: 'manager',
935
+ footer: ['estimatedBudget', { field: 'dateStart', widget: 'daysLeft' }],
936
+ },
937
+ }),
938
+ 'project.plan.form': form(ProjectPlan, (k) => ({
939
+ header: {
940
+ statusbar: 'state',
941
+ buttons: [
942
+ k.button('submit', { primary: true, label: 'Submit for approval' }),
943
+ k.button('start', {
944
+ primary: true,
945
+ label: 'Start the project',
946
+ confirm: 'Start the project? It is made from the plan, with its dates as the baseline.',
947
+ }),
948
+ k.button('baseline', {
949
+ label: 'Take the baseline again',
950
+ confirm: 'Take the baseline again? The projects’, phases’ and work packages’ current dates become the baseline.',
951
+ }),
952
+ k.button('complete', { label: 'Completed' }),
953
+ k.button('redraft', { label: 'Set to draft' }),
954
+ k.button('cancel', { label: 'Cancel' }),
955
+ ],
956
+ },
957
+ sheet: [
958
+ k.stats('related', [
959
+ {
960
+ id: 'plan_projects',
961
+ label: 'Projects',
962
+ model: ProjectProject,
963
+ where: { plan: { $record: 'id' } },
964
+ action: 'projects.action_projects',
965
+ },
966
+ ]),
967
+ k.group('main', ['title', 'name', 'type', 'priority']),
968
+ k.group('people', ['requester', 'manager', 'sponsor'], { label: 'People' }),
969
+ k.component('approvals', 'approvals.Panel'),
970
+ k.group('when', ['dateStart', 'dateEnd', 'estimatedBudget', 'approvedBudget', 'approvedAt'], {
971
+ label: 'Dates and budget',
972
+ description: 'The estimate decides who approves: the sponsor, and above 1 000 000 a Projects manager too.',
973
+ }),
974
+ k.group('case', ['objectives', 'expectedOutcome', 'strategicGoal', 'description'], {
975
+ columns: 1,
976
+ label: 'The case',
977
+ }),
978
+ ],
979
+ chatter: true,
980
+ })),
981
+ 'project.project.hierarchy': hierarchy(ProjectProject, {
982
+ parent: 'parentProject',
983
+ title: 'name',
984
+ subtitle: 'manager',
985
+ }),
986
+ 'project.phase.list': list(ProjectPhase, {
987
+ columns: [
988
+ 'project',
989
+ 'sequence',
990
+ 'name',
991
+ 'parentPhase',
992
+ 'manager',
993
+ 'dateStart',
994
+ { field: 'dateEnd', widget: 'daysLeft' },
995
+ { field: 'status', widget: 'badge' },
996
+ { field: 'progress', widget: 'progress' },
997
+ ],
998
+ decorations: {
999
+ danger: { late: true },
1000
+ neutral: { status: { in: ['done', 'cancelled'] } },
1001
+ },
1002
+ }),
1003
+ 'project.phase.form': form(ProjectPhase, (k) => ({
1004
+ sheet: [
1005
+ k.stats('related', [
1006
+ {
1007
+ id: 'phase_tasks',
1008
+ label: 'Tasks',
1009
+ model: ProjectTask,
1010
+ where: { phase: { $record: 'id' } },
1011
+ action: 'projects.action_tasks',
1012
+ },
1013
+ {
1014
+ id: 'phase_work_packages',
1015
+ label: 'Work packages',
1016
+ model: ProjectWorkPackage,
1017
+ where: { phase: { $record: 'id' } },
1018
+ action: 'projects.action_work_packages',
1019
+ },
1020
+ ]),
1021
+ k.group('main', ['name', 'code', 'project', 'parentPhase', 'sequence', 'priority']),
1022
+ k.group('people', ['manager', 'responsible', 'dateStart', 'dateEnd', 'status']),
1023
+ k.group('baseline', ['baselineStart', 'baselineEnd'], { label: 'Baseline' }),
1024
+ k.group('progress_group', ['progress', 'progressOverride'], {
1025
+ label: 'Progress',
1026
+ description: 'Computed from its tasks, weighted by their planned hours; set it by hand only when the tasks do not tell the whole story.',
1027
+ }),
1028
+ k.group('about', ['description'], { columns: 1 }),
1029
+ ],
1030
+ chatter: true,
1031
+ })),
1032
+ 'project.phase.gantt': gantt(ProjectPhase, {
1033
+ dateStart: 'dateStart',
1034
+ dateStop: 'dateEnd',
1035
+ title: 'name',
1036
+ scale: 'week',
1037
+ }),
1038
+ 'project.work.package.list': list(ProjectWorkPackage, {
1039
+ columns: [
1040
+ 'project',
1041
+ 'phase',
1042
+ 'name',
1043
+ 'manager',
1044
+ { field: 'dateEnd', widget: 'daysLeft' },
1045
+ { field: 'status', widget: 'badge' },
1046
+ { field: 'progress', widget: 'progress' },
1047
+ ],
1048
+ decorations: { neutral: { status: { in: ['done', 'cancelled'] } } },
1049
+ }),
1050
+ 'project.work.package.kanban': kanban(ProjectWorkPackage, {
1051
+ groupBy: 'status',
1052
+ card: {
1053
+ title: 'name',
1054
+ subtitle: 'project',
1055
+ avatar: 'manager',
1056
+ footer: [{ field: 'dateEnd', widget: 'daysLeft' }],
1057
+ progress: 'progress',
1058
+ },
1059
+ }),
1060
+ 'project.work.package.form': form(ProjectWorkPackage, (k) => ({
1061
+ sheet: [
1062
+ k.stats('related', [
1063
+ {
1064
+ id: 'wp_tasks',
1065
+ label: 'Tasks',
1066
+ model: ProjectTask,
1067
+ where: { workPackage: { $record: 'id' } },
1068
+ action: 'projects.action_tasks',
1069
+ },
1070
+ ]),
1071
+ k.group('main', ['name', 'code', 'project', 'phase', 'sequence']),
1072
+ k.group('people', ['manager', 'dateStart', 'dateEnd', 'status']),
1073
+ k.group('progress_group', ['progress', 'progressOverride'], { label: 'Progress' }),
1074
+ k.group('about', ['deliverables', 'description'], { columns: 1 }),
1075
+ ],
1076
+ chatter: true,
1077
+ })),
1078
+ 'project.type.list': list(ProjectType, {
1079
+ columns: ['sequence', 'code', 'name'],
1080
+ inlineEdit: ['sequence', 'code', 'name'],
1081
+ }),
1082
+ 'project.type.form': form(ProjectType, (k) => ({
1083
+ sheet: [
1084
+ k.group('main', ['name', 'code', 'sequence']),
1085
+ k.group('about', ['description'], { columns: 1 }),
1086
+ ],
1087
+ })),
1088
+ 'project.task.category.list': list(ProjectTaskCategory, {
1089
+ columns: ['sequence', 'code', 'name', 'type'],
1090
+ inlineEdit: ['sequence', 'code', 'name', 'type'],
1091
+ }),
1092
+ 'project.task.category.form': form(ProjectTaskCategory, (k) => ({
1093
+ sheet: [k.group('main', ['name', 'code', 'type', 'sequence'])],
1094
+ })),
1095
+ 'project.tag.list': list(ProjectTag, {
1096
+ columns: ['name', 'color'],
1097
+ inlineEdit: ['name', 'color'],
1098
+ }),
1099
+ 'project.tag.form': form(ProjectTag, (k) => ({ sheet: [k.group('main', ['name', 'color'])] })),
1100
+ 'project.task.link.list': list(ProjectTaskLink, {
1101
+ columns: ['successor', 'predecessor', 'lag'],
1102
+ }),
1103
+ 'project.task.link.form': form(ProjectTaskLink, (k) => ({
1104
+ sheet: [k.group('main', ['successor', 'predecessor', 'lag'])],
1105
+ })),
334
1106
  'project.task.stage.list': list(ProjectTaskStage, {
335
1107
  columns: ['sequence', 'name', 'fold', 'done'],
336
1108
  inlineEdit: ['name', 'sequence', 'fold', 'done'],
@@ -341,9 +1113,113 @@ export const project = defineModule({
341
1113
  })),
342
1114
  },
343
1115
  search: {
1116
+ 'project.task.stage': search(ProjectTaskStage, {
1117
+ fields: ['name'],
1118
+ filters: {
1119
+ closing: { label: 'Closes the task', domain: { done: true }, group: 'done' },
1120
+ folded: { label: 'Folded on the board', domain: { fold: true }, group: 'fold' },
1121
+ },
1122
+ }),
1123
+ 'project.phase': search(ProjectPhase, {
1124
+ fields: ['name', 'code', 'project.name'],
1125
+ filters: {
1126
+ open: {
1127
+ label: 'Open',
1128
+ domain: { status: { in: ['draft', 'in_progress', 'on_hold'] } },
1129
+ group: 'status',
1130
+ },
1131
+ late: {
1132
+ label: 'Late',
1133
+ domain: { late: true },
1134
+ },
1135
+ },
1136
+ groupBy: ['project', 'status', 'manager'],
1137
+ }),
1138
+ 'project.work.package': search(ProjectWorkPackage, {
1139
+ fields: ['name', 'code', 'project.name', 'phase.name'],
1140
+ filters: {
1141
+ open: {
1142
+ label: 'Open',
1143
+ domain: { status: { in: ['draft', 'in_progress', 'on_hold'] } },
1144
+ group: 'status',
1145
+ },
1146
+ },
1147
+ groupBy: ['project', 'phase', 'status', 'manager'],
1148
+ }),
1149
+ 'project.type': search(ProjectType, { fields: ['name', 'code'] }),
1150
+ 'project.task.category': search(ProjectTaskCategory, {
1151
+ fields: ['name', 'code'],
1152
+ groupBy: ['type'],
1153
+ }),
1154
+ 'project.tag': search(ProjectTag, { fields: ['name'] }),
1155
+ 'project.task.link': search(ProjectTaskLink, {
1156
+ fields: ['successor.name', 'predecessor.name'],
1157
+ }),
1158
+ 'project.risk': search(ProjectRisk, {
1159
+ fields: ['name', 'project.name'],
1160
+ filters: {
1161
+ open: {
1162
+ label: 'Open',
1163
+ domain: { status: { in: ['open', 'mitigating'] } },
1164
+ group: 'status',
1165
+ },
1166
+ severe: { label: 'High and critical', domain: { level: { in: ['high', 'critical'] } } },
1167
+ mine: { label: 'Mine', domain: { owner: { $env: 'uid' } } },
1168
+ },
1169
+ groupBy: ['project', 'level', 'category', 'status', 'owner'],
1170
+ }),
1171
+ 'project.issue': search(ProjectIssue, {
1172
+ fields: ['name', 'project.name'],
1173
+ filters: {
1174
+ open: {
1175
+ label: 'Open',
1176
+ domain: { status: { in: ['open', 'in_progress'] } },
1177
+ group: 'status',
1178
+ },
1179
+ mine: { label: 'Mine', domain: { owner: { $env: 'uid' } } },
1180
+ },
1181
+ groupBy: ['project', 'severity', 'status', 'owner'],
1182
+ }),
1183
+ 'project.change': search(ProjectChange, {
1184
+ fields: ['title', 'name', 'project.name'],
1185
+ filters: { waiting: { label: 'Waiting for approval', domain: { state: 'submitted' } } },
1186
+ groupBy: ['project', 'state'],
1187
+ }),
1188
+ 'project.status.report': search(ProjectStatusReport, {
1189
+ fields: ['name', 'project.name'],
1190
+ filters: { drafts: { label: 'Drafts', domain: { state: 'draft' } } },
1191
+ groupBy: ['project', 'health', 'author', 'date:month'],
1192
+ }),
1193
+ 'project.role': search(ProjectRole, { fields: ['name', 'code'] }),
1194
+ 'project.budget.line': search(ProjectBudgetLine, {
1195
+ fields: ['name', 'project.name'],
1196
+ groupBy: ['project', 'category', 'phase'],
1197
+ }),
1198
+ 'project.member': search(ProjectMember, {
1199
+ fields: ['user.name', 'project.name'],
1200
+ groupBy: ['project', 'user', 'role'],
1201
+ }),
1202
+ 'project.plan': search(ProjectPlan, {
1203
+ fields: ['title', 'name'],
1204
+ filters: {
1205
+ mine: {
1206
+ label: 'Mine',
1207
+ domain: { or: [{ requester: { $env: 'uid' } }, { manager: { $env: 'uid' } }] },
1208
+ },
1209
+ waiting: { label: 'Waiting for approval', domain: { state: 'submitted' }, group: 'state' },
1210
+ approved: { label: 'Approved', domain: { state: 'approved' }, group: 'state' },
1211
+ },
1212
+ groupBy: ['state', 'type', 'manager', 'sponsor'],
1213
+ }),
344
1214
  'project.project': search(ProjectProject, {
345
- fields: ['name', 'partner.name'],
346
- groupBy: ['manager', 'partner'],
1215
+ fields: ['name', 'code', 'partner.name'],
1216
+ filters: {
1217
+ atRisk: { label: 'At risk', domain: { health: 'at_risk' }, group: 'health' },
1218
+ offTrack: { label: 'Off track', domain: { health: 'off_track' }, group: 'health' },
1219
+ risky: { label: 'High risk', domain: { riskLevel: { in: ['high', 'critical'] } } },
1220
+ programmes: { label: 'Programmes', domain: { children: { any: {} } } },
1221
+ },
1222
+ groupBy: ['health', 'manager', 'partner', 'type', 'parentProject', 'riskLevel'],
347
1223
  }),
348
1224
  'project.task': search(ProjectTask, {
349
1225
  fields: ['name', 'project.name', 'partner.name'],
@@ -351,8 +1227,19 @@ export const project = defineModule({
351
1227
  open: { label: 'Open', domain: { done: false }, group: 'state' },
352
1228
  done: { label: 'Done', domain: { done: true }, group: 'state' },
353
1229
  high: { label: 'High priority', domain: { priority: 'high' } },
1230
+ blocked: { label: 'Waiting for another task', domain: { blocked: true } },
1231
+ milestones: { label: 'Milestones', domain: { milestone: true } },
1232
+ top: { label: 'Not sub-tasks', domain: { parentTask: { isNull: true } } },
354
1233
  },
355
- groupBy: ['project', 'stage', 'assignee', 'deadline:week'],
1234
+ groupBy: [
1235
+ 'project',
1236
+ 'phase',
1237
+ 'workPackage',
1238
+ 'stage',
1239
+ 'assignee',
1240
+ 'category',
1241
+ 'deadline:week',
1242
+ ],
356
1243
  }),
357
1244
  'project.timesheet': search(ProjectTimesheet, {
358
1245
  fields: ['description', 'task.name', 'project.name'],