shutro-erp 0.2.1 → 0.3.0
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/README.md +17 -10
- package/dist/account_portal/.kosh/bindings.d.ts +22 -0
- package/dist/account_portal/.kosh/bindings.js +15 -0
- package/dist/account_portal/.kosh/schema.d.ts +1350 -0
- package/dist/account_portal/index.d.ts +3 -0
- package/dist/account_portal/index.js +73 -0
- package/dist/account_portal/module.d.ts +5983 -0
- package/dist/account_portal/module.js +18 -0
- package/dist/accounting/.kosh/bindings.js +1 -1
- package/dist/accounting/.kosh/schema.d.ts +142 -9
- package/dist/accounting/chart.d.ts +40 -8
- package/dist/accounting/chart.js +124 -30
- package/dist/accounting/closing.d.ts +6 -1
- package/dist/accounting/closing.js +5 -1
- package/dist/accounting/demo.js +6 -5
- package/dist/accounting/index.d.ts +3 -3
- package/dist/accounting/index.js +200 -23
- package/dist/accounting/module.d.ts +3326 -1086
- package/dist/accounting/module.js +408 -66
- package/dist/accounting/payments.d.ts +25 -0
- package/dist/accounting/payments.js +96 -4
- package/dist/accounting/web/RegisterPayment.d.ts +3 -2
- package/dist/accounting/web/RegisterPayment.js +39 -6
- package/dist/accounting/web/SettingsPage.js +5 -1
- package/dist/accounting/web/messages.js +10 -0
- package/dist/cli/init.js +172 -48
- package/dist/cli/launch.d.ts +16 -0
- package/dist/cli/launch.js +138 -0
- package/dist/cli/prompt.d.ts +35 -0
- package/dist/cli/prompt.js +46 -0
- package/dist/cli/templates.d.ts +11 -3
- package/dist/cli/templates.js +32 -7
- package/dist/cli/tui.d.ts +7 -0
- package/dist/cli/tui.js +254 -0
- package/dist/cli/ui.d.ts +25 -5
- package/dist/cli/ui.js +49 -9
- package/dist/contacts/.kosh/bindings.js +1 -1
- package/dist/contacts/.kosh/schema.d.ts +3 -1
- package/dist/contacts/index.js +24 -1
- package/dist/contacts/module.d.ts +42 -0
- package/dist/contacts/module.js +3 -1
- package/dist/import/convert.d.ts +55 -0
- package/dist/import/convert.js +224 -0
- package/dist/import/csv.d.ts +28 -0
- package/dist/import/csv.js +115 -0
- package/dist/import/index.d.ts +33 -0
- package/dist/import/index.js +60 -0
- package/dist/import/mapping.d.ts +15 -0
- package/dist/import/mapping.js +33 -0
- package/dist/import/match.d.ts +24 -0
- package/dist/import/match.js +60 -0
- package/dist/import/models.d.ts +2 -0
- package/dist/import/models.js +102 -0
- package/dist/import/routes.d.ts +13 -0
- package/dist/import/routes.js +392 -0
- package/dist/import/run.d.ts +131 -0
- package/dist/import/run.js +568 -0
- package/dist/import/service.d.ts +153 -0
- package/dist/import/service.js +367 -0
- package/dist/import/web/ImportButton.d.ts +7 -0
- package/dist/import/web/ImportButton.js +31 -0
- package/dist/import/web/ImportWizard.d.ts +75 -0
- package/dist/import/web/ImportWizard.js +217 -0
- package/dist/import/web/index.d.ts +13 -0
- package/dist/import/web/index.js +18 -0
- package/dist/import/web/messages.d.ts +2 -0
- package/dist/import/web/messages.js +139 -0
- package/dist/import/worker.d.ts +3 -0
- package/dist/import/worker.js +52 -0
- package/dist/import/xlsx.d.ts +20 -0
- package/dist/import/xlsx.js +192 -0
- package/dist/l10n_bd/.kosh/bindings.d.ts +22 -0
- package/dist/l10n_bd/.kosh/bindings.js +15 -0
- package/dist/l10n_bd/.kosh/schema.d.ts +1281 -0
- package/dist/l10n_bd/documents.d.ts +8 -0
- package/dist/l10n_bd/documents.js +183 -0
- package/dist/l10n_bd/index.d.ts +8 -0
- package/dist/l10n_bd/index.js +156 -0
- package/dist/l10n_bd/module.d.ts +5705 -0
- package/dist/l10n_bd/module.js +163 -0
- package/dist/l10n_bd/mushak.d.ts +67 -0
- package/dist/l10n_bd/mushak.js +139 -0
- package/dist/l10n_bd/routes.d.ts +3 -0
- package/dist/l10n_bd/routes.js +205 -0
- package/dist/l10n_bd/web/MushakPage.d.ts +7 -0
- package/dist/l10n_bd/web/MushakPage.js +53 -0
- package/dist/l10n_bd/web/index.d.ts +13 -0
- package/dist/l10n_bd/web/index.js +18 -0
- package/dist/l10n_bd/web/messages.d.ts +2 -0
- package/dist/l10n_bd/web/messages.js +101 -0
- package/dist/l10n_in/.kosh/bindings.d.ts +22 -0
- package/dist/l10n_in/.kosh/bindings.js +15 -0
- package/dist/l10n_in/.kosh/schema.d.ts +1343 -0
- package/dist/l10n_in/documents.d.ts +8 -0
- package/dist/l10n_in/documents.js +114 -0
- package/dist/l10n_in/einvoice.d.ts +253 -0
- package/dist/l10n_in/einvoice.js +485 -0
- package/dist/l10n_in/gstr.d.ts +109 -0
- package/dist/l10n_in/gstr.js +430 -0
- package/dist/l10n_in/index.d.ts +20 -0
- package/dist/l10n_in/index.js +232 -0
- package/dist/l10n_in/module.d.ts +7823 -0
- package/dist/l10n_in/module.js +427 -0
- package/dist/l10n_in/routes-einvoice.d.ts +15 -0
- package/dist/l10n_in/routes-einvoice.js +124 -0
- package/dist/l10n_in/routes.d.ts +17 -0
- package/dist/l10n_in/routes.js +282 -0
- package/dist/l10n_in/web/EInvoicePanel.d.ts +8 -0
- package/dist/l10n_in/web/EInvoicePanel.js +63 -0
- package/dist/l10n_in/web/GstPage.d.ts +7 -0
- package/dist/l10n_in/web/GstPage.js +57 -0
- package/dist/l10n_in/web/GstSettings.d.ts +10 -0
- package/dist/l10n_in/web/GstSettings.js +36 -0
- package/dist/l10n_in/web/index.d.ts +15 -0
- package/dist/l10n_in/web/index.js +22 -0
- package/dist/l10n_in/web/messages.d.ts +2 -0
- package/dist/l10n_in/web/messages.js +166 -0
- package/dist/modules-sdk/demo.d.ts +2 -0
- package/dist/modules-sdk/demo.js +7 -3
- package/dist/modules-sdk/index.d.ts +2 -2
- package/dist/modules-sdk/index.js +1 -1
- package/dist/modules-sdk/manifest.d.ts +132 -0
- package/dist/modules-sdk/manifest.js +22 -0
- package/dist/notify/inbox.js +21 -0
- package/dist/notify/messages.js +4 -0
- package/dist/notify/models.d.ts +1 -1
- package/dist/notify/models.js +2 -0
- package/dist/notify/web/messages.js +4 -0
- package/dist/portal/.kosh/bindings.d.ts +22 -0
- package/dist/portal/.kosh/bindings.js +15 -0
- package/dist/portal/.kosh/schema.d.ts +346 -0
- package/dist/portal/announce.d.ts +16 -0
- package/dist/portal/announce.js +117 -0
- package/dist/portal/documents.d.ts +17 -0
- package/dist/portal/documents.js +61 -0
- package/dist/portal/index.d.ts +20 -0
- package/dist/portal/index.js +65 -0
- package/dist/portal/module.d.ts +1405 -0
- package/dist/portal/module.js +84 -0
- package/dist/portal/routes-documents.d.ts +2 -0
- package/dist/portal/routes-documents.js +391 -0
- package/dist/portal/routes.d.ts +13 -0
- package/dist/portal/routes.js +313 -0
- package/dist/portal/rules.d.ts +11 -0
- package/dist/portal/rules.js +25 -0
- package/dist/portal/web/PortalAccess.d.ts +8 -0
- package/dist/portal/web/PortalAccess.js +66 -0
- package/dist/portal/web/index.d.ts +12 -0
- package/dist/portal/web/index.js +17 -0
- package/dist/portal/web/messages.d.ts +2 -0
- package/dist/portal/web/messages.js +33 -0
- package/dist/product/.kosh/bindings.js +1 -1
- package/dist/product/.kosh/schema.d.ts +12 -3
- package/dist/product/demo.js +6 -5
- package/dist/product/index.d.ts +1 -0
- package/dist/product/index.js +17 -4
- package/dist/product/module.d.ts +346 -14
- package/dist/product/module.js +48 -18
- package/dist/product/taxes.d.ts +59 -0
- package/dist/product/taxes.js +61 -0
- package/dist/project/.kosh/bindings.js +1 -1
- package/dist/project/.kosh/schema.d.ts +3 -1
- package/dist/project/module.d.ts +20 -0
- package/dist/project_portal/.kosh/bindings.d.ts +22 -0
- package/dist/project_portal/.kosh/bindings.js +15 -0
- package/dist/project_portal/.kosh/schema.d.ts +671 -0
- package/dist/project_portal/index.d.ts +9 -0
- package/dist/project_portal/index.js +42 -0
- package/dist/project_portal/module.d.ts +2142 -0
- package/dist/project_portal/module.js +22 -0
- package/dist/purchase/.kosh/bindings.js +1 -1
- package/dist/purchase/.kosh/schema.d.ts +15 -4
- package/dist/purchase/demo.js +3 -3
- package/dist/purchase/index.js +1 -1
- package/dist/purchase/module.d.ts +232 -8
- package/dist/purchase/module.js +51 -9
- package/dist/purchase_account/.kosh/bindings.js +1 -1
- package/dist/purchase_account/.kosh/schema.d.ts +144 -10
- package/dist/purchase_account/module.d.ts +2008 -641
- package/dist/purchase_account/module.js +2 -2
- package/dist/purchase_portal/.kosh/bindings.d.ts +22 -0
- package/dist/purchase_portal/.kosh/bindings.js +15 -0
- package/dist/purchase_portal/.kosh/schema.d.ts +822 -0
- package/dist/purchase_portal/index.d.ts +9 -0
- package/dist/purchase_portal/index.js +53 -0
- package/dist/purchase_portal/module.d.ts +2758 -0
- package/dist/purchase_portal/module.js +18 -0
- package/dist/reporting/documents.js +20 -3
- package/dist/reporting/index.d.ts +1 -0
- package/dist/reporting/index.js +1 -0
- package/dist/reporting/routes-documents.js +9 -2
- package/dist/reporting/words.d.ts +11 -0
- package/dist/reporting/words.js +229 -0
- package/dist/sale_account/.kosh/bindings.js +1 -1
- package/dist/sale_account/.kosh/schema.d.ts +144 -10
- package/dist/sale_account/module.d.ts +2008 -641
- package/dist/sale_account/module.js +3 -3
- package/dist/sale_portal/.kosh/bindings.d.ts +22 -0
- package/dist/sale_portal/.kosh/bindings.js +15 -0
- package/dist/sale_portal/.kosh/schema.d.ts +736 -0
- package/dist/sale_portal/index.d.ts +9 -0
- package/dist/sale_portal/index.js +71 -0
- package/dist/sale_portal/module.d.ts +2718 -0
- package/dist/sale_portal/module.js +19 -0
- package/dist/sale_project/.kosh/bindings.js +1 -1
- package/dist/sale_project/.kosh/schema.d.ts +15 -4
- package/dist/sale_project/module.d.ts +390 -10
- package/dist/sales/.kosh/bindings.js +1 -1
- package/dist/sales/.kosh/schema.d.ts +15 -4
- package/dist/sales/demo.js +3 -3
- package/dist/sales/index.js +67 -1
- package/dist/sales/module.d.ts +232 -8
- package/dist/sales/module.js +51 -12
- package/dist/server/auth/base.js +2 -0
- package/dist/server/auth/service.d.ts +2 -0
- package/dist/server/auth/service.js +7 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/server.js +26 -1
- package/dist/ui/api.d.ts +2 -0
- package/dist/ui/app.js +1 -1
- package/dist/ui/context.d.ts +3 -1
- package/dist/ui/context.js +2 -2
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +1 -1
- package/dist/ui/lib/format.d.ts +2 -0
- package/dist/ui/lib/format.js +3 -1
- package/dist/ui/views/FormView.js +19 -6
- package/package.json +50 -2
|
@@ -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: 531f9724f4925363
|
|
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
|
|
|
@@ -43,7 +43,13 @@ export interface AccountTax {
|
|
|
43
43
|
readonly active: F.Bool<{ readonly required: true; readonly default: true }>;
|
|
44
44
|
readonly name: F.Char<{ readonly required: true; readonly translate: true }>;
|
|
45
45
|
readonly use: F.Selection<'sale' | 'purchase', { readonly required: true; readonly default: true }>;
|
|
46
|
+
readonly sequence: F.Integer<{ readonly required: true; readonly default: true }>;
|
|
47
|
+
readonly amountType: F.Selection<'percent' | 'fixed', { readonly required: true; readonly default: true }>;
|
|
46
48
|
readonly rate: F.Decimal<{ readonly required: true; readonly default: true }>;
|
|
49
|
+
readonly fixedAmount: F.Decimal<{ readonly required: true; readonly default: true }>;
|
|
50
|
+
readonly affectsBase: F.Bool<{ readonly required: true; readonly default: true }>;
|
|
51
|
+
readonly priceIncluded: F.Bool<{ readonly required: true; readonly default: true }>;
|
|
52
|
+
readonly reverseCharge: F.Bool<{ readonly required: true; readonly default: true }>;
|
|
47
53
|
};
|
|
48
54
|
readonly methods: AccountTaxMethods;
|
|
49
55
|
}
|
|
@@ -416,8 +422,10 @@ export interface ProductProduct {
|
|
|
416
422
|
readonly standardPrice: F.Decimal<{ readonly required: true; readonly default: true }>;
|
|
417
423
|
readonly saleOk: F.Bool<{ readonly required: true; readonly default: true }>;
|
|
418
424
|
readonly purchaseOk: F.Bool<{ readonly required: true; readonly default: true }>;
|
|
419
|
-
readonly
|
|
420
|
-
readonly
|
|
425
|
+
readonly taxes: F.Many2many<'account.tax', { readonly required: true }>;
|
|
426
|
+
readonly purchaseTaxes: F.Many2many<'account.tax', { readonly required: true }>;
|
|
427
|
+
readonly tax: F.Many2one<'account.tax', { readonly readonly: true }>;
|
|
428
|
+
readonly purchaseTax: F.Many2one<'account.tax', { readonly readonly: true }>;
|
|
421
429
|
readonly description: F.Text<{ readonly translate: true }>;
|
|
422
430
|
};
|
|
423
431
|
readonly methods: ProductProductMethods;
|
|
@@ -439,6 +447,7 @@ export interface ResCompany {
|
|
|
439
447
|
readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
|
|
440
448
|
readonly name: F.Char<{ readonly required: true }>;
|
|
441
449
|
readonly currency: F.Many2one<'res.currency', { readonly required: true }>;
|
|
450
|
+
readonly numberGrouping: F.Selection<'international' | 'lakh', { readonly required: true; readonly default: true }>;
|
|
442
451
|
};
|
|
443
452
|
readonly methods: ResCompanyMethods;
|
|
444
453
|
}
|
|
@@ -492,6 +501,7 @@ export interface ResPartner {
|
|
|
492
501
|
readonly city: F.Char;
|
|
493
502
|
readonly zip: F.Char;
|
|
494
503
|
readonly country: F.Char;
|
|
504
|
+
readonly state: F.Char;
|
|
495
505
|
readonly taxId: F.Char;
|
|
496
506
|
readonly isCustomer: F.Bool<{ readonly required: true; readonly default: true }>;
|
|
497
507
|
readonly isVendor: F.Bool<{ readonly required: true; readonly default: true }>;
|
|
@@ -587,7 +597,8 @@ export interface SaleOrderLine {
|
|
|
587
597
|
readonly uom: F.Many2one<'uom.uom'>;
|
|
588
598
|
readonly priceUnit: F.Decimal<{ readonly required: true; readonly default: true }>;
|
|
589
599
|
readonly discount: F.Decimal<{ readonly required: true; readonly default: true }>;
|
|
590
|
-
readonly
|
|
600
|
+
readonly taxes: F.Many2many<'account.tax', { readonly required: true }>;
|
|
601
|
+
readonly tax: F.Many2one<'account.tax', { readonly readonly: true }>;
|
|
591
602
|
readonly currency: F.Many2one<'res.currency', { readonly readonly: true; readonly compute: true; readonly store: true }>;
|
|
592
603
|
readonly subtotal: F.Monetary<'currency', { readonly readonly: true; readonly compute: true; readonly store: true }>;
|
|
593
604
|
readonly taxAmount: F.Monetary<'currency', { readonly readonly: true; readonly compute: true; readonly store: true }>;
|
package/dist/sales/demo.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Demo data of Sales (RFC 0008 §5.8): quotations and confirmed orders of a salesperson, with VAT. */
|
|
2
|
-
import { idByName } from '../modules-sdk/index.js';
|
|
2
|
+
import { idByName, maybeIdByName } from '../modules-sdk/index.js';
|
|
3
3
|
import { orm } from '../server/orm.js';
|
|
4
4
|
/** The demo salesperson. */
|
|
5
5
|
export const RAHIM = { login: 'rahim', name: 'Rahim Uddin', groups: ['sales.user'] };
|
|
@@ -54,7 +54,7 @@ export async function salesDemo(context) {
|
|
|
54
54
|
.load({ currency: true });
|
|
55
55
|
if (company === undefined)
|
|
56
56
|
throw new Error('Demo data: no company.');
|
|
57
|
-
const vat = await
|
|
57
|
+
const vat = await maybeIdByName(env, 'account.tax', 'VAT 15%');
|
|
58
58
|
let confirmed = 0;
|
|
59
59
|
for (const o of ORDERS) {
|
|
60
60
|
const lines = [];
|
|
@@ -65,7 +65,7 @@ export async function salesDemo(context) {
|
|
|
65
65
|
name: l.product,
|
|
66
66
|
quantity: l.quantity,
|
|
67
67
|
priceUnit: l.price,
|
|
68
|
-
|
|
68
|
+
taxes: { set: vat === null ? [] : [orm.asId(vat, 'account.tax')] },
|
|
69
69
|
});
|
|
70
70
|
}
|
|
71
71
|
const created = await env.model('sale.order').create([
|
package/dist/sales/index.js
CHANGED
|
@@ -29,6 +29,72 @@ export const sales = defineModule({
|
|
|
29
29
|
user: { label: 'Salesperson (own orders)', groups: ['sales.user'] },
|
|
30
30
|
manager: { label: 'Manager (all orders)', groups: ['sales.manager'], implies: ['user'] },
|
|
31
31
|
},
|
|
32
|
+
// The printed quotation (RFC 0005), installed as a template designers can change; the portal prints it too.
|
|
33
|
+
documents: [
|
|
34
|
+
{
|
|
35
|
+
key: 'quotation',
|
|
36
|
+
name: 'Quotation',
|
|
37
|
+
model: 'sale.order',
|
|
38
|
+
layout: {
|
|
39
|
+
paper: 'A4',
|
|
40
|
+
header: '{{company.name}}',
|
|
41
|
+
footer: 'Page {{page}} of {{pages}}',
|
|
42
|
+
blocks: [
|
|
43
|
+
{ kind: 'heading', id: 'title', text: '{{state}} {{name}}', level: 1 },
|
|
44
|
+
{
|
|
45
|
+
kind: 'columns',
|
|
46
|
+
id: 'parties',
|
|
47
|
+
left: [
|
|
48
|
+
{
|
|
49
|
+
kind: 'fields',
|
|
50
|
+
id: 'customer',
|
|
51
|
+
items: [
|
|
52
|
+
{ label: 'Customer', bind: 'partner.name' },
|
|
53
|
+
{ label: 'Customer reference', bind: 'clientReference' },
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
right: [
|
|
58
|
+
{
|
|
59
|
+
kind: 'fields',
|
|
60
|
+
id: 'dates',
|
|
61
|
+
items: [
|
|
62
|
+
{ label: 'Order date', bind: 'dateOrder' },
|
|
63
|
+
{ label: 'Valid until', bind: 'validityDate' },
|
|
64
|
+
{ label: 'Salesperson', bind: 'user.name' },
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
kind: 'table',
|
|
71
|
+
id: 'lines',
|
|
72
|
+
bind: 'lines',
|
|
73
|
+
columns: [
|
|
74
|
+
{ label: 'Description', bind: 'name' },
|
|
75
|
+
{ label: 'Quantity', bind: 'quantity', align: 'end' },
|
|
76
|
+
{ label: 'Unit price', bind: 'priceUnit', align: 'end' },
|
|
77
|
+
{ label: 'Discount %', bind: 'discount', align: 'end' },
|
|
78
|
+
{ label: 'Tax', bind: 'taxAmount', align: 'end' },
|
|
79
|
+
{ label: 'Subtotal', bind: 'subtotal', align: 'end', sum: true },
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
kind: 'fields',
|
|
84
|
+
id: 'totals',
|
|
85
|
+
columns: 3,
|
|
86
|
+
items: [
|
|
87
|
+
{ label: 'Untaxed', bind: 'amountUntaxed' },
|
|
88
|
+
{ label: 'Taxes', bind: 'amountTax' },
|
|
89
|
+
{ label: 'Total', bind: 'amountTotal' },
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
{ kind: 'text', id: 'in_words', text: '{{amountTotal|words}}' },
|
|
93
|
+
{ kind: 'text', id: 'terms', text: '{{note}}' },
|
|
94
|
+
],
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
],
|
|
32
98
|
actions: {
|
|
33
99
|
'sales.action_quotations': action(SaleOrder, {
|
|
34
100
|
label: 'Quotations',
|
|
@@ -109,7 +175,7 @@ export const sales = defineModule({
|
|
|
109
175
|
'uom',
|
|
110
176
|
'priceUnit',
|
|
111
177
|
'discount',
|
|
112
|
-
'
|
|
178
|
+
'taxes',
|
|
113
179
|
'subtotal',
|
|
114
180
|
], { readonlyWhen: { state: { in: ['done', 'cancel'] } } }),
|
|
115
181
|
k.group('totals', ['amountUntaxed', 'amountTax', 'amountTotal'], { label: 'Totals' }),
|
package/dist/sales/module.d.ts
CHANGED
|
@@ -467,6 +467,16 @@ export declare const SaleOrderLine: import("../server/orm.js").Model<"sale.order
|
|
|
467
467
|
readonly hasDefault: true;
|
|
468
468
|
readonly readonly: false;
|
|
469
469
|
}>;
|
|
470
|
+
readonly taxes: import("../server/orm.js").Many2manyField<"account.tax", {
|
|
471
|
+
readonly required: true;
|
|
472
|
+
readonly computed: false;
|
|
473
|
+
readonly inverse: false;
|
|
474
|
+
readonly sequence: false;
|
|
475
|
+
readonly computeName: undefined;
|
|
476
|
+
readonly store: true;
|
|
477
|
+
readonly hasDefault: true;
|
|
478
|
+
readonly readonly: false;
|
|
479
|
+
}>;
|
|
470
480
|
readonly tax: import("../server/orm.js").Many2oneField<"account.tax", {
|
|
471
481
|
readonly required: false;
|
|
472
482
|
readonly computed: false;
|
|
@@ -475,7 +485,7 @@ export declare const SaleOrderLine: import("../server/orm.js").Model<"sale.order
|
|
|
475
485
|
readonly computeName: undefined;
|
|
476
486
|
readonly store: true;
|
|
477
487
|
readonly hasDefault: false;
|
|
478
|
-
readonly readonly:
|
|
488
|
+
readonly readonly: true;
|
|
479
489
|
}>;
|
|
480
490
|
readonly currency: import("../server/orm.js").Many2oneField<"res.currency", {
|
|
481
491
|
readonly required: false;
|
|
@@ -579,6 +589,18 @@ export declare const SaleOrderLine: import("../server/orm.js").Model<"sale.order
|
|
|
579
589
|
readonly hasDefault: true;
|
|
580
590
|
readonly readonly: false;
|
|
581
591
|
}>;
|
|
592
|
+
/** The line's taxes, applied in order (RFC 0016). */
|
|
593
|
+
readonly taxes: import("../server/orm.js").Many2manyField<"account.tax", {
|
|
594
|
+
readonly required: true;
|
|
595
|
+
readonly computed: false;
|
|
596
|
+
readonly inverse: false;
|
|
597
|
+
readonly sequence: false;
|
|
598
|
+
readonly computeName: undefined;
|
|
599
|
+
readonly store: true;
|
|
600
|
+
readonly hasDefault: true;
|
|
601
|
+
readonly readonly: false;
|
|
602
|
+
}>;
|
|
603
|
+
/** Before 0.2.0, one tax per line: copied into `taxes` by the migration; dropped later. */
|
|
582
604
|
readonly tax: import("../server/orm.js").Many2oneField<"account.tax", {
|
|
583
605
|
readonly required: false;
|
|
584
606
|
readonly computed: false;
|
|
@@ -587,7 +609,7 @@ export declare const SaleOrderLine: import("../server/orm.js").Model<"sale.order
|
|
|
587
609
|
readonly computeName: undefined;
|
|
588
610
|
readonly store: true;
|
|
589
611
|
readonly hasDefault: false;
|
|
590
|
-
readonly readonly:
|
|
612
|
+
readonly readonly: true;
|
|
591
613
|
}>;
|
|
592
614
|
/** The order's currency, so line amounts are Money in it. */
|
|
593
615
|
readonly currency: import("../server/orm.js").Many2oneField<"res.currency", {
|
|
@@ -1089,6 +1111,16 @@ export declare const salesShutro: import("../server/orm.js").Module<readonly [im
|
|
|
1089
1111
|
readonly hasDefault: true;
|
|
1090
1112
|
readonly readonly: false;
|
|
1091
1113
|
}>;
|
|
1114
|
+
readonly taxes: import("../server/orm.js").Many2manyField<"account.tax", {
|
|
1115
|
+
readonly required: true;
|
|
1116
|
+
readonly computed: false;
|
|
1117
|
+
readonly inverse: false;
|
|
1118
|
+
readonly sequence: false;
|
|
1119
|
+
readonly computeName: undefined;
|
|
1120
|
+
readonly store: true;
|
|
1121
|
+
readonly hasDefault: true;
|
|
1122
|
+
readonly readonly: false;
|
|
1123
|
+
}>;
|
|
1092
1124
|
readonly tax: import("../server/orm.js").Many2oneField<"account.tax", {
|
|
1093
1125
|
readonly required: false;
|
|
1094
1126
|
readonly computed: false;
|
|
@@ -1097,7 +1129,7 @@ export declare const salesShutro: import("../server/orm.js").Module<readonly [im
|
|
|
1097
1129
|
readonly computeName: undefined;
|
|
1098
1130
|
readonly store: true;
|
|
1099
1131
|
readonly hasDefault: false;
|
|
1100
|
-
readonly readonly:
|
|
1132
|
+
readonly readonly: true;
|
|
1101
1133
|
}>;
|
|
1102
1134
|
readonly currency: import("../server/orm.js").Many2oneField<"res.currency", {
|
|
1103
1135
|
readonly required: false;
|
|
@@ -1201,6 +1233,18 @@ export declare const salesShutro: import("../server/orm.js").Module<readonly [im
|
|
|
1201
1233
|
readonly hasDefault: true;
|
|
1202
1234
|
readonly readonly: false;
|
|
1203
1235
|
}>;
|
|
1236
|
+
/** The line's taxes, applied in order (RFC 0016). */
|
|
1237
|
+
readonly taxes: import("../server/orm.js").Many2manyField<"account.tax", {
|
|
1238
|
+
readonly required: true;
|
|
1239
|
+
readonly computed: false;
|
|
1240
|
+
readonly inverse: false;
|
|
1241
|
+
readonly sequence: false;
|
|
1242
|
+
readonly computeName: undefined;
|
|
1243
|
+
readonly store: true;
|
|
1244
|
+
readonly hasDefault: true;
|
|
1245
|
+
readonly readonly: false;
|
|
1246
|
+
}>;
|
|
1247
|
+
/** Before 0.2.0, one tax per line: copied into `taxes` by the migration; dropped later. */
|
|
1204
1248
|
readonly tax: import("../server/orm.js").Many2oneField<"account.tax", {
|
|
1205
1249
|
readonly required: false;
|
|
1206
1250
|
readonly computed: false;
|
|
@@ -1209,7 +1253,7 @@ export declare const salesShutro: import("../server/orm.js").Module<readonly [im
|
|
|
1209
1253
|
readonly computeName: undefined;
|
|
1210
1254
|
readonly store: true;
|
|
1211
1255
|
readonly hasDefault: false;
|
|
1212
|
-
readonly readonly:
|
|
1256
|
+
readonly readonly: true;
|
|
1213
1257
|
}>;
|
|
1214
1258
|
/** The order's currency, so line amounts are Money in it. */
|
|
1215
1259
|
readonly currency: import("../server/orm.js").Many2oneField<"res.currency", {
|
|
@@ -1406,6 +1450,16 @@ export declare const salesShutro: import("../server/orm.js").Module<readonly [im
|
|
|
1406
1450
|
readonly hasDefault: false;
|
|
1407
1451
|
readonly readonly: false;
|
|
1408
1452
|
}, string>;
|
|
1453
|
+
readonly state: import("../server/orm.js").CharField<{
|
|
1454
|
+
readonly required: false;
|
|
1455
|
+
readonly computed: false;
|
|
1456
|
+
readonly inverse: false;
|
|
1457
|
+
readonly sequence: false;
|
|
1458
|
+
readonly computeName: undefined;
|
|
1459
|
+
readonly store: true;
|
|
1460
|
+
readonly hasDefault: false;
|
|
1461
|
+
readonly readonly: false;
|
|
1462
|
+
}, string>;
|
|
1409
1463
|
readonly taxId: import("../server/orm.js").CharField<{
|
|
1410
1464
|
readonly required: false;
|
|
1411
1465
|
readonly computed: false;
|
|
@@ -1577,6 +1631,16 @@ export declare const salesShutro: import("../server/orm.js").Module<readonly [im
|
|
|
1577
1631
|
readonly hasDefault: false;
|
|
1578
1632
|
readonly readonly: false;
|
|
1579
1633
|
}, string>;
|
|
1634
|
+
readonly state: import("../server/orm.js").CharField<{
|
|
1635
|
+
readonly required: false;
|
|
1636
|
+
readonly computed: false;
|
|
1637
|
+
readonly inverse: false;
|
|
1638
|
+
readonly sequence: false;
|
|
1639
|
+
readonly computeName: undefined;
|
|
1640
|
+
readonly store: true;
|
|
1641
|
+
readonly hasDefault: false;
|
|
1642
|
+
readonly readonly: false;
|
|
1643
|
+
}, string>;
|
|
1580
1644
|
readonly taxId: import("../server/orm.js").CharField<{
|
|
1581
1645
|
readonly required: false;
|
|
1582
1646
|
readonly computed: false;
|
|
@@ -1897,6 +1961,26 @@ export declare const salesShutro: import("../server/orm.js").Module<readonly [im
|
|
|
1897
1961
|
readonly hasDefault: true;
|
|
1898
1962
|
readonly readonly: false;
|
|
1899
1963
|
}>;
|
|
1964
|
+
readonly sequence: import("../server/orm.js").ScalarField<"integer", number, number, {
|
|
1965
|
+
readonly required: true;
|
|
1966
|
+
readonly computed: false;
|
|
1967
|
+
readonly inverse: false;
|
|
1968
|
+
readonly sequence: false;
|
|
1969
|
+
readonly computeName: undefined;
|
|
1970
|
+
readonly store: true;
|
|
1971
|
+
readonly hasDefault: true;
|
|
1972
|
+
readonly readonly: false;
|
|
1973
|
+
}>;
|
|
1974
|
+
readonly amountType: import("../server/orm.js").SelectionField<"fixed" | "percent", {
|
|
1975
|
+
readonly required: true;
|
|
1976
|
+
readonly computed: false;
|
|
1977
|
+
readonly inverse: false;
|
|
1978
|
+
readonly sequence: false;
|
|
1979
|
+
readonly computeName: undefined;
|
|
1980
|
+
readonly store: true;
|
|
1981
|
+
readonly hasDefault: true;
|
|
1982
|
+
readonly readonly: false;
|
|
1983
|
+
}>;
|
|
1900
1984
|
readonly rate: import("../server/orm.js").DecimalField<{
|
|
1901
1985
|
readonly required: true;
|
|
1902
1986
|
readonly computed: false;
|
|
@@ -1907,6 +1991,46 @@ export declare const salesShutro: import("../server/orm.js").Module<readonly [im
|
|
|
1907
1991
|
readonly hasDefault: true;
|
|
1908
1992
|
readonly readonly: false;
|
|
1909
1993
|
}>;
|
|
1994
|
+
readonly fixedAmount: import("../server/orm.js").DecimalField<{
|
|
1995
|
+
readonly required: true;
|
|
1996
|
+
readonly computed: false;
|
|
1997
|
+
readonly inverse: false;
|
|
1998
|
+
readonly sequence: false;
|
|
1999
|
+
readonly computeName: undefined;
|
|
2000
|
+
readonly store: true;
|
|
2001
|
+
readonly hasDefault: true;
|
|
2002
|
+
readonly readonly: false;
|
|
2003
|
+
}>;
|
|
2004
|
+
readonly affectsBase: import("../server/orm.js").ScalarField<"boolean", boolean, boolean, {
|
|
2005
|
+
readonly required: true;
|
|
2006
|
+
readonly computed: false;
|
|
2007
|
+
readonly inverse: false;
|
|
2008
|
+
readonly sequence: false;
|
|
2009
|
+
readonly computeName: undefined;
|
|
2010
|
+
readonly store: true;
|
|
2011
|
+
readonly hasDefault: true;
|
|
2012
|
+
readonly readonly: false;
|
|
2013
|
+
}>;
|
|
2014
|
+
readonly priceIncluded: import("../server/orm.js").ScalarField<"boolean", boolean, boolean, {
|
|
2015
|
+
readonly required: true;
|
|
2016
|
+
readonly computed: false;
|
|
2017
|
+
readonly inverse: false;
|
|
2018
|
+
readonly sequence: false;
|
|
2019
|
+
readonly computeName: undefined;
|
|
2020
|
+
readonly store: true;
|
|
2021
|
+
readonly hasDefault: true;
|
|
2022
|
+
readonly readonly: false;
|
|
2023
|
+
}>;
|
|
2024
|
+
readonly reverseCharge: import("../server/orm.js").ScalarField<"boolean", boolean, boolean, {
|
|
2025
|
+
readonly required: true;
|
|
2026
|
+
readonly computed: false;
|
|
2027
|
+
readonly inverse: false;
|
|
2028
|
+
readonly sequence: false;
|
|
2029
|
+
readonly computeName: undefined;
|
|
2030
|
+
readonly store: true;
|
|
2031
|
+
readonly hasDefault: true;
|
|
2032
|
+
readonly readonly: false;
|
|
2033
|
+
}>;
|
|
1910
2034
|
}, {} & import("../server/orm.js").TransitionMethods<{
|
|
1911
2035
|
readonly name: import("../server/orm.js").CharField<{
|
|
1912
2036
|
readonly required: true;
|
|
@@ -1928,6 +2052,26 @@ export declare const salesShutro: import("../server/orm.js").Module<readonly [im
|
|
|
1928
2052
|
readonly hasDefault: true;
|
|
1929
2053
|
readonly readonly: false;
|
|
1930
2054
|
}>;
|
|
2055
|
+
readonly sequence: import("../server/orm.js").ScalarField<"integer", number, number, {
|
|
2056
|
+
readonly required: true;
|
|
2057
|
+
readonly computed: false;
|
|
2058
|
+
readonly inverse: false;
|
|
2059
|
+
readonly sequence: false;
|
|
2060
|
+
readonly computeName: undefined;
|
|
2061
|
+
readonly store: true;
|
|
2062
|
+
readonly hasDefault: true;
|
|
2063
|
+
readonly readonly: false;
|
|
2064
|
+
}>;
|
|
2065
|
+
readonly amountType: import("../server/orm.js").SelectionField<"fixed" | "percent", {
|
|
2066
|
+
readonly required: true;
|
|
2067
|
+
readonly computed: false;
|
|
2068
|
+
readonly inverse: false;
|
|
2069
|
+
readonly sequence: false;
|
|
2070
|
+
readonly computeName: undefined;
|
|
2071
|
+
readonly store: true;
|
|
2072
|
+
readonly hasDefault: true;
|
|
2073
|
+
readonly readonly: false;
|
|
2074
|
+
}>;
|
|
1931
2075
|
readonly rate: import("../server/orm.js").DecimalField<{
|
|
1932
2076
|
readonly required: true;
|
|
1933
2077
|
readonly computed: false;
|
|
@@ -1938,6 +2082,46 @@ export declare const salesShutro: import("../server/orm.js").Module<readonly [im
|
|
|
1938
2082
|
readonly hasDefault: true;
|
|
1939
2083
|
readonly readonly: false;
|
|
1940
2084
|
}>;
|
|
2085
|
+
readonly fixedAmount: import("../server/orm.js").DecimalField<{
|
|
2086
|
+
readonly required: true;
|
|
2087
|
+
readonly computed: false;
|
|
2088
|
+
readonly inverse: false;
|
|
2089
|
+
readonly sequence: false;
|
|
2090
|
+
readonly computeName: undefined;
|
|
2091
|
+
readonly store: true;
|
|
2092
|
+
readonly hasDefault: true;
|
|
2093
|
+
readonly readonly: false;
|
|
2094
|
+
}>;
|
|
2095
|
+
readonly affectsBase: import("../server/orm.js").ScalarField<"boolean", boolean, boolean, {
|
|
2096
|
+
readonly required: true;
|
|
2097
|
+
readonly computed: false;
|
|
2098
|
+
readonly inverse: false;
|
|
2099
|
+
readonly sequence: false;
|
|
2100
|
+
readonly computeName: undefined;
|
|
2101
|
+
readonly store: true;
|
|
2102
|
+
readonly hasDefault: true;
|
|
2103
|
+
readonly readonly: false;
|
|
2104
|
+
}>;
|
|
2105
|
+
readonly priceIncluded: import("../server/orm.js").ScalarField<"boolean", boolean, boolean, {
|
|
2106
|
+
readonly required: true;
|
|
2107
|
+
readonly computed: false;
|
|
2108
|
+
readonly inverse: false;
|
|
2109
|
+
readonly sequence: false;
|
|
2110
|
+
readonly computeName: undefined;
|
|
2111
|
+
readonly store: true;
|
|
2112
|
+
readonly hasDefault: true;
|
|
2113
|
+
readonly readonly: false;
|
|
2114
|
+
}>;
|
|
2115
|
+
readonly reverseCharge: import("../server/orm.js").ScalarField<"boolean", boolean, boolean, {
|
|
2116
|
+
readonly required: true;
|
|
2117
|
+
readonly computed: false;
|
|
2118
|
+
readonly inverse: false;
|
|
2119
|
+
readonly sequence: false;
|
|
2120
|
+
readonly computeName: undefined;
|
|
2121
|
+
readonly store: true;
|
|
2122
|
+
readonly hasDefault: true;
|
|
2123
|
+
readonly readonly: false;
|
|
2124
|
+
}>;
|
|
1941
2125
|
}>>, import("../server/orm.js").Model<"product.product", {
|
|
1942
2126
|
readonly id: import("../server/orm.js").IdField<"product.product">;
|
|
1943
2127
|
readonly createdAt: import("../server/orm.js").ScalarField<'datetime', Date, Date, {
|
|
@@ -2081,6 +2265,26 @@ export declare const salesShutro: import("../server/orm.js").Module<readonly [im
|
|
|
2081
2265
|
readonly hasDefault: true;
|
|
2082
2266
|
readonly readonly: false;
|
|
2083
2267
|
}>;
|
|
2268
|
+
readonly taxes: import("../server/orm.js").Many2manyField<"account.tax", {
|
|
2269
|
+
readonly required: true;
|
|
2270
|
+
readonly computed: false;
|
|
2271
|
+
readonly inverse: false;
|
|
2272
|
+
readonly sequence: false;
|
|
2273
|
+
readonly computeName: undefined;
|
|
2274
|
+
readonly store: true;
|
|
2275
|
+
readonly hasDefault: true;
|
|
2276
|
+
readonly readonly: false;
|
|
2277
|
+
}>;
|
|
2278
|
+
readonly purchaseTaxes: import("../server/orm.js").Many2manyField<"account.tax", {
|
|
2279
|
+
readonly required: true;
|
|
2280
|
+
readonly computed: false;
|
|
2281
|
+
readonly inverse: false;
|
|
2282
|
+
readonly sequence: false;
|
|
2283
|
+
readonly computeName: undefined;
|
|
2284
|
+
readonly store: true;
|
|
2285
|
+
readonly hasDefault: true;
|
|
2286
|
+
readonly readonly: false;
|
|
2287
|
+
}>;
|
|
2084
2288
|
readonly tax: import("../server/orm.js").Many2oneField<"account.tax", {
|
|
2085
2289
|
readonly required: false;
|
|
2086
2290
|
readonly computed: false;
|
|
@@ -2089,7 +2293,7 @@ export declare const salesShutro: import("../server/orm.js").Module<readonly [im
|
|
|
2089
2293
|
readonly computeName: undefined;
|
|
2090
2294
|
readonly store: true;
|
|
2091
2295
|
readonly hasDefault: false;
|
|
2092
|
-
readonly readonly:
|
|
2296
|
+
readonly readonly: true;
|
|
2093
2297
|
}>;
|
|
2094
2298
|
readonly purchaseTax: import("../server/orm.js").Many2oneField<"account.tax", {
|
|
2095
2299
|
readonly required: false;
|
|
@@ -2099,7 +2303,7 @@ export declare const salesShutro: import("../server/orm.js").Module<readonly [im
|
|
|
2099
2303
|
readonly computeName: undefined;
|
|
2100
2304
|
readonly store: true;
|
|
2101
2305
|
readonly hasDefault: false;
|
|
2102
|
-
readonly readonly:
|
|
2306
|
+
readonly readonly: true;
|
|
2103
2307
|
}>;
|
|
2104
2308
|
readonly description: import("../server/orm.js").ScalarField<"text", string, string | Readonly<Record<string, string>>, {
|
|
2105
2309
|
readonly required: false;
|
|
@@ -2212,6 +2416,26 @@ export declare const salesShutro: import("../server/orm.js").Module<readonly [im
|
|
|
2212
2416
|
readonly hasDefault: true;
|
|
2213
2417
|
readonly readonly: false;
|
|
2214
2418
|
}>;
|
|
2419
|
+
readonly taxes: import("../server/orm.js").Many2manyField<"account.tax", {
|
|
2420
|
+
readonly required: true;
|
|
2421
|
+
readonly computed: false;
|
|
2422
|
+
readonly inverse: false;
|
|
2423
|
+
readonly sequence: false;
|
|
2424
|
+
readonly computeName: undefined;
|
|
2425
|
+
readonly store: true;
|
|
2426
|
+
readonly hasDefault: true;
|
|
2427
|
+
readonly readonly: false;
|
|
2428
|
+
}>;
|
|
2429
|
+
readonly purchaseTaxes: import("../server/orm.js").Many2manyField<"account.tax", {
|
|
2430
|
+
readonly required: true;
|
|
2431
|
+
readonly computed: false;
|
|
2432
|
+
readonly inverse: false;
|
|
2433
|
+
readonly sequence: false;
|
|
2434
|
+
readonly computeName: undefined;
|
|
2435
|
+
readonly store: true;
|
|
2436
|
+
readonly hasDefault: true;
|
|
2437
|
+
readonly readonly: false;
|
|
2438
|
+
}>;
|
|
2215
2439
|
readonly tax: import("../server/orm.js").Many2oneField<"account.tax", {
|
|
2216
2440
|
readonly required: false;
|
|
2217
2441
|
readonly computed: false;
|
|
@@ -2220,7 +2444,7 @@ export declare const salesShutro: import("../server/orm.js").Module<readonly [im
|
|
|
2220
2444
|
readonly computeName: undefined;
|
|
2221
2445
|
readonly store: true;
|
|
2222
2446
|
readonly hasDefault: false;
|
|
2223
|
-
readonly readonly:
|
|
2447
|
+
readonly readonly: true;
|
|
2224
2448
|
}>;
|
|
2225
2449
|
readonly purchaseTax: import("../server/orm.js").Many2oneField<"account.tax", {
|
|
2226
2450
|
readonly required: false;
|
|
@@ -2230,7 +2454,7 @@ export declare const salesShutro: import("../server/orm.js").Module<readonly [im
|
|
|
2230
2454
|
readonly computeName: undefined;
|
|
2231
2455
|
readonly store: true;
|
|
2232
2456
|
readonly hasDefault: false;
|
|
2233
|
-
readonly readonly:
|
|
2457
|
+
readonly readonly: true;
|
|
2234
2458
|
}>;
|
|
2235
2459
|
readonly description: import("../server/orm.js").ScalarField<"text", string, string | Readonly<Record<string, string>>, {
|
|
2236
2460
|
readonly required: false;
|
package/dist/sales/module.js
CHANGED
|
@@ -5,9 +5,14 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { contactsShutro } from '../contacts/index.js';
|
|
7
7
|
import { messagingShutro } from '../messaging/index.js';
|
|
8
|
-
import { productShutro } from '../product/index.js';
|
|
8
|
+
import { computeTaxes, productShutro, taxRule } from '../product/index.js';
|
|
9
9
|
import { orm } from '../server/orm.js';
|
|
10
10
|
import { check, compute, defineModel, defineModule, f, onchange, records, } from './.kosh/bindings.js';
|
|
11
|
+
/** A line's taxes through the engine (RFC 0016): its amount after discount, its taxes in order. */
|
|
12
|
+
function taxesOf(l) {
|
|
13
|
+
const amount = l.quantity.times(l.priceUnit).times(orm.toDecimal(100).minus(l.discount)).div(100);
|
|
14
|
+
return computeTaxes(amount, l.quantity, [...l.taxes].map(taxRule));
|
|
15
|
+
}
|
|
11
16
|
const amounts = compute('sale.order', ['amountUntaxed', 'amountTax', 'amountTotal'], ['lines.subtotal', 'lines.taxAmount'], (orders) => {
|
|
12
17
|
for (const o of orders) {
|
|
13
18
|
// A new order has no currency until its partner is chosen: no amounts yet.
|
|
@@ -124,7 +129,10 @@ export const SaleOrderLine = defineModel('sale.order.line', {
|
|
|
124
129
|
priceUnit: f.decimal({ scale: 2, required: true, default: '0', label: 'Unit price' }),
|
|
125
130
|
/** Percent off the unit price (0–100). */
|
|
126
131
|
discount: f.decimal({ scale: 2, required: true, default: '0', label: 'Discount %' }),
|
|
127
|
-
|
|
132
|
+
/** The line's taxes, applied in order (RFC 0016). */
|
|
133
|
+
taxes: f.many2many('account.tax'),
|
|
134
|
+
/** Before 0.2.0, one tax per line: copied into `taxes` by the migration; dropped later. */
|
|
135
|
+
tax: f.many2one('account.tax', { label: 'Tax (before 0.2.0)', readonly: true }),
|
|
128
136
|
/** The order's currency, so line amounts are Money in it. */
|
|
129
137
|
currency: f.many2one('res.currency', {
|
|
130
138
|
store: true,
|
|
@@ -136,33 +144,54 @@ export const SaleOrderLine = defineModel('sale.order.line', {
|
|
|
136
144
|
subtotal: f.monetary({
|
|
137
145
|
currency: 'currency',
|
|
138
146
|
store: true,
|
|
139
|
-
...compute('sale.order.line', 'subtotal', [
|
|
147
|
+
...compute('sale.order.line', 'subtotal', [
|
|
148
|
+
'quantity',
|
|
149
|
+
'priceUnit',
|
|
150
|
+
'discount',
|
|
151
|
+
'taxes.rate',
|
|
152
|
+
'taxes.sequence',
|
|
153
|
+
'taxes.amountType',
|
|
154
|
+
'taxes.fixedAmount',
|
|
155
|
+
'taxes.affectsBase',
|
|
156
|
+
'taxes.priceIncluded',
|
|
157
|
+
'taxes.reverseCharge',
|
|
158
|
+
], (lines) => {
|
|
140
159
|
for (const l of lines)
|
|
141
|
-
l.subtotal = l.
|
|
142
|
-
.times(l.priceUnit)
|
|
143
|
-
.times(orm.toDecimal(100).minus(l.discount))
|
|
144
|
-
.div(100);
|
|
160
|
+
l.subtotal = taxesOf(l).untaxed;
|
|
145
161
|
}),
|
|
146
162
|
}),
|
|
147
163
|
taxAmount: f.monetary({
|
|
148
164
|
currency: 'currency',
|
|
149
165
|
store: true,
|
|
150
166
|
label: 'Tax',
|
|
151
|
-
...compute('sale.order.line', 'taxAmount', [
|
|
167
|
+
...compute('sale.order.line', 'taxAmount', [
|
|
168
|
+
'quantity',
|
|
169
|
+
'priceUnit',
|
|
170
|
+
'discount',
|
|
171
|
+
'taxes.rate',
|
|
172
|
+
'taxes.sequence',
|
|
173
|
+
'taxes.amountType',
|
|
174
|
+
'taxes.fixedAmount',
|
|
175
|
+
'taxes.affectsBase',
|
|
176
|
+
'taxes.priceIncluded',
|
|
177
|
+
'taxes.reverseCharge',
|
|
178
|
+
], (lines) => {
|
|
152
179
|
for (const l of lines)
|
|
153
|
-
l.taxAmount = (l
|
|
180
|
+
l.taxAmount = taxesOf(l).taxTotal;
|
|
154
181
|
}),
|
|
155
182
|
}),
|
|
156
183
|
},
|
|
157
184
|
onchange: {
|
|
158
|
-
product: onchange('sale.order.line', async (d) => {
|
|
185
|
+
product: onchange('sale.order.line', async (d, env) => {
|
|
159
186
|
const p = await d.record('product');
|
|
160
187
|
if (p === null)
|
|
161
188
|
return;
|
|
162
189
|
d.set('name', p.name);
|
|
163
190
|
d.set('priceUnit', p.listPrice);
|
|
164
191
|
d.set('uom', p.uom?.id ?? null);
|
|
165
|
-
|
|
192
|
+
// The product's taxes, loaded (a draft's related record has its plain fields only).
|
|
193
|
+
const [taxed] = await env.model('product.product').browse([p.id]).load({ taxes: true });
|
|
194
|
+
d.set('taxes', { set: [...(taxed?.taxes.ids ?? [])] });
|
|
166
195
|
}),
|
|
167
196
|
},
|
|
168
197
|
constraints: {
|
|
@@ -178,7 +207,17 @@ export const SaleOrderLine = defineModel('sale.order.line', {
|
|
|
178
207
|
});
|
|
179
208
|
export const salesShutro = defineModule({
|
|
180
209
|
name: 'sales',
|
|
181
|
-
version: '0.
|
|
210
|
+
version: '0.2.0',
|
|
211
|
+
migrations: [
|
|
212
|
+
{
|
|
213
|
+
version: '0.2.0',
|
|
214
|
+
description: 'Several taxes per line: the single tax of each line becomes its first',
|
|
215
|
+
up: async (ctx) => {
|
|
216
|
+
await ctx.sql `INSERT INTO sale_order_line_account_tax_rel (sale_order_line_id, account_tax_id)
|
|
217
|
+
SELECT id, tax_id FROM sale_order_line WHERE tax_id IS NOT NULL ON CONFLICT DO NOTHING`;
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
],
|
|
182
221
|
depends: [contactsShutro, productShutro, messagingShutro],
|
|
183
222
|
groups: [
|
|
184
223
|
orm.defineGroup({
|
package/dist/server/auth/base.js
CHANGED
|
@@ -20,6 +20,8 @@ const ResCompany = defineModel('res.company', {
|
|
|
20
20
|
fields: {
|
|
21
21
|
name: f.char({ required: true }),
|
|
22
22
|
currency: f.many2one('res.currency', { required: true }),
|
|
23
|
+
/** How numbers are grouped on screen and in documents (RFC 0016): 1,234,567 or 12,34,567 (lakh and crore). */
|
|
24
|
+
numberGrouping: f.selection({ international: 'International (1,234,567)', lakh: 'Lakh and crore (12,34,567)' }, { required: true, default: 'international', label: 'Number grouping' }),
|
|
23
25
|
},
|
|
24
26
|
});
|
|
25
27
|
const readRows = async (env, model, ids, keys) => env.asSuperuser({ reason: 'check administrators' }, async (su) => {
|
|
@@ -37,6 +37,8 @@ export interface UserInfo {
|
|
|
37
37
|
readonly name: string;
|
|
38
38
|
readonly company: number | null;
|
|
39
39
|
readonly companies: readonly number[];
|
|
40
|
+
/** The number grouping of each of the user's companies (RFC 0016): `lakh` or `international`. */
|
|
41
|
+
readonly groupings: Readonly<Record<string, 'international' | 'lakh'>>;
|
|
40
42
|
readonly twoFactorEnabled: boolean;
|
|
41
43
|
/** Holds an administrator role (in some company). */
|
|
42
44
|
readonly administrator: boolean;
|