@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.
- package/dist-client/document/document-amount.d.ts +7 -2
- package/dist-client/document/document-amount.js +11 -6
- package/dist-client/document/document-amount.js.map +1 -1
- package/dist-client/document/document-defaults.d.ts +24 -0
- package/dist-client/document/document-defaults.js +43 -0
- package/dist-client/document/document-defaults.js.map +1 -0
- package/dist-client/document/document-form.d.ts +24 -6
- package/dist-client/document/document-form.js +126 -15
- package/dist-client/document/document-form.js.map +1 -1
- package/dist-client/document/document-lines.d.ts +35 -1
- package/dist-client/document/document-lines.js +58 -9
- package/dist-client/document/document-lines.js.map +1 -1
- package/dist-client/document/document-party.d.ts +37 -0
- package/dist-client/document/document-party.js +217 -0
- package/dist-client/document/document-party.js.map +1 -0
- package/dist-client/document/document-preview.d.ts +37 -0
- package/dist-client/document/document-preview.js +181 -0
- package/dist-client/document/document-preview.js.map +1 -0
- package/dist-client/document/document-print.d.ts +3 -13
- package/dist-client/document/document-print.js +3 -45
- package/dist-client/document/document-print.js.map +1 -1
- package/dist-client/index.d.ts +9 -3
- package/dist-client/index.js +9 -3
- package/dist-client/index.js.map +1 -1
- package/dist-client/pages/invoice-editor.d.ts +37 -12
- package/dist-client/pages/invoice-editor.js +171 -79
- package/dist-client/pages/invoice-editor.js.map +1 -1
- package/dist-client/pages/invoice-list.d.ts +21 -1
- package/dist-client/pages/invoice-list.js +145 -14
- package/dist-client/pages/invoice-list.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/viewparts/document-defaults-setting-let.d.ts +19 -0
- package/dist-client/viewparts/document-defaults-setting-let.js +139 -0
- package/dist-client/viewparts/document-defaults-setting-let.js.map +1 -0
- package/dist-server/role-tasks.js +5 -2
- package/dist-server/role-tasks.js.map +1 -1
- package/dist-server/service/document-defaults/document-defaults-resolver.d.ts +28 -0
- package/dist-server/service/document-defaults/document-defaults-resolver.js +136 -0
- package/dist-server/service/document-defaults/document-defaults-resolver.js.map +1 -0
- package/dist-server/service/document-defaults/document-defaults-rules.d.ts +25 -0
- package/dist-server/service/document-defaults/document-defaults-rules.js +50 -0
- package/dist-server/service/document-defaults/document-defaults-rules.js.map +1 -0
- package/dist-server/service/document-defaults/index.d.ts +6 -0
- package/dist-server/service/document-defaults/index.js +11 -0
- package/dist-server/service/document-defaults/index.js.map +1 -0
- package/dist-server/service/index.d.ts +2 -0
- package/dist-server/service/index.js +4 -1
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/invoice/commercial-document.d.ts +2 -0
- package/dist-server/service/invoice/commercial-document.js +11 -1
- package/dist-server/service/invoice/commercial-document.js.map +1 -1
- package/dist-server/service/invoice/invoice-document-file.d.ts +20 -0
- package/dist-server/service/invoice/invoice-document-file.js +38 -0
- package/dist-server/service/invoice/invoice-document-file.js.map +1 -0
- package/dist-server/service/invoice/invoice-query.d.ts +3 -1
- package/dist-server/service/invoice/invoice-query.js +33 -0
- package/dist-server/service/invoice/invoice-query.js.map +1 -1
- package/dist-server/service/invoice/invoice-rules.d.ts +18 -11
- package/dist-server/service/invoice/invoice-rules.js +49 -96
- package/dist-server/service/invoice/invoice-rules.js.map +1 -1
- package/dist-server/service/invoice/invoice-service.d.ts +1 -0
- package/dist-server/service/invoice/invoice-service.js +5 -2
- package/dist-server/service/invoice/invoice-service.js.map +1 -1
- package/dist-server/service/invoice/invoice-type.d.ts +12 -0
- package/dist-server/service/invoice/invoice-type.js +37 -1
- package/dist-server/service/invoice/invoice-type.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/dist-shared/document-amounts.d.ts +56 -0
- package/dist-shared/document-amounts.js +134 -0
- package/dist-shared/document-amounts.js.map +1 -0
- package/dist-shared/document-money.d.ts +12 -0
- package/dist-shared/document-money.js +38 -0
- package/dist-shared/document-money.js.map +1 -0
- package/dist-shared/document-print.d.ts +37 -0
- package/dist-shared/document-print.js +87 -0
- package/dist-shared/document-print.js.map +1 -0
- package/dist-shared/document-start.d.ts +15 -0
- package/dist-shared/document-start.js +51 -0
- package/dist-shared/document-start.js.map +1 -0
- package/dist-shared/invoice-standing.d.ts +25 -0
- package/dist-shared/invoice-standing.js +51 -0
- package/dist-shared/invoice-standing.js.map +1 -0
- package/package.json +9 -7
- package/shared/document-amounts.ts +209 -0
- package/shared/document-money.ts +33 -0
- package/shared/document-print.ts +131 -0
- package/shared/document-start.ts +46 -0
- package/shared/invoice-standing.ts +49 -0
- package/translations/en.json +32 -6
- package/translations/es.json +22 -1
- package/translations/ja.json +22 -1
- package/translations/ko.json +32 -6
- package/translations/ms.json +22 -1
- package/translations/zh.json +22 -1
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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'),
|
|
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'),
|
|
85
|
-
|
|
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'),
|
|
89
|
-
readonly('string', 'dueDate', i18next.t('field.invoice-due-date'),
|
|
90
|
-
readonly('float', 'totalAmount', i18next.t('field.invoice-total-amount'),
|
|
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"]}
|