shutro-erp 0.3.4 → 0.3.5
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.
- package/dist/account_portal/.kosh/bindings.js +1 -1
- package/dist/account_portal/.kosh/schema.d.ts +54 -3
- package/dist/account_portal/module.d.ts +359 -6
- package/dist/accounting/.kosh/bindings.js +1 -1
- package/dist/accounting/.kosh/schema.d.ts +54 -3
- package/dist/accounting/index.js +214 -2
- package/dist/accounting/module.d.ts +217 -5
- package/dist/accounting/module.js +23 -2
- package/dist/calendar/.kosh/bindings.d.ts +22 -0
- package/dist/calendar/.kosh/bindings.js +15 -0
- package/dist/calendar/.kosh/schema.d.ts +795 -0
- package/dist/calendar/demo.d.ts +6 -0
- package/dist/calendar/demo.js +24 -0
- package/dist/calendar/index.d.ts +3 -0
- package/dist/calendar/index.js +291 -0
- package/dist/calendar/module.d.ts +1705 -0
- package/dist/calendar/module.js +180 -0
- package/dist/cli/init.js +48 -0
- package/dist/cli/templates.d.ts +1 -1
- package/dist/cli/templates.js +137 -0
- package/dist/contacts/.kosh/bindings.js +1 -1
- package/dist/contacts/.kosh/schema.d.ts +78 -3
- package/dist/contacts/demo.js +30 -1
- package/dist/contacts/index.d.ts +1 -1
- package/dist/contacts/index.js +155 -9
- package/dist/contacts/module.d.ts +338 -2
- package/dist/contacts/module.js +82 -5
- package/dist/crm/.kosh/bindings.d.ts +22 -0
- package/dist/crm/.kosh/bindings.js +15 -0
- package/dist/crm/.kosh/schema.d.ts +799 -0
- package/dist/crm/demo.d.ts +6 -0
- package/dist/crm/demo.js +45 -0
- package/dist/crm/index.d.ts +3 -0
- package/dist/crm/index.js +361 -0
- package/dist/crm/module.d.ts +1843 -0
- package/dist/crm/module.js +207 -0
- package/dist/event/.kosh/bindings.d.ts +22 -0
- package/dist/event/.kosh/bindings.js +15 -0
- package/dist/event/.kosh/schema.d.ts +843 -0
- package/dist/event/demo.d.ts +6 -0
- package/dist/event/demo.js +65 -0
- package/dist/event/index.d.ts +14 -0
- package/dist/event/index.js +333 -0
- package/dist/event/mails.d.ts +15 -0
- package/dist/event/mails.js +112 -0
- package/dist/event/module.d.ts +2800 -0
- package/dist/event/module.js +323 -0
- package/dist/event/web/CheckInBox.d.ts +9 -0
- package/dist/event/web/CheckInBox.js +87 -0
- package/dist/event/web/index.d.ts +11 -0
- package/dist/event/web/index.js +16 -0
- package/dist/event/web/messages.d.ts +2 -0
- package/dist/event/web/messages.js +23 -0
- package/dist/event_account/.kosh/bindings.d.ts +22 -0
- package/dist/event_account/.kosh/bindings.js +15 -0
- package/dist/event_account/.kosh/schema.d.ts +1639 -0
- package/dist/event_account/index.d.ts +3 -0
- package/dist/event_account/index.js +28 -0
- package/dist/event_account/module.d.ts +6968 -0
- package/dist/event_account/module.js +90 -0
- package/dist/hr/.kosh/bindings.d.ts +22 -0
- package/dist/hr/.kosh/bindings.js +15 -0
- package/dist/hr/.kosh/schema.d.ts +878 -0
- package/dist/hr/demo.d.ts +6 -0
- package/dist/hr/demo.js +60 -0
- package/dist/hr/index.d.ts +3 -0
- package/dist/hr/index.js +483 -0
- package/dist/hr/module.d.ts +2611 -0
- package/dist/hr/module.js +350 -0
- package/dist/l10n_bd/.kosh/bindings.js +1 -1
- package/dist/l10n_bd/.kosh/schema.d.ts +54 -3
- package/dist/l10n_bd/module.d.ts +359 -6
- package/dist/l10n_in/.kosh/bindings.js +1 -1
- package/dist/l10n_in/.kosh/schema.d.ts +54 -3
- package/dist/l10n_in/module.d.ts +380 -7
- package/dist/maintenance/.kosh/bindings.d.ts +22 -0
- package/dist/maintenance/.kosh/bindings.js +15 -0
- package/dist/maintenance/.kosh/schema.d.ts +911 -0
- package/dist/maintenance/demo.d.ts +6 -0
- package/dist/maintenance/demo.js +60 -0
- package/dist/maintenance/index.d.ts +3 -0
- package/dist/maintenance/index.js +422 -0
- package/dist/maintenance/module.d.ts +3545 -0
- package/dist/maintenance/module.js +446 -0
- package/dist/maintenance_stock/.kosh/bindings.d.ts +22 -0
- package/dist/maintenance_stock/.kosh/bindings.js +15 -0
- package/dist/maintenance_stock/.kosh/schema.d.ts +1371 -0
- package/dist/maintenance_stock/index.d.ts +9 -0
- package/dist/maintenance_stock/index.js +52 -0
- package/dist/maintenance_stock/module.d.ts +6953 -0
- package/dist/maintenance_stock/module.js +192 -0
- package/dist/modules-sdk/index.d.ts +1 -1
- package/dist/modules-sdk/manifest.d.ts +70 -0
- package/dist/modules-sdk/manifest.js +35 -1
- package/dist/mrp/.kosh/bindings.d.ts +22 -0
- package/dist/mrp/.kosh/bindings.js +15 -0
- package/dist/mrp/.kosh/schema.d.ts +1378 -0
- package/dist/mrp/demo.d.ts +7 -0
- package/dist/mrp/demo.js +42 -0
- package/dist/mrp/index.d.ts +3 -0
- package/dist/mrp/index.js +392 -0
- package/dist/mrp/module.d.ts +8608 -0
- package/dist/mrp/module.js +695 -0
- package/dist/mrp_account/.kosh/bindings.d.ts +22 -0
- package/dist/mrp_account/.kosh/bindings.js +15 -0
- package/dist/mrp_account/.kosh/schema.d.ts +2106 -0
- package/dist/mrp_account/index.d.ts +3 -0
- package/dist/mrp_account/index.js +22 -0
- package/dist/mrp_account/module.d.ts +20840 -0
- package/dist/mrp_account/module.js +123 -0
- package/dist/payment/.kosh/bindings.js +1 -1
- package/dist/payment/.kosh/schema.d.ts +54 -3
- package/dist/payment/module.d.ts +359 -6
- package/dist/portal/.kosh/bindings.js +1 -1
- package/dist/portal/.kosh/schema.d.ts +78 -3
- package/dist/portal/module.d.ts +166 -2
- package/dist/pos/.kosh/bindings.d.ts +22 -0
- package/dist/pos/.kosh/bindings.js +15 -0
- package/dist/pos/.kosh/schema.d.ts +1690 -0
- package/dist/pos/accounting.d.ts +10 -0
- package/dist/pos/accounting.js +149 -0
- package/dist/pos/demo.d.ts +6 -0
- package/dist/pos/demo.js +90 -0
- package/dist/pos/index.d.ts +9 -0
- package/dist/pos/index.js +349 -0
- package/dist/pos/module.d.ts +9636 -0
- package/dist/pos/module.js +423 -0
- package/dist/pos/routes.d.ts +39 -0
- package/dist/pos/routes.js +368 -0
- package/dist/pos/web/Register.d.ts +9 -0
- package/dist/pos/web/Register.js +252 -0
- package/dist/pos/web/index.d.ts +11 -0
- package/dist/pos/web/index.js +16 -0
- package/dist/pos/web/messages.d.ts +2 -0
- package/dist/pos/web/messages.js +87 -0
- package/dist/pos_stock/.kosh/bindings.d.ts +22 -0
- package/dist/pos_stock/.kosh/bindings.js +15 -0
- package/dist/pos_stock/.kosh/schema.d.ts +2015 -0
- package/dist/pos_stock/index.d.ts +9 -0
- package/dist/pos_stock/index.js +35 -0
- package/dist/pos_stock/module.d.ts +11935 -0
- package/dist/pos_stock/module.js +115 -0
- package/dist/product/.kosh/bindings.js +1 -1
- package/dist/product/.kosh/schema.d.ts +51 -1
- package/dist/product/index.js +81 -4
- package/dist/product/module.d.ts +43 -1
- package/dist/product/module.js +9 -2
- package/dist/project/.kosh/bindings.js +1 -1
- package/dist/project/.kosh/schema.d.ts +54 -3
- package/dist/project/index.js +147 -7
- package/dist/project/module.d.ts +210 -2
- package/dist/project/module.js +52 -5
- package/dist/project_portal/.kosh/bindings.js +1 -1
- package/dist/project_portal/.kosh/schema.d.ts +54 -3
- package/dist/project_portal/module.d.ts +353 -4
- package/dist/purchase/.kosh/bindings.js +1 -1
- package/dist/purchase/.kosh/schema.d.ts +54 -3
- package/dist/purchase/index.js +163 -3
- package/dist/purchase/module.d.ts +215 -3
- package/dist/purchase/module.js +21 -3
- package/dist/purchase_account/.kosh/bindings.js +1 -1
- package/dist/purchase_account/.kosh/schema.d.ts +55 -3
- package/dist/purchase_account/index.js +26 -1
- package/dist/purchase_account/module.d.ts +393 -7
- package/dist/purchase_portal/.kosh/bindings.js +1 -1
- package/dist/purchase_portal/.kosh/schema.d.ts +54 -3
- package/dist/purchase_portal/module.d.ts +366 -5
- package/dist/purchase_stock/.kosh/bindings.d.ts +22 -0
- package/dist/purchase_stock/.kosh/bindings.js +15 -0
- package/dist/purchase_stock/.kosh/schema.d.ts +1310 -0
- package/dist/purchase_stock/index.d.ts +7 -0
- package/dist/purchase_stock/index.js +91 -0
- package/dist/purchase_stock/module.d.ts +6763 -0
- package/dist/purchase_stock/module.js +144 -0
- package/dist/purchase_stock_account/.kosh/bindings.d.ts +22 -0
- package/dist/purchase_stock_account/.kosh/bindings.js +15 -0
- package/dist/purchase_stock_account/.kosh/schema.d.ts +1959 -0
- package/dist/purchase_stock_account/index.d.ts +3 -0
- package/dist/purchase_stock_account/index.js +24 -0
- package/dist/purchase_stock_account/module.d.ts +35366 -0
- package/dist/purchase_stock_account/module.js +162 -0
- package/dist/recruitment/.kosh/bindings.d.ts +22 -0
- package/dist/recruitment/.kosh/bindings.js +15 -0
- package/dist/recruitment/.kosh/schema.d.ts +990 -0
- package/dist/recruitment/demo.d.ts +6 -0
- package/dist/recruitment/demo.js +45 -0
- package/dist/recruitment/index.d.ts +3 -0
- package/dist/recruitment/index.js +385 -0
- package/dist/recruitment/module.d.ts +3247 -0
- package/dist/recruitment/module.js +193 -0
- package/dist/recruitment/web/HireButton.d.ts +9 -0
- package/dist/recruitment/web/HireButton.js +32 -0
- package/dist/recruitment/web/index.d.ts +11 -0
- package/dist/recruitment/web/index.js +16 -0
- package/dist/recruitment/web/messages.d.ts +2 -0
- package/dist/recruitment/web/messages.js +19 -0
- package/dist/reporting/documents.d.ts +5 -0
- package/dist/reporting/documents.js +28 -1
- package/dist/reporting/index.d.ts +1 -1
- package/dist/reporting/index.js +4 -2
- package/dist/reporting/models.js +9 -0
- package/dist/reporting/overviews.d.ts +16 -0
- package/dist/reporting/overviews.js +56 -0
- package/dist/reporting/routes-documents.js +1 -1
- package/dist/reporting/routes.js +138 -80
- package/dist/reporting/web/DashboardView.d.ts +11 -0
- package/dist/reporting/web/DashboardView.js +2 -2
- package/dist/reporting/web/DesignerView.js +5 -0
- package/dist/reporting/web/Overview.d.ts +9 -0
- package/dist/reporting/web/Overview.js +53 -0
- package/dist/reporting/web/index.d.ts +1 -0
- package/dist/reporting/web/index.js +4 -1
- package/dist/reporting/web/messages.js +9 -0
- package/dist/sale_account/.kosh/bindings.js +1 -1
- package/dist/sale_account/.kosh/schema.d.ts +59 -3
- package/dist/sale_account/index.js +22 -1
- package/dist/sale_account/module.d.ts +461 -7
- package/dist/sale_portal/.kosh/bindings.js +1 -1
- package/dist/sale_portal/.kosh/schema.d.ts +58 -3
- package/dist/sale_portal/module.d.ts +434 -5
- package/dist/sale_project/.kosh/bindings.js +1 -1
- package/dist/sale_project/.kosh/schema.d.ts +60 -3
- package/dist/sale_project/module.d.ts +476 -6
- package/dist/sale_stock/.kosh/bindings.d.ts +22 -0
- package/dist/sale_stock/.kosh/bindings.js +15 -0
- package/dist/sale_stock/.kosh/schema.d.ts +1228 -0
- package/dist/sale_stock/index.d.ts +7 -0
- package/dist/sale_stock/index.js +84 -0
- package/dist/sale_stock/module.d.ts +6791 -0
- package/dist/sale_stock/module.js +146 -0
- package/dist/sales/.kosh/bindings.js +1 -1
- package/dist/sales/.kosh/schema.d.ts +58 -3
- package/dist/sales/index.js +191 -4
- package/dist/sales/module.d.ts +355 -3
- package/dist/sales/module.js +78 -3
- package/dist/server/api/metadata.d.ts +5 -0
- package/dist/server/api/metadata.js +5 -0
- package/dist/server/api/rest.js +64 -1
- package/dist/server/api/views.js +1 -0
- package/dist/server/app-settings.d.ts +7 -0
- package/dist/server/app-settings.js +10 -0
- package/dist/server/auth/base.js +9 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +1 -0
- package/dist/settings/app-settings.d.ts +2 -0
- package/dist/settings/app-settings.js +518 -0
- package/dist/settings/index.d.ts +1 -0
- package/dist/settings/index.js +15 -0
- package/dist/settings/people.js +29 -5
- package/dist/settings/web/AppSettingsPage.d.ts +11 -0
- package/dist/settings/web/AppSettingsPage.js +210 -0
- package/dist/settings/web/OverviewPage.js +16 -3
- package/dist/settings/web/PeoplePage.js +20 -6
- package/dist/settings/web/index.d.ts +1 -0
- package/dist/settings/web/index.js +3 -0
- package/dist/settings/web/messages.js +118 -2
- package/dist/stock/.kosh/bindings.d.ts +22 -0
- package/dist/stock/.kosh/bindings.js +15 -0
- package/dist/stock/.kosh/schema.d.ts +1147 -0
- package/dist/stock/demo.d.ts +7 -0
- package/dist/stock/demo.js +55 -0
- package/dist/stock/index.d.ts +3 -0
- package/dist/stock/index.js +674 -0
- package/dist/stock/module.d.ts +6330 -0
- package/dist/stock/module.js +1325 -0
- package/dist/stock/web/ScanBox.d.ts +8 -0
- package/dist/stock/web/ScanBox.js +90 -0
- package/dist/stock/web/index.d.ts +11 -0
- package/dist/stock/web/index.js +16 -0
- package/dist/stock/web/messages.d.ts +2 -0
- package/dist/stock/web/messages.js +25 -0
- package/dist/stock_account/.kosh/bindings.d.ts +22 -0
- package/dist/stock_account/.kosh/bindings.js +15 -0
- package/dist/stock_account/.kosh/schema.d.ts +1875 -0
- package/dist/stock_account/index.d.ts +3 -0
- package/dist/stock_account/index.js +130 -0
- package/dist/stock_account/module.d.ts +10655 -0
- package/dist/stock_account/module.js +339 -0
- package/dist/storage/attachments.d.ts +5 -0
- package/dist/storage/attachments.js +12 -1
- package/dist/storage/models.js +3 -0
- package/dist/storage/routes.js +13 -2
- package/dist/todo/.kosh/bindings.d.ts +22 -0
- package/dist/todo/.kosh/bindings.js +15 -0
- package/dist/todo/.kosh/schema.d.ts +732 -0
- package/dist/todo/demo.d.ts +6 -0
- package/dist/todo/demo.js +35 -0
- package/dist/todo/index.d.ts +3 -0
- package/dist/todo/index.js +187 -0
- package/dist/todo/module.d.ts +1180 -0
- package/dist/todo/module.js +130 -0
- package/dist/trade_finance/.kosh/bindings.d.ts +22 -0
- package/dist/trade_finance/.kosh/bindings.js +15 -0
- package/dist/trade_finance/.kosh/schema.d.ts +884 -0
- package/dist/trade_finance/demo.d.ts +6 -0
- package/dist/trade_finance/demo.js +63 -0
- package/dist/trade_finance/index.d.ts +3 -0
- package/dist/trade_finance/index.js +413 -0
- package/dist/trade_finance/module.d.ts +3779 -0
- package/dist/trade_finance/module.js +505 -0
- package/dist/trade_finance_account/.kosh/bindings.d.ts +22 -0
- package/dist/trade_finance_account/.kosh/bindings.js +15 -0
- package/dist/trade_finance_account/.kosh/schema.d.ts +1711 -0
- package/dist/trade_finance_account/index.d.ts +3 -0
- package/dist/trade_finance_account/index.js +92 -0
- package/dist/trade_finance_account/module.d.ts +7928 -0
- package/dist/trade_finance_account/module.js +244 -0
- package/dist/trade_finance_purchase/.kosh/bindings.d.ts +22 -0
- package/dist/trade_finance_purchase/.kosh/bindings.js +15 -0
- package/dist/trade_finance_purchase/.kosh/schema.d.ts +1153 -0
- package/dist/trade_finance_purchase/index.d.ts +8 -0
- package/dist/trade_finance_purchase/index.js +50 -0
- package/dist/trade_finance_purchase/module.d.ts +4252 -0
- package/dist/trade_finance_purchase/module.js +44 -0
- package/dist/trade_finance_sale/.kosh/bindings.d.ts +22 -0
- package/dist/trade_finance_sale/.kosh/bindings.js +15 -0
- package/dist/trade_finance_sale/.kosh/schema.d.ts +1071 -0
- package/dist/trade_finance_sale/index.d.ts +8 -0
- package/dist/trade_finance_sale/index.js +50 -0
- package/dist/trade_finance_sale/module.d.ts +4280 -0
- package/dist/trade_finance_sale/module.js +44 -0
- package/dist/ui/api.d.ts +2 -1
- package/dist/ui/api.js +2 -1
- package/dist/ui/app.js +2 -1
- package/dist/ui/components/AppIcon.js +23 -1
- package/dist/ui/components/primitives.d.ts +2 -0
- package/dist/ui/components/primitives.js +7 -1
- package/dist/ui/i18n/messages.d.ts +23 -0
- package/dist/ui/i18n/messages.js +38 -0
- package/dist/ui/index.d.ts +1 -0
- package/dist/ui/index.js +1 -0
- package/dist/ui/offline/queue.d.ts +5 -1
- package/dist/ui/offline/queue.js +2 -0
- package/dist/ui/registry.d.ts +5 -0
- package/dist/ui/shell/Home.js +55 -4
- package/dist/ui/views/FormView.js +98 -17
- package/dist/ui/views/KanbanView.d.ts +2 -0
- package/dist/ui/views/KanbanView.js +32 -3
- package/dist/ui/views/ListView.js +108 -11
- package/dist/ui/views/StatsRow.d.ts +14 -0
- package/dist/ui/views/StatsRow.js +88 -0
- package/dist/ui/views/widgets.d.ts +2 -1
- package/dist/ui/views/widgets.js +194 -1
- package/dist/views/builders.d.ts +19 -2
- package/dist/views/builders.js +21 -1
- package/dist/views/condition.d.ts +6 -0
- package/dist/views/condition.js +20 -0
- package/dist/views/documents.d.ts +8 -0
- package/dist/views/extend.d.ts +2 -2
- package/dist/views/extend.js +11 -1
- package/dist/views/index.d.ts +2 -2
- package/dist/views/index.js +2 -2
- package/dist/views/types.d.ts +52 -5
- package/dist/views/validate.js +39 -1
- package/dist/website/.kosh/bindings.d.ts +22 -0
- package/dist/website/.kosh/bindings.js +15 -0
- package/dist/website/.kosh/schema.d.ts +881 -0
- package/dist/website/demo.d.ts +6 -0
- package/dist/website/demo.js +115 -0
- package/dist/website/index.d.ts +9 -0
- package/dist/website/index.js +250 -0
- package/dist/website/module.d.ts +2987 -0
- package/dist/website/module.js +281 -0
- package/dist/website/render.d.ts +45 -0
- package/dist/website/render.js +102 -0
- package/dist/website/routes.d.ts +12 -0
- package/dist/website/routes.js +246 -0
- package/dist/website/web/PagePreview.d.ts +7 -0
- package/dist/website/web/PagePreview.js +33 -0
- package/dist/website/web/index.d.ts +11 -0
- package/dist/website/web/index.js +16 -0
- package/dist/website/web/messages.d.ts +2 -0
- package/dist/website/web/messages.js +15 -0
- package/dist/website_crm/.kosh/bindings.d.ts +22 -0
- package/dist/website_crm/.kosh/bindings.js +15 -0
- package/dist/website_crm/.kosh/schema.d.ts +966 -0
- package/dist/website_crm/index.d.ts +3 -0
- package/dist/website_crm/index.js +39 -0
- package/dist/website_crm/module.d.ts +2955 -0
- package/dist/website_crm/module.js +44 -0
- package/package.json +118 -1
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The data layer of the Sales ↔ Stockroom bridge (RFC 0021): a confirmed sales order gets its delivery — one
|
|
3
|
+
* Stockroom transfer with a line per goods line, in the line's unit, from the company's main warehouse to the
|
|
4
|
+
* customers — made once through the outbox (`sale.order.confirmed`) and confirmed, so its stock is reserved. The
|
|
5
|
+
* order shows its deliveries and what is delivered; each line, its delivered quantity.
|
|
6
|
+
*/
|
|
7
|
+
import { productShutro } from '../product/index.js';
|
|
8
|
+
import { salesShutro } from '../sales/index.js';
|
|
9
|
+
import { orm } from '../server/orm.js';
|
|
10
|
+
import { defaultLocations, stockShutro } from '../stock/index.js';
|
|
11
|
+
import { compute, defineModule, extendModel, f } from './.kosh/bindings.js';
|
|
12
|
+
const zero = orm.toDecimal(0);
|
|
13
|
+
export const PickingSale = extendModel('stock.picking', {
|
|
14
|
+
fields: { saleOrder: f.many2one('sale.order', { ondelete: 'set null', label: 'Sales order' }) },
|
|
15
|
+
overrides: {
|
|
16
|
+
// A backorder stays with its order.
|
|
17
|
+
backorderValues: async function (next) {
|
|
18
|
+
const out = await next();
|
|
19
|
+
for (const p of await this.load({}))
|
|
20
|
+
out.set(p.id, { ...out.get(p.id), saleOrder: p.saleOrder?.id ?? null });
|
|
21
|
+
return out;
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
export const MoveSale = extendModel('stock.move', {
|
|
26
|
+
fields: {
|
|
27
|
+
saleLine: f.many2one('sale.order.line', { ondelete: 'set null', label: 'Order line' }),
|
|
28
|
+
},
|
|
29
|
+
overrides: {
|
|
30
|
+
// The rest of a line stays tied to its order line.
|
|
31
|
+
backorderValues: async function (next) {
|
|
32
|
+
const out = await next();
|
|
33
|
+
for (const m of await this.load({}))
|
|
34
|
+
out.set(m.id, { ...out.get(m.id), saleLine: m.saleLine?.id ?? null });
|
|
35
|
+
return out;
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
export const LineDelivered = extendModel('sale.order.line', {
|
|
40
|
+
fields: {
|
|
41
|
+
moves: f.one2many('stock.move', 'saleLine'),
|
|
42
|
+
/** Delivered by validated deliveries, in the line's unit. */
|
|
43
|
+
qtyDelivered: f.decimal({
|
|
44
|
+
scale: 3,
|
|
45
|
+
store: true,
|
|
46
|
+
label: 'Delivered',
|
|
47
|
+
...compute('sale.order.line', 'qtyDelivered', ['moves.quantity', 'moves.quantityDone', 'moves.picking.state'], (lines) => {
|
|
48
|
+
for (const l of lines)
|
|
49
|
+
l.qtyDelivered = [...l.moves]
|
|
50
|
+
.filter((m) => m.picking.state === 'done')
|
|
51
|
+
.reduce((s, m) => s.plus(m.quantityDone ?? m.quantity), zero);
|
|
52
|
+
}),
|
|
53
|
+
}),
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
export const OrderDeliveries = extendModel('sale.order', {
|
|
57
|
+
fields: {
|
|
58
|
+
deliveries: f.one2many('stock.picking', 'saleOrder'),
|
|
59
|
+
deliveryState: f.selection({
|
|
60
|
+
nothing: 'Nothing to deliver',
|
|
61
|
+
to_deliver: 'To deliver',
|
|
62
|
+
partial: 'Partly delivered',
|
|
63
|
+
delivered: 'Delivered',
|
|
64
|
+
}, {
|
|
65
|
+
store: true,
|
|
66
|
+
label: 'Delivery',
|
|
67
|
+
...compute('sale.order', 'deliveryState', ['state', 'lines.quantity', 'lines.qtyDelivered', 'lines.product.kind'], (orders) => {
|
|
68
|
+
for (const o of orders) {
|
|
69
|
+
const goods = [...o.lines].filter((l) => l.product.kind === 'goods');
|
|
70
|
+
if (goods.length === 0 || (o.state !== 'sale' && o.state !== 'done')) {
|
|
71
|
+
o.deliveryState = 'nothing';
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const done = goods.every((l) => (l.qtyDelivered ?? zero).gte(l.quantity));
|
|
75
|
+
const some = goods.some((l) => (l.qtyDelivered ?? zero).gt(0));
|
|
76
|
+
o.deliveryState = done ? 'delivered' : some ? 'partial' : 'to_deliver';
|
|
77
|
+
}
|
|
78
|
+
}),
|
|
79
|
+
}),
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
/**
|
|
83
|
+
* Makes and confirms the delivery of a confirmed order's goods lines, once (an order with a delivery that is not
|
|
84
|
+
* cancelled gets no other). Runs in an audited superuser scope: the salesperson who confirmed needs no Stockroom
|
|
85
|
+
* rights for the warehouse to get its delivery. Returns the delivery, or null when there is nothing to deliver.
|
|
86
|
+
*/
|
|
87
|
+
export async function createDeliveryFor(env, orderId) {
|
|
88
|
+
return env.asSuperuser({ reason: 'delivery for a confirmed sales order' }, async (su) => {
|
|
89
|
+
const [order] = await su
|
|
90
|
+
.model('sale.order')
|
|
91
|
+
.browse([orm.asId(orderId, 'sale.order')])
|
|
92
|
+
.load({
|
|
93
|
+
lines: { product: true, uom: true },
|
|
94
|
+
partner: true,
|
|
95
|
+
company: true,
|
|
96
|
+
deliveries: true,
|
|
97
|
+
});
|
|
98
|
+
if (order === undefined || (order.state !== 'sale' && order.state !== 'done'))
|
|
99
|
+
return null;
|
|
100
|
+
if ([...order.deliveries].some((d) => d.state !== 'cancel'))
|
|
101
|
+
return null;
|
|
102
|
+
const goods = order.lines.filter((l) => l.product.kind === 'goods');
|
|
103
|
+
if (goods.length === 0)
|
|
104
|
+
return null;
|
|
105
|
+
const places = await defaultLocations(su, 'delivery', null, order.company.id);
|
|
106
|
+
if (places.source === null || places.destination === null)
|
|
107
|
+
throw new orm.ValidationError('sale.order', ['state'], `The company of ${order.name} has no warehouse to deliver from.`, 'Add a warehouse in Stockroom › Configuration › Warehouses.');
|
|
108
|
+
const made = await su.model('stock.picking').create([
|
|
109
|
+
{
|
|
110
|
+
kind: 'delivery',
|
|
111
|
+
partner: order.partner.id,
|
|
112
|
+
company: order.company.id,
|
|
113
|
+
warehouse: places.warehouse,
|
|
114
|
+
source: places.source,
|
|
115
|
+
destination: places.destination,
|
|
116
|
+
origin: order.name,
|
|
117
|
+
saleOrder: order.id,
|
|
118
|
+
moves: {
|
|
119
|
+
create: goods.map((l) => ({
|
|
120
|
+
product: l.product.id,
|
|
121
|
+
name: l.name,
|
|
122
|
+
quantity: l.quantity,
|
|
123
|
+
uom: l.uom?.id ?? null,
|
|
124
|
+
saleLine: l.id,
|
|
125
|
+
})),
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
]);
|
|
129
|
+
await made.confirm();
|
|
130
|
+
return made.ids[0] ?? null;
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
export const saleStockShutro = defineModule({
|
|
134
|
+
name: 'sale_stock',
|
|
135
|
+
version: '0.1.0',
|
|
136
|
+
depends: [salesShutro, stockShutro, productShutro],
|
|
137
|
+
groups: [
|
|
138
|
+
orm.defineGroup({
|
|
139
|
+
code: 'sale_stock.user',
|
|
140
|
+
label: 'Sales with deliveries',
|
|
141
|
+
implies: ['sales.user', 'stock.user'],
|
|
142
|
+
}),
|
|
143
|
+
],
|
|
144
|
+
models: [],
|
|
145
|
+
extensions: [PickingSale, MoveSale, LineDelivered, OrderDeliveries],
|
|
146
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash:
|
|
1
|
+
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash: 7a0589ddfebd3ce9
|
|
2
2
|
// Bindings of module `sales`: import the definition API from here to get types scoped to what it can see.
|
|
3
3
|
export { defineModel, defineModule, extendModel, f, replace } from '../../server/orm.js';
|
|
4
4
|
import { definitions } from '../../server/orm.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash:
|
|
1
|
+
// GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash: 7a0589ddfebd3ce9
|
|
2
2
|
// Schema view of module `sales` (RFC 0002 §7.7): the models it owns or depends on, with the extensions it can see.
|
|
3
3
|
import type { F } from '../../server/orm.js';
|
|
4
4
|
|
|
@@ -14,6 +14,7 @@ export interface SchemaView {
|
|
|
14
14
|
readonly 'auth.user_group': AuthUserGroup;
|
|
15
15
|
readonly 'kosh.image': KoshImage;
|
|
16
16
|
readonly 'kosh.saved_view': KoshSavedView;
|
|
17
|
+
readonly 'kosh.setting': KoshSetting;
|
|
17
18
|
readonly 'mail.activity': MailActivity;
|
|
18
19
|
readonly 'mail.activity.type': MailActivityType;
|
|
19
20
|
readonly 'mail.channel': MailChannel;
|
|
@@ -30,6 +31,7 @@ export interface SchemaView {
|
|
|
30
31
|
readonly 'res.company': ResCompany;
|
|
31
32
|
readonly 'res.currency': ResCurrency;
|
|
32
33
|
readonly 'res.partner': ResPartner;
|
|
34
|
+
readonly 'res.partner.tag': ResPartnerTag;
|
|
33
35
|
readonly 'res.users': ResUsers;
|
|
34
36
|
readonly 'sale.order': SaleOrder;
|
|
35
37
|
readonly 'sale.order.line': SaleOrderLine;
|
|
@@ -281,6 +283,26 @@ export interface KoshSavedView {
|
|
|
281
283
|
export interface KoshSavedViewMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'kosh.saved_view'> {
|
|
282
284
|
}
|
|
283
285
|
|
|
286
|
+
/** `kosh.setting` (owner: base). */
|
|
287
|
+
export interface KoshSetting {
|
|
288
|
+
readonly name: 'kosh.setting';
|
|
289
|
+
readonly fields: {
|
|
290
|
+
readonly id: F.Id<'kosh.setting'>;
|
|
291
|
+
readonly createdAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
|
|
292
|
+
readonly updatedAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
|
|
293
|
+
readonly createdBy: F.Many2one<'res.users', { readonly readonly: true }>;
|
|
294
|
+
readonly updatedBy: F.Many2one<'res.users', { readonly readonly: true }>;
|
|
295
|
+
readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
|
|
296
|
+
readonly key: F.Char<{ readonly required: true }>;
|
|
297
|
+
readonly value: F.Json;
|
|
298
|
+
};
|
|
299
|
+
readonly methods: KoshSettingMethods;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/** Methods of `kosh.setting`: declared ones and transitions. */
|
|
303
|
+
export interface KoshSettingMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'kosh.setting'> {
|
|
304
|
+
}
|
|
305
|
+
|
|
284
306
|
/** `mail.activity` (owner: messaging). */
|
|
285
307
|
export interface MailActivity {
|
|
286
308
|
readonly name: 'mail.activity';
|
|
@@ -595,6 +617,7 @@ export interface ProductProduct {
|
|
|
595
617
|
readonly category: F.Many2one<'product.category'>;
|
|
596
618
|
readonly uom: F.Many2one<'uom.uom'>;
|
|
597
619
|
readonly barcode: F.Char;
|
|
620
|
+
readonly image: F.Many2one<'storage.attachment'>;
|
|
598
621
|
readonly listPrice: F.Decimal<{ readonly required: true; readonly default: true }>;
|
|
599
622
|
readonly standardPrice: F.Decimal<{ readonly required: true; readonly default: true }>;
|
|
600
623
|
readonly saleOk: F.Bool<{ readonly required: true; readonly default: true }>;
|
|
@@ -612,7 +635,7 @@ export interface ProductProduct {
|
|
|
612
635
|
export interface ProductProductMethods extends F.Methods<typeof import('../../product/index.js').productShutro, 'product.product'> {
|
|
613
636
|
}
|
|
614
637
|
|
|
615
|
-
/** `res.company` (owner: base). */
|
|
638
|
+
/** `res.company` (owner: base; extended by: contacts, sales). */
|
|
616
639
|
export interface ResCompany {
|
|
617
640
|
readonly name: 'res.company';
|
|
618
641
|
readonly fields: {
|
|
@@ -632,12 +655,16 @@ export interface ResCompany {
|
|
|
632
655
|
readonly email: F.Char;
|
|
633
656
|
readonly phone: F.Char;
|
|
634
657
|
readonly website: F.Char;
|
|
658
|
+
readonly contactTaxIdRequired: F.Bool<{ readonly required: true; readonly default: true }>; // contacts
|
|
659
|
+
readonly contactUniqueEmail: F.Bool<{ readonly required: true; readonly default: true }>; // contacts
|
|
660
|
+
readonly saleValidityDays: F.Integer<{ readonly default: true }>; // sales
|
|
661
|
+
readonly saleTerms: F.Text; // sales
|
|
635
662
|
};
|
|
636
663
|
readonly methods: ResCompanyMethods;
|
|
637
664
|
}
|
|
638
665
|
|
|
639
666
|
/** Methods of `res.company`: declared ones and transitions. */
|
|
640
|
-
export interface ResCompanyMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'res.company'> {
|
|
667
|
+
export interface ResCompanyMethods extends F.Methods<typeof import('../../server/index.js').baseShutro, 'res.company'>, F.Methods<typeof import('../../contacts/index.js').contactsShutro, 'res.company'>, F.Methods<typeof import('../module.js').salesShutro, 'res.company'> {
|
|
641
668
|
}
|
|
642
669
|
|
|
643
670
|
/** `res.currency` (owner: base). */
|
|
@@ -674,6 +701,10 @@ export interface ResPartner {
|
|
|
674
701
|
readonly active: F.Bool<{ readonly required: true; readonly default: true }>;
|
|
675
702
|
readonly company: F.Many2one<'res.company', { readonly default: true }>;
|
|
676
703
|
readonly name: F.Char<{ readonly required: true }>;
|
|
704
|
+
readonly image: F.Many2one<'storage.attachment'>;
|
|
705
|
+
readonly tags: F.Many2many<'res.partner.tag', { readonly required: true }>;
|
|
706
|
+
readonly latitude: F.Decimal;
|
|
707
|
+
readonly longitude: F.Decimal;
|
|
677
708
|
readonly isCompany: F.Bool<{ readonly required: true; readonly default: true }>;
|
|
678
709
|
readonly parent: F.Many2one<'res.partner'>;
|
|
679
710
|
readonly contacts: F.One2many<'res.partner', { readonly required: true }>;
|
|
@@ -699,6 +730,25 @@ export interface ResPartner {
|
|
|
699
730
|
export interface ResPartnerMethods extends F.Methods<typeof import('../../contacts/index.js').contactsShutro, 'res.partner'> {
|
|
700
731
|
}
|
|
701
732
|
|
|
733
|
+
/** `res.partner.tag` (owner: contacts). */
|
|
734
|
+
export interface ResPartnerTag {
|
|
735
|
+
readonly name: 'res.partner.tag';
|
|
736
|
+
readonly fields: {
|
|
737
|
+
readonly id: F.Id<'res.partner.tag'>;
|
|
738
|
+
readonly createdAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
|
|
739
|
+
readonly updatedAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
|
|
740
|
+
readonly createdBy: F.Many2one<'res.users', { readonly readonly: true }>;
|
|
741
|
+
readonly updatedBy: F.Many2one<'res.users', { readonly readonly: true }>;
|
|
742
|
+
readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
|
|
743
|
+
readonly name: F.Char<{ readonly required: true }>;
|
|
744
|
+
};
|
|
745
|
+
readonly methods: ResPartnerTagMethods;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
/** Methods of `res.partner.tag`: declared ones and transitions. */
|
|
749
|
+
export interface ResPartnerTagMethods extends F.Methods<typeof import('../../contacts/index.js').contactsShutro, 'res.partner.tag'> {
|
|
750
|
+
}
|
|
751
|
+
|
|
702
752
|
/** `res.users` (owner: base). */
|
|
703
753
|
export interface ResUsers {
|
|
704
754
|
readonly name: 'res.users';
|
|
@@ -750,6 +800,8 @@ export interface SaleOrder {
|
|
|
750
800
|
readonly amountUntaxed: F.Monetary<'currency', { readonly readonly: true; readonly compute: true; readonly store: true }>;
|
|
751
801
|
readonly amountTax: F.Monetary<'currency', { readonly readonly: true; readonly compute: true; readonly store: true }>;
|
|
752
802
|
readonly amountTotal: F.Monetary<'currency', { readonly readonly: true; readonly compute: true; readonly store: true }>;
|
|
803
|
+
readonly margin: F.Monetary<'currency', { readonly readonly: true; readonly compute: true; readonly store: true }>;
|
|
804
|
+
readonly marginPercent: F.Decimal<{ readonly readonly: true; readonly compute: true; readonly store: true }>;
|
|
753
805
|
readonly state: F.State<'draft' | 'sent' | 'sale' | 'done' | 'cancel', { readonly required: true; readonly readonly: true; readonly default: true }>;
|
|
754
806
|
};
|
|
755
807
|
readonly methods: SaleOrderMethods;
|
|
@@ -786,6 +838,7 @@ export interface SaleOrderLine {
|
|
|
786
838
|
readonly tax: F.Many2one<'account.tax', { readonly readonly: true }>;
|
|
787
839
|
readonly currency: F.Many2one<'res.currency', { readonly readonly: true; readonly compute: true; readonly store: true }>;
|
|
788
840
|
readonly subtotal: F.Monetary<'currency', { readonly readonly: true; readonly compute: true; readonly store: true }>;
|
|
841
|
+
readonly margin: F.Monetary<'currency', { readonly readonly: true; readonly compute: true; readonly store: true }>;
|
|
789
842
|
readonly taxAmount: F.Monetary<'currency', { readonly readonly: true; readonly compute: true; readonly store: true }>;
|
|
790
843
|
};
|
|
791
844
|
readonly methods: SaleOrderLineMethods;
|
|
@@ -812,6 +865,8 @@ export interface StorageAttachment {
|
|
|
812
865
|
readonly key: F.Char<{ readonly required: true }>;
|
|
813
866
|
readonly resModel: F.Char<{ readonly required: true }>;
|
|
814
867
|
readonly resId: F.Integer<{ readonly required: true }>;
|
|
868
|
+
readonly variantOf: F.Many2one<'storage.attachment'>;
|
|
869
|
+
readonly width: F.Integer;
|
|
815
870
|
};
|
|
816
871
|
readonly methods: StorageAttachmentMethods;
|
|
817
872
|
}
|
package/dist/sales/index.js
CHANGED
|
@@ -8,7 +8,8 @@ import { contacts } from '../contacts/index.js';
|
|
|
8
8
|
import { messaging } from '../messaging/index.js';
|
|
9
9
|
import { defineModule } from '../modules-sdk/index.js';
|
|
10
10
|
import { product } from '../product/index.js';
|
|
11
|
-
import {
|
|
11
|
+
import { reporting } from '../reporting/index.js';
|
|
12
|
+
import { action, calendar, form, kanban, list, search, stat } from '../views/index.js';
|
|
12
13
|
import { salesDemo } from './demo.js';
|
|
13
14
|
import { SaleOrder, SaleOrderLine, salesShutro } from './module.js';
|
|
14
15
|
export { SaleOrder, SaleOrderLine, salesShutro } from './module.js';
|
|
@@ -16,7 +17,7 @@ export const sales = defineModule({
|
|
|
16
17
|
shutro: salesShutro,
|
|
17
18
|
kosh: '^0.1.0',
|
|
18
19
|
hooks: { demo: salesDemo },
|
|
19
|
-
depends: [contacts, product, messaging],
|
|
20
|
+
depends: [contacts, product, messaging, reporting],
|
|
20
21
|
// What webhooks may subscribe to besides record changes (RFC 0017 §5.3).
|
|
21
22
|
events: [{ topic: 'sale.order.confirmed', model: 'sale.order', label: 'Sales order confirmed' }],
|
|
22
23
|
app: {
|
|
@@ -31,6 +32,31 @@ export const sales = defineModule({
|
|
|
31
32
|
user: { label: 'Salesperson (own orders)', groups: ['sales.user'] },
|
|
32
33
|
manager: { label: 'Manager (all orders)', groups: ['sales.manager'], implies: ['user'] },
|
|
33
34
|
},
|
|
35
|
+
// Settings › App settings › Sales (RFC 0020): per company, changed by sales managers.
|
|
36
|
+
settings: {
|
|
37
|
+
sections: [
|
|
38
|
+
{
|
|
39
|
+
key: 'quotations',
|
|
40
|
+
label: 'Quotations',
|
|
41
|
+
description: 'How long new quotations stay valid, and the terms they start with.',
|
|
42
|
+
keywords: 'quote validity expiry terms conditions',
|
|
43
|
+
scope: 'company',
|
|
44
|
+
editors: ['sales.manager'],
|
|
45
|
+
fields: [
|
|
46
|
+
{
|
|
47
|
+
key: 'saleValidityDays',
|
|
48
|
+
min: 0,
|
|
49
|
+
max: 365,
|
|
50
|
+
help: 'A new quotation is valid until its date plus these days; 0 leaves it open.',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
key: 'saleTerms',
|
|
54
|
+
help: 'Filled in on new quotations; each can still be changed.',
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
},
|
|
34
60
|
// The printed quotation (RFC 0005), installed as a template designers can change; the portal prints it too.
|
|
35
61
|
documents: [
|
|
36
62
|
{
|
|
@@ -97,10 +123,157 @@ export const sales = defineModule({
|
|
|
97
123
|
},
|
|
98
124
|
},
|
|
99
125
|
],
|
|
126
|
+
// The Overview page (RFC 0022 §3.2): this month against the last, the year's curve, who buys, what to chase.
|
|
127
|
+
overview: {
|
|
128
|
+
cards: [
|
|
129
|
+
{
|
|
130
|
+
id: 'sales_month',
|
|
131
|
+
title: 'Sales this month',
|
|
132
|
+
kind: 'kpi',
|
|
133
|
+
model: 'sale.order',
|
|
134
|
+
measure: 'sum:amountTotal',
|
|
135
|
+
filter: { state: { in: ['sale', 'done'] } },
|
|
136
|
+
comparison: { field: 'dateOrder', mode: 'previous' },
|
|
137
|
+
w: 3,
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
id: 'orders_month',
|
|
141
|
+
title: 'Orders this month',
|
|
142
|
+
kind: 'kpi',
|
|
143
|
+
model: 'sale.order',
|
|
144
|
+
measure: 'count',
|
|
145
|
+
filter: { state: { in: ['sale', 'done'] } },
|
|
146
|
+
comparison: { field: 'dateOrder', mode: 'previous' },
|
|
147
|
+
w: 3,
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
id: 'open_quotations',
|
|
151
|
+
title: 'Open quotations',
|
|
152
|
+
kind: 'kpi',
|
|
153
|
+
model: 'sale.order',
|
|
154
|
+
measure: 'count',
|
|
155
|
+
filter: { state: { in: ['draft', 'sent'] } },
|
|
156
|
+
w: 3,
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
id: 'average_order',
|
|
160
|
+
title: 'Average order',
|
|
161
|
+
kind: 'kpi',
|
|
162
|
+
model: 'sale.order',
|
|
163
|
+
measure: 'avg:amountTotal',
|
|
164
|
+
filter: { state: { in: ['sale', 'done'] } },
|
|
165
|
+
w: 3,
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
id: 'margin_month',
|
|
169
|
+
title: 'Margin this month',
|
|
170
|
+
kind: 'kpi',
|
|
171
|
+
model: 'sale.order',
|
|
172
|
+
measure: 'sum:margin',
|
|
173
|
+
filter: { state: { in: ['sale', 'done'] } },
|
|
174
|
+
comparison: { field: 'dateOrder', mode: 'previous' },
|
|
175
|
+
w: 3,
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
id: 'sales_by_month',
|
|
179
|
+
title: 'Sales by month',
|
|
180
|
+
kind: 'chart',
|
|
181
|
+
model: 'sale.order',
|
|
182
|
+
measure: 'sum:amountTotal',
|
|
183
|
+
groupBy: 'dateOrder:month',
|
|
184
|
+
filter: { state: { in: ['sale', 'done'] } },
|
|
185
|
+
chart: 'bar',
|
|
186
|
+
w: 6,
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
id: 'top_customers',
|
|
190
|
+
title: 'Top customers',
|
|
191
|
+
kind: 'pivot',
|
|
192
|
+
model: 'sale.order',
|
|
193
|
+
measure: 'sum:amountTotal',
|
|
194
|
+
groupBy: 'partner',
|
|
195
|
+
filter: { state: { in: ['sale', 'done'] } },
|
|
196
|
+
w: 6,
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
id: 'by_salesperson',
|
|
200
|
+
title: 'By salesperson',
|
|
201
|
+
kind: 'chart',
|
|
202
|
+
model: 'sale.order',
|
|
203
|
+
measure: 'sum:amountTotal',
|
|
204
|
+
groupBy: 'user',
|
|
205
|
+
filter: { state: { in: ['sale', 'done'] } },
|
|
206
|
+
chart: 'pie',
|
|
207
|
+
w: 6,
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
id: 'quotations_to_chase',
|
|
211
|
+
title: 'Biggest open quotations',
|
|
212
|
+
kind: 'list',
|
|
213
|
+
model: 'sale.order',
|
|
214
|
+
measure: 'sum:amountTotal',
|
|
215
|
+
filter: { state: { in: ['draft', 'sent'] } },
|
|
216
|
+
w: 6,
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
},
|
|
220
|
+
viewExtensions: [
|
|
221
|
+
{
|
|
222
|
+
view: 'product.product.form',
|
|
223
|
+
operations: [
|
|
224
|
+
{
|
|
225
|
+
append: 'related',
|
|
226
|
+
nodes: [
|
|
227
|
+
stat({
|
|
228
|
+
id: 'product_sold',
|
|
229
|
+
label: 'Sold',
|
|
230
|
+
model: SaleOrderLine,
|
|
231
|
+
where: { product: { $record: 'id' }, 'order.state': { in: ['sale', 'done'] } },
|
|
232
|
+
measure: { sum: 'quantity' },
|
|
233
|
+
}),
|
|
234
|
+
stat({
|
|
235
|
+
id: 'product_revenue',
|
|
236
|
+
label: 'Sales',
|
|
237
|
+
model: SaleOrderLine,
|
|
238
|
+
where: { product: { $record: 'id' }, 'order.state': { in: ['sale', 'done'] } },
|
|
239
|
+
measure: { sum: 'subtotal' },
|
|
240
|
+
tone: 'success',
|
|
241
|
+
}),
|
|
242
|
+
],
|
|
243
|
+
},
|
|
244
|
+
],
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
view: 'res.partner.form',
|
|
248
|
+
operations: [
|
|
249
|
+
{
|
|
250
|
+
append: 'related',
|
|
251
|
+
nodes: [
|
|
252
|
+
stat({
|
|
253
|
+
id: 'sale_orders',
|
|
254
|
+
label: 'Sales orders',
|
|
255
|
+
model: SaleOrder,
|
|
256
|
+
where: { partner: { $record: 'id' }, state: { in: ['sale', 'done'] } },
|
|
257
|
+
action: 'sales.action_orders',
|
|
258
|
+
}),
|
|
259
|
+
stat({
|
|
260
|
+
id: 'sale_revenue',
|
|
261
|
+
label: 'Sales',
|
|
262
|
+
model: SaleOrder,
|
|
263
|
+
where: { partner: { $record: 'id' }, state: { in: ['sale', 'done'] } },
|
|
264
|
+
measure: { sum: 'amountTotal' },
|
|
265
|
+
action: 'sales.action_orders',
|
|
266
|
+
tone: 'success',
|
|
267
|
+
}),
|
|
268
|
+
],
|
|
269
|
+
},
|
|
270
|
+
],
|
|
271
|
+
},
|
|
272
|
+
],
|
|
100
273
|
actions: {
|
|
101
274
|
'sales.action_quotations': action(SaleOrder, {
|
|
102
275
|
label: 'Quotations',
|
|
103
|
-
views: ['list', 'kanban', 'form'],
|
|
276
|
+
views: ['list', 'kanban', 'calendar', 'form'],
|
|
104
277
|
defaultFilters: ['quotations'],
|
|
105
278
|
}),
|
|
106
279
|
'sales.action_orders': action(SaleOrder, {
|
|
@@ -147,9 +320,12 @@ export const sales = defineModule({
|
|
|
147
320
|
'partner',
|
|
148
321
|
'user',
|
|
149
322
|
{ field: 'amountTotal', sum: true },
|
|
323
|
+
{ field: 'margin', sum: true },
|
|
324
|
+
{ field: 'marginPercent', widget: 'percentage' },
|
|
150
325
|
{ field: 'state', widget: 'badge' },
|
|
151
326
|
],
|
|
152
327
|
defaultOrder: ['dateOrder desc'],
|
|
328
|
+
decorations: { success: { state: 'done' }, neutral: { state: 'cancel' } },
|
|
153
329
|
}),
|
|
154
330
|
'sale.order.kanban': kanban(SaleOrder, {
|
|
155
331
|
groupBy: 'state',
|
|
@@ -168,6 +344,8 @@ export const sales = defineModule({
|
|
|
168
344
|
],
|
|
169
345
|
},
|
|
170
346
|
sheet: [
|
|
347
|
+
// Invoices, deliveries, tasks: the bridges append their tiles (RFC 0022 §3.1).
|
|
348
|
+
k.stats('related', []),
|
|
171
349
|
k.group('customer', ['partner', 'clientReference', 'currency']),
|
|
172
350
|
k.group('dates', ['name', 'dateOrder', 'validityDate', 'user']),
|
|
173
351
|
k.lines('lines', [
|
|
@@ -180,12 +358,21 @@ export const sales = defineModule({
|
|
|
180
358
|
'taxes',
|
|
181
359
|
'subtotal',
|
|
182
360
|
], { readonlyWhen: { state: { in: ['done', 'cancel'] } } }),
|
|
183
|
-
k.group('totals', ['amountUntaxed', 'amountTax', 'amountTotal'
|
|
361
|
+
k.group('totals', ['amountUntaxed', 'amountTax', 'amountTotal', 'margin', 'marginPercent'], {
|
|
362
|
+
label: 'Totals',
|
|
363
|
+
}),
|
|
184
364
|
k.group('terms', ['note'], { columns: 1 }),
|
|
185
365
|
],
|
|
186
366
|
readonlyWhen: { state: { in: ['done', 'cancel'] } },
|
|
187
367
|
chatter: true,
|
|
188
368
|
})),
|
|
369
|
+
// Quotations by the day they expire: what to chase this week.
|
|
370
|
+
'sale.order.calendar': calendar(SaleOrder, {
|
|
371
|
+
dateStart: 'validityDate',
|
|
372
|
+
title: 'name',
|
|
373
|
+
color: 'state',
|
|
374
|
+
mode: 'month',
|
|
375
|
+
}),
|
|
189
376
|
'sale.order.line.list': list(SaleOrderLine, {
|
|
190
377
|
columns: ['order', 'product', 'quantity', 'priceUnit', 'subtotal'],
|
|
191
378
|
}),
|