@things-factory/invoice 10.1.259 → 10.1.260

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.
@@ -1,6 +1,5 @@
1
1
  import '@operato/data-grist/ox-grist.js';
2
- import '@operato/input/ox-select.js';
3
- import '@operato/popup/ox-popup-list.js';
2
+ import '@operato/data-grist/ox-filters-form.js';
4
3
  import { FetchOption } from '@operato/data-grist';
5
4
  import { PageView } from '@operato/shell';
6
5
  declare const InvoiceList_base: (new (...args: any[]) => import("lit").LitElement) & typeof PageView;
@@ -8,14 +7,12 @@ declare const InvoiceList_base: (new (...args: any[]) => import("lit").LitElemen
8
7
  * 청구서 — every invoice the domain sent or received. The other party's name opens the invoice's 360; the edit gutter
9
8
  * opens the editor. Search is the server's: number, parties, purchase order and notes. Rows picked go to the assistant
10
9
  * (「AI와 작업」) as `invoice:<uuid>`, read by the invoice list's read (server invoice-read.ts). The headroom narrows it by
11
- * status, direction and issue period; the totals of the rows shown stand over it (ADR-0170 decision 11).
10
+ * status, direction and issue period - the grid's own column filters, kept in the address with search, sort and page
11
+ * (FOOTER-BUTTON-REVIEW G09); the totals of the rows shown stand over it (ADR-0170 decision 11).
12
12
  */
13
13
  export declare class InvoiceList extends InvoiceList_base {
14
14
  static styles: import("lit").CSSResult[];
15
15
  gristConfig: any;
16
- status: string;
17
- direction: string;
18
- period: string;
19
16
  /** The totals of the rows on the page, by direction and currency. */
20
17
  totals: {
21
18
  direction: string;
@@ -51,10 +48,5 @@ export declare class InvoiceList extends InvoiceList_base {
51
48
  total: any;
52
49
  records: any;
53
50
  }>;
54
- /**
55
- * The headroom's choices as the list's filters. Overdue is issued and due before today - the invoice module keeps no
56
- * payments, so the list reads it from the status and the due date alone (invoice-standing.ts).
57
- */
58
- private headroomFilters;
59
51
  }
60
52
  export {};
@@ -1,11 +1,10 @@
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
+ import '@operato/data-grist/ox-filters-form.js';
5
4
  import gql from 'graphql-tag';
6
5
  import { css, html, nothing } from 'lit';
7
6
  import { customElement, query, state } from 'lit/decorators.js';
8
- import { DataGrist } from '@operato/data-grist';
7
+ import { DataGrist, isFilterCondition } from '@operato/data-grist';
9
8
  import { client } from '@operato/graphql';
10
9
  import { i18next, localize } from '@operato/i18n';
11
10
  import { entity360Name } from '@operato/layout';
@@ -13,7 +12,7 @@ import { navigate, PageView } from '@operato/shell';
13
12
  import { CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles';
14
13
  import { isMobileDevice } from '@operato/utils';
15
14
  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';
15
+ import { invoiceListFilters, overdue, totalsOf } from '@things-factory/invoice/dist-shared/invoice-standing.js';
17
16
  import { documentAmount } from '../document/document-amount';
18
17
  import { counterpartCell, counterpartOf, invoiceStatusWord } from '../entity360/invoice-360';
19
18
  const today = () => new Date().toLocaleDateString('en-CA');
@@ -21,14 +20,12 @@ const today = () => new Date().toLocaleDateString('en-CA');
21
20
  * 청구서 — every invoice the domain sent or received. The other party's name opens the invoice's 360; the edit gutter
22
21
  * opens the editor. Search is the server's: number, parties, purchase order and notes. Rows picked go to the assistant
23
22
  * (「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).
23
+ * status, direction and issue period - the grid's own column filters, kept in the address with search, sort and page
24
+ * (FOOTER-BUTTON-REVIEW G09); the totals of the rows shown stand over it (ADR-0170 decision 11).
25
25
  */
26
26
  let InvoiceList = class InvoiceList extends localize(i18next)(PageView) {
27
27
  constructor() {
28
28
  super(...arguments);
29
- this.status = '';
30
- this.direction = '';
31
- this.period = '';
32
29
  /** The totals of the rows on the page, by direction and currency. */
33
30
  this.totals = [];
34
31
  }
@@ -38,15 +35,6 @@ let InvoiceList = class InvoiceList extends localize(i18next)(PageView) {
38
35
  CommonHeaderStyles,
39
36
  ScrollbarStyles,
40
37
  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
38
  .totals {
51
39
  font-size: var(--ui-t-small, 11.5px);
52
40
  color: var(--ui-muted, var(--md-sys-color-on-surface-variant));
@@ -77,37 +65,6 @@ let InvoiceList = class InvoiceList extends localize(i18next)(PageView) {
77
65
  };
78
66
  }
79
67
  render() {
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
68
  return html `${this.totals.length
112
69
  ? html `<div class="page-headroom totals" aria-label=${i18next.t('text.invoice-totals-shown')}>
113
70
  ${i18next.t('text.invoice-totals-shown')}
@@ -129,13 +86,10 @@ let InvoiceList = class InvoiceList extends localize(i18next)(PageView) {
129
86
  .mode=${isMobileDevice() ? 'CARD' : 'GRID'}
130
87
  .config=${this.gristConfig}
131
88
  .fetchHandler=${this.fetchHandler.bind(this)}
89
+ ?url-params-sensitive=${this.active}
132
90
  >
133
91
  <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>
92
+ <div class="filters"><ox-filters-form without-search></ox-filters-form></div>
139
93
  </div>
140
94
  </ox-grist>`;
141
95
  }
@@ -149,6 +103,8 @@ let InvoiceList = class InvoiceList extends localize(i18next)(PageView) {
149
103
  ...extra,
150
104
  record: { editable: false, ...extra.record }
151
105
  });
106
+ /* The headroom's choices - a select of the column's values, the first one no condition. */
107
+ const choices = (all, values) => ({ type: 'select', operator: 'eq', options: [{ value: '', display: i18next.t(all) }, ...values] });
152
108
  this.gristConfig = {
153
109
  rows: { appendable: false, selectable: { multiple: true } },
154
110
  pagination: { limit: 50, pages: [50, 100, 500] },
@@ -173,6 +129,10 @@ let InvoiceList = class InvoiceList extends localize(i18next)(PageView) {
173
129
  record: { renderer: (_value, _column, record) => counterpartCell(record) }
174
130
  }),
175
131
  readonly('string', 'status', i18next.t('field.invoice-status'), 110, {
132
+ filter: choices('text.invoice-filter-all-statuses', [
133
+ ...['DRAFT', 'ISSUED', 'VOID'].map(value => ({ value, display: invoiceStatusWord(value) })),
134
+ { value: 'OVERDUE', display: i18next.t('text.invoice-overdue') }
135
+ ]),
176
136
  record: {
177
137
  renderer: (value, _column, record) => overdue(record ?? {}, today())
178
138
  ? html `${invoiceStatusWord(value)} · <span style="color:var(--md-sys-color-error)">${i18next.t('text.invoice-overdue')}</span>`
@@ -180,9 +140,16 @@ let InvoiceList = class InvoiceList extends localize(i18next)(PageView) {
180
140
  }
181
141
  }),
182
142
  readonly('string', 'direction', i18next.t('field.invoice-direction'), 56, {
143
+ filter: choices('text.invoice-filter-all-directions', [
144
+ { value: 'SALES', display: i18next.t('text.invoice-direction-sales') },
145
+ { value: 'PURCHASE', display: i18next.t('text.invoice-direction-purchase') }
146
+ ]),
183
147
  record: { renderer: (value) => (value === 'PURCHASE' ? i18next.t('text.invoice-direction-purchase') : i18next.t('text.invoice-direction-sales')) }
184
148
  }),
185
- readonly('string', 'issueDate', i18next.t('field.invoice-issue-date'), 92),
149
+ /* The issue date narrows by a period around today, read as the days between (invoiceListFilters). */
150
+ readonly('string', 'issueDate', i18next.t('field.invoice-issue-date'), 92, {
151
+ filter: choices('text.invoice-period-all', ['this-month', 'last-month', 'this-year', 'last-year'].map(value => ({ value, display: i18next.t(`text.invoice-period-${value}`) })))
152
+ }),
186
153
  readonly('string', 'dueDate', i18next.t('field.invoice-due-date'), 92),
187
154
  readonly('float', 'totalAmount', i18next.t('field.invoice-total-amount'), 140, {
188
155
  record: { align: 'right', renderer: (value, _column, record) => documentAmount(value, record?.currency || 'KRW') }
@@ -208,12 +175,13 @@ let InvoiceList = class InvoiceList extends localize(i18next)(PageView) {
208
175
  issueDate
209
176
  dueDate
210
177
  totalAmount
178
+ remainingAmount
211
179
  }
212
180
  total
213
181
  }
214
182
  }
215
183
  `,
216
- variables: { filters: [...filters, ...this.headroomFilters()], pagination: { page, limit }, sortings, search: search?.trim() || undefined },
184
+ variables: { filters: invoiceListFilters(filters.filter(isFilterCondition), today()), pagination: { page, limit }, sortings, search: search?.trim() || undefined },
217
185
  fetchPolicy: 'network-only'
218
186
  });
219
187
  if (response.errors?.length)
@@ -221,40 +189,11 @@ let InvoiceList = class InvoiceList extends localize(i18next)(PageView) {
221
189
  this.totals = totalsOf(response.data.responses.items);
222
190
  return { total: response.data.responses.total, records: response.data.responses.items };
223
191
  }
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
- }
241
192
  };
242
193
  __decorate([
243
194
  state(),
244
195
  __metadata("design:type", Object)
245
196
  ], 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
197
  __decorate([
259
198
  state(),
260
199
  __metadata("design:type", Array)
@@ -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'\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'), 130, {\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"]}
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/data-grist/ox-filters-form.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, isFilterCondition } 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 { invoiceListFilters, 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 grid's own column filters, kept in the address with search, sort and page\n * (FOOTER-BUTTON-REVIEW G09); 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 .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 /** 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 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 ?url-params-sensitive=${this.active}\n >\n <div slot=\"headroom\" class=\"header\">\n <div class=\"filters\"><ox-filters-form without-search></ox-filters-form></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 /* The headroom's choices - a select of the column's values, the first one no condition. */\n const choices = (all: string, values: { value: string; display: string }[]) => ({ type: 'select', operator: 'eq', options: [{ value: '', display: i18next.t(all) }, ...values] })\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'), 130, {\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 filter: choices('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 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 filter: choices('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 record: { renderer: (value: string) => (value === 'PURCHASE' ? i18next.t('text.invoice-direction-purchase') : i18next.t('text.invoice-direction-sales')) }\n }),\n /* The issue date narrows by a period around today, read as the days between (invoiceListFilters). */\n readonly('string', 'issueDate', i18next.t('field.invoice-issue-date'), 92, {\n filter: choices(\n 'text.invoice-period-all',\n ['this-month', 'last-month', 'this-year', 'last-year'].map(value => ({ value, display: i18next.t(`text.invoice-period-${value}`) }))\n )\n }),\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 remainingAmount\n }\n total\n }\n }\n `,\n variables: { filters: invoiceListFilters(filters.filter(isFilterCondition), today()), 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"]}