@things-factory/invoice 10.1.223 → 10.1.227

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 (95) hide show
  1. package/dist-client/document/document-amount.d.ts +7 -2
  2. package/dist-client/document/document-amount.js +11 -6
  3. package/dist-client/document/document-amount.js.map +1 -1
  4. package/dist-client/document/document-defaults.d.ts +24 -0
  5. package/dist-client/document/document-defaults.js +43 -0
  6. package/dist-client/document/document-defaults.js.map +1 -0
  7. package/dist-client/document/document-form.d.ts +24 -6
  8. package/dist-client/document/document-form.js +126 -15
  9. package/dist-client/document/document-form.js.map +1 -1
  10. package/dist-client/document/document-lines.d.ts +35 -1
  11. package/dist-client/document/document-lines.js +58 -9
  12. package/dist-client/document/document-lines.js.map +1 -1
  13. package/dist-client/document/document-party.d.ts +37 -0
  14. package/dist-client/document/document-party.js +217 -0
  15. package/dist-client/document/document-party.js.map +1 -0
  16. package/dist-client/document/document-preview.d.ts +37 -0
  17. package/dist-client/document/document-preview.js +181 -0
  18. package/dist-client/document/document-preview.js.map +1 -0
  19. package/dist-client/document/document-print.d.ts +3 -13
  20. package/dist-client/document/document-print.js +3 -45
  21. package/dist-client/document/document-print.js.map +1 -1
  22. package/dist-client/index.d.ts +9 -3
  23. package/dist-client/index.js +9 -3
  24. package/dist-client/index.js.map +1 -1
  25. package/dist-client/pages/invoice-editor.d.ts +37 -12
  26. package/dist-client/pages/invoice-editor.js +171 -79
  27. package/dist-client/pages/invoice-editor.js.map +1 -1
  28. package/dist-client/pages/invoice-list.d.ts +21 -1
  29. package/dist-client/pages/invoice-list.js +145 -14
  30. package/dist-client/pages/invoice-list.js.map +1 -1
  31. package/dist-client/tsconfig.tsbuildinfo +1 -1
  32. package/dist-client/viewparts/document-defaults-setting-let.d.ts +19 -0
  33. package/dist-client/viewparts/document-defaults-setting-let.js +139 -0
  34. package/dist-client/viewparts/document-defaults-setting-let.js.map +1 -0
  35. package/dist-server/role-tasks.js +5 -2
  36. package/dist-server/role-tasks.js.map +1 -1
  37. package/dist-server/service/document-defaults/document-defaults-resolver.d.ts +28 -0
  38. package/dist-server/service/document-defaults/document-defaults-resolver.js +136 -0
  39. package/dist-server/service/document-defaults/document-defaults-resolver.js.map +1 -0
  40. package/dist-server/service/document-defaults/document-defaults-rules.d.ts +25 -0
  41. package/dist-server/service/document-defaults/document-defaults-rules.js +50 -0
  42. package/dist-server/service/document-defaults/document-defaults-rules.js.map +1 -0
  43. package/dist-server/service/document-defaults/index.d.ts +6 -0
  44. package/dist-server/service/document-defaults/index.js +11 -0
  45. package/dist-server/service/document-defaults/index.js.map +1 -0
  46. package/dist-server/service/index.d.ts +2 -0
  47. package/dist-server/service/index.js +4 -1
  48. package/dist-server/service/index.js.map +1 -1
  49. package/dist-server/service/invoice/commercial-document.d.ts +2 -0
  50. package/dist-server/service/invoice/commercial-document.js +11 -1
  51. package/dist-server/service/invoice/commercial-document.js.map +1 -1
  52. package/dist-server/service/invoice/invoice-document-file.d.ts +20 -0
  53. package/dist-server/service/invoice/invoice-document-file.js +38 -0
  54. package/dist-server/service/invoice/invoice-document-file.js.map +1 -0
  55. package/dist-server/service/invoice/invoice-query.d.ts +3 -1
  56. package/dist-server/service/invoice/invoice-query.js +33 -0
  57. package/dist-server/service/invoice/invoice-query.js.map +1 -1
  58. package/dist-server/service/invoice/invoice-rules.d.ts +18 -11
  59. package/dist-server/service/invoice/invoice-rules.js +49 -96
  60. package/dist-server/service/invoice/invoice-rules.js.map +1 -1
  61. package/dist-server/service/invoice/invoice-service.d.ts +1 -0
  62. package/dist-server/service/invoice/invoice-service.js +5 -2
  63. package/dist-server/service/invoice/invoice-service.js.map +1 -1
  64. package/dist-server/service/invoice/invoice-type.d.ts +12 -0
  65. package/dist-server/service/invoice/invoice-type.js +37 -1
  66. package/dist-server/service/invoice/invoice-type.js.map +1 -1
  67. package/dist-server/tsconfig.tsbuildinfo +1 -1
  68. package/dist-shared/document-amounts.d.ts +56 -0
  69. package/dist-shared/document-amounts.js +134 -0
  70. package/dist-shared/document-amounts.js.map +1 -0
  71. package/dist-shared/document-money.d.ts +12 -0
  72. package/dist-shared/document-money.js +38 -0
  73. package/dist-shared/document-money.js.map +1 -0
  74. package/dist-shared/document-print.d.ts +37 -0
  75. package/dist-shared/document-print.js +87 -0
  76. package/dist-shared/document-print.js.map +1 -0
  77. package/dist-shared/document-start.d.ts +15 -0
  78. package/dist-shared/document-start.js +51 -0
  79. package/dist-shared/document-start.js.map +1 -0
  80. package/dist-shared/invoice-standing.d.ts +25 -0
  81. package/dist-shared/invoice-standing.js +51 -0
  82. package/dist-shared/invoice-standing.js.map +1 -0
  83. package/package.json +9 -7
  84. package/shared/document-amounts.ts +209 -0
  85. package/shared/document-money.ts +33 -0
  86. package/shared/document-print.ts +131 -0
  87. package/shared/document-start.ts +46 -0
  88. package/shared/invoice-standing.ts +49 -0
  89. package/translations/en.json +32 -6
  90. package/translations/es.json +22 -1
  91. package/translations/ja.json +22 -1
  92. package/translations/ko.json +32 -6
  93. package/translations/ms.json +22 -1
  94. package/translations/zh.json +22 -1
  95. package/tsconfig.shared.tsbuildinfo +1 -1
@@ -1,25 +1,63 @@
1
1
  import { __decorate, __metadata } from "tslib";
2
2
  import '@operato/data-grist/ox-grist.js';
3
+ import '@operato/input/ox-select.js';
4
+ import '@operato/popup/ox-popup-list.js';
3
5
  import gql from 'graphql-tag';
4
- import { html } from 'lit';
6
+ import { css, html, nothing } from 'lit';
5
7
  import { customElement, query, state } from 'lit/decorators.js';
6
8
  import { DataGrist } from '@operato/data-grist';
7
9
  import { client } from '@operato/graphql';
8
10
  import { i18next, localize } from '@operato/i18n';
9
11
  import { entity360Name } from '@operato/layout';
10
12
  import { navigate, PageView } from '@operato/shell';
11
- import { CommonGristStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles';
13
+ import { CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles';
12
14
  import { isMobileDevice } from '@operato/utils';
13
15
  import { SELECTION_ROW_PICKER } from '@things-factory/ai-assistant/dist-client/index.js';
16
+ import { issuePeriodOf, overdue, totalsOf } from '@things-factory/invoice/dist-shared/invoice-standing.js';
14
17
  import { documentAmount } from '../document/document-amount';
15
18
  import { counterpartCell, counterpartOf, invoiceStatusWord } from '../entity360/invoice-360';
19
+ const today = () => new Date().toLocaleDateString('en-CA');
16
20
  /**
17
21
  * 청구서 — every invoice the domain sent or received. The other party's name opens the invoice's 360; the edit gutter
18
22
  * opens the editor. Search is the server's: number, parties, purchase order and notes. Rows picked go to the assistant
19
- * (「AI와 작업」) as `invoice:<uuid>`, read by the invoice list's read (server invoice-read.ts).
23
+ * (「AI와 작업」) as `invoice:<uuid>`, read by the invoice list's read (server invoice-read.ts). The headroom narrows it by
24
+ * status, direction and issue period; the totals of the rows shown stand over it (ADR-0170 decision 11).
20
25
  */
21
26
  let InvoiceList = class InvoiceList extends localize(i18next)(PageView) {
22
- static { this.styles = [WorkSurfacePageStyles, CommonGristStyles, ScrollbarStyles]; }
27
+ constructor() {
28
+ super(...arguments);
29
+ this.status = '';
30
+ this.direction = '';
31
+ this.period = '';
32
+ /** The totals of the rows on the page, by direction and currency. */
33
+ this.totals = [];
34
+ }
35
+ static { this.styles = [
36
+ WorkSurfacePageStyles,
37
+ CommonGristStyles,
38
+ CommonHeaderStyles,
39
+ ScrollbarStyles,
40
+ css `
41
+ .filters {
42
+ display: flex;
43
+ flex-wrap: wrap;
44
+ align-items: center;
45
+ gap: var(--spacing-medium, 8px);
46
+ }
47
+ ox-select {
48
+ min-width: 120px;
49
+ }
50
+ .totals {
51
+ font-size: var(--ui-t-small, 11.5px);
52
+ color: var(--ui-muted, var(--md-sys-color-on-surface-variant));
53
+ font-variant-numeric: tabular-nums;
54
+ }
55
+ .totals strong {
56
+ color: var(--ui-ink, var(--md-sys-color-on-surface));
57
+ font-weight: 600;
58
+ }
59
+ `
60
+ ]; }
23
61
  get context() {
24
62
  return {
25
63
  title: i18next.t('title.invoice-list'),
@@ -29,12 +67,56 @@ let InvoiceList = class InvoiceList extends localize(i18next)(PageView) {
29
67
  },
30
68
  value: this.grist?.searchText || ''
31
69
  },
70
+ filter: {
71
+ handler: () => {
72
+ this.grist.toggleHeadroom();
73
+ }
74
+ },
32
75
  actions: [{ title: i18next.t('button.invoice-new'), icon: 'add', emphasis: { raised: true }, action: () => navigate('invoice-editor') }],
33
76
  exportable: { name: i18next.t('title.invoice-list'), data: () => this.grist.exportRecords() }
34
77
  };
35
78
  }
36
79
  render() {
37
- return html `<ox-assistant-selection-bar
80
+ const statuses = [
81
+ { value: '', display: i18next.t('text.invoice-filter-all-statuses') },
82
+ ...['DRAFT', 'ISSUED', 'VOID'].map(value => ({ value, display: invoiceStatusWord(value) })),
83
+ { value: 'OVERDUE', display: i18next.t('text.invoice-overdue') }
84
+ ];
85
+ const directions = [
86
+ { value: '', display: i18next.t('text.invoice-filter-all-directions') },
87
+ { value: 'SALES', display: i18next.t('text.invoice-direction-sales') },
88
+ { value: 'PURCHASE', display: i18next.t('text.invoice-direction-purchase') }
89
+ ];
90
+ const periods = [
91
+ { value: '', display: i18next.t('text.invoice-period-all') },
92
+ { value: 'this-month', display: i18next.t('text.invoice-period-this-month') },
93
+ { value: 'last-month', display: i18next.t('text.invoice-period-last-month') },
94
+ { value: 'this-year', display: i18next.t('text.invoice-period-this-year') },
95
+ { value: 'last-year', display: i18next.t('text.invoice-period-last-year') }
96
+ ];
97
+ const choice = (label, value, choices, set) => html `<ox-select
98
+ .value=${value}
99
+ aria-label=${label}
100
+ @change=${(e) => {
101
+ const next = String(e.detail ?? '');
102
+ if (next === value)
103
+ return;
104
+ set(next);
105
+ this.grist.fetch();
106
+ }}
107
+ >
108
+ <span slot="label">${choices.find(one => one.value === value)?.display}</span>
109
+ <ox-popup-list align-left nowrap>${choices.map(one => html `<div option value=${one.value}>${one.display}</div>`)}</ox-popup-list>
110
+ </ox-select>`;
111
+ return html `${this.totals.length
112
+ ? html `<div class="page-headroom totals" aria-label=${i18next.t('text.invoice-totals-shown')}>
113
+ ${i18next.t('text.invoice-totals-shown')}
114
+ ${this.totals.map(one => html `<span
115
+ >${one.direction === 'PURCHASE' ? i18next.t('text.invoice-direction-purchase') : i18next.t('text.invoice-direction-sales')}
116
+ <strong>${documentAmount(one.amount, one.currency)}</strong></span
117
+ >`)}
118
+ </div>`
119
+ : nothing}<ox-assistant-selection-bar
38
120
  .gridOf=${() => this.grist}
39
121
  name=${i18next.t('title.invoice-list')}
40
122
  list="invoices"
@@ -47,7 +129,15 @@ let InvoiceList = class InvoiceList extends localize(i18next)(PageView) {
47
129
  .mode=${isMobileDevice() ? 'CARD' : 'GRID'}
48
130
  .config=${this.gristConfig}
49
131
  .fetchHandler=${this.fetchHandler.bind(this)}
50
- ></ox-grist>`;
132
+ >
133
+ <div slot="headroom" class="header">
134
+ <div class="filters">
135
+ ${choice(i18next.t('field.invoice-status'), this.status, statuses, value => (this.status = value))}
136
+ ${choice(i18next.t('field.invoice-direction'), this.direction, directions, value => (this.direction = value))}
137
+ ${choice(i18next.t('field.invoice-issue-date'), this.period, periods, value => (this.period = value))}
138
+ </div>
139
+ </div>
140
+ </ox-grist>`;
51
141
  }
52
142
  async pageInitialized() {
53
143
  const readonly = (type, name, header, width, extra = {}) => ({
@@ -74,20 +164,27 @@ let InvoiceList = class InvoiceList extends localize(i18next)(PageView) {
74
164
  handlers: { click: (_columns, _data, _column, record) => record?.id && navigate(`invoice-editor?id=${record.id}`) }
75
165
  },
76
166
  /* The number is the invoice's own name and opens its 360; the other party opens the counterparty's (ADR-0067 decision 1). */
77
- readonly('string', 'number', i18next.t('field.invoice-number'), 140, {
167
+ /* Narrow enough that the total stays in view on a laptop. */
168
+ readonly('string', 'number', i18next.t('field.invoice-number'), 120, {
78
169
  record: { renderer: (value, _column, record) => (record?.id ? entity360Name({ __typename: 'Invoice', ...record }, value) : value) }
79
170
  }),
80
- readonly('string', 'counterpart', i18next.t('field.invoice-counterpart'), 200, {
171
+ readonly('string', 'counterpart', i18next.t('field.invoice-counterpart'), 170, {
81
172
  sortable: false,
82
173
  record: { renderer: (_value, _column, record) => counterpartCell(record) }
83
174
  }),
84
- readonly('string', 'status', i18next.t('field.invoice-status'), 80, { record: { renderer: (value) => invoiceStatusWord(value) } }),
85
- readonly('string', 'direction', i18next.t('field.invoice-direction'), 80, {
175
+ readonly('string', 'status', i18next.t('field.invoice-status'), 110, {
176
+ record: {
177
+ renderer: (value, _column, record) => overdue(record ?? {}, today())
178
+ ? html `${invoiceStatusWord(value)} · <span style="color:var(--md-sys-color-error)">${i18next.t('text.invoice-overdue')}</span>`
179
+ : invoiceStatusWord(value)
180
+ }
181
+ }),
182
+ readonly('string', 'direction', i18next.t('field.invoice-direction'), 56, {
86
183
  record: { renderer: (value) => (value === 'PURCHASE' ? i18next.t('text.invoice-direction-purchase') : i18next.t('text.invoice-direction-sales')) }
87
184
  }),
88
- readonly('string', 'issueDate', i18next.t('field.invoice-issue-date'), 110),
89
- readonly('string', 'dueDate', i18next.t('field.invoice-due-date'), 110),
90
- readonly('float', 'totalAmount', i18next.t('field.invoice-total-amount'), 160, {
185
+ readonly('string', 'issueDate', i18next.t('field.invoice-issue-date'), 92),
186
+ readonly('string', 'dueDate', i18next.t('field.invoice-due-date'), 92),
187
+ readonly('float', 'totalAmount', i18next.t('field.invoice-total-amount'), 140, {
91
188
  record: { align: 'right', renderer: (value, _column, record) => documentAmount(value, record?.currency || 'KRW') }
92
189
  })
93
190
  ],
@@ -116,18 +213,52 @@ let InvoiceList = class InvoiceList extends localize(i18next)(PageView) {
116
213
  }
117
214
  }
118
215
  `,
119
- variables: { filters, pagination: { page, limit }, sortings, search: search?.trim() || undefined },
216
+ variables: { filters: [...filters, ...this.headroomFilters()], pagination: { page, limit }, sortings, search: search?.trim() || undefined },
120
217
  fetchPolicy: 'network-only'
121
218
  });
122
219
  if (response.errors?.length)
123
220
  throw response;
221
+ this.totals = totalsOf(response.data.responses.items);
124
222
  return { total: response.data.responses.total, records: response.data.responses.items };
125
223
  }
224
+ /**
225
+ * The headroom's choices as the list's filters. Overdue is issued and due before today - the invoice module keeps no
226
+ * payments, so the list reads it from the status and the due date alone (invoice-standing.ts).
227
+ */
228
+ headroomFilters() {
229
+ const filters = [];
230
+ if (this.status === 'OVERDUE')
231
+ filters.push({ name: 'status', operator: 'eq', value: 'ISSUED' }, { name: 'dueDate', operator: 'lt', value: today() });
232
+ else if (this.status)
233
+ filters.push({ name: 'status', operator: 'eq', value: this.status });
234
+ if (this.direction)
235
+ filters.push({ name: 'direction', operator: 'eq', value: this.direction });
236
+ const period = issuePeriodOf(this.period, today());
237
+ if (period)
238
+ filters.push({ name: 'issueDate', operator: 'between', value: period });
239
+ return filters;
240
+ }
126
241
  };
127
242
  __decorate([
128
243
  state(),
129
244
  __metadata("design:type", Object)
130
245
  ], InvoiceList.prototype, "gristConfig", void 0);
246
+ __decorate([
247
+ state(),
248
+ __metadata("design:type", Object)
249
+ ], InvoiceList.prototype, "status", void 0);
250
+ __decorate([
251
+ state(),
252
+ __metadata("design:type", Object)
253
+ ], InvoiceList.prototype, "direction", void 0);
254
+ __decorate([
255
+ state(),
256
+ __metadata("design:type", Object)
257
+ ], InvoiceList.prototype, "period", void 0);
258
+ __decorate([
259
+ state(),
260
+ __metadata("design:type", Array)
261
+ ], InvoiceList.prototype, "totals", void 0);
131
262
  __decorate([
132
263
  query('ox-grist'),
133
264
  __metadata("design:type", DataGrist)
@@ -1 +1 @@
1
- {"version":3,"file":"invoice-list.js","sourceRoot":"","sources":["../../client/pages/invoice-list.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/data-grist/ox-grist.js'\n\nimport gql from 'graphql-tag'\nimport { html } from 'lit'\nimport { customElement, query, state } from 'lit/decorators.js'\n\nimport { DataGrist, FetchOption } from '@operato/data-grist'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { entity360Name } from '@operato/layout'\nimport { navigate, PageView } from '@operato/shell'\nimport { CommonGristStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { isMobileDevice } from '@operato/utils'\nimport { SELECTION_ROW_PICKER } from '@things-factory/ai-assistant/dist-client/index.js'\n\nimport { documentAmount } from '../document/document-amount'\nimport { counterpartCell, counterpartOf, invoiceStatusWord } from '../entity360/invoice-360'\n\n/**\n * 청구서 — every invoice the domain sent or received. The other party's name opens the invoice's 360; the edit gutter\n * opens the editor. Search is the server's: number, parties, purchase order and notes. Rows picked go to the assistant\n * (「AI와 작업」) as `invoice:<uuid>`, read by the invoice list's read (server invoice-read.ts).\n */\n@customElement('invoice-list')\nexport class InvoiceList extends localize(i18next)(PageView) {\n static styles = [WorkSurfacePageStyles, CommonGristStyles, ScrollbarStyles]\n\n @state() gristConfig: any\n @query('ox-grist') private grist!: DataGrist\n\n get context() {\n return {\n title: i18next.t('title.invoice-list'),\n search: {\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist?.searchText || ''\n },\n actions: [{ title: i18next.t('button.invoice-new'), icon: 'add', emphasis: { raised: true }, action: () => navigate('invoice-editor') }],\n exportable: { name: i18next.t('title.invoice-list'), data: () => this.grist.exportRecords() }\n }\n }\n\n render() {\n return html`<ox-assistant-selection-bar\n .gridOf=${() => this.grist}\n name=${i18next.t('title.invoice-list')}\n list=\"invoices\"\n axis=\"invoice\"\n .labelOf=${(row: any) => [row.number, counterpartOf(row)].filter(Boolean).join(' · ')}\n ></ox-assistant-selection-bar>\n <ox-grist\n class=\"page-fill\"\n search-mode=\"term\"\n .mode=${isMobileDevice() ? 'CARD' : 'GRID'}\n .config=${this.gristConfig}\n .fetchHandler=${this.fetchHandler.bind(this)}\n ></ox-grist>`\n }\n\n async pageInitialized() {\n const readonly = (type: string, name: string, header: string, width: number, extra: any = {}) => ({\n type,\n name,\n header,\n width,\n sortable: true,\n ...extra,\n record: { editable: false, ...extra.record }\n })\n this.gristConfig = {\n rows: { appendable: false, selectable: { multiple: true } },\n pagination: { limit: 50, pages: [50, 100, 500] },\n emptyNote: { title: i18next.t('text.invoice-empty'), description: i18next.t('text.invoice-empty-description') },\n list: { fields: ['number', 'counterpart'], details: ['status', 'dueDate', 'totalAmount'] },\n columns: [\n { type: 'gutter', gutterName: 'sequence' },\n SELECTION_ROW_PICKER,\n {\n type: 'gutter',\n gutterName: 'button',\n icon: 'edit_note',\n handlers: { click: (_columns: any, _data: any, _column: any, record: any) => record?.id && navigate(`invoice-editor?id=${record.id}`) }\n },\n /* The number is the invoice's own name and opens its 360; the other party opens the counterparty's (ADR-0067 decision 1). */\n readonly('string', 'number', i18next.t('field.invoice-number'), 140, {\n record: { renderer: (value: string, _column: any, record: any) => (record?.id ? entity360Name({ __typename: 'Invoice', ...record }, value) : value) }\n }),\n readonly('string', 'counterpart', i18next.t('field.invoice-counterpart'), 200, {\n sortable: false,\n record: { renderer: (_value: any, _column: any, record: any) => counterpartCell(record) }\n }),\n readonly('string', 'status', i18next.t('field.invoice-status'), 80, { record: { renderer: (value: string) => invoiceStatusWord(value) } }),\n readonly('string', 'direction', i18next.t('field.invoice-direction'), 80, {\n record: { renderer: (value: string) => (value === 'PURCHASE' ? i18next.t('text.invoice-direction-purchase') : i18next.t('text.invoice-direction-sales')) }\n }),\n readonly('string', 'issueDate', i18next.t('field.invoice-issue-date'), 110),\n readonly('string', 'dueDate', i18next.t('field.invoice-due-date'), 110),\n readonly('float', 'totalAmount', i18next.t('field.invoice-total-amount'), 160, {\n record: { align: 'right', renderer: (value: number, _column: any, record: any) => documentAmount(value, record?.currency || 'KRW') }\n })\n ],\n sorters: [{ name: 'issueDate', desc: true }]\n }\n }\n\n async fetchHandler({ page = 1, limit = 50, sortings = [], filters = [], search }: FetchOption) {\n const response = await client.query({\n query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!], $search: String) {\n responses: invoices(filters: $filters, pagination: $pagination, sortings: $sortings, search: $search) {\n items {\n id\n number\n status\n direction\n currency\n counterpartyId\n supplierName\n buyerName\n issueDate\n dueDate\n totalAmount\n }\n total\n }\n }\n `,\n variables: { filters, pagination: { page, limit }, sortings, search: search?.trim() || undefined },\n fetchPolicy: 'network-only'\n })\n if (response.errors?.length) throw response\n return { total: response.data.responses.total, records: response.data.responses.items }\n }\n}\n"]}
1
+ {"version":3,"file":"invoice-list.js","sourceRoot":"","sources":["../../client/pages/invoice-list.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/data-grist/ox-grist.js'\nimport '@operato/input/ox-select.js'\nimport '@operato/popup/ox-popup-list.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, nothing } from 'lit'\nimport { customElement, query, state } from 'lit/decorators.js'\n\nimport { DataGrist, FetchOption } from '@operato/data-grist'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { entity360Name } from '@operato/layout'\nimport { navigate, PageView } from '@operato/shell'\nimport { CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { isMobileDevice } from '@operato/utils'\nimport { SELECTION_ROW_PICKER } from '@things-factory/ai-assistant/dist-client/index.js'\nimport { issuePeriodOf, overdue, totalsOf } from '@things-factory/invoice/dist-shared/invoice-standing.js'\n\nimport { documentAmount } from '../document/document-amount'\nimport { counterpartCell, counterpartOf, invoiceStatusWord } from '../entity360/invoice-360'\n\nconst today = () => new Date().toLocaleDateString('en-CA')\n\n/**\n * 청구서 — every invoice the domain sent or received. The other party's name opens the invoice's 360; the edit gutter\n * opens the editor. Search is the server's: number, parties, purchase order and notes. Rows picked go to the assistant\n * (「AI와 작업」) as `invoice:<uuid>`, read by the invoice list's read (server invoice-read.ts). The headroom narrows it by\n * status, direction and issue period; the totals of the rows shown stand over it (ADR-0170 decision 11).\n */\n@customElement('invoice-list')\nexport class InvoiceList extends localize(i18next)(PageView) {\n static styles = [\n WorkSurfacePageStyles,\n CommonGristStyles,\n CommonHeaderStyles,\n ScrollbarStyles,\n css`\n .filters {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--spacing-medium, 8px);\n }\n ox-select {\n min-width: 120px;\n }\n .totals {\n font-size: var(--ui-t-small, 11.5px);\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n font-variant-numeric: tabular-nums;\n }\n .totals strong {\n color: var(--ui-ink, var(--md-sys-color-on-surface));\n font-weight: 600;\n }\n `\n ]\n\n @state() gristConfig: any\n @state() status = ''\n @state() direction = ''\n @state() period = ''\n /** The totals of the rows on the page, by direction and currency. */\n @state() totals: { direction: string; currency: string; amount: number }[] = []\n @query('ox-grist') private grist!: DataGrist\n\n get context() {\n return {\n title: i18next.t('title.invoice-list'),\n search: {\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist?.searchText || ''\n },\n filter: {\n handler: () => {\n this.grist.toggleHeadroom()\n }\n },\n actions: [{ title: i18next.t('button.invoice-new'), icon: 'add', emphasis: { raised: true }, action: () => navigate('invoice-editor') }],\n exportable: { name: i18next.t('title.invoice-list'), data: () => this.grist.exportRecords() }\n }\n }\n\n render() {\n const statuses = [\n { value: '', display: i18next.t('text.invoice-filter-all-statuses') },\n ...['DRAFT', 'ISSUED', 'VOID'].map(value => ({ value, display: invoiceStatusWord(value) })),\n { value: 'OVERDUE', display: i18next.t('text.invoice-overdue') }\n ]\n const directions = [\n { value: '', display: i18next.t('text.invoice-filter-all-directions') },\n { value: 'SALES', display: i18next.t('text.invoice-direction-sales') },\n { value: 'PURCHASE', display: i18next.t('text.invoice-direction-purchase') }\n ]\n const periods = [\n { value: '', display: i18next.t('text.invoice-period-all') },\n { value: 'this-month', display: i18next.t('text.invoice-period-this-month') },\n { value: 'last-month', display: i18next.t('text.invoice-period-last-month') },\n { value: 'this-year', display: i18next.t('text.invoice-period-this-year') },\n { value: 'last-year', display: i18next.t('text.invoice-period-last-year') }\n ]\n const choice = (label: string, value: string, choices: { value: string; display: string }[], set: (value: string) => void) =>\n html`<ox-select\n .value=${value}\n aria-label=${label}\n @change=${(e: CustomEvent) => {\n const next = String(e.detail ?? '')\n if (next === value) return\n set(next)\n this.grist.fetch()\n }}\n >\n <span slot=\"label\">${choices.find(one => one.value === value)?.display}</span>\n <ox-popup-list align-left nowrap>${choices.map(one => html`<div option value=${one.value}>${one.display}</div>`)}</ox-popup-list>\n </ox-select>`\n return html`${this.totals.length\n ? html`<div class=\"page-headroom totals\" aria-label=${i18next.t('text.invoice-totals-shown')}>\n ${i18next.t('text.invoice-totals-shown')}\n ${this.totals.map(\n one =>\n html`<span\n >${one.direction === 'PURCHASE' ? i18next.t('text.invoice-direction-purchase') : i18next.t('text.invoice-direction-sales')}\n <strong>${documentAmount(one.amount, one.currency)}</strong></span\n >`\n )}\n </div>`\n : nothing}<ox-assistant-selection-bar\n .gridOf=${() => this.grist}\n name=${i18next.t('title.invoice-list')}\n list=\"invoices\"\n axis=\"invoice\"\n .labelOf=${(row: any) => [row.number, counterpartOf(row)].filter(Boolean).join(' · ')}\n ></ox-assistant-selection-bar>\n <ox-grist\n class=\"page-fill\"\n search-mode=\"term\"\n .mode=${isMobileDevice() ? 'CARD' : 'GRID'}\n .config=${this.gristConfig}\n .fetchHandler=${this.fetchHandler.bind(this)}\n >\n <div slot=\"headroom\" class=\"header\">\n <div class=\"filters\">\n ${choice(i18next.t('field.invoice-status'), this.status, statuses, value => (this.status = value))}\n ${choice(i18next.t('field.invoice-direction'), this.direction, directions, value => (this.direction = value))}\n ${choice(i18next.t('field.invoice-issue-date'), this.period, periods, value => (this.period = value))}\n </div>\n </div>\n </ox-grist>`\n }\n\n async pageInitialized() {\n const readonly = (type: string, name: string, header: string, width: number, extra: any = {}) => ({\n type,\n name,\n header,\n width,\n sortable: true,\n ...extra,\n record: { editable: false, ...extra.record }\n })\n this.gristConfig = {\n rows: { appendable: false, selectable: { multiple: true } },\n pagination: { limit: 50, pages: [50, 100, 500] },\n emptyNote: { title: i18next.t('text.invoice-empty'), description: i18next.t('text.invoice-empty-description') },\n list: { fields: ['number', 'counterpart'], details: ['status', 'dueDate', 'totalAmount'] },\n columns: [\n { type: 'gutter', gutterName: 'sequence' },\n SELECTION_ROW_PICKER,\n {\n type: 'gutter',\n gutterName: 'button',\n icon: 'edit_note',\n handlers: { click: (_columns: any, _data: any, _column: any, record: any) => record?.id && navigate(`invoice-editor?id=${record.id}`) }\n },\n /* The number is the invoice's own name and opens its 360; the other party opens the counterparty's (ADR-0067 decision 1). */\n /* Narrow enough that the total stays in view on a laptop. */\n readonly('string', 'number', i18next.t('field.invoice-number'), 120, {\n record: { renderer: (value: string, _column: any, record: any) => (record?.id ? entity360Name({ __typename: 'Invoice', ...record }, value) : value) }\n }),\n readonly('string', 'counterpart', i18next.t('field.invoice-counterpart'), 170, {\n sortable: false,\n record: { renderer: (_value: any, _column: any, record: any) => counterpartCell(record) }\n }),\n readonly('string', 'status', i18next.t('field.invoice-status'), 110, {\n record: {\n renderer: (value: string, _column: any, record: any) =>\n overdue(record ?? {}, today())\n ? html`${invoiceStatusWord(value)} · <span style=\"color:var(--md-sys-color-error)\">${i18next.t('text.invoice-overdue')}</span>`\n : invoiceStatusWord(value)\n }\n }),\n readonly('string', 'direction', i18next.t('field.invoice-direction'), 56, {\n record: { renderer: (value: string) => (value === 'PURCHASE' ? i18next.t('text.invoice-direction-purchase') : i18next.t('text.invoice-direction-sales')) }\n }),\n readonly('string', 'issueDate', i18next.t('field.invoice-issue-date'), 92),\n readonly('string', 'dueDate', i18next.t('field.invoice-due-date'), 92),\n readonly('float', 'totalAmount', i18next.t('field.invoice-total-amount'), 140, {\n record: { align: 'right', renderer: (value: number, _column: any, record: any) => documentAmount(value, record?.currency || 'KRW') }\n })\n ],\n sorters: [{ name: 'issueDate', desc: true }]\n }\n }\n\n async fetchHandler({ page = 1, limit = 50, sortings = [], filters = [], search }: FetchOption) {\n const response = await client.query({\n query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!], $search: String) {\n responses: invoices(filters: $filters, pagination: $pagination, sortings: $sortings, search: $search) {\n items {\n id\n number\n status\n direction\n currency\n counterpartyId\n supplierName\n buyerName\n issueDate\n dueDate\n totalAmount\n }\n total\n }\n }\n `,\n variables: { filters: [...filters, ...this.headroomFilters()], pagination: { page, limit }, sortings, search: search?.trim() || undefined },\n fetchPolicy: 'network-only'\n })\n if (response.errors?.length) throw response\n this.totals = totalsOf(response.data.responses.items)\n return { total: response.data.responses.total, records: response.data.responses.items }\n }\n\n /**\n * The headroom's choices as the list's filters. Overdue is issued and due before today - the invoice module keeps no\n * payments, so the list reads it from the status and the due date alone (invoice-standing.ts).\n */\n private headroomFilters() {\n const filters: { name: string; operator: string; value: any }[] = []\n if (this.status === 'OVERDUE') filters.push({ name: 'status', operator: 'eq', value: 'ISSUED' }, { name: 'dueDate', operator: 'lt', value: today() })\n else if (this.status) filters.push({ name: 'status', operator: 'eq', value: this.status })\n if (this.direction) filters.push({ name: 'direction', operator: 'eq', value: this.direction })\n const period = issuePeriodOf(this.period, today())\n if (period) filters.push({ name: 'issueDate', operator: 'between', value: period })\n return filters\n }\n}\n"]}