@things-factory/sales 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.
- package/dist-client/list-filters.d.ts +23 -0
- package/dist-client/list-filters.js +58 -0
- package/dist-client/list-filters.js.map +1 -0
- package/dist-client/pages/opportunity-list.d.ts +9 -10
- package/dist-client/pages/opportunity-list.js +49 -78
- package/dist-client/pages/opportunity-list.js.map +1 -1
- package/dist-client/pages/quotation-list.d.ts +3 -4
- package/dist-client/pages/quotation-list.js +33 -47
- package/dist-client/pages/quotation-list.js.map +1 -1
- package/dist-client/pages/sales-product-list.d.ts +7 -4
- package/dist-client/pages/sales-product-list.js +68 -50
- package/dist-client/pages/sales-product-list.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
- package/translations/en.json +1 -1
- package/translations/es.json +1 -1
- package/translations/ja.json +1 -1
- package/translations/ko.json +1 -1
- package/translations/ms.json +1 -1
- package/translations/zh.json +1 -1
- package/dist-client/headroom-choice.d.ts +0 -10
- package/dist-client/headroom-choice.js +0 -22
- package/dist-client/headroom-choice.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quotation-list.js","sourceRoot":"","sources":["../../client/pages/quotation-list.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/data-grist/ox-grist.js'\nimport '@operato/input/ox-input-select-buttons.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 { 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 { counterpartOf, documentAmount, issuePeriodOf } from '@things-factory/invoice/dist-client'\n\nimport { headroomChoice } from '../headroom-choice'\nimport { quotationStatusWord } from '../quotation-words'\n\nconst today = () => new Date().toLocaleDateString('en-CA')\n\n/**\n * 견적 — every version of every quotation; the latest of a number is the one still in play. Rows picked go to the\n * assistant (「AI와 작업」) as `quotation:<uuid>`, read by the quotation list's read (sales-read.ts).\n *\n * The headroom narrows it by issue period, as the invoice list does, and by status chips, each with how many quotations\n * it holds under the other conditions - counted by the server. With no status pressed every status shows.\n */\n@customElement('quotation-list')\nexport class QuotationList extends localize(i18next)(PageView) {\n static styles = [WorkSurfacePageStyles, CommonGristStyles, CommonHeaderStyles, ScrollbarStyles]\n\n @state() gristConfig: any\n @state() private statuses: string[] = []\n @state() private period = ''\n @query('ox-grist') private grist!: DataGrist\n\n get context() {\n return {\n title: i18next.t('title.quotation-list'),\n search: {\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist?.searchText || ''\n },\n /* The issue period and the statuses narrow it in the headroom, and this folds it. */\n filter: {\n handler: () => {\n this.grist.toggleHeadroom()\n }\n },\n actions: [{ title: i18next.t('button.quotation-new'), icon: 'add', emphasis: { raised: true }, action: () => navigate('quotation-editor') }],\n exportable: { name: i18next.t('title.quotation-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.quotation-list')}\n list=\"quotations\"\n axis=\"quotation\"\n .labelOf=${(row: any) => [row.number && `${row.number} v${row.version}`, 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 .countHandler=${this.countHandler.bind(this)}\n @counts-change=${() => this.requestUpdate()}\n >\n <div slot=\"headroom\" class=\"header\">\n <div class=\"filters\">\n ${headroomChoice(\n i18next.t('field.quotation-issue-date'),\n this.period,\n ['', 'this-month', 'last-month', 'this-year', 'last-year'].map(value => ({ value, display: i18next.t(`text.invoice-period-${value || 'all'}`) })),\n value => ((this.period = value), this.grist.fetch())\n )}\n <ox-input-select-buttons\n multiple\n .value=${this.statuses}\n .options=${Object.entries(this.grist?.counts?.status ?? {}).map(([value, count]) => ({ value, display: quotationStatusWord(value), count }))}\n @change=${(e: CustomEvent) => {\n this.statuses = (e.currentTarget as any).value ?? []\n this.grist.fetch()\n }}\n ></ox-input-select-buttons>\n </div>\n </div>\n </ox-grist>`\n }\n\n async pageInitialized() {\n const open = (record: any) => record?.id && navigate(`quotation-editor?id=${record.id}`)\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.quotation-empty'), description: i18next.t('text.quotation-empty-description') },\n list: { fields: ['counterpart', 'number'], details: ['status', 'validUntil', 'totalAmount'] },\n columns: [\n { type: 'gutter', gutterName: 'sequence' },\n SELECTION_ROW_PICKER,\n { type: 'gutter', gutterName: 'button', icon: 'edit_note', handlers: { click: (_c: any, _d: any, _col: any, record: any) => open(record) } },\n readonly('string', 'counterpart', i18next.t('field.quotation-counterpart'), 200, { sortable: false, record: { renderer: (_v: any, _c: any, record: any) => counterpartOf(record) } }),\n readonly('string', 'number', i18next.t('field.quotation-number'), 140),\n readonly('integer', 'version', i18next.t('field.quotation-version'), 60),\n readonly('string', 'status', i18next.t('field.quotation-status'), 90, { record: { renderer: (value: string) => quotationStatusWord(value) } }),\n readonly('string', 'issueDate', i18next.t('field.quotation-issue-date'), 110),\n readonly('string', 'validUntil', i18next.t('field.quotation-valid-until'), 110),\n readonly('float', 'totalAmount', i18next.t('field.quotation-total-amount'), 160, {\n record: { align: 'right', renderer: (value: number, _c: any, record: any) => documentAmount(value, record?.currency || 'KRW') }\n })\n ],\n sorters: [{ name: 'issueDate', desc: true }]\n }\n }\n\n /* The list's conditions before the statuses are added: the grid's, the issue period and the search. */\n private conditions(filters: any[] = [], search?: string) {\n const period = issuePeriodOf(this.period, today())\n return { filters: [...filters, ...(period ? [{ name: 'issueDate', operator: 'between', value: period }] : [])], search: search?.trim() || undefined }\n }\n\n /* The status chips and their numbers, under the list's other conditions; a chip keeps its number until the next land. */\n async countHandler({ filters, search, signal }: FetchOption) {\n const response = await client.query({\n query: gql`\n query ($filters: [Filter!], $search: String) {\n quotationStatusCounts(filters: $filters, search: $search) { value count }\n }\n `,\n variables: this.conditions(filters, search),\n fetchPolicy: 'no-cache',\n context: { fetchOptions: { signal }, queryDeduplication: false }\n })\n if (response.errors?.length) throw response.errors[0]\n return { status: Object.fromEntries(response.data.quotationStatusCounts.map((row: { value: string; count: number }) => [row.value, row.count])) }\n }\n\n async fetchHandler({ page = 1, limit = 50, sortings = [], ...asked }: FetchOption) {\n const { filters: others, search } = this.conditions(asked.filters, asked.search)\n const filters = this.statuses.length ? [...others, { name: 'status', operator: 'in', value: this.statuses }] : others\n const response = await client.query({\n query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!], $search: String) {\n responses: quotations(filters: $filters, pagination: $pagination, sortings: $sortings, search: $search) {\n items {\n id\n number\n version\n status\n direction\n currency\n supplierName\n buyerName\n issueDate\n validUntil\n totalAmount\n }\n total\n }\n }\n `,\n variables: { filters, pagination: { page, limit }, sortings, search },\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":"quotation-list.js","sourceRoot":"","sources":["../../client/pages/quotation-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 { 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 { 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 { counterpartOf, documentAmount, issuePeriodOf } from '@things-factory/invoice/dist-client'\n\nimport { QUOTATION_STATUSES, quotationFilters } from '../list-filters'\nimport { quotationStatusWord } from '../quotation-words'\n\nconst today = () => new Date().toLocaleDateString('en-CA')\n\n/**\n * 견적 — every version of every quotation; the latest of a number is the one still in play. Rows picked go to the\n * assistant (「AI와 작업」) as `quotation:<uuid>`, read by the quotation list's read (sales-read.ts).\n *\n * The headroom narrows it by issue period, as the invoice list does, and by status chips, each with how many quotations\n * it holds under the other conditions - counted by the server. With no status pressed every status shows. Both are the\n * grid's own column filters, kept in the address with the search, sort and page (FOOTER-BUTTON-REVIEW G09).\n */\n@customElement('quotation-list')\nexport class QuotationList extends localize(i18next)(PageView) {\n static styles = [WorkSurfacePageStyles, CommonGristStyles, CommonHeaderStyles, ScrollbarStyles]\n\n @state() gristConfig: any\n @query('ox-grist') private grist!: DataGrist\n\n get context() {\n return {\n title: i18next.t('title.quotation-list'),\n search: {\n handler: (search: string) => {\n this.grist.searchText = search\n },\n value: this.grist?.searchText || ''\n },\n /* The issue period and the statuses narrow it in the headroom, and this folds it. */\n filter: {\n handler: () => {\n this.grist.toggleHeadroom()\n }\n },\n actions: [{ title: i18next.t('button.quotation-new'), icon: 'add', emphasis: { raised: true }, action: () => navigate('quotation-editor') }],\n exportable: { name: i18next.t('title.quotation-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.quotation-list')}\n list=\"quotations\"\n axis=\"quotation\"\n .labelOf=${(row: any) => [row.number && `${row.number} v${row.version}`, 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 .countHandler=${this.countHandler.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 open = (record: any) => record?.id && navigate(`quotation-editor?id=${record.id}`)\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.quotation-empty'), description: i18next.t('text.quotation-empty-description') },\n list: { fields: ['counterpart', 'number'], details: ['status', 'validUntil', 'totalAmount'] },\n columns: [\n { type: 'gutter', gutterName: 'sequence' },\n SELECTION_ROW_PICKER,\n { type: 'gutter', gutterName: 'button', icon: 'edit_note', handlers: { click: (_c: any, _d: any, _col: any, record: any) => open(record) } },\n readonly('string', 'counterpart', i18next.t('field.quotation-counterpart'), 200, { sortable: false, record: { renderer: (_v: any, _c: any, record: any) => counterpartOf(record) } }),\n readonly('string', 'number', i18next.t('field.quotation-number'), 140),\n readonly('integer', 'version', i18next.t('field.quotation-version'), 60),\n readonly('string', 'status', i18next.t('field.quotation-status'), 90, {\n record: { renderer: (value: string) => quotationStatusWord(value) },\n /* Chips with their counts; none pressed is every status. */\n filter: { type: 'select-buttons', operator: 'in', options: QUOTATION_STATUSES.map(value => ({ value, display: quotationStatusWord(value) })) }\n }),\n readonly('string', 'issueDate', i18next.t('field.quotation-issue-date'), 110, {\n /* A period named relative to today, as the invoice list narrows by it. */\n filter: {\n type: 'select',\n operator: 'eq',\n options: ['', 'this-month', 'last-month', 'this-year', 'last-year'].map(value => ({ value, display: i18next.t(`text.invoice-period-${value || 'all'}`) }))\n }\n }),\n readonly('string', 'validUntil', i18next.t('field.quotation-valid-until'), 110),\n readonly('float', 'totalAmount', i18next.t('field.quotation-total-amount'), 160, {\n record: { align: 'right', renderer: (value: number, _c: any, record: any) => documentAmount(value, record?.currency || 'KRW') }\n })\n ],\n sorters: [{ name: 'issueDate', desc: true }]\n }\n }\n\n /* The grid's filters as the server reads them - the issue period as its days - and the search. */\n private conditions(filters: any[] = [], search?: string) {\n return { filters: quotationFilters(filters, period => issuePeriodOf(period, today())), search: search?.trim() || undefined }\n }\n\n /* The status chips' numbers, under the list's other conditions - the chips' own left out; a chip keeps its number until the next land. */\n async countHandler({ filters, search, signal }: FetchOption) {\n const response = await client.query({\n query: gql`\n query ($filters: [Filter!], $search: String) {\n quotationStatusCounts(filters: $filters, search: $search) { value count }\n }\n `,\n variables: (({ filters: all, search: term }) => ({ filters: all.filter(one => one.name !== 'status'), search: term }))(this.conditions(filters, search)),\n fetchPolicy: 'no-cache',\n context: { fetchOptions: { signal }, queryDeduplication: false }\n })\n if (response.errors?.length) throw response.errors[0]\n return { status: Object.fromEntries(response.data.quotationStatusCounts.map((row: { value: string; count: number }) => [row.value, row.count])) }\n }\n\n async fetchHandler({ page = 1, limit = 50, sortings = [], ...asked }: FetchOption) {\n const { filters, search } = this.conditions(asked.filters, asked.search)\n const response = await client.query({\n query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!], $search: String) {\n responses: quotations(filters: $filters, pagination: $pagination, sortings: $sortings, search: $search) {\n items {\n id\n number\n version\n status\n direction\n currency\n supplierName\n buyerName\n issueDate\n validUntil\n totalAmount\n }\n total\n }\n }\n `,\n variables: { filters, pagination: { page, limit }, sortings, search },\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,6 +1,6 @@
|
|
|
1
1
|
import '@operato/data-grist/ox-grist.js';
|
|
2
2
|
import '@operato/data-grist/ox-filters-form.js';
|
|
3
|
-
import '@
|
|
3
|
+
import '@things-factory/ai-assistant/dist-client/index.js';
|
|
4
4
|
import { FetchOption } from '@operato/data-grist';
|
|
5
5
|
import { PageView } from '@operato/shell';
|
|
6
6
|
declare const SalesProductList_base: (new (...args: any[]) => import("lit").LitElement) & typeof PageView;
|
|
@@ -8,12 +8,13 @@ declare const SalesProductList_base: (new (...args: any[]) => import("lit").LitE
|
|
|
8
8
|
* 상품 — what the domain sells and the price it offers it at: goods, a service, or labor by the grade of the people
|
|
9
9
|
* (ADR-0171). Typed like a spreadsheet and saved together. A quotation line chosen from a product copies it at that
|
|
10
10
|
* moment; changing a price here changes no written quotation. The headroom narrows it to the products in use or out of
|
|
11
|
-
* use, each chip with how many it holds under the other conditions
|
|
11
|
+
* use, each chip with how many it holds under the other conditions - a filter of the grid's 사용 column, so it stays in
|
|
12
|
+
* the address with the search, sort and page (FOOTER-BUTTON-REVIEW G09). Deleting works on the picked rows, from the
|
|
13
|
+
* selection bar over the grid (F06).
|
|
12
14
|
*/
|
|
13
15
|
export declare class SalesProductList extends SalesProductList_base {
|
|
14
16
|
static styles: import("lit").CSSResult[];
|
|
15
17
|
gristConfig: any;
|
|
16
|
-
private inUse;
|
|
17
18
|
private saving;
|
|
18
19
|
private deleting;
|
|
19
20
|
private grist;
|
|
@@ -27,9 +28,10 @@ export declare class SalesProductList extends SalesProductList_base {
|
|
|
27
28
|
handler: () => void;
|
|
28
29
|
};
|
|
29
30
|
actions: ({
|
|
31
|
+
id: string;
|
|
30
32
|
title: string;
|
|
31
33
|
icon: string;
|
|
32
|
-
action: () =>
|
|
34
|
+
action: () => import("@operato/data-grist").GristRecord;
|
|
33
35
|
} | {
|
|
34
36
|
icon: string;
|
|
35
37
|
emphasis: {
|
|
@@ -38,6 +40,7 @@ export declare class SalesProductList extends SalesProductList_base {
|
|
|
38
40
|
dense: boolean;
|
|
39
41
|
danger: boolean;
|
|
40
42
|
};
|
|
43
|
+
id: string;
|
|
41
44
|
title: string;
|
|
42
45
|
action: () => Promise<void>;
|
|
43
46
|
})[];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { __decorate, __metadata } from "tslib";
|
|
2
2
|
import '@operato/data-grist/ox-grist.js';
|
|
3
3
|
import '@operato/data-grist/ox-filters-form.js';
|
|
4
|
-
import '@
|
|
4
|
+
import '@things-factory/ai-assistant/dist-client/index.js';
|
|
5
5
|
import gql from 'graphql-tag';
|
|
6
6
|
import { html } from 'lit';
|
|
7
7
|
import { customElement, query, state } from 'lit/decorators.js';
|
|
@@ -14,21 +14,26 @@ import { PageView } from '@operato/shell';
|
|
|
14
14
|
import { CommonButtonStyles, CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles';
|
|
15
15
|
import { isMobileDevice } from '@operato/utils';
|
|
16
16
|
import { documentNumber } from '@things-factory/invoice/dist-client';
|
|
17
|
+
import { salesProductFilters } from '../list-filters';
|
|
17
18
|
import { salesProductKindWord } from '../sales-product-words';
|
|
18
19
|
const KINDS = ['GOODS', 'SERVICE', 'LABOR'];
|
|
20
|
+
/** What a new row starts with - 「행 추가」 and a paste past the last row alike. */
|
|
21
|
+
const DRAFT = () => ({ kind: 'GOODS', currency: 'KRW', taxKind: 'TAXABLE', active: true });
|
|
22
|
+
/** The column layout the name-first order is made on - a person's older column order gives way to it. */
|
|
23
|
+
const COLUMNS_VERSION = 'lead-2026-11-08';
|
|
19
24
|
/** The fields a row writes - all of them for a new row, the changed ones otherwise. */
|
|
20
25
|
const FIELDS = ['code', 'name', 'kind', 'grade', 'spec', 'unit', 'unitPrice', 'currency', 'taxKind', 'active', 'description'];
|
|
21
26
|
/**
|
|
22
27
|
* 상품 — what the domain sells and the price it offers it at: goods, a service, or labor by the grade of the people
|
|
23
28
|
* (ADR-0171). Typed like a spreadsheet and saved together. A quotation line chosen from a product copies it at that
|
|
24
29
|
* moment; changing a price here changes no written quotation. The headroom narrows it to the products in use or out of
|
|
25
|
-
* use, each chip with how many it holds under the other conditions
|
|
30
|
+
* use, each chip with how many it holds under the other conditions - a filter of the grid's 사용 column, so it stays in
|
|
31
|
+
* the address with the search, sort and page (FOOTER-BUTTON-REVIEW G09). Deleting works on the picked rows, from the
|
|
32
|
+
* selection bar over the grid (F06).
|
|
26
33
|
*/
|
|
27
34
|
let SalesProductList = class SalesProductList extends localize(i18next)(PageView) {
|
|
28
35
|
constructor() {
|
|
29
36
|
super(...arguments);
|
|
30
|
-
/* In use or out of use - none chosen is every product. */
|
|
31
|
-
this.inUse = '';
|
|
32
37
|
/* A save or a delete reads the list again, and the chips count with it. */
|
|
33
38
|
this.saving = new MutationController(this, gql `
|
|
34
39
|
mutation ($patches: [SalesProductPatch!]!) {
|
|
@@ -57,59 +62,62 @@ let SalesProductList = class SalesProductList extends localize(i18next)(PageView
|
|
|
57
62
|
}
|
|
58
63
|
},
|
|
59
64
|
actions: [
|
|
60
|
-
{ title: i18next.t('button.add'), icon: 'add', action: () => this.grist.
|
|
61
|
-
{ title: i18next.t('button.
|
|
62
|
-
{ title: i18next.t('button.save'), action: () => this.save(), ...CommonButtonStyles.save }
|
|
65
|
+
{ id: 'add-row', title: i18next.t('button.add-row'), icon: 'add', action: () => this.grist.addNewRecord() },
|
|
66
|
+
{ id: 'save', title: i18next.t('button.save'), action: () => this.save(), ...CommonButtonStyles.save }
|
|
63
67
|
],
|
|
64
68
|
exportable: { name: i18next.t('title.sales-product-list'), data: () => this.grist.exportRecords() }
|
|
65
69
|
};
|
|
66
70
|
}
|
|
67
71
|
render() {
|
|
68
|
-
return html `<ox-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
72
|
+
return html `<ox-assistant-selection-bar
|
|
73
|
+
.gridOf=${() => this.grist}
|
|
74
|
+
name=${i18next.t('title.sales-product-list')}
|
|
75
|
+
.assistant=${false}
|
|
76
|
+
.actions=${[{ id: 'delete', title: i18next.t('button.delete'), icon: 'delete_outline', emphasis: { danger: true }, action: () => this.delete() }]}
|
|
77
|
+
></ox-assistant-selection-bar>
|
|
78
|
+
<ox-grist
|
|
79
|
+
class="page-fill"
|
|
80
|
+
search-mode="term"
|
|
81
|
+
.mode=${isMobileDevice() ? 'CARD' : 'GRID'}
|
|
82
|
+
.config=${this.gristConfig}
|
|
83
|
+
.fetchHandler=${this.fetchHandler.bind(this)}
|
|
84
|
+
.countHandler=${this.countHandler.bind(this)}
|
|
85
|
+
?url-params-sensitive=${this.active}
|
|
86
|
+
>
|
|
87
|
+
<div slot="headroom" class="header">
|
|
88
|
+
<div class="filters">
|
|
89
|
+
<ox-filters-form without-search autofocus></ox-filters-form>
|
|
90
|
+
</div>
|
|
85
91
|
</div>
|
|
86
|
-
</
|
|
87
|
-
</ox-grist>`;
|
|
92
|
+
</ox-grist>`;
|
|
88
93
|
}
|
|
89
94
|
async pageInitialized() {
|
|
90
95
|
const text = (name, header, width, extra = {}) => ({ type: 'string', name, header, width, sortable: true, ...extra, record: { editable: true, ...extra.record } });
|
|
91
96
|
this.gristConfig = {
|
|
92
|
-
|
|
97
|
+
/* No empty row under the records: 「행 추가」 starts one, and a paste past the last row adds rows with the same draft. */
|
|
98
|
+
rows: { appendable: false, pasteAppendable: true, newRecord: DRAFT, selectable: { multiple: true } },
|
|
99
|
+
columnsVersion: COLUMNS_VERSION,
|
|
93
100
|
pagination: { limit: 100, pages: [50, 100, 500] },
|
|
94
101
|
emptyNote: { title: i18next.t('text.sales-product-empty'), description: i18next.t('text.sales-product-empty-description') },
|
|
95
102
|
list: { fields: ['name', 'code'], details: ['kind', 'unit', 'unitPrice'] },
|
|
96
103
|
columns: [
|
|
104
|
+
/* A row's state (new, changed); a new row's mark removes it until it is saved (data-grist 행 제거). */
|
|
105
|
+
{ type: 'gutter', gutterName: 'dirty' },
|
|
97
106
|
{ type: 'gutter', gutterName: 'sequence' },
|
|
98
107
|
{ type: 'gutter', gutterName: 'row-selector', multiple: true },
|
|
108
|
+
/* The name is the row's identity and stays in view; what a product is offered at comes before how it is described. */
|
|
109
|
+
text('name', i18next.t('field.sales-product-name'), 200, { fixed: true, record: { mandatory: true } }),
|
|
99
110
|
text('code', i18next.t('field.sales-product-code'), 110, { record: { mandatory: true } }),
|
|
100
|
-
text('name', i18next.t('field.sales-product-name'), 200, { record: { mandatory: true } }),
|
|
101
111
|
{
|
|
102
|
-
type: '
|
|
103
|
-
name: '
|
|
104
|
-
header: i18next.t('field.sales-product-
|
|
105
|
-
width:
|
|
112
|
+
type: 'checkbox',
|
|
113
|
+
name: 'active',
|
|
114
|
+
header: i18next.t('field.sales-product-active'),
|
|
115
|
+
width: 60,
|
|
106
116
|
sortable: true,
|
|
107
|
-
record: { editable: true
|
|
108
|
-
|
|
117
|
+
record: { editable: true },
|
|
118
|
+
/* In use or out of use as chips, each with its count; none pressed is every product. */
|
|
119
|
+
filter: { type: 'select-buttons', operator: 'eq', options: ['active', 'inactive'].map(value => ({ value, display: i18next.t(`text.sales-product-${value}`) })) }
|
|
109
120
|
},
|
|
110
|
-
text('grade', i18next.t('field.sales-product-grade'), 110),
|
|
111
|
-
text('spec', i18next.t('field.sales-product-spec'), 160),
|
|
112
|
-
text('unit', i18next.t('field.sales-product-unit'), 70, { record: { align: 'center' } }),
|
|
113
121
|
{
|
|
114
122
|
type: 'float',
|
|
115
123
|
name: 'unitPrice',
|
|
@@ -119,6 +127,16 @@ let SalesProductList = class SalesProductList extends localize(i18next)(PageView
|
|
|
119
127
|
record: { editable: true, align: 'right', renderer: (value, _c, record) => documentNumber(value, record?.currency || 'KRW') }
|
|
120
128
|
},
|
|
121
129
|
text('currency', i18next.t('field.sales-product-currency'), 70, { record: { align: 'center' } }),
|
|
130
|
+
text('unit', i18next.t('field.sales-product-unit'), 70, { record: { align: 'center' } }),
|
|
131
|
+
{
|
|
132
|
+
type: 'select',
|
|
133
|
+
name: 'kind',
|
|
134
|
+
header: i18next.t('field.sales-product-kind'),
|
|
135
|
+
width: 80,
|
|
136
|
+
sortable: true,
|
|
137
|
+
record: { editable: true, options: KINDS.map(kind => ({ value: kind, display: salesProductKindWord(kind) })) },
|
|
138
|
+
filter: { type: 'select', operator: 'eq', options: [{ display: '', value: '' }, ...KINDS.map(kind => ({ display: salesProductKindWord(kind), value: kind }))] }
|
|
139
|
+
},
|
|
122
140
|
{
|
|
123
141
|
type: 'select',
|
|
124
142
|
name: 'taxKind',
|
|
@@ -133,21 +151,22 @@ let SalesProductList = class SalesProductList extends localize(i18next)(PageView
|
|
|
133
151
|
]
|
|
134
152
|
}
|
|
135
153
|
},
|
|
136
|
-
|
|
154
|
+
text('grade', i18next.t('field.sales-product-grade'), 110),
|
|
155
|
+
text('spec', i18next.t('field.sales-product-spec'), 160),
|
|
137
156
|
text('description', i18next.t('field.sales-product-description'), 220)
|
|
138
157
|
],
|
|
139
158
|
sorters: [{ name: 'code' }]
|
|
140
159
|
};
|
|
141
160
|
}
|
|
142
|
-
/* The in-use chips' numbers, on the list's filters
|
|
143
|
-
async countHandler({ filters, search, signal }) {
|
|
161
|
+
/* The in-use chips' numbers, on the list's other filters - the chip's own left out; a chip keeps its number until the next land. */
|
|
162
|
+
async countHandler({ filters = [], search, signal }) {
|
|
144
163
|
const response = await client.query({
|
|
145
164
|
query: gql `
|
|
146
165
|
query ($filters: [Filter!], $search: String) {
|
|
147
166
|
salesProductActiveCounts(filters: $filters, search: $search) { value count }
|
|
148
167
|
}
|
|
149
168
|
`,
|
|
150
|
-
variables: { filters, search: search?.trim() || undefined },
|
|
169
|
+
variables: { filters: salesProductFilters(filters).filter(one => one.name !== 'active'), search: search?.trim() || undefined },
|
|
151
170
|
fetchPolicy: 'no-cache',
|
|
152
171
|
context: { fetchOptions: { signal }, queryDeduplication: false }
|
|
153
172
|
});
|
|
@@ -157,8 +176,7 @@ let SalesProductList = class SalesProductList extends localize(i18next)(PageView
|
|
|
157
176
|
}
|
|
158
177
|
async fetchHandler({ page = 1, limit = 100, sortings = [], filters = [], search }) {
|
|
159
178
|
search = search?.trim() || undefined;
|
|
160
|
-
|
|
161
|
-
filters = [...filters, { name: 'active', operator: this.inUse === 'active' ? 'is_true' : 'is_not_true', value: null }];
|
|
179
|
+
const conditions = salesProductFilters(filters);
|
|
162
180
|
const response = await client.query({
|
|
163
181
|
query: gql `
|
|
164
182
|
query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!], $search: String) {
|
|
@@ -168,7 +186,7 @@ let SalesProductList = class SalesProductList extends localize(i18next)(PageView
|
|
|
168
186
|
}
|
|
169
187
|
}
|
|
170
188
|
`,
|
|
171
|
-
variables: { filters, pagination: { page, limit }, sortings, search },
|
|
189
|
+
variables: { filters: conditions, pagination: { page, limit }, sortings, search },
|
|
172
190
|
fetchPolicy: 'network-only'
|
|
173
191
|
});
|
|
174
192
|
if (response.errors?.length)
|
|
@@ -181,8 +199,10 @@ let SalesProductList = class SalesProductList extends localize(i18next)(PageView
|
|
|
181
199
|
const changed = record.__dirty__ === '+' ? FIELDS.filter(field => record[field] !== undefined) : Object.keys(record.__dirtyfields__ ?? {}).filter(field => FIELDS.includes(field));
|
|
182
200
|
return { ...(record.id ? { id: record.id } : {}), cuFlag: record.__dirty__, ...Object.fromEntries(changed.map(field => [field, record[field] === '' ? null : record[field]])) };
|
|
183
201
|
});
|
|
184
|
-
if (!patches.length)
|
|
202
|
+
if (!patches.length) {
|
|
203
|
+
notify({ level: 'info', message: i18next.t('text.nothing-to-save') });
|
|
185
204
|
return;
|
|
205
|
+
}
|
|
186
206
|
if (!(await this.saving.run({ patches })))
|
|
187
207
|
return;
|
|
188
208
|
notify({ level: 'info', message: i18next.t('text.sales-product-saved') });
|
|
@@ -190,8 +210,10 @@ let SalesProductList = class SalesProductList extends localize(i18next)(PageView
|
|
|
190
210
|
}
|
|
191
211
|
async delete() {
|
|
192
212
|
const ids = this.grist.selected.map((record) => record.id).filter(Boolean);
|
|
193
|
-
if (!ids.length)
|
|
213
|
+
if (!ids.length) {
|
|
214
|
+
notify({ level: 'info', message: i18next.t('text.select-rows-to-delete') });
|
|
194
215
|
return;
|
|
216
|
+
}
|
|
195
217
|
const confirmed = await OxPrompt.open({
|
|
196
218
|
title: i18next.t('button.delete'),
|
|
197
219
|
text: i18next.t('text.sales-product-delete-confirm', { count: ids.length }),
|
|
@@ -208,10 +230,6 @@ __decorate([
|
|
|
208
230
|
state(),
|
|
209
231
|
__metadata("design:type", Object)
|
|
210
232
|
], SalesProductList.prototype, "gristConfig", void 0);
|
|
211
|
-
__decorate([
|
|
212
|
-
state(),
|
|
213
|
-
__metadata("design:type", Object)
|
|
214
|
-
], SalesProductList.prototype, "inUse", void 0);
|
|
215
233
|
__decorate([
|
|
216
234
|
query('ox-grist'),
|
|
217
235
|
__metadata("design:type", DataGrist)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sales-product-list.js","sourceRoot":"","sources":["../../client/pages/sales-product-list.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/data-grist/ox-grist.js'\nimport '@operato/data-grist/ox-filters-form.js'\nimport '@operato/input/ox-input-select-buttons.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, MutationController } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { notify } from '@operato/layout'\nimport { OxPrompt } from '@operato/popup/ox-prompt.js'\nimport { PageView } from '@operato/shell'\nimport { CommonButtonStyles, CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { isMobileDevice } from '@operato/utils'\nimport { documentNumber } from '@things-factory/invoice/dist-client'\n\nimport { salesProductKindWord } from '../sales-product-words'\n\nconst KINDS = ['GOODS', 'SERVICE', 'LABOR']\n\n/** The fields a row writes - all of them for a new row, the changed ones otherwise. */\nconst FIELDS = ['code', 'name', 'kind', 'grade', 'spec', 'unit', 'unitPrice', 'currency', 'taxKind', 'active', 'description']\n\n/**\n * 상품 — what the domain sells and the price it offers it at: goods, a service, or labor by the grade of the people\n * (ADR-0171). Typed like a spreadsheet and saved together. A quotation line chosen from a product copies it at that\n * moment; changing a price here changes no written quotation. The headroom narrows it to the products in use or out of\n * use, each chip with how many it holds under the other conditions.\n */\n@customElement('sales-product-list')\nexport class SalesProductList extends localize(i18next)(PageView) {\n static styles = [WorkSurfacePageStyles, CommonGristStyles, CommonHeaderStyles, ScrollbarStyles]\n\n @state() gristConfig: any\n /* In use or out of use - none chosen is every product. */\n @state() private inUse = ''\n /* A save or a delete reads the list again, and the chips count with it. */\n private saving = new MutationController(\n this,\n gql`\n mutation ($patches: [SalesProductPatch!]!) {\n updateMultipleSalesProduct(patches: $patches) { id }\n }\n `\n )\n private deleting = new MutationController(\n this,\n gql`\n mutation ($ids: [String!]!) {\n deleteSalesProducts(ids: $ids)\n }\n `\n )\n @query('ox-grist') private grist!: DataGrist\n\n get context() {\n return {\n title: i18next.t('title.sales-product-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: [\n { title: i18next.t('button.add'), icon: 'add', action: () => this.grist.addRecordToTop({ kind: 'GOODS', currency: 'KRW', taxKind: 'TAXABLE', active: true }) },\n { title: i18next.t('button.delete'), action: () => this.delete(), ...CommonButtonStyles.delete },\n { title: i18next.t('button.save'), action: () => this.save(), ...CommonButtonStyles.save }\n ],\n exportable: { name: i18next.t('title.sales-product-list'), data: () => this.grist.exportRecords() }\n }\n }\n\n render() {\n return html`<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 .countHandler=${this.countHandler.bind(this)}\n @counts-change=${() => this.requestUpdate()}\n >\n <div slot=\"headroom\" class=\"header\">\n <div class=\"filters\">\n <ox-filters-form without-search autofocus></ox-filters-form>\n <ox-input-select-buttons\n .options=${['active', 'inactive'].map(value => ({ value, display: i18next.t(`text.sales-product-${value}`), count: this.grist?.counts?.active?.[value] ?? 0 }))}\n .value=${this.inUse || undefined}\n @change=${(e: CustomEvent) => ((this.inUse = (e.detail as string) || ''), this.grist.fetch())}\n ></ox-input-select-buttons>\n </div>\n </div>\n </ox-grist>`\n }\n\n async pageInitialized() {\n const text = (name: string, header: string, width: number, extra: any = {}) => ({ type: 'string', name, header, width, sortable: true, ...extra, record: { editable: true, ...extra.record } })\n this.gristConfig = {\n rows: { appendable: true, selectable: { multiple: true } },\n pagination: { limit: 100, pages: [50, 100, 500] },\n emptyNote: { title: i18next.t('text.sales-product-empty'), description: i18next.t('text.sales-product-empty-description') },\n list: { fields: ['name', 'code'], details: ['kind', 'unit', 'unitPrice'] },\n columns: [\n { type: 'gutter', gutterName: 'sequence' },\n { type: 'gutter', gutterName: 'row-selector', multiple: true },\n text('code', i18next.t('field.sales-product-code'), 110, { record: { mandatory: true } }),\n text('name', i18next.t('field.sales-product-name'), 200, { record: { mandatory: true } }),\n {\n type: 'select',\n name: 'kind',\n header: i18next.t('field.sales-product-kind'),\n width: 80,\n sortable: true,\n record: { editable: true, options: KINDS.map(kind => ({ value: kind, display: salesProductKindWord(kind) })) },\n filter: { type: 'select', operator: 'eq', options: [{ display: '', value: '' }, ...KINDS.map(kind => ({ display: salesProductKindWord(kind), value: kind }))] }\n },\n text('grade', i18next.t('field.sales-product-grade'), 110),\n text('spec', i18next.t('field.sales-product-spec'), 160),\n text('unit', i18next.t('field.sales-product-unit'), 70, { record: { align: 'center' } }),\n {\n type: 'float',\n name: 'unitPrice',\n header: i18next.t('field.sales-product-unit-price'),\n width: 130,\n sortable: true,\n record: { editable: true, align: 'right', renderer: (value: number, _c: any, record: any) => documentNumber(value, record?.currency || 'KRW') }\n },\n text('currency', i18next.t('field.sales-product-currency'), 70, { record: { align: 'center' } }),\n {\n type: 'select',\n name: 'taxKind',\n header: i18next.t('field.sales-product-tax-kind'),\n width: 80,\n record: {\n editable: true,\n options: [\n { value: 'TAXABLE', display: i18next.t('text.tax-kind-taxable') },\n { value: 'ZERO_RATED', display: i18next.t('text.tax-kind-zero-rated') },\n { value: 'EXEMPT', display: i18next.t('text.tax-kind-exempt') }\n ]\n }\n },\n { type: 'checkbox', name: 'active', header: i18next.t('field.sales-product-active'), width: 60, sortable: true, record: { editable: true } },\n text('description', i18next.t('field.sales-product-description'), 220)\n ],\n sorters: [{ name: 'code' }]\n }\n }\n\n /* The in-use chips' numbers, on the list's filters before the chip is added; a chip keeps its number until the next land. */\n async countHandler({ filters, search, signal }: FetchOption) {\n const response = await client.query({\n query: gql`\n query ($filters: [Filter!], $search: String) {\n salesProductActiveCounts(filters: $filters, search: $search) { value count }\n }\n `,\n variables: { filters, search: search?.trim() || undefined },\n fetchPolicy: 'no-cache',\n context: { fetchOptions: { signal }, queryDeduplication: false }\n })\n if (response.errors?.length) throw response.errors[0]\n return { active: Object.fromEntries(response.data.salesProductActiveCounts.map((row: { value: string; count: number }) => [row.value, row.count])) }\n }\n\n async fetchHandler({ page = 1, limit = 100, sortings = [], filters = [], search }: FetchOption) {\n search = search?.trim() || undefined\n if (this.inUse) filters = [...filters, { name: 'active', operator: this.inUse === 'active' ? 'is_true' : 'is_not_true', value: null }]\n const response = await client.query({\n query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!], $search: String) {\n responses: salesProducts(filters: $filters, pagination: $pagination, sortings: $sortings, search: $search) {\n items { id code name kind grade spec unit unitPrice currency taxKind active description }\n total\n }\n }\n `,\n variables: { filters, pagination: { page, limit }, sortings, search },\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 /** New, changed and deleted rows together; a refusal is said in the server's words and nothing is kept. */\n private async save() {\n const patches = this.grist.dirtyRecords.map((record: any) => {\n const changed = record.__dirty__ === '+' ? FIELDS.filter(field => record[field] !== undefined) : Object.keys(record.__dirtyfields__ ?? {}).filter(field => FIELDS.includes(field))\n return { ...(record.id ? { id: record.id } : {}), cuFlag: record.__dirty__, ...Object.fromEntries(changed.map(field => [field, record[field] === '' ? null : record[field]])) }\n })\n if (!patches.length) return\n if (!(await this.saving.run({ patches }))) return\n notify({ level: 'info', message: i18next.t('text.sales-product-saved') })\n this.grist.fetch()\n }\n\n private async delete() {\n const ids = this.grist.selected.map((record: any) => record.id).filter(Boolean)\n if (!ids.length) return\n const confirmed = await OxPrompt.open({\n title: i18next.t('button.delete'),\n text: i18next.t('text.sales-product-delete-confirm', { count: ids.length }),\n confirmButton: { text: i18next.t('button.delete'), destructive: true },\n cancelButton: { text: i18next.t('button.cancel') }\n })\n if (!confirmed) return\n if (await this.deleting.run({ ids })) this.grist.fetch()\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"sales-product-list.js","sourceRoot":"","sources":["../../client/pages/sales-product-list.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/data-grist/ox-grist.js'\nimport '@operato/data-grist/ox-filters-form.js'\nimport '@things-factory/ai-assistant/dist-client/index.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, MutationController } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { notify } from '@operato/layout'\nimport { OxPrompt } from '@operato/popup/ox-prompt.js'\nimport { PageView } from '@operato/shell'\nimport { CommonButtonStyles, CommonGristStyles, CommonHeaderStyles, ScrollbarStyles, WorkSurfacePageStyles } from '@operato/styles'\nimport { isMobileDevice } from '@operato/utils'\nimport { documentNumber } from '@things-factory/invoice/dist-client'\n\nimport { salesProductFilters } from '../list-filters'\nimport { salesProductKindWord } from '../sales-product-words'\n\nconst KINDS = ['GOODS', 'SERVICE', 'LABOR']\n\n/** What a new row starts with - 「행 추가」 and a paste past the last row alike. */\nconst DRAFT = () => ({ kind: 'GOODS', currency: 'KRW', taxKind: 'TAXABLE', active: true })\n\n/** The column layout the name-first order is made on - a person's older column order gives way to it. */\nconst COLUMNS_VERSION = 'lead-2026-11-08'\n\n/** The fields a row writes - all of them for a new row, the changed ones otherwise. */\nconst FIELDS = ['code', 'name', 'kind', 'grade', 'spec', 'unit', 'unitPrice', 'currency', 'taxKind', 'active', 'description']\n\n/**\n * 상품 — what the domain sells and the price it offers it at: goods, a service, or labor by the grade of the people\n * (ADR-0171). Typed like a spreadsheet and saved together. A quotation line chosen from a product copies it at that\n * moment; changing a price here changes no written quotation. The headroom narrows it to the products in use or out of\n * use, each chip with how many it holds under the other conditions - a filter of the grid's 사용 column, so it stays in\n * the address with the search, sort and page (FOOTER-BUTTON-REVIEW G09). Deleting works on the picked rows, from the\n * selection bar over the grid (F06).\n */\n@customElement('sales-product-list')\nexport class SalesProductList extends localize(i18next)(PageView) {\n static styles = [WorkSurfacePageStyles, CommonGristStyles, CommonHeaderStyles, ScrollbarStyles]\n\n @state() gristConfig: any\n /* A save or a delete reads the list again, and the chips count with it. */\n private saving = new MutationController(\n this,\n gql`\n mutation ($patches: [SalesProductPatch!]!) {\n updateMultipleSalesProduct(patches: $patches) { id }\n }\n `\n )\n private deleting = new MutationController(\n this,\n gql`\n mutation ($ids: [String!]!) {\n deleteSalesProducts(ids: $ids)\n }\n `\n )\n @query('ox-grist') private grist!: DataGrist\n\n get context() {\n return {\n title: i18next.t('title.sales-product-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: [\n { id: 'add-row', title: i18next.t('button.add-row'), icon: 'add', action: () => this.grist.addNewRecord() },\n { id: 'save', title: i18next.t('button.save'), action: () => this.save(), ...CommonButtonStyles.save }\n ],\n exportable: { name: i18next.t('title.sales-product-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.sales-product-list')}\n .assistant=${false}\n .actions=${[{ id: 'delete', title: i18next.t('button.delete'), icon: 'delete_outline', emphasis: { danger: true }, action: () => this.delete() }]}\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 .countHandler=${this.countHandler.bind(this)}\n ?url-params-sensitive=${this.active}\n >\n <div slot=\"headroom\" class=\"header\">\n <div class=\"filters\">\n <ox-filters-form without-search autofocus></ox-filters-form>\n </div>\n </div>\n </ox-grist>`\n }\n\n async pageInitialized() {\n const text = (name: string, header: string, width: number, extra: any = {}) => ({ type: 'string', name, header, width, sortable: true, ...extra, record: { editable: true, ...extra.record } })\n this.gristConfig = {\n /* No empty row under the records: 「행 추가」 starts one, and a paste past the last row adds rows with the same draft. */\n rows: { appendable: false, pasteAppendable: true, newRecord: DRAFT, selectable: { multiple: true } },\n columnsVersion: COLUMNS_VERSION,\n pagination: { limit: 100, pages: [50, 100, 500] },\n emptyNote: { title: i18next.t('text.sales-product-empty'), description: i18next.t('text.sales-product-empty-description') },\n list: { fields: ['name', 'code'], details: ['kind', 'unit', 'unitPrice'] },\n columns: [\n /* A row's state (new, changed); a new row's mark removes it until it is saved (data-grist 행 제거). */\n { type: 'gutter', gutterName: 'dirty' },\n { type: 'gutter', gutterName: 'sequence' },\n { type: 'gutter', gutterName: 'row-selector', multiple: true },\n /* The name is the row's identity and stays in view; what a product is offered at comes before how it is described. */\n text('name', i18next.t('field.sales-product-name'), 200, { fixed: true, record: { mandatory: true } }),\n text('code', i18next.t('field.sales-product-code'), 110, { record: { mandatory: true } }),\n {\n type: 'checkbox',\n name: 'active',\n header: i18next.t('field.sales-product-active'),\n width: 60,\n sortable: true,\n record: { editable: true },\n /* In use or out of use as chips, each with its count; none pressed is every product. */\n filter: { type: 'select-buttons', operator: 'eq', options: ['active', 'inactive'].map(value => ({ value, display: i18next.t(`text.sales-product-${value}`) })) }\n },\n {\n type: 'float',\n name: 'unitPrice',\n header: i18next.t('field.sales-product-unit-price'),\n width: 130,\n sortable: true,\n record: { editable: true, align: 'right', renderer: (value: number, _c: any, record: any) => documentNumber(value, record?.currency || 'KRW') }\n },\n text('currency', i18next.t('field.sales-product-currency'), 70, { record: { align: 'center' } }),\n text('unit', i18next.t('field.sales-product-unit'), 70, { record: { align: 'center' } }),\n {\n type: 'select',\n name: 'kind',\n header: i18next.t('field.sales-product-kind'),\n width: 80,\n sortable: true,\n record: { editable: true, options: KINDS.map(kind => ({ value: kind, display: salesProductKindWord(kind) })) },\n filter: { type: 'select', operator: 'eq', options: [{ display: '', value: '' }, ...KINDS.map(kind => ({ display: salesProductKindWord(kind), value: kind }))] }\n },\n {\n type: 'select',\n name: 'taxKind',\n header: i18next.t('field.sales-product-tax-kind'),\n width: 80,\n record: {\n editable: true,\n options: [\n { value: 'TAXABLE', display: i18next.t('text.tax-kind-taxable') },\n { value: 'ZERO_RATED', display: i18next.t('text.tax-kind-zero-rated') },\n { value: 'EXEMPT', display: i18next.t('text.tax-kind-exempt') }\n ]\n }\n },\n text('grade', i18next.t('field.sales-product-grade'), 110),\n text('spec', i18next.t('field.sales-product-spec'), 160),\n text('description', i18next.t('field.sales-product-description'), 220)\n ],\n sorters: [{ name: 'code' }]\n }\n }\n\n /* The in-use chips' numbers, on the list's other filters - the chip's own left out; a chip keeps its number until the next land. */\n async countHandler({ filters = [], search, signal }: FetchOption) {\n const response = await client.query({\n query: gql`\n query ($filters: [Filter!], $search: String) {\n salesProductActiveCounts(filters: $filters, search: $search) { value count }\n }\n `,\n variables: { filters: salesProductFilters(filters).filter(one => one.name !== 'active'), search: search?.trim() || undefined },\n fetchPolicy: 'no-cache',\n context: { fetchOptions: { signal }, queryDeduplication: false }\n })\n if (response.errors?.length) throw response.errors[0]\n return { active: Object.fromEntries(response.data.salesProductActiveCounts.map((row: { value: string; count: number }) => [row.value, row.count])) }\n }\n\n async fetchHandler({ page = 1, limit = 100, sortings = [], filters = [], search }: FetchOption) {\n search = search?.trim() || undefined\n const conditions = salesProductFilters(filters)\n const response = await client.query({\n query: gql`\n query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!], $search: String) {\n responses: salesProducts(filters: $filters, pagination: $pagination, sortings: $sortings, search: $search) {\n items { id code name kind grade spec unit unitPrice currency taxKind active description }\n total\n }\n }\n `,\n variables: { filters: conditions, pagination: { page, limit }, sortings, search },\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 /** New, changed and deleted rows together; a refusal is said in the server's words and nothing is kept. */\n private async save() {\n const patches = this.grist.dirtyRecords.map((record: any) => {\n const changed = record.__dirty__ === '+' ? FIELDS.filter(field => record[field] !== undefined) : Object.keys(record.__dirtyfields__ ?? {}).filter(field => FIELDS.includes(field))\n return { ...(record.id ? { id: record.id } : {}), cuFlag: record.__dirty__, ...Object.fromEntries(changed.map(field => [field, record[field] === '' ? null : record[field]])) }\n })\n if (!patches.length) {\n notify({ level: 'info', message: i18next.t('text.nothing-to-save') })\n return\n }\n if (!(await this.saving.run({ patches }))) return\n notify({ level: 'info', message: i18next.t('text.sales-product-saved') })\n this.grist.fetch()\n }\n\n private async delete() {\n const ids = this.grist.selected.map((record: any) => record.id).filter(Boolean)\n if (!ids.length) {\n notify({ level: 'info', message: i18next.t('text.select-rows-to-delete') })\n return\n }\n const confirmed = await OxPrompt.open({\n title: i18next.t('button.delete'),\n text: i18next.t('text.sales-product-delete-confirm', { count: ids.length }),\n confirmButton: { text: i18next.t('button.delete'), destructive: true },\n cancelButton: { text: i18next.t('button.cancel') }\n })\n if (!confirmed) return\n if (await this.deleting.run({ ids })) this.grist.fetch()\n }\n}\n"]}
|