shutro-erp 0.2.0 → 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.
Files changed (232) hide show
  1. package/README.md +17 -10
  2. package/dist/account_portal/.kosh/bindings.d.ts +22 -0
  3. package/dist/account_portal/.kosh/bindings.js +15 -0
  4. package/dist/account_portal/.kosh/schema.d.ts +1350 -0
  5. package/dist/account_portal/index.d.ts +3 -0
  6. package/dist/account_portal/index.js +73 -0
  7. package/dist/account_portal/module.d.ts +5983 -0
  8. package/dist/account_portal/module.js +18 -0
  9. package/dist/accounting/.kosh/bindings.js +1 -1
  10. package/dist/accounting/.kosh/schema.d.ts +142 -9
  11. package/dist/accounting/chart.d.ts +40 -8
  12. package/dist/accounting/chart.js +124 -30
  13. package/dist/accounting/closing.d.ts +6 -1
  14. package/dist/accounting/closing.js +5 -1
  15. package/dist/accounting/demo.js +6 -5
  16. package/dist/accounting/index.d.ts +3 -3
  17. package/dist/accounting/index.js +200 -23
  18. package/dist/accounting/module.d.ts +3326 -1086
  19. package/dist/accounting/module.js +408 -66
  20. package/dist/accounting/payments.d.ts +25 -0
  21. package/dist/accounting/payments.js +96 -4
  22. package/dist/accounting/web/RegisterPayment.d.ts +3 -2
  23. package/dist/accounting/web/RegisterPayment.js +39 -6
  24. package/dist/accounting/web/SettingsPage.js +5 -1
  25. package/dist/accounting/web/messages.js +10 -0
  26. package/dist/cli/index.d.ts +1 -1
  27. package/dist/cli/index.js +1 -1
  28. package/dist/cli/init.d.ts +5 -0
  29. package/dist/cli/init.js +195 -53
  30. package/dist/cli/launch.d.ts +16 -0
  31. package/dist/cli/launch.js +138 -0
  32. package/dist/cli/prompt.d.ts +35 -0
  33. package/dist/cli/prompt.js +46 -0
  34. package/dist/cli/templates.d.ts +11 -3
  35. package/dist/cli/templates.js +32 -7
  36. package/dist/cli/tui.d.ts +7 -0
  37. package/dist/cli/tui.js +254 -0
  38. package/dist/cli/ui.d.ts +25 -5
  39. package/dist/cli/ui.js +49 -9
  40. package/dist/contacts/.kosh/bindings.js +1 -1
  41. package/dist/contacts/.kosh/schema.d.ts +3 -1
  42. package/dist/contacts/index.js +24 -1
  43. package/dist/contacts/module.d.ts +42 -0
  44. package/dist/contacts/module.js +3 -1
  45. package/dist/import/convert.d.ts +55 -0
  46. package/dist/import/convert.js +224 -0
  47. package/dist/import/csv.d.ts +28 -0
  48. package/dist/import/csv.js +115 -0
  49. package/dist/import/index.d.ts +33 -0
  50. package/dist/import/index.js +60 -0
  51. package/dist/import/mapping.d.ts +15 -0
  52. package/dist/import/mapping.js +33 -0
  53. package/dist/import/match.d.ts +24 -0
  54. package/dist/import/match.js +60 -0
  55. package/dist/import/models.d.ts +2 -0
  56. package/dist/import/models.js +102 -0
  57. package/dist/import/routes.d.ts +13 -0
  58. package/dist/import/routes.js +392 -0
  59. package/dist/import/run.d.ts +131 -0
  60. package/dist/import/run.js +568 -0
  61. package/dist/import/service.d.ts +153 -0
  62. package/dist/import/service.js +367 -0
  63. package/dist/import/web/ImportButton.d.ts +7 -0
  64. package/dist/import/web/ImportButton.js +31 -0
  65. package/dist/import/web/ImportWizard.d.ts +75 -0
  66. package/dist/import/web/ImportWizard.js +217 -0
  67. package/dist/import/web/index.d.ts +13 -0
  68. package/dist/import/web/index.js +18 -0
  69. package/dist/import/web/messages.d.ts +2 -0
  70. package/dist/import/web/messages.js +139 -0
  71. package/dist/import/worker.d.ts +3 -0
  72. package/dist/import/worker.js +52 -0
  73. package/dist/import/xlsx.d.ts +20 -0
  74. package/dist/import/xlsx.js +192 -0
  75. package/dist/l10n_bd/.kosh/bindings.d.ts +22 -0
  76. package/dist/l10n_bd/.kosh/bindings.js +15 -0
  77. package/dist/l10n_bd/.kosh/schema.d.ts +1281 -0
  78. package/dist/l10n_bd/documents.d.ts +8 -0
  79. package/dist/l10n_bd/documents.js +183 -0
  80. package/dist/l10n_bd/index.d.ts +8 -0
  81. package/dist/l10n_bd/index.js +156 -0
  82. package/dist/l10n_bd/module.d.ts +5705 -0
  83. package/dist/l10n_bd/module.js +163 -0
  84. package/dist/l10n_bd/mushak.d.ts +67 -0
  85. package/dist/l10n_bd/mushak.js +139 -0
  86. package/dist/l10n_bd/routes.d.ts +3 -0
  87. package/dist/l10n_bd/routes.js +205 -0
  88. package/dist/l10n_bd/web/MushakPage.d.ts +7 -0
  89. package/dist/l10n_bd/web/MushakPage.js +53 -0
  90. package/dist/l10n_bd/web/index.d.ts +13 -0
  91. package/dist/l10n_bd/web/index.js +18 -0
  92. package/dist/l10n_bd/web/messages.d.ts +2 -0
  93. package/dist/l10n_bd/web/messages.js +101 -0
  94. package/dist/l10n_in/.kosh/bindings.d.ts +22 -0
  95. package/dist/l10n_in/.kosh/bindings.js +15 -0
  96. package/dist/l10n_in/.kosh/schema.d.ts +1343 -0
  97. package/dist/l10n_in/documents.d.ts +8 -0
  98. package/dist/l10n_in/documents.js +114 -0
  99. package/dist/l10n_in/einvoice.d.ts +253 -0
  100. package/dist/l10n_in/einvoice.js +485 -0
  101. package/dist/l10n_in/gstr.d.ts +109 -0
  102. package/dist/l10n_in/gstr.js +430 -0
  103. package/dist/l10n_in/index.d.ts +20 -0
  104. package/dist/l10n_in/index.js +232 -0
  105. package/dist/l10n_in/module.d.ts +7823 -0
  106. package/dist/l10n_in/module.js +427 -0
  107. package/dist/l10n_in/routes-einvoice.d.ts +15 -0
  108. package/dist/l10n_in/routes-einvoice.js +124 -0
  109. package/dist/l10n_in/routes.d.ts +17 -0
  110. package/dist/l10n_in/routes.js +282 -0
  111. package/dist/l10n_in/web/EInvoicePanel.d.ts +8 -0
  112. package/dist/l10n_in/web/EInvoicePanel.js +63 -0
  113. package/dist/l10n_in/web/GstPage.d.ts +7 -0
  114. package/dist/l10n_in/web/GstPage.js +57 -0
  115. package/dist/l10n_in/web/GstSettings.d.ts +10 -0
  116. package/dist/l10n_in/web/GstSettings.js +36 -0
  117. package/dist/l10n_in/web/index.d.ts +15 -0
  118. package/dist/l10n_in/web/index.js +22 -0
  119. package/dist/l10n_in/web/messages.d.ts +2 -0
  120. package/dist/l10n_in/web/messages.js +166 -0
  121. package/dist/modules-sdk/demo.d.ts +2 -0
  122. package/dist/modules-sdk/demo.js +7 -3
  123. package/dist/modules-sdk/index.d.ts +2 -2
  124. package/dist/modules-sdk/index.js +1 -1
  125. package/dist/modules-sdk/manifest.d.ts +132 -0
  126. package/dist/modules-sdk/manifest.js +22 -0
  127. package/dist/notify/inbox.js +21 -0
  128. package/dist/notify/messages.js +4 -0
  129. package/dist/notify/models.d.ts +1 -1
  130. package/dist/notify/models.js +2 -0
  131. package/dist/notify/web/messages.js +4 -0
  132. package/dist/portal/.kosh/bindings.d.ts +22 -0
  133. package/dist/portal/.kosh/bindings.js +15 -0
  134. package/dist/portal/.kosh/schema.d.ts +346 -0
  135. package/dist/portal/announce.d.ts +16 -0
  136. package/dist/portal/announce.js +117 -0
  137. package/dist/portal/documents.d.ts +17 -0
  138. package/dist/portal/documents.js +61 -0
  139. package/dist/portal/index.d.ts +20 -0
  140. package/dist/portal/index.js +65 -0
  141. package/dist/portal/module.d.ts +1405 -0
  142. package/dist/portal/module.js +84 -0
  143. package/dist/portal/routes-documents.d.ts +2 -0
  144. package/dist/portal/routes-documents.js +391 -0
  145. package/dist/portal/routes.d.ts +13 -0
  146. package/dist/portal/routes.js +313 -0
  147. package/dist/portal/rules.d.ts +11 -0
  148. package/dist/portal/rules.js +25 -0
  149. package/dist/portal/web/PortalAccess.d.ts +8 -0
  150. package/dist/portal/web/PortalAccess.js +66 -0
  151. package/dist/portal/web/index.d.ts +12 -0
  152. package/dist/portal/web/index.js +17 -0
  153. package/dist/portal/web/messages.d.ts +2 -0
  154. package/dist/portal/web/messages.js +33 -0
  155. package/dist/product/.kosh/bindings.js +1 -1
  156. package/dist/product/.kosh/schema.d.ts +12 -3
  157. package/dist/product/demo.js +6 -5
  158. package/dist/product/index.d.ts +1 -0
  159. package/dist/product/index.js +17 -4
  160. package/dist/product/module.d.ts +346 -14
  161. package/dist/product/module.js +48 -18
  162. package/dist/product/taxes.d.ts +59 -0
  163. package/dist/product/taxes.js +61 -0
  164. package/dist/project/.kosh/bindings.js +1 -1
  165. package/dist/project/.kosh/schema.d.ts +3 -1
  166. package/dist/project/module.d.ts +20 -0
  167. package/dist/project_portal/.kosh/bindings.d.ts +22 -0
  168. package/dist/project_portal/.kosh/bindings.js +15 -0
  169. package/dist/project_portal/.kosh/schema.d.ts +671 -0
  170. package/dist/project_portal/index.d.ts +9 -0
  171. package/dist/project_portal/index.js +42 -0
  172. package/dist/project_portal/module.d.ts +2142 -0
  173. package/dist/project_portal/module.js +22 -0
  174. package/dist/purchase/.kosh/bindings.js +1 -1
  175. package/dist/purchase/.kosh/schema.d.ts +15 -4
  176. package/dist/purchase/demo.js +3 -3
  177. package/dist/purchase/index.js +1 -1
  178. package/dist/purchase/module.d.ts +232 -8
  179. package/dist/purchase/module.js +51 -9
  180. package/dist/purchase_account/.kosh/bindings.js +1 -1
  181. package/dist/purchase_account/.kosh/schema.d.ts +144 -10
  182. package/dist/purchase_account/module.d.ts +2008 -641
  183. package/dist/purchase_account/module.js +2 -2
  184. package/dist/purchase_portal/.kosh/bindings.d.ts +22 -0
  185. package/dist/purchase_portal/.kosh/bindings.js +15 -0
  186. package/dist/purchase_portal/.kosh/schema.d.ts +822 -0
  187. package/dist/purchase_portal/index.d.ts +9 -0
  188. package/dist/purchase_portal/index.js +53 -0
  189. package/dist/purchase_portal/module.d.ts +2758 -0
  190. package/dist/purchase_portal/module.js +18 -0
  191. package/dist/reporting/documents.js +20 -3
  192. package/dist/reporting/index.d.ts +1 -0
  193. package/dist/reporting/index.js +1 -0
  194. package/dist/reporting/routes-documents.js +9 -2
  195. package/dist/reporting/words.d.ts +11 -0
  196. package/dist/reporting/words.js +229 -0
  197. package/dist/sale_account/.kosh/bindings.js +1 -1
  198. package/dist/sale_account/.kosh/schema.d.ts +144 -10
  199. package/dist/sale_account/module.d.ts +2008 -641
  200. package/dist/sale_account/module.js +3 -3
  201. package/dist/sale_portal/.kosh/bindings.d.ts +22 -0
  202. package/dist/sale_portal/.kosh/bindings.js +15 -0
  203. package/dist/sale_portal/.kosh/schema.d.ts +736 -0
  204. package/dist/sale_portal/index.d.ts +9 -0
  205. package/dist/sale_portal/index.js +71 -0
  206. package/dist/sale_portal/module.d.ts +2718 -0
  207. package/dist/sale_portal/module.js +19 -0
  208. package/dist/sale_project/.kosh/bindings.js +1 -1
  209. package/dist/sale_project/.kosh/schema.d.ts +15 -4
  210. package/dist/sale_project/module.d.ts +390 -10
  211. package/dist/sales/.kosh/bindings.js +1 -1
  212. package/dist/sales/.kosh/schema.d.ts +15 -4
  213. package/dist/sales/demo.js +3 -3
  214. package/dist/sales/index.js +67 -1
  215. package/dist/sales/module.d.ts +232 -8
  216. package/dist/sales/module.js +51 -12
  217. package/dist/server/auth/base.js +2 -0
  218. package/dist/server/auth/service.d.ts +2 -0
  219. package/dist/server/auth/service.js +7 -1
  220. package/dist/server/index.d.ts +1 -1
  221. package/dist/server/index.js +1 -1
  222. package/dist/server/server.js +26 -1
  223. package/dist/ui/api.d.ts +2 -0
  224. package/dist/ui/app.js +1 -1
  225. package/dist/ui/context.d.ts +3 -1
  226. package/dist/ui/context.js +2 -2
  227. package/dist/ui/index.d.ts +1 -1
  228. package/dist/ui/index.js +1 -1
  229. package/dist/ui/lib/format.d.ts +2 -0
  230. package/dist/ui/lib/format.js +3 -1
  231. package/dist/ui/views/FormView.js +19 -6
  232. package/package.json +50 -2
@@ -0,0 +1,18 @@
1
+ /**
2
+ * The data layer of Purchase in the portal (RFC 0015 §5.4): vendors' portal users read the requests for quotation
3
+ * and orders of their contact and company (the portal's record rule) and nothing else of Purchase.
4
+ */
5
+ import { portalRule, portalShutro } from '../portal/index.js';
6
+ import { purchaseShutro } from '../purchase/index.js';
7
+ import { defineModule, extendModel } from './.kosh/bindings.js';
8
+ export const PurchaseOrderPortal = extendModel('purchase.order', {
9
+ access: { 'portal.user': ['read'] },
10
+ rules: { portal: portalRule('partner') },
11
+ });
12
+ export const purchasePortalShutro = defineModule({
13
+ name: 'purchase_portal',
14
+ version: '0.1.0',
15
+ depends: [purchaseShutro, portalShutro],
16
+ models: [],
17
+ extensions: [PurchaseOrderPortal],
18
+ });
@@ -1,3 +1,10 @@
1
+ /**
2
+ * Documents (RFC 0005 §5): a template is a **layout** (JSON blocks bound to fields and x2many lines, editable in the
3
+ * designer), compiled to HTML with CSS paged media and printed to PDF by Playwright's Chromium. The record is read
4
+ * as the caller (rules and field security), values are formatted for the document's language, and every render is
5
+ * audited. Modules ship default templates in their manifests; administrators edit copies as data.
6
+ */
7
+ import { amountInWords } from './words.js';
1
8
  const esc = (text) => String(text ?? '').replace(/[&<>"']/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' })[c]);
2
9
  /** Formats a value for print: Money, decimals, dates, booleans, related records (their display name). */
3
10
  export function formatValue(value, kind, format) {
@@ -99,11 +106,21 @@ function resolve(data, fields, path) {
99
106
  }
100
107
  return { value: optionLabel(current, options), kind, label };
101
108
  }
109
+ /** `{{path}}`, or `{{path|words}}`: an amount in words, in the document's language (RFC 0016). */
102
110
  function text(data, fields, template) {
103
- return esc(template).replace(/\{\{\s*([\w.]+)\s*\}\}/g, (_, path) => {
111
+ return esc(template).replace(/\{\{\s*([\w.]+)\s*(?:\|\s*(\w+)\s*)?\}\}/g, (_, path, filter) => {
104
112
  if (path === 'page' || path === 'pages')
105
113
  return `<span class="${path}"></span>`;
106
114
  const r = resolve(data, fields, path);
115
+ if (filter === 'words') {
116
+ const json = r.value !== null && typeof r.value === 'object' && 'toJSON' in r.value
117
+ ? r.value.toJSON()
118
+ : r.value;
119
+ if (json === null || typeof json !== 'object' || !('amount' in json))
120
+ return '';
121
+ const money = json;
122
+ return esc(amountInWords(String(money.amount), money.currency, data.locale ?? 'en'));
123
+ }
107
124
  return esc(formatValue(r.value, r.kind, { locale: data.locale ?? 'en-US', tz: data.tz ?? 'UTC' }));
108
125
  });
109
126
  }
@@ -249,14 +266,14 @@ export async function loadDocumentData(env, model, ids, layout, fields) {
249
266
  collect(b.right, prefix);
250
267
  }
251
268
  else if (b.kind === 'heading' || b.kind === 'text')
252
- for (const m of b.text.matchAll(/\{\{\s*([\w.]+)\s*\}\}/g))
269
+ for (const m of b.text.matchAll(/\{\{\s*([\w.]+)\s*(?:\|\s*\w+\s*)?\}\}/g))
253
270
  paths.add(m[1]);
254
271
  }
255
272
  };
256
273
  collect(layout.blocks);
257
274
  for (const t of [layout.header, layout.footer])
258
275
  if (t !== undefined)
259
- for (const m of t.matchAll(/\{\{\s*([\w.]+)\s*\}\}/g))
276
+ for (const m of t.matchAll(/\{\{\s*([\w.]+)\s*(?:\|\s*\w+\s*)?\}\}/g))
260
277
  paths.add(m[1]);
261
278
  const ref = (name) => env.model(name);
262
279
  /** Loads `keys` on `rows` of `name`, recursing into relation paths. */
@@ -13,6 +13,7 @@ export { type Amount, type Condition, type FieldInfo, type Header, type Measure,
13
13
  export { parseReportQuery, registerReportRoutes, reportTable } from './routes.js';
14
14
  export { documentFields, installTemplates, layoutProblems, registerDocumentRoutes, renderDocument, scheduleRenderer, } from './routes-documents.js';
15
15
  export { type DeliveryAdapter, type JobQueue, nextRun, type Rendered, ScheduleEngine, type ScheduleRenderer, type ScheduleSpec, } from './schedules.js';
16
+ export { amountInWords, banglaWords, englishWords } from './words.js';
16
17
  export { type Cell, moneyFormat, type Sheet, workbook, zip } from './xlsx.js';
17
18
  export { reportingShutro };
18
19
  /** Package identity. */
@@ -17,6 +17,7 @@ export { nextBucket, ReportError, runReport, zonedStart, } from './pivot.js';
17
17
  export { parseReportQuery, registerReportRoutes, reportTable } from './routes.js';
18
18
  export { documentFields, installTemplates, layoutProblems, registerDocumentRoutes, renderDocument, scheduleRenderer, } from './routes-documents.js';
19
19
  export { nextRun, ScheduleEngine, } from './schedules.js';
20
+ export { amountInWords, banglaWords, englishWords } from './words.js';
20
21
  export { moneyFormat, workbook, zip } from './xlsx.js';
21
22
  export { reportingShutro };
22
23
  /** Package identity. */
@@ -46,7 +46,7 @@ export function layoutProblems(layout, model, fields) {
46
46
  }
47
47
  };
48
48
  const texts = (t, from) => {
49
- for (const m of t.matchAll(/\{\{\s*([\w.]+)\s*\}\}/g))
49
+ for (const m of t.matchAll(/\{\{\s*([\w.]+)\s*(?:\|\s*\w+\s*)?\}\}/g))
50
50
  check(m[1], from);
51
51
  };
52
52
  const walk = (blocks) => {
@@ -125,7 +125,14 @@ export async function renderDocument(env, model, template, fields, target, forma
125
125
  if (ids.length === 0)
126
126
  throw bad('No records to print.');
127
127
  const data = await loadDocumentData(env, model.name, ids, layout, fields);
128
- const locale = env.lang.replace('_', '-');
128
+ // The company's number grouping (RFC 0016): lakh and crore print in the Indian English pattern.
129
+ const grouping = await env.asSuperuser({ reason: 'document number grouping' }, async (su) => {
130
+ const found = await ref(su, 'res.company').search({ where: { id: env.companyId }, limit: 1 });
131
+ const [row] = (await found.load(['numberGrouping'])).read(['numberGrouping']);
132
+ return row?.['numberGrouping'];
133
+ });
134
+ const lang = env.lang.replace('_', '-');
135
+ const locale = grouping === 'lakh' && lang.startsWith('en') ? 'en-IN' : lang;
129
136
  const dir = /^(ar|fa|he|ur)/.test(env.lang) ? 'rtl' : 'ltr';
130
137
  const parts = [];
131
138
  const base = {
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Amounts in words for documents (RFC 0016 §5.1): `{{amountTotal|words}}` on an invoice writes "Taka One Lakh Twenty
3
+ * Thousand Only", or in Bangla "এক লক্ষ বিশ হাজার টাকা মাত্র". South Asian currencies count in lakh and crore,
4
+ * the others in thousands and millions. Exact: the amount is decimal text, never a float.
5
+ */
6
+ /** A whole number in English words, by lakh and crore or by thousands. */
7
+ export declare function englishWords(value: bigint, southAsian: boolean): string;
8
+ /** A whole number in Bangla words (always lakh and crore, as Bangla counts). */
9
+ export declare function banglaWords(value: bigint): string;
10
+ /** An amount (decimal text) of `currency` in words, in English or Bangla, ending "Only" / "মাত্র". */
11
+ export declare function amountInWords(amount: string, currency: string, lang: string): string;
@@ -0,0 +1,229 @@
1
+ /**
2
+ * Amounts in words for documents (RFC 0016 §5.1): `{{amountTotal|words}}` on an invoice writes "Taka One Lakh Twenty
3
+ * Thousand Only", or in Bangla "এক লক্ষ বিশ হাজার টাকা মাত্র". South Asian currencies count in lakh and crore,
4
+ * the others in thousands and millions. Exact: the amount is decimal text, never a float.
5
+ */
6
+ const ONES = [
7
+ '',
8
+ 'One',
9
+ 'Two',
10
+ 'Three',
11
+ 'Four',
12
+ 'Five',
13
+ 'Six',
14
+ 'Seven',
15
+ 'Eight',
16
+ 'Nine',
17
+ 'Ten',
18
+ 'Eleven',
19
+ 'Twelve',
20
+ 'Thirteen',
21
+ 'Fourteen',
22
+ 'Fifteen',
23
+ 'Sixteen',
24
+ 'Seventeen',
25
+ 'Eighteen',
26
+ 'Nineteen',
27
+ ];
28
+ const TENS = ['', '', 'Twenty', 'Thirty', 'Forty', 'Fifty', 'Sixty', 'Seventy', 'Eighty', 'Ninety'];
29
+ /** 0–99 in Bangla: each number has its own word. */
30
+ const BN = [
31
+ 'শূন্য',
32
+ 'এক',
33
+ 'দুই',
34
+ 'তিন',
35
+ 'চার',
36
+ 'পাঁচ',
37
+ 'ছয়',
38
+ 'সাত',
39
+ 'আট',
40
+ 'নয়',
41
+ 'দশ',
42
+ 'এগারো',
43
+ 'বারো',
44
+ 'তেরো',
45
+ 'চৌদ্দ',
46
+ 'পনেরো',
47
+ 'ষোলো',
48
+ 'সতেরো',
49
+ 'আঠারো',
50
+ 'উনিশ',
51
+ 'বিশ',
52
+ 'একুশ',
53
+ 'বাইশ',
54
+ 'তেইশ',
55
+ 'চব্বিশ',
56
+ 'পঁচিশ',
57
+ 'ছাব্বিশ',
58
+ 'সাতাশ',
59
+ 'আটাশ',
60
+ 'ঊনত্রিশ',
61
+ 'ত্রিশ',
62
+ 'একত্রিশ',
63
+ 'বত্রিশ',
64
+ 'তেত্রিশ',
65
+ 'চৌত্রিশ',
66
+ 'পঁয়ত্রিশ',
67
+ 'ছত্রিশ',
68
+ 'সাঁইত্রিশ',
69
+ 'আটত্রিশ',
70
+ 'ঊনচল্লিশ',
71
+ 'চল্লিশ',
72
+ 'একচল্লিশ',
73
+ 'বিয়াল্লিশ',
74
+ 'তেতাল্লিশ',
75
+ 'চুয়াল্লিশ',
76
+ 'পঁয়তাল্লিশ',
77
+ 'ছেচল্লিশ',
78
+ 'সাতচল্লিশ',
79
+ 'আটচল্লিশ',
80
+ 'ঊনপঞ্চাশ',
81
+ 'পঞ্চাশ',
82
+ 'একান্ন',
83
+ 'বায়ান্ন',
84
+ 'তিপ্পান্ন',
85
+ 'চুয়ান্ন',
86
+ 'পঞ্চান্ন',
87
+ 'ছাপ্পান্ন',
88
+ 'সাতান্ন',
89
+ 'আটান্ন',
90
+ 'ঊনষাট',
91
+ 'ষাট',
92
+ 'একষট্টি',
93
+ 'বাষট্টি',
94
+ 'তেষট্টি',
95
+ 'চৌষট্টি',
96
+ 'পঁয়ষট্টি',
97
+ 'ছেষট্টি',
98
+ 'সাতষট্টি',
99
+ 'আটষট্টি',
100
+ 'ঊনসত্তর',
101
+ 'সত্তর',
102
+ 'একাত্তর',
103
+ 'বাহাত্তর',
104
+ 'তিয়াত্তর',
105
+ 'চুয়াত্তর',
106
+ 'পঁচাত্তর',
107
+ 'ছিয়াত্তর',
108
+ 'সাতাত্তর',
109
+ 'আটাত্তর',
110
+ 'ঊনআশি',
111
+ 'আশি',
112
+ 'একাশি',
113
+ 'বিরাশি',
114
+ 'তিরাশি',
115
+ 'চুরাশি',
116
+ 'পঁচাশি',
117
+ 'ছিয়াশি',
118
+ 'সাতাশি',
119
+ 'আটাশি',
120
+ 'ঊননব্বই',
121
+ 'নব্বই',
122
+ 'একানব্বই',
123
+ 'বিরানব্বই',
124
+ 'তিরানব্বই',
125
+ 'চুরানব্বই',
126
+ 'পঁচানব্বই',
127
+ 'ছিয়ানব্বই',
128
+ 'সাতানব্বই',
129
+ 'আটানব্বই',
130
+ 'নিরানব্বই',
131
+ ];
132
+ /** Currencies counted in lakh and crore. */
133
+ const SOUTH_ASIAN = new Set(['BDT', 'INR', 'PKR', 'NPR', 'LKR']);
134
+ const UNITS = {
135
+ BDT: { en: ['Taka', 'Paisa'], bn: ['টাকা', 'পয়সা'] },
136
+ INR: { en: ['Rupees', 'Paise'], bn: ['রুপি', 'পয়সা'] },
137
+ PKR: { en: ['Rupees', 'Paisa'], bn: ['রুপি', 'পয়সা'] },
138
+ USD: { en: ['Dollars', 'Cents'], bn: ['ডলার', 'সেন্ট'] },
139
+ EUR: { en: ['Euros', 'Cents'], bn: ['ইউরো', 'সেন্ট'] },
140
+ GBP: { en: ['Pounds', 'Pence'], bn: ['পাউন্ড', 'পেনি'] },
141
+ };
142
+ function under1000(value) {
143
+ const parts = [];
144
+ let n = value;
145
+ if (n >= 100) {
146
+ parts.push(`${ONES[Math.floor(n / 100)]} Hundred`);
147
+ n %= 100;
148
+ }
149
+ if (n >= 20) {
150
+ parts.push(TENS[Math.floor(n / 10)]);
151
+ n %= 10;
152
+ }
153
+ if (n > 0)
154
+ parts.push(ONES[n]);
155
+ return parts.join(' ');
156
+ }
157
+ /** A whole number in English words, by lakh and crore or by thousands. */
158
+ export function englishWords(value, southAsian) {
159
+ if (value === 0n)
160
+ return 'Zero';
161
+ const parts = [];
162
+ let n = value;
163
+ const scales = southAsian
164
+ ? [
165
+ [10000000n, 'Crore'],
166
+ [100000n, 'Lakh'],
167
+ [1000n, 'Thousand'],
168
+ ]
169
+ : [
170
+ [1000000000000n, 'Trillion'],
171
+ [1000000000n, 'Billion'],
172
+ [1000000n, 'Million'],
173
+ [1000n, 'Thousand'],
174
+ ];
175
+ for (const [scale, name] of scales) {
176
+ if (n < scale)
177
+ continue;
178
+ const count = n / scale;
179
+ n %= scale;
180
+ // Above the largest scale (crores of crores), the count is itself in words.
181
+ parts.push(`${count >= 1000n ? englishWords(count, southAsian) : under1000(Number(count))} ${name}`);
182
+ }
183
+ if (n > 0n)
184
+ parts.push(under1000(Number(n)));
185
+ return parts.join(' ');
186
+ }
187
+ /** A whole number in Bangla words (always lakh and crore, as Bangla counts). */
188
+ export function banglaWords(value) {
189
+ if (value === 0n)
190
+ return BN[0];
191
+ const parts = [];
192
+ let n = value;
193
+ for (const [scale, name] of [
194
+ [10000000n, 'কোটি'],
195
+ [100000n, 'লক্ষ'],
196
+ [1000n, 'হাজার'],
197
+ [100n, 'শত'],
198
+ ]) {
199
+ if (n < scale)
200
+ continue;
201
+ const count = n / scale;
202
+ n %= scale;
203
+ const words = count >= 100n ? banglaWords(count) : BN[Number(count)];
204
+ parts.push(scale === 100n ? `${words}${name}` : `${words} ${name}`);
205
+ }
206
+ if (n > 0n)
207
+ parts.push(BN[Number(n)]);
208
+ return parts.join(' ');
209
+ }
210
+ /** An amount (decimal text) of `currency` in words, in English or Bangla, ending "Only" / "মাত্র". */
211
+ export function amountInWords(amount, currency, lang) {
212
+ const negative = amount.trim().startsWith('-');
213
+ const [whole = '0', fraction = ''] = amount.trim().replace(/^[-+]/, '').split('.');
214
+ const major = BigInt(whole === '' ? '0' : whole);
215
+ const minor = BigInt(`${fraction}00`.slice(0, 2));
216
+ const bangla = lang.startsWith('bn');
217
+ const units = UNITS[currency]?.[bangla ? 'bn' : 'en'] ?? [currency, bangla ? 'পয়সা' : 'Cents'];
218
+ if (bangla) {
219
+ const parts = [`${banglaWords(major)} ${units[0]}`];
220
+ if (minor > 0n)
221
+ parts.push(`${banglaWords(minor)} ${units[1]}`);
222
+ return `${negative ? 'ঋণাত্মক ' : ''}${parts.join(' ')} মাত্র`;
223
+ }
224
+ const southAsian = SOUTH_ASIAN.has(currency);
225
+ const parts = [`${units[0]} ${englishWords(major, southAsian)}`];
226
+ if (minor > 0n)
227
+ parts.push(`and ${englishWords(minor, southAsian)} ${units[1]}`);
228
+ return `${negative ? 'Minus ' : ''}${parts.join(' ')} Only`;
229
+ }
@@ -1,4 +1,4 @@
1
- // GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash: fbfc0cfd9ef451fc
1
+ // GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash: dbbbc1f6d027934e
2
2
  // Bindings of module `sale_account`: 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: fbfc0cfd9ef451fc
1
+ // GENERATED by `pnpm generate:models` (Shutro’s generator). Do not edit. definitions-hash: dbbbc1f6d027934e
2
2
  // Schema view of module `sale_account` (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,7 +14,10 @@ export interface SchemaView {
14
14
  readonly 'account.payment': AccountPayment;
15
15
  readonly 'account.payment.term': AccountPaymentTerm;
16
16
  readonly 'account.payment.term.line': AccountPaymentTermLine;
17
+ readonly 'account.payment.withholding': AccountPaymentWithholding;
17
18
  readonly 'account.tax': AccountTax;
19
+ readonly 'account.tax.component': AccountTaxComponent;
20
+ readonly 'account.withholding': AccountWithholding;
18
21
  readonly 'approval.level': ApprovalLevel;
19
22
  readonly 'approval.policy': ApprovalPolicy;
20
23
  readonly 'approval.request': ApprovalRequest;
@@ -38,6 +41,7 @@ export interface SchemaView {
38
41
  readonly 'report.schedule': ReportSchedule;
39
42
  readonly 'report.spreadsheet': ReportSpreadsheet;
40
43
  readonly 'report.template': ReportTemplate;
44
+ readonly 'res.bank.account': ResBankAccount;
41
45
  readonly 'res.company': ResCompany;
42
46
  readonly 'res.currency': ResCurrency;
43
47
  readonly 'res.currency.rate': ResCurrencyRate;
@@ -165,7 +169,7 @@ export interface AccountMove {
165
169
  readonly numberGeneral: F.Char<{ readonly readonly: true; readonly sequence: true }>;
166
170
  readonly journal: F.Many2one<'account.journal', { readonly required: true }>;
167
171
  readonly date: F.DateOnly<{ readonly required: true; readonly default: true }>;
168
- readonly kind: F.Selection<'entry' | 'out_invoice' | 'out_refund' | 'in_invoice' | 'in_refund', { readonly required: true; readonly default: true }>;
172
+ readonly kind: F.Selection<'entry' | 'out_invoice' | 'out_refund' | 'in_invoice' | 'in_refund' | 'out_debit' | 'in_debit', { readonly required: true; readonly default: true }>;
169
173
  readonly partner: F.Many2one<'res.partner'>;
170
174
  readonly ref: F.Char;
171
175
  readonly currency: F.Many2one<'res.currency', { readonly required: true }>;
@@ -177,6 +181,7 @@ export interface AccountMove {
177
181
  readonly amountDebit: F.Monetary<'companyCurrency', { readonly readonly: true; readonly compute: true; readonly store: true }>;
178
182
  readonly amountCredit: F.Monetary<'companyCurrency', { readonly readonly: true; readonly compute: true; readonly store: true }>;
179
183
  readonly dateDue: F.DateOnly;
184
+ readonly paymentDetails: F.Text<{ readonly readonly: true; readonly compute: true }>;
180
185
  readonly paymentTerm: F.Many2one<'account.payment.term'>;
181
186
  readonly invoiceOrigin: F.Char;
182
187
  readonly amountUntaxed: F.Monetary<'currency', { readonly readonly: true; readonly compute: true; readonly store: true }>;
@@ -189,6 +194,8 @@ export interface AccountMove {
189
194
  readonly postedAt: F.Datetime;
190
195
  readonly postedTx: F.Char;
191
196
  readonly reversalOf: F.Many2one<'account.move'>;
197
+ readonly debitOf: F.Many2one<'account.move'>;
198
+ readonly placeOfSupply: F.Char;
192
199
  readonly reversedBy: F.Many2one<'account.move'>;
193
200
  readonly saleOrder: F.Many2one<'sale.order'>; // sale_account
194
201
  };
@@ -231,10 +238,14 @@ export interface AccountMoveLine {
231
238
  readonly quantity: F.Decimal<{ readonly default: true }>;
232
239
  readonly priceUnit: F.Decimal<{ readonly default: true }>;
233
240
  readonly discount: F.Decimal<{ readonly default: true }>;
234
- readonly tax: F.Many2one<'account.tax'>;
241
+ readonly taxes: F.Many2many<'account.tax', { readonly required: true }>;
242
+ readonly tax: F.Many2one<'account.tax', { readonly readonly: true }>;
235
243
  readonly subtotal: F.Monetary<'currency', { readonly readonly: true; readonly compute: true; readonly store: true }>;
236
244
  readonly taxAmount: F.Monetary<'currency', { readonly readonly: true; readonly compute: true; readonly store: true }>;
237
245
  readonly taxLineOf: F.Many2one<'account.tax'>;
246
+ readonly taxComponent: F.Many2one<'account.tax.component'>;
247
+ readonly taxReverseCharge: F.Bool<{ readonly required: true; readonly default: true }>;
248
+ readonly taxBase: F.Monetary<'currency'>;
238
249
  readonly balance: F.Monetary<'companyCurrency', { readonly readonly: true; readonly compute: true; readonly store: true }>;
239
250
  readonly posted: F.Bool<{ readonly required: true; readonly readonly: true; readonly default: true; readonly compute: true; readonly store: true }>;
240
251
  readonly accountType: F.Selection<'asset_receivable' | 'asset_cash' | 'asset_current' | 'asset_prepayments' | 'asset_fixed' | 'asset_non_current' | 'liability_payable' | 'liability_current' | 'liability_non_current' | 'equity' | 'equity_unaffected' | 'income' | 'income_other' | 'expense' | 'expense_direct_cost' | 'expense_depreciation' | 'off_balance', { readonly readonly: true; readonly compute: true; readonly store: true }>;
@@ -298,6 +309,8 @@ export interface AccountPayment {
298
309
  readonly amount: F.Monetary<'currency', { readonly required: true }>;
299
310
  readonly memo: F.Char;
300
311
  readonly documents: F.Many2many<'account.move', { readonly required: true }>;
312
+ readonly withholdings: F.One2many<'account.payment.withholding', { readonly required: true }>;
313
+ readonly amountWithheld: F.Monetary<'currency', { readonly readonly: true; readonly compute: true; readonly store: true }>;
301
314
  readonly move: F.Many2one<'account.move'>;
302
315
  readonly state: F.State<'draft' | 'posted' | 'cancel', { readonly required: true; readonly readonly: true; readonly default: true }>;
303
316
  };
@@ -354,6 +367,29 @@ export interface AccountPaymentTermLine {
354
367
  export interface AccountPaymentTermLineMethods extends F.Methods<typeof import('../../accounting/index.js').accountingShutro, 'account.payment.term.line'> {
355
368
  }
356
369
 
370
+ /** `account.payment.withholding` (owner: accounting). */
371
+ export interface AccountPaymentWithholding {
372
+ readonly name: 'account.payment.withholding';
373
+ readonly fields: {
374
+ readonly id: F.Id<'account.payment.withholding'>;
375
+ readonly createdAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
376
+ readonly updatedAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
377
+ readonly createdBy: F.Many2one<'res.users', { readonly readonly: true }>;
378
+ readonly updatedBy: F.Many2one<'res.users', { readonly readonly: true }>;
379
+ readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
380
+ readonly payment: F.Many2one<'account.payment', { readonly required: true }>;
381
+ readonly withholding: F.Many2one<'account.withholding', { readonly required: true }>;
382
+ readonly currency: F.Many2one<'res.currency', { readonly readonly: true; readonly compute: true; readonly store: true }>;
383
+ readonly base: F.Monetary<'currency'>;
384
+ readonly amount: F.Monetary<'currency', { readonly required: true }>;
385
+ };
386
+ readonly methods: AccountPaymentWithholdingMethods;
387
+ }
388
+
389
+ /** Methods of `account.payment.withholding`: declared ones and transitions. */
390
+ export interface AccountPaymentWithholdingMethods extends F.Methods<typeof import('../../accounting/index.js').accountingShutro, 'account.payment.withholding'> {
391
+ }
392
+
357
393
  /** `account.tax` (owner: product; extended by: accounting). */
358
394
  export interface AccountTax {
359
395
  readonly name: 'account.tax';
@@ -367,10 +403,17 @@ export interface AccountTax {
367
403
  readonly active: F.Bool<{ readonly required: true; readonly default: true }>;
368
404
  readonly name: F.Char<{ readonly required: true; readonly translate: true }>;
369
405
  readonly use: F.Selection<'sale' | 'purchase', { readonly required: true; readonly default: true }>;
406
+ readonly sequence: F.Integer<{ readonly required: true; readonly default: true }>;
407
+ readonly amountType: F.Selection<'percent' | 'fixed', { readonly required: true; readonly default: true }>;
370
408
  readonly rate: F.Decimal<{ readonly required: true; readonly default: true }>;
409
+ readonly fixedAmount: F.Decimal<{ readonly required: true; readonly default: true }>;
410
+ readonly affectsBase: F.Bool<{ readonly required: true; readonly default: true }>;
411
+ readonly priceIncluded: F.Bool<{ readonly required: true; readonly default: true }>;
412
+ readonly reverseCharge: F.Bool<{ readonly required: true; readonly default: true }>;
371
413
  readonly account: F.Many2one<'account.account'>; // accounting
372
414
  readonly refundAccount: F.Many2one<'account.account'>; // accounting
373
- readonly priceIncluded: F.Bool<{ readonly required: true; readonly default: true }>; // accounting
415
+ readonly reverseChargeAccount: F.Many2one<'account.account'>; // accounting
416
+ readonly components: F.One2many<'account.tax.component', { readonly required: true }>; // accounting
374
417
  };
375
418
  readonly methods: AccountTaxMethods;
376
419
  }
@@ -379,6 +422,60 @@ export interface AccountTax {
379
422
  export interface AccountTaxMethods extends F.Methods<typeof import('../../product/index.js').productShutro, 'account.tax'>, F.Methods<typeof import('../../accounting/index.js').accountingShutro, 'account.tax'> {
380
423
  }
381
424
 
425
+ /** `account.tax.component` (owner: accounting). */
426
+ export interface AccountTaxComponent {
427
+ readonly name: 'account.tax.component';
428
+ readonly fields: {
429
+ readonly id: F.Id<'account.tax.component'>;
430
+ readonly createdAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
431
+ readonly updatedAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
432
+ readonly createdBy: F.Many2one<'res.users', { readonly readonly: true }>;
433
+ readonly updatedBy: F.Many2one<'res.users', { readonly readonly: true }>;
434
+ readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
435
+ readonly tax: F.Many2one<'account.tax', { readonly required: true }>;
436
+ readonly sequence: F.Integer<{ readonly required: true; readonly default: true }>;
437
+ readonly name: F.Char<{ readonly required: true; readonly translate: true }>;
438
+ readonly share: F.Decimal<{ readonly required: true; readonly default: true }>;
439
+ readonly scope: F.Selection<'always' | 'intra' | 'inter', { readonly required: true; readonly default: true }>;
440
+ readonly code: F.Char;
441
+ readonly account: F.Many2one<'account.account'>;
442
+ readonly refundAccount: F.Many2one<'account.account'>;
443
+ readonly reverseChargeAccount: F.Many2one<'account.account'>;
444
+ };
445
+ readonly methods: AccountTaxComponentMethods;
446
+ }
447
+
448
+ /** Methods of `account.tax.component`: declared ones and transitions. */
449
+ export interface AccountTaxComponentMethods extends F.Methods<typeof import('../../accounting/index.js').accountingShutro, 'account.tax.component'> {
450
+ }
451
+
452
+ /** `account.withholding` (owner: accounting). */
453
+ export interface AccountWithholding {
454
+ readonly name: 'account.withholding';
455
+ readonly fields: {
456
+ readonly id: F.Id<'account.withholding'>;
457
+ readonly createdAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
458
+ readonly updatedAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
459
+ readonly createdBy: F.Many2one<'res.users', { readonly readonly: true }>;
460
+ readonly updatedBy: F.Many2one<'res.users', { readonly readonly: true }>;
461
+ readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
462
+ readonly active: F.Bool<{ readonly required: true; readonly default: true }>;
463
+ readonly company: F.Many2one<'res.company', { readonly required: true; readonly default: true }>;
464
+ readonly name: F.Char<{ readonly required: true; readonly translate: true }>;
465
+ readonly sequence: F.Integer<{ readonly required: true; readonly default: true }>;
466
+ readonly direction: F.Selection<'vendor' | 'customer', { readonly required: true; readonly default: true }>;
467
+ readonly base: F.Selection<'untaxed' | 'tax' | 'total', { readonly required: true; readonly default: true }>;
468
+ readonly rate: F.Decimal<{ readonly required: true; readonly default: true }>;
469
+ readonly threshold: F.Decimal<{ readonly required: true; readonly default: true }>;
470
+ readonly account: F.Many2one<'account.account', { readonly required: true }>;
471
+ };
472
+ readonly methods: AccountWithholdingMethods;
473
+ }
474
+
475
+ /** Methods of `account.withholding`: declared ones and transitions. */
476
+ export interface AccountWithholdingMethods extends F.Methods<typeof import('../../accounting/index.js').accountingShutro, 'account.withholding'> {
477
+ }
478
+
382
479
  /** `approval.level` (owner: permissions). */
383
480
  export interface ApprovalLevel {
384
481
  readonly name: 'approval.level';
@@ -823,8 +920,10 @@ export interface ProductProduct {
823
920
  readonly standardPrice: F.Decimal<{ readonly required: true; readonly default: true }>;
824
921
  readonly saleOk: F.Bool<{ readonly required: true; readonly default: true }>;
825
922
  readonly purchaseOk: F.Bool<{ readonly required: true; readonly default: true }>;
826
- readonly tax: F.Many2one<'account.tax'>;
827
- readonly purchaseTax: F.Many2one<'account.tax'>;
923
+ readonly taxes: F.Many2many<'account.tax', { readonly required: true }>;
924
+ readonly purchaseTaxes: F.Many2many<'account.tax', { readonly required: true }>;
925
+ readonly tax: F.Many2one<'account.tax', { readonly readonly: true }>;
926
+ readonly purchaseTax: F.Many2one<'account.tax', { readonly readonly: true }>;
828
927
  readonly description: F.Text<{ readonly translate: true }>;
829
928
  };
830
929
  readonly methods: ProductProductMethods;
@@ -959,6 +1058,34 @@ export interface ReportTemplate {
959
1058
  export interface ReportTemplateMethods extends F.Methods<typeof import('../../reporting/index.js').reportingShutro, 'report.template'> {
960
1059
  }
961
1060
 
1061
+ /** `res.bank.account` (owner: accounting). */
1062
+ export interface ResBankAccount {
1063
+ readonly name: 'res.bank.account';
1064
+ readonly fields: {
1065
+ readonly id: F.Id<'res.bank.account'>;
1066
+ readonly createdAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
1067
+ readonly updatedAt: F.Datetime<{ readonly required: true; readonly readonly: true }>;
1068
+ readonly createdBy: F.Many2one<'res.users', { readonly readonly: true }>;
1069
+ readonly updatedBy: F.Many2one<'res.users', { readonly readonly: true }>;
1070
+ readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
1071
+ readonly active: F.Bool<{ readonly required: true; readonly default: true }>;
1072
+ readonly company: F.Many2one<'res.company', { readonly required: true; readonly default: true }>;
1073
+ readonly sequence: F.Integer<{ readonly required: true; readonly default: true }>;
1074
+ readonly bank: F.Char<{ readonly required: true }>;
1075
+ readonly branch: F.Char;
1076
+ readonly number: F.Char<{ readonly required: true }>;
1077
+ readonly holder: F.Char;
1078
+ readonly routing: F.Char;
1079
+ readonly swift: F.Char;
1080
+ readonly currency: F.Many2one<'res.currency'>;
1081
+ };
1082
+ readonly methods: ResBankAccountMethods;
1083
+ }
1084
+
1085
+ /** Methods of `res.bank.account`: declared ones and transitions. */
1086
+ export interface ResBankAccountMethods extends F.Methods<typeof import('../../accounting/index.js').accountingShutro, 'res.bank.account'> {
1087
+ }
1088
+
962
1089
  /** `res.company` (owner: base; extended by: accounting). */
963
1090
  export interface ResCompany {
964
1091
  readonly name: 'res.company';
@@ -971,7 +1098,11 @@ export interface ResCompany {
971
1098
  readonly displayName: F.Char<{ readonly required: true; readonly readonly: true; readonly compute: true }>;
972
1099
  readonly name: F.Char<{ readonly required: true }>;
973
1100
  readonly currency: F.Many2one<'res.currency', { readonly required: true }>;
974
- readonly chartTemplate: F.Selection<'generic' | 'bd'>; // accounting
1101
+ readonly numberGrouping: F.Selection<'international' | 'lakh', { readonly required: true; readonly default: true }>;
1102
+ readonly fiscalYearStart: F.Integer<{ readonly required: true; readonly default: true }>; // accounting
1103
+ readonly chartTemplate: F.Char; // accounting
1104
+ readonly country: F.Char; // accounting
1105
+ readonly state: F.Char; // accounting
975
1106
  readonly lockDate: F.DateOnly; // accounting
976
1107
  readonly taxLockDate: F.DateOnly; // accounting
977
1108
  readonly accountReceivable: F.Many2one<'account.account'>; // accounting
@@ -1030,7 +1161,7 @@ export interface ResCurrencyRate {
1030
1161
  export interface ResCurrencyRateMethods extends F.Methods<typeof import('../../accounting/index.js').accountingShutro, 'res.currency.rate'> {
1031
1162
  }
1032
1163
 
1033
- /** `res.partner` (owner: contacts). */
1164
+ /** `res.partner` (owner: contacts; extended by: accounting). */
1034
1165
  export interface ResPartner {
1035
1166
  readonly name: 'res.partner';
1036
1167
  readonly fields: {
@@ -1054,17 +1185,19 @@ export interface ResPartner {
1054
1185
  readonly city: F.Char;
1055
1186
  readonly zip: F.Char;
1056
1187
  readonly country: F.Char;
1188
+ readonly state: F.Char;
1057
1189
  readonly taxId: F.Char;
1058
1190
  readonly isCustomer: F.Bool<{ readonly required: true; readonly default: true }>;
1059
1191
  readonly isVendor: F.Bool<{ readonly required: true; readonly default: true }>;
1060
1192
  readonly currency: F.Many2one<'res.currency'>;
1061
1193
  readonly notes: F.Text;
1194
+ readonly withholdings: F.Many2many<'account.withholding', { readonly required: true }>; // accounting
1062
1195
  };
1063
1196
  readonly methods: ResPartnerMethods;
1064
1197
  }
1065
1198
 
1066
1199
  /** Methods of `res.partner`: declared ones and transitions. */
1067
- export interface ResPartnerMethods extends F.Methods<typeof import('../../contacts/index.js').contactsShutro, 'res.partner'> {
1200
+ export interface ResPartnerMethods extends F.Methods<typeof import('../../contacts/index.js').contactsShutro, 'res.partner'>, F.Methods<typeof import('../../accounting/index.js').accountingShutro, 'res.partner'> {
1068
1201
  }
1069
1202
 
1070
1203
  /** `res.users` (owner: base). */
@@ -1152,7 +1285,8 @@ export interface SaleOrderLine {
1152
1285
  readonly uom: F.Many2one<'uom.uom'>;
1153
1286
  readonly priceUnit: F.Decimal<{ readonly required: true; readonly default: true }>;
1154
1287
  readonly discount: F.Decimal<{ readonly required: true; readonly default: true }>;
1155
- readonly tax: F.Many2one<'account.tax'>;
1288
+ readonly taxes: F.Many2many<'account.tax', { readonly required: true }>;
1289
+ readonly tax: F.Many2one<'account.tax', { readonly readonly: true }>;
1156
1290
  readonly currency: F.Many2one<'res.currency', { readonly readonly: true; readonly compute: true; readonly store: true }>;
1157
1291
  readonly subtotal: F.Monetary<'currency', { readonly readonly: true; readonly compute: true; readonly store: true }>;
1158
1292
  readonly taxAmount: F.Monetary<'currency', { readonly readonly: true; readonly compute: true; readonly store: true }>;