@things-factory/invoice 10.1.233 → 10.1.241

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.
@@ -108,7 +108,7 @@ export declare function documentLinesConfig({ editable, received, currency }: {
108
108
  multiple?: undefined;
109
109
  })[];
110
110
  };
111
- /** The lines on the grid, as the save mutation takes them; blank rows are left out. */
111
+ /** The lines on the grid, as the save mutation takes them. */
112
112
  export declare function linesOf(grist: DataGrist | null | undefined): {
113
113
  receivedTaxAmount?: number;
114
114
  description: string;
@@ -1,5 +1,5 @@
1
1
  import { i18next } from '@operato/i18n';
2
- import { defaultTaxRate, documentAmounts } from '@things-factory/invoice/dist-shared/document-amounts.js';
2
+ import { defaultTaxRate, documentAmounts, untouchedRow } from '@things-factory/invoice/dist-shared/document-amounts.js';
3
3
  import { documentAmount, documentNumber } from './document-amount';
4
4
  /** The grid of a document's lines — typed or pasted like a spreadsheet while the document is a draft. */
5
5
  export function documentLinesConfig({ editable, received, currency }) {
@@ -50,13 +50,16 @@ export function documentLinesConfig({ editable, received, currency }) {
50
50
  ]
51
51
  };
52
52
  }
53
- /** The lines on the grid, as the save mutation takes them; blank rows are left out. */
53
+ const blank = (value) => value === undefined || value === null || value === '';
54
+ /** The rows of the grid that are lines of the document - deleted and untouched rows left out. */
55
+ function lineRecords(grist) {
56
+ return (grist?.dirtyData?.records ?? []).filter(record => record.__dirty__ !== '-' && !untouchedRow(record));
57
+ }
58
+ /** The lines on the grid, as the save mutation takes them. */
54
59
  export function linesOf(grist) {
55
- const records = (grist?.dirtyData?.records ?? []);
56
- return records
57
- .filter(record => record.__dirty__ !== '-' && String(record.description ?? '').trim())
60
+ return lineRecords(grist)
58
61
  .map(record => ({
59
- description: String(record.description).trim(),
62
+ description: String(record.description ?? '').trim(),
60
63
  quantity: Number(record.quantity ?? 1),
61
64
  unit: String(record.unit ?? '').trim() || null,
62
65
  unitPrice: Number(record.unitPrice ?? 0),
@@ -68,7 +71,6 @@ export function linesOf(grist) {
68
71
  : { receivedTaxAmount: Number(record.receivedTaxAmount) })
69
72
  }));
70
73
  }
71
- const blank = (value) => value === undefined || value === null || value === '';
72
74
  /**
73
75
  * What a line typed into is missing, filled - a quantity of one, no discount, taxable at the standard rate - and its
74
76
  * rate following its tax kind when the kind is what changed (taxable 10 %, zero-rated and exempt none). A select shows
@@ -92,7 +94,7 @@ export function settleLine(record, changed) {
92
94
  * discount of the whole document - are returned for the totals table.
93
95
  */
94
96
  export function reckonLines(grist, currency, received = false, discountAmount = 0) {
95
- const records = (grist?.dirtyData?.records ?? []).filter(record => record.__dirty__ !== '-' && String(record.description ?? '').trim());
97
+ const records = lineRecords(grist);
96
98
  const amounts = documentAmounts(records, currency || 'KRW', received, discountAmount);
97
99
  records.forEach((record, index) => (record.supplyAmount = amounts.lines[index].supplyAmount ?? null));
98
100
  return amounts;
@@ -1 +1 @@
1
- {"version":3,"file":"document-lines.js","sourceRoot":"","sources":["../../client/document/document-lines.ts"],"names":[],"mappings":"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","sourcesContent":["import { DataGrist } from '@operato/data-grist'\nimport { i18next } from '@operato/i18n'\n\nimport { defaultTaxRate, documentAmounts, type DocumentAmounts } from '@things-factory/invoice/dist-shared/document-amounts.js'\n\nimport { documentAmount, documentNumber } from './document-amount'\n\n/** The grid of a document's lines — typed or pasted like a spreadsheet while the document is a draft. */\nexport function documentLinesConfig({ editable, received, currency }: { editable: boolean; received?: boolean; currency: string }) {\n /* Prices and discounts read with thousands marks; the widths keep the supply in view at about 900px, the unit's column too. */\n const number = (name: string, header: string, width = 100) => ({\n type: 'float',\n name,\n header,\n width,\n record: { editable, align: 'right', renderer: (value: number) => documentNumber(value, currency) }\n })\n return {\n rows: { appendable: editable, selectable: { multiple: true }, accumulator: true },\n pagination: { infinite: true },\n emptyNote: { title: i18next.t('text.invoice-lines-empty') },\n columns: [\n { type: 'gutter', gutterName: 'sequence' },\n ...(editable ? [{ type: 'gutter', gutterName: 'row-selector', multiple: true }] : []),\n { type: 'string', name: 'description', header: i18next.t('field.invoice-line-description'), width: 220, record: { editable } },\n number('quantity', i18next.t('field.invoice-quantity'), 60),\n { type: 'string', name: 'unit', header: i18next.t('field.invoice-unit'), width: 60, record: { editable, align: 'center' } },\n number('unitPrice', i18next.t('field.invoice-unit-price'), 110),\n number('discount', i18next.t('field.invoice-discount'), 80),\n {\n type: 'select',\n name: 'taxKind',\n header: i18next.t('field.invoice-tax-kind'),\n width: 70,\n record: {\n editable,\n options: [\n { value: 'TAXABLE', display: i18next.t('text.tax-kind-taxable') },\n { value: 'ZERO_RATED', display: i18next.t('text.tax-kind-zero-rated') },\n { value: 'EXEMPT', display: i18next.t('text.tax-kind-exempt') }\n ]\n }\n },\n number('taxRate', i18next.t('field.invoice-tax-rate-percent'), 56),\n ...(received ? [number('receivedTaxAmount', i18next.t('field.invoice-received-tax-amount'), 120)] : []),\n {\n type: 'float',\n name: 'supplyAmount',\n header: i18next.t('field.invoice-supply-amount'),\n width: 130,\n record: { editable: false, align: 'right', renderer: (value: number) => documentAmount(value, currency) },\n accumulator: 'sum'\n }\n ]\n }\n}\n\n/** The lines on the grid, as the save mutation takes them; blank rows are left out. */\nexport function linesOf(grist: DataGrist | null | undefined) {\n const records = (grist?.dirtyData?.records ?? []) as any[]\n return records\n .filter(record => record.__dirty__ !== '-' && String(record.description ?? '').trim())\n .map(record => ({\n description: String(record.description).trim(),\n quantity: Number(record.quantity ?? 1),\n unit: String(record.unit ?? '').trim() || null,\n unitPrice: Number(record.unitPrice ?? 0),\n discount: Number(record.discount ?? 0),\n taxKind: record.taxKind || 'TAXABLE',\n taxRate: Number(record.taxRate ?? 0),\n ...(record.receivedTaxAmount === undefined || record.receivedTaxAmount === null || record.receivedTaxAmount === ''\n ? {}\n : { receivedTaxAmount: Number(record.receivedTaxAmount) })\n }))\n}\n\nconst blank = (value: unknown) => value === undefined || value === null || value === ''\n\n/**\n * What a line typed into is missing, filled - a quantity of one, no discount, taxable at the standard rate - and its\n * rate following its tax kind when the kind is what changed (taxable 10 %, zero-rated and exempt none). A select shows\n * its first option for an empty value, so 「과세」 looked chosen and choosing it changed nothing; the line now holds it.\n */\nexport function settleLine(record: any, changed?: string) {\n if (!record || record.__dirty__ === '-') return\n if (blank(record.quantity)) record.quantity = 1\n if (blank(record.discount)) record.discount = 0\n if (!record.taxKind) record.taxKind = 'TAXABLE'\n if (changed === 'taxKind' || blank(record.taxRate)) record.taxRate = defaultTaxRate(record.taxKind)\n}\n\n/**\n * The lines on the grid reckoned as the document will keep them (shared/document-amounts.ts): each row's supply is\n * written onto it for the grid to show, and the document's tax groups and totals - after `discountAmount`, the\n * discount of the whole document - are returned for the totals table.\n */\nexport function reckonLines(grist: DataGrist | null | undefined, currency: string, received = false, discountAmount: unknown = 0): DocumentAmounts {\n const records = ((grist?.dirtyData?.records ?? []) as any[]).filter(record => record.__dirty__ !== '-' && String(record.description ?? '').trim())\n const amounts = documentAmounts(records, currency || 'KRW', received, discountAmount)\n records.forEach((record, index) => (record.supplyAmount = amounts.lines[index].supplyAmount ?? null))\n return amounts\n}\n\n/**\n * A change on the grid as an editor takes it: the changed line settled, every line reckoned, the grid redrawn with\n * the supplies. Returns the totals to show.\n */\nexport function onLineChange(grist: DataGrist | null | undefined, event: CustomEvent, currency: string, received = false, discountAmount: unknown = 0): DocumentAmounts {\n settleLine(event.detail?.after, event.detail?.column?.name)\n const amounts = reckonLines(grist, currency, received, discountAmount)\n grist?.refresh()\n return amounts\n}\n"]}
1
+ {"version":3,"file":"document-lines.js","sourceRoot":"","sources":["../../client/document/document-lines.ts"],"names":[],"mappings":"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","sourcesContent":["import { DataGrist } from '@operato/data-grist'\nimport { i18next } from '@operato/i18n'\n\nimport { defaultTaxRate, documentAmounts, untouchedRow, type DocumentAmounts } from '@things-factory/invoice/dist-shared/document-amounts.js'\n\nimport { documentAmount, documentNumber } from './document-amount'\n\n/** The grid of a document's lines — typed or pasted like a spreadsheet while the document is a draft. */\nexport function documentLinesConfig({ editable, received, currency }: { editable: boolean; received?: boolean; currency: string }) {\n /* Prices and discounts read with thousands marks; the widths keep the supply in view at about 900px, the unit's column too. */\n const number = (name: string, header: string, width = 100) => ({\n type: 'float',\n name,\n header,\n width,\n record: { editable, align: 'right', renderer: (value: number) => documentNumber(value, currency) }\n })\n return {\n rows: { appendable: editable, selectable: { multiple: true }, accumulator: true },\n pagination: { infinite: true },\n emptyNote: { title: i18next.t('text.invoice-lines-empty') },\n columns: [\n { type: 'gutter', gutterName: 'sequence' },\n ...(editable ? [{ type: 'gutter', gutterName: 'row-selector', multiple: true }] : []),\n { type: 'string', name: 'description', header: i18next.t('field.invoice-line-description'), width: 220, record: { editable } },\n number('quantity', i18next.t('field.invoice-quantity'), 60),\n { type: 'string', name: 'unit', header: i18next.t('field.invoice-unit'), width: 60, record: { editable, align: 'center' } },\n number('unitPrice', i18next.t('field.invoice-unit-price'), 110),\n number('discount', i18next.t('field.invoice-discount'), 80),\n {\n type: 'select',\n name: 'taxKind',\n header: i18next.t('field.invoice-tax-kind'),\n width: 70,\n record: {\n editable,\n options: [\n { value: 'TAXABLE', display: i18next.t('text.tax-kind-taxable') },\n { value: 'ZERO_RATED', display: i18next.t('text.tax-kind-zero-rated') },\n { value: 'EXEMPT', display: i18next.t('text.tax-kind-exempt') }\n ]\n }\n },\n number('taxRate', i18next.t('field.invoice-tax-rate-percent'), 56),\n ...(received ? [number('receivedTaxAmount', i18next.t('field.invoice-received-tax-amount'), 120)] : []),\n {\n type: 'float',\n name: 'supplyAmount',\n header: i18next.t('field.invoice-supply-amount'),\n width: 130,\n record: { editable: false, align: 'right', renderer: (value: number) => documentAmount(value, currency) },\n accumulator: 'sum'\n }\n ]\n }\n}\n\nconst blank = (value: unknown) => value === undefined || value === null || value === ''\n\n/** The rows of the grid that are lines of the document - deleted and untouched rows left out. */\nfunction lineRecords(grist: DataGrist | null | undefined): any[] {\n return ((grist?.dirtyData?.records ?? []) as any[]).filter(record => record.__dirty__ !== '-' && !untouchedRow(record))\n}\n\n/** The lines on the grid, as the save mutation takes them. */\nexport function linesOf(grist: DataGrist | null | undefined) {\n return lineRecords(grist)\n .map(record => ({\n description: String(record.description ?? '').trim(),\n quantity: Number(record.quantity ?? 1),\n unit: String(record.unit ?? '').trim() || null,\n unitPrice: Number(record.unitPrice ?? 0),\n discount: Number(record.discount ?? 0),\n taxKind: record.taxKind || 'TAXABLE',\n taxRate: Number(record.taxRate ?? 0),\n ...(record.receivedTaxAmount === undefined || record.receivedTaxAmount === null || record.receivedTaxAmount === ''\n ? {}\n : { receivedTaxAmount: Number(record.receivedTaxAmount) })\n }))\n}\n\n/**\n * What a line typed into is missing, filled - a quantity of one, no discount, taxable at the standard rate - and its\n * rate following its tax kind when the kind is what changed (taxable 10 %, zero-rated and exempt none). A select shows\n * its first option for an empty value, so 「과세」 looked chosen and choosing it changed nothing; the line now holds it.\n */\nexport function settleLine(record: any, changed?: string) {\n if (!record || record.__dirty__ === '-') return\n if (blank(record.quantity)) record.quantity = 1\n if (blank(record.discount)) record.discount = 0\n if (!record.taxKind) record.taxKind = 'TAXABLE'\n if (changed === 'taxKind' || blank(record.taxRate)) record.taxRate = defaultTaxRate(record.taxKind)\n}\n\n/**\n * The lines on the grid reckoned as the document will keep them (shared/document-amounts.ts): each row's supply is\n * written onto it for the grid to show, and the document's tax groups and totals - after `discountAmount`, the\n * discount of the whole document - are returned for the totals table.\n */\nexport function reckonLines(grist: DataGrist | null | undefined, currency: string, received = false, discountAmount: unknown = 0): DocumentAmounts {\n const records = lineRecords(grist)\n const amounts = documentAmounts(records, currency || 'KRW', received, discountAmount)\n records.forEach((record, index) => (record.supplyAmount = amounts.lines[index].supplyAmount ?? null))\n return amounts\n}\n\n/**\n * A change on the grid as an editor takes it: the changed line settled, every line reckoned, the grid redrawn with\n * the supplies. Returns the totals to show.\n */\nexport function onLineChange(grist: DataGrist | null | undefined, event: CustomEvent, currency: string, received = false, discountAmount: unknown = 0): DocumentAmounts {\n settleLine(event.detail?.after, event.detail?.column?.name)\n const amounts = reckonLines(grist, currency, received, discountAmount)\n grist?.refresh()\n return amounts\n}\n"]}