@things-factory/sales 10.1.227 → 10.1.229
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/entity360/opportunity-360.js +1 -0
- package/dist-client/entity360/opportunity-360.js.map +1 -1
- package/dist-client/opportunity-attach.d.ts +5 -0
- package/dist-client/opportunity-attach.js.map +1 -1
- package/dist-client/pages/opportunity-editor.d.ts +2 -0
- package/dist-client/pages/opportunity-editor.js +10 -1
- package/dist-client/pages/opportunity-editor.js.map +1 -1
- package/dist-client/pages/quotation-editor.d.ts +2 -0
- package/dist-client/pages/quotation-editor.js +13 -4
- package/dist-client/pages/quotation-editor.js.map +1 -1
- package/dist-client/pages/sales-product-list.js +3 -3
- package/dist-client/pages/sales-product-list.js.map +1 -1
- package/dist-client/quotation-attach.d.ts +5 -0
- package/dist-client/quotation-attach.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/index.js +2 -0
- package/dist-server/index.js.map +1 -1
- package/dist-server/service/opportunity/opportunity-subject.d.ts +9 -0
- package/dist-server/service/opportunity/opportunity-subject.js +24 -0
- package/dist-server/service/opportunity/opportunity-subject.js.map +1 -0
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
|
@@ -12,6 +12,7 @@ export function registerOpportunityKind() {
|
|
|
12
12
|
registerEntity360Kind({
|
|
13
13
|
kind: 'opportunity',
|
|
14
14
|
typenames: ['Opportunity'],
|
|
15
|
+
assistantSubject: true,
|
|
15
16
|
title: ({ value }) => `${i18next.t('title.opportunity')} · ${value.name || ''}`,
|
|
16
17
|
context: ({ value }) => [value.counterparty?.name, value.stage ? opportunityStageWord(value.stage) : '', value.expectedCloseMonth].filter(Boolean).join(' · ')
|
|
17
18
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opportunity-360.js","sourceRoot":"","sources":["../../client/entity360/opportunity-360.ts"],"names":[],"mappings":"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","sourcesContent":["import gql from 'graphql-tag'\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { client } from '@operato/graphql'\nimport { i18next } from '@operato/i18n'\nimport { entity360Name, readEntity360Door, registerEntity360Kind, registerEntity360Section, type Entity360DoorAnswer, type Entity360Subject } from '@operato/layout'\nimport { documentAmount } from '@things-factory/invoice/dist-client'\n\nimport { opportunityStageWord } from '../opportunity-words'\n\n/** An opportunity's 360 (ADR-0067). The module draws the opportunity; an application hangs its own sections on 'opportunity'. */\nexport function registerOpportunityKind() {\n registerEntity360Kind({\n kind: 'opportunity',\n typenames: ['Opportunity'],\n title: ({ value }) => `${i18next.t('title.opportunity')} · ${value.name || ''}`,\n context: ({ value }) => [value.counterparty?.name, value.stage ? opportunityStageWord(value.stage) : '', value.expectedCloseMonth].filter(Boolean).join(' · ')\n })\n registerEntity360Section('opportunity', {\n name: 'overview',\n order: 10,\n render: subject => html`<opportunity-overview-section .subject=${subject}></opportunity-overview-section>`\n })\n}\n\n@customElement('opportunity-overview-section')\nexport class OpportunityOverviewSection extends LitElement {\n static styles = css`\n :host {\n font-size: var(--ui-t-body);\n line-height: 1.5;\n }\n dl {\n margin: 0;\n display: grid;\n grid-template-columns: max-content 1fr;\n gap: var(--spacing-small) var(--spacing-large);\n }\n dt {\n color: var(--ui-muted);\n }\n dd {\n margin: 0;\n overflow-wrap: anywhere;\n font-variant-numeric: tabular-nums;\n }\n `\n\n @property({ attribute: false }) subject?: Entity360Subject\n @state() answer?: Entity360DoorAnswer<any>\n\n updated(changed: Map<string, unknown>) {\n if (changed.has('subject')) this.read()\n }\n\n private async read() {\n const id = this.subject?.id\n this.answer = undefined\n if (!id) return\n let response: any\n try {\n response = await client.query({\n query: gql`\n query ($id: String!) {\n opportunity(id: $id) {\n id name stage probability amount currency expectedCloseMonth closedOn lostReason description\n counterparty { id name } endCustomer { id name } owner { id name }\n }\n }\n `,\n variables: { id },\n fetchPolicy: 'no-cache',\n errorPolicy: 'all'\n } as any)\n } catch (e: any) {\n response = { data: null, errors: e?.graphQLErrors?.length ? e.graphQLErrors : [{ message: e?.message ?? String(e) }] }\n }\n if (this.subject?.id !== id) return\n this.answer = readEntity360Door(response, data => data?.opportunity)\n }\n\n render() {\n const one = this.answer?.data\n const party = (value?: { id: string; name: string }) => (value ? entity360Name({ __typename: 'Counterparty', ...value }, value.name) : '—')\n return html`<ox-entity360-section .heading=${i18next.t('title.opportunity')} .state=${this.answer?.state ?? 'loading'} .message=${this.answer?.message ?? ''}>\n ${one\n ? html`<dl>\n <dt>${i18next.t('field.opportunity-stage')}</dt>\n <dd>${opportunityStageWord(one.stage)} · ${one.probability}%</dd>\n <dt>${i18next.t('field.opportunity-counterparty')}</dt>\n <dd>${party(one.counterparty)}</dd>\n <dt>${i18next.t('field.opportunity-end-customer')}</dt>\n <dd>${party(one.endCustomer)}</dd>\n <dt>${i18next.t('field.opportunity-amount')}</dt>\n <dd>${documentAmount(one.amount, one.currency || 'KRW')}</dd>\n <dt>${i18next.t('field.opportunity-expected-close-month')}</dt>\n <dd>${one.expectedCloseMonth}</dd>\n <dt>${i18next.t('field.opportunity-owner')}</dt>\n <dd>${one.owner?.name ?? '—'}</dd>\n ${one.closedOn ? html`<dt>${i18next.t('field.opportunity-closed-on')}</dt><dd>${one.closedOn}</dd>` : ''}\n ${one.lostReason ? html`<dt>${i18next.t('field.opportunity-lost-reason')}</dt><dd>${one.lostReason}</dd>` : ''}\n </dl>`\n : ''}\n </ox-entity360-section>`\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"opportunity-360.js","sourceRoot":"","sources":["../../client/entity360/opportunity-360.ts"],"names":[],"mappings":"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","sourcesContent":["import gql from 'graphql-tag'\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { client } from '@operato/graphql'\nimport { i18next } from '@operato/i18n'\nimport { entity360Name, readEntity360Door, registerEntity360Kind, registerEntity360Section, type Entity360DoorAnswer, type Entity360Subject } from '@operato/layout'\nimport { documentAmount } from '@things-factory/invoice/dist-client'\n\nimport { opportunityStageWord } from '../opportunity-words'\n\n/** An opportunity's 360 (ADR-0067). The module draws the opportunity; an application hangs its own sections on 'opportunity'. */\nexport function registerOpportunityKind() {\n registerEntity360Kind({\n kind: 'opportunity',\n typenames: ['Opportunity'],\n assistantSubject: true,\n title: ({ value }) => `${i18next.t('title.opportunity')} · ${value.name || ''}`,\n context: ({ value }) => [value.counterparty?.name, value.stage ? opportunityStageWord(value.stage) : '', value.expectedCloseMonth].filter(Boolean).join(' · ')\n })\n registerEntity360Section('opportunity', {\n name: 'overview',\n order: 10,\n render: subject => html`<opportunity-overview-section .subject=${subject}></opportunity-overview-section>`\n })\n}\n\n@customElement('opportunity-overview-section')\nexport class OpportunityOverviewSection extends LitElement {\n static styles = css`\n :host {\n font-size: var(--ui-t-body);\n line-height: 1.5;\n }\n dl {\n margin: 0;\n display: grid;\n grid-template-columns: max-content 1fr;\n gap: var(--spacing-small) var(--spacing-large);\n }\n dt {\n color: var(--ui-muted);\n }\n dd {\n margin: 0;\n overflow-wrap: anywhere;\n font-variant-numeric: tabular-nums;\n }\n `\n\n @property({ attribute: false }) subject?: Entity360Subject\n @state() answer?: Entity360DoorAnswer<any>\n\n updated(changed: Map<string, unknown>) {\n if (changed.has('subject')) this.read()\n }\n\n private async read() {\n const id = this.subject?.id\n this.answer = undefined\n if (!id) return\n let response: any\n try {\n response = await client.query({\n query: gql`\n query ($id: String!) {\n opportunity(id: $id) {\n id name stage probability amount currency expectedCloseMonth closedOn lostReason description\n counterparty { id name } endCustomer { id name } owner { id name }\n }\n }\n `,\n variables: { id },\n fetchPolicy: 'no-cache',\n errorPolicy: 'all'\n } as any)\n } catch (e: any) {\n response = { data: null, errors: e?.graphQLErrors?.length ? e.graphQLErrors : [{ message: e?.message ?? String(e) }] }\n }\n if (this.subject?.id !== id) return\n this.answer = readEntity360Door(response, data => data?.opportunity)\n }\n\n render() {\n const one = this.answer?.data\n const party = (value?: { id: string; name: string }) => (value ? entity360Name({ __typename: 'Counterparty', ...value }, value.name) : '—')\n return html`<ox-entity360-section .heading=${i18next.t('title.opportunity')} .state=${this.answer?.state ?? 'loading'} .message=${this.answer?.message ?? ''}>\n ${one\n ? html`<dl>\n <dt>${i18next.t('field.opportunity-stage')}</dt>\n <dd>${opportunityStageWord(one.stage)} · ${one.probability}%</dd>\n <dt>${i18next.t('field.opportunity-counterparty')}</dt>\n <dd>${party(one.counterparty)}</dd>\n <dt>${i18next.t('field.opportunity-end-customer')}</dt>\n <dd>${party(one.endCustomer)}</dd>\n <dt>${i18next.t('field.opportunity-amount')}</dt>\n <dd>${documentAmount(one.amount, one.currency || 'KRW')}</dd>\n <dt>${i18next.t('field.opportunity-expected-close-month')}</dt>\n <dd>${one.expectedCloseMonth}</dd>\n <dt>${i18next.t('field.opportunity-owner')}</dt>\n <dd>${one.owner?.name ?? '—'}</dd>\n ${one.closedOn ? html`<dt>${i18next.t('field.opportunity-closed-on')}</dt><dd>${one.closedOn}</dd>` : ''}\n ${one.lostReason ? html`<dt>${i18next.t('field.opportunity-lost-reason')}</dt><dd>${one.lostReason}</dd>` : ''}\n </dl>`\n : ''}\n </ox-entity360-section>`\n }\n}\n"]}
|
|
@@ -3,6 +3,11 @@ export type OpportunitySection = {
|
|
|
3
3
|
/** The section's heading, already in the reader's words. */
|
|
4
4
|
heading: () => string;
|
|
5
5
|
/** The section's body for one saved opportunity; it reads and writes through the application's own API. */
|
|
6
|
+
/**
|
|
7
|
+
* Whether this person may read the section. The application's section reads its own doors; someone who may not
|
|
8
|
+
* open them gets no section at all - no heading, and no query refused on their screen. Left out, everyone sees it.
|
|
9
|
+
*/
|
|
10
|
+
readable?: () => Promise<boolean>;
|
|
6
11
|
render: (opportunity: {
|
|
7
12
|
id: string;
|
|
8
13
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opportunity-attach.js","sourceRoot":"","sources":["../client/opportunity-attach.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"opportunity-attach.js","sourceRoot":"","sources":["../client/opportunity-attach.ts"],"names":[],"mappings":"AAoBA,IAAI,OAAuC,CAAA;AAE3C,MAAM,UAAU,2BAA2B,CAAC,GAAuB;IACjE,OAAO,GAAG,GAAG,CAAA;AACf,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,OAAO,CAAA;AAChB,CAAC","sourcesContent":["import { type TemplateResult } from 'lit'\n\n/*\n * Where an application attaches its own work to an opportunity — Office ties it to the contract it became and to the\n * classification its pivot judgement reads (ADR-0138 decision 8). The sales module knows no application words. A\n * section that changed the opportunity (closed it as won) dispatches `opportunity-changed`; the editor reads it again.\n */\n\nexport type OpportunitySection = {\n /** The section's heading, already in the reader's words. */\n heading: () => string\n /** The section's body for one saved opportunity; it reads and writes through the application's own API. */\n /**\n * Whether this person may read the section. The application's section reads its own doors; someone who may not\n * open them gets no section at all - no heading, and no query refused on their screen. Left out, everyone sees it.\n */\n readable?: () => Promise<boolean>\n render: (opportunity: { id: string; name: string; stage: string; counterpartyId: string; currency: string; amount: number; expectedCloseMonth: string }) => TemplateResult\n}\n\nlet section: OpportunitySection | undefined\n\nexport function configureOpportunitySection(one: OpportunitySection): void {\n section = one\n}\n\nexport function opportunitySection(): OpportunitySection | undefined {\n return section\n}\n"]}
|
|
@@ -44,6 +44,8 @@ export declare class OpportunityEditor extends OpportunityEditor_base {
|
|
|
44
44
|
name: string;
|
|
45
45
|
email?: string;
|
|
46
46
|
}[];
|
|
47
|
+
/** Whether the application's section is this person's to read - asked once, before it is shown. */
|
|
48
|
+
sectionReadable: boolean;
|
|
47
49
|
events: any[];
|
|
48
50
|
reason: string;
|
|
49
51
|
loading: boolean;
|
|
@@ -33,6 +33,8 @@ let OpportunityEditor = class OpportunityEditor extends localize(i18next)(PageVi
|
|
|
33
33
|
this.pickers = { counterparty: { search: '', found: [] }, endCustomer: { search: '', found: [] } };
|
|
34
34
|
this.stages = [];
|
|
35
35
|
this.owners = [];
|
|
36
|
+
/** Whether the application's section is this person's to read - asked once, before it is shown. */
|
|
37
|
+
this.sectionReadable = false;
|
|
36
38
|
this.events = [];
|
|
37
39
|
this.reason = '';
|
|
38
40
|
this.loading = false;
|
|
@@ -100,6 +102,9 @@ let OpportunityEditor = class OpportunityEditor extends localize(i18next)(PageVi
|
|
|
100
102
|
return;
|
|
101
103
|
if (!this.stages.length)
|
|
102
104
|
await this.readChoices();
|
|
105
|
+
const section = opportunitySection();
|
|
106
|
+
if (section && !this.sectionReadable)
|
|
107
|
+
(section.readable?.() ?? Promise.resolve(true)).then(may => (this.sectionReadable = !!may));
|
|
103
108
|
const id = lifecycle?.params?.id;
|
|
104
109
|
if (!id) {
|
|
105
110
|
this.opportunity = null;
|
|
@@ -112,7 +117,7 @@ let OpportunityEditor = class OpportunityEditor extends localize(i18next)(PageVi
|
|
|
112
117
|
await this.load(id);
|
|
113
118
|
}
|
|
114
119
|
render() {
|
|
115
|
-
const attached = this.opportunity ? opportunitySection() : undefined;
|
|
120
|
+
const attached = this.opportunity && this.sectionReadable ? opportunitySection() : undefined;
|
|
116
121
|
const editable = this.editable;
|
|
117
122
|
const set = (patch) => (this.form = { ...this.form, ...patch });
|
|
118
123
|
const stageChoices = this.stages.filter(one => one.open || one.stage === this.opportunity?.stage);
|
|
@@ -477,6 +482,10 @@ __decorate([
|
|
|
477
482
|
state(),
|
|
478
483
|
__metadata("design:type", Array)
|
|
479
484
|
], OpportunityEditor.prototype, "owners", void 0);
|
|
485
|
+
__decorate([
|
|
486
|
+
state(),
|
|
487
|
+
__metadata("design:type", Object)
|
|
488
|
+
], OpportunityEditor.prototype, "sectionReadable", void 0);
|
|
480
489
|
__decorate([
|
|
481
490
|
state(),
|
|
482
491
|
__metadata("design:type", Array)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opportunity-editor.js","sourceRoot":"","sources":["../../client/pages/opportunity-editor.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/list-state/ox-page-state.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, nothing } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\n\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { notify } from '@operato/layout'\nimport { navigate, PageView } from '@operato/shell'\nimport { ButtonStyles, DocumentPageStyles, FormFieldStyles } from '@operato/styles'\nimport { currencyChoices, documentAmount, DocumentFormStyles } from '@things-factory/invoice/dist-client'\n\nimport { opportunitySection } from '../opportunity-attach'\nimport { opportunityStageWord } from '../opportunity-words'\nimport { quotationStatusWord } from '../quotation-words'\n\nconst FIELDS = `\n id name stage probability amount currency expectedCloseMonth closedOn lostReason description\n counterpartyId endCustomerId ownerId counterparty { id name } endCustomer { id name } owner { id name }\n quotations { id number version status issueDate validUntil totalAmount currency }\n`\n\ntype Party = { id: string; name: string; businessNumber?: string }\ntype Picker = { search: string; found: Party[] }\ntype Form = {\n name: string\n counterparty: Party | null\n endCustomer: Party | null\n amount: string\n currency: string\n expectedCloseMonth: string\n stage: string\n probability: string\n ownerId: string\n description: string\n}\n\nconst thisMonth = () => new Date().toLocaleDateString('en-CA').slice(0, 7)\n\n/**\n * 영업 기회 편집 — with whom, for how much, by when and how likely.\n *\n * A person moves an open opportunity through the stages; changing the stage puts that stage's probability in, and the\n * person may change it. An open one is closed as lost with the reason; a lost one is opened again by choosing an open\n * stage. Winning is the application's: it closes the opportunity when the opportunity becomes its contract.\n */\n@customElement('opportunity-editor')\nexport class OpportunityEditor extends localize(i18next)(PageView) {\n static styles = [\n FormFieldStyles,\n ButtonStyles,\n DocumentPageStyles,\n DocumentFormStyles,\n css`\n .party {\n display: flex;\n gap: var(--spacing-small);\n align-items: center;\n }\n .party input {\n flex: 1;\n }\n table {\n width: 100%;\n border-collapse: collapse;\n font-variant-numeric: tabular-nums;\n }\n th,\n td {\n text-align: left;\n padding: var(--spacing-small);\n border-bottom: 1px solid var(--ui-line-soft);\n font-size: var(--ui-t-body);\n }\n th.number,\n td.number {\n text-align: right;\n }\n td a {\n color: inherit;\n text-decoration: underline;\n }\n `\n ]\n\n @state() opportunity: any = null\n @state() form: Form = blank()\n @state() pickers: Record<'counterparty' | 'endCustomer', Picker> = { counterparty: { search: '', found: [] }, endCustomer: { search: '', found: [] } }\n @state() stages: { stage: string; probability: number; open: boolean }[] = []\n @state() owners: { id: string; name: string; email?: string }[] = []\n @state() events: any[] = []\n @state() reason = ''\n @state() loading = false\n @state() error: unknown = null\n @state() busy = false\n\n private isOpen(stage: string) {\n return this.stages.some(one => one.stage === stage && one.open)\n }\n\n /** Won is final; a lost one is changed only by being opened again. */\n get editable() {\n return !this.busy && this.opportunity?.stage !== 'WON' && this.isOpen(this.form.stage)\n }\n\n get context() {\n const actions: any[] = []\n if (this.editable) actions.push({ title: i18next.t('button.save'), icon: 'save', emphasis: { raised: true }, action: () => this.save() })\n return {\n title: this.opportunity ? `${i18next.t('title.opportunity')} ${this.opportunity.name}` : i18next.t('title.opportunity-new'),\n ...(this.opportunity ? { description: opportunityStageWord(this.opportunity.stage) } : {}),\n frame: 'document',\n /* Opened from the opportunity list; the menu marks it. */\n menu: 'opportunity-list',\n actions: this.error ? [] : actions\n }\n }\n\n async pageUpdated(changes: any, lifecycle: any) {\n if (!this.active || !(changes.active || changes.params)) return\n if (!this.stages.length) await this.readChoices()\n const id = lifecycle?.params?.id\n if (!id) {\n this.opportunity = null\n this.form = blank(this.stages)\n this.events = []\n this.updateContext()\n return\n }\n if (id !== this.opportunity?.id) await this.load(id)\n }\n\n render() {\n const attached = this.opportunity ? opportunitySection() : undefined\n const editable = this.editable\n const set = (patch: Partial<Form>) => (this.form = { ...this.form, ...patch })\n const stageChoices = this.stages.filter(one => one.open || one.stage === this.opportunity?.stage)\n return html`<ox-page-state .loading=${this.loading} .error=${this.error} @retry=${() => this.opportunity && this.load(this.opportunity.id)}>\n <div class=\"page\">\n <section class=\"page-section\">\n <header class=\"page-section-header\"><h3>${i18next.t('text.opportunity-section-head')}</h3></header>\n <div class=\"form\">\n <label class=\"wide\"\n >${i18next.t('field.opportunity-name')}\n <input .value=${this.form.name} ?disabled=${!editable} @input=${(e: any) => set({ name: e.target.value })}\n /></label>\n ${this.renderParty('counterparty', i18next.t('field.opportunity-counterparty'), editable)}\n ${this.renderParty('endCustomer', i18next.t('field.opportunity-end-customer'), editable)}\n <label\n >${i18next.t('field.opportunity-amount')}\n <input type=\"number\" min=\"0\" .value=${this.form.amount} ?disabled=${!editable} @input=${(e: any) => set({ amount: e.target.value })}\n /></label>\n <label\n >${i18next.t('field.opportunity-currency')}\n <select .value=${this.form.currency} ?disabled=${!editable} @change=${(e: any) => set({ currency: e.target.value })}>\n ${currencyChoices().map((code: string) => html`<option value=${code} ?selected=${code === this.form.currency}>${code}</option>`)}\n </select>\n </label>\n <label\n >${i18next.t('field.opportunity-expected-close-month')}\n <input type=\"month\" .value=${this.form.expectedCloseMonth} ?disabled=${!editable} @input=${(e: any) => set({ expectedCloseMonth: e.target.value })}\n /></label>\n <label\n >${i18next.t('field.opportunity-owner')}\n <select .value=${this.form.ownerId} ?disabled=${!editable} @change=${(e: any) => set({ ownerId: e.target.value })}>\n ${this.form.ownerId ? nothing : html`<option value=\"\" selected>${i18next.t('text.opportunity-owner-me')}</option>`}\n ${this.owners.map(one => html`<option value=${one.id} ?selected=${one.id === this.form.ownerId}>${one.name}</option>`)}\n </select>\n </label>\n <label class=\"wide\"\n >${i18next.t('field.opportunity-description')}\n <textarea .value=${this.form.description} ?disabled=${!editable} @input=${(e: any) => set({ description: e.target.value })}></textarea>\n </label>\n </div>\n </section>\n <section class=\"page-section\">\n <header class=\"page-section-header\"><h3>${i18next.t('text.opportunity-section-stage')}</h3></header>\n <div class=\"form\">\n <label\n >${i18next.t('field.opportunity-stage')}\n <select .value=${this.form.stage} ?disabled=${this.busy || this.opportunity?.stage === 'WON'} @change=${(e: any) => this.chooseStage(e.target.value)}>\n ${stageChoices.map(one => html`<option value=${one.stage} ?selected=${one.stage === this.form.stage} ?disabled=${!one.open}>${opportunityStageWord(one.stage)}</option>`)}\n </select>\n </label>\n <label\n >${i18next.t('field.opportunity-probability')}\n <input type=\"number\" min=\"0\" max=\"100\" step=\"1\" .value=${this.form.probability} ?disabled=${!editable} @input=${(e: any) => set({ probability: e.target.value })}\n /></label>\n ${this.opportunity?.closedOn\n ? html`<label>${i18next.t('field.opportunity-closed-on')} <strong>${this.opportunity.closedOn}</strong></label>`\n : nothing}\n </div>\n </section>\n ${this.opportunity && this.isOpen(this.opportunity.stage) ? this.renderLose() : nothing}\n ${this.opportunity?.lostReason\n ? html`<section class=\"page-section\">\n <header class=\"page-section-header\"><h3>${i18next.t('field.opportunity-lost-reason')}</h3></header>\n <p>${this.opportunity.lostReason}</p>\n </section>`\n : nothing}\n ${this.opportunity ? this.renderQuotations() : nothing}\n ${attached && this.opportunity\n ? html`<section class=\"page-section\" @opportunity-changed=${() => this.load(this.opportunity.id)}>\n <header class=\"page-section-header\"><h3>${attached.heading()}</h3></header>\n ${attached.render(this.opportunity)}\n </section>`\n : nothing}\n ${this.events.length ? this.renderEvents() : nothing}\n </div>\n </ox-page-state>`\n }\n\n /** A counterparty of the domain, found by name or business number. */\n private renderParty(which: 'counterparty' | 'endCustomer', label: string, editable: boolean) {\n const picker = this.pickers[which]\n const chosen = this.form[which]\n return html`<label\n >${label}\n <span class=\"party\">\n <input\n .value=${picker.search}\n placeholder=${chosen?.name ?? i18next.t('text.opportunity-counterparty-search')}\n ?disabled=${!editable}\n @input=${(e: any) => this.setPicker(which, { search: e.target.value })}\n @keydown=${(e: KeyboardEvent) => e.key === 'Enter' && this.findParties(which)}\n />\n <button ?disabled=${!editable} @click=${() => this.findParties(which)}>${i18next.t('button.search')}</button>\n ${which === 'endCustomer' && chosen ? html`<button ?disabled=${!editable} @click=${() => (this.form = { ...this.form, endCustomer: null })}>${i18next.t('button.opportunity-clear')}</button>` : nothing}\n </span>\n ${picker.found.length\n ? html`<select ?disabled=${!editable} @change=${(e: any) => this.chooseParty(which, picker.found.find(one => one.id === e.target.value) ?? null)}>\n <option value=\"\">${chosen?.name ?? ''}</option>\n ${picker.found.map(one => html`<option value=${one.id}>${one.name}${one.businessNumber ? ` (${one.businessNumber})` : ''}</option>`)}\n </select>`\n : nothing}\n </label>`\n }\n\n private renderLose() {\n return html`<section class=\"page-section\">\n <header class=\"page-section-header\">\n <h3>${i18next.t('text.opportunity-section-lose')}</h3>\n <div class=\"page-section-actions\">\n <button ?disabled=${this.busy || !this.reason.trim()} @click=${() => this.lose()}>${i18next.t('button.opportunity-lose')}</button>\n </div>\n </header>\n <div class=\"form\">\n <label class=\"wide\"\n >${i18next.t('field.opportunity-lost-reason')}\n <input .value=${this.reason} ?disabled=${this.busy} @input=${(e: any) => (this.reason = e.target.value)}\n /></label>\n </div>\n </section>`\n }\n\n /** The quotations that answer this opportunity; a new one is written from here and answers it. */\n private renderQuotations() {\n const quotations: any[] = this.opportunity.quotations ?? []\n return html`<section class=\"page-section\">\n <header class=\"page-section-header\">\n <h3>${i18next.t('text.opportunity-section-quotations')}</h3>\n <div class=\"page-section-actions\">\n <button ?disabled=${this.busy || this.opportunity.stage === 'WON' || this.opportunity.stage === 'LOST'} @click=${() => navigate(`quotation-editor?opportunity=${this.opportunity.id}`)}>\n ${i18next.t('button.opportunity-new-quotation')}\n </button>\n </div>\n </header>\n ${quotations.length\n ? html`<table>\n <thead>\n <tr>\n <th>${i18next.t('field.quotation-number')}</th>\n <th>${i18next.t('field.quotation-version')}</th>\n <th>${i18next.t('field.quotation-status')}</th>\n <th>${i18next.t('field.quotation-issue-date')}</th>\n <th class=\"number\">${i18next.t('field.quotation-total-amount')}</th>\n </tr>\n </thead>\n <tbody>\n ${quotations.map(\n one => html`<tr>\n <td><a href=${`quotation-editor?id=${one.id}`}>${one.number}</a></td>\n <td>v${one.version}</td>\n <td>${quotationStatusWord(one.status)}</td>\n <td>${one.issueDate ?? ''}</td>\n <td class=\"number\">${documentAmount(one.totalAmount, one.currency || 'KRW')}</td>\n </tr>`\n )}\n </tbody>\n </table>`\n : nothing}\n </section>`\n }\n\n private renderEvents() {\n return html`<section class=\"page-section\">\n <header class=\"page-section-header\"><h3>${i18next.t('text.opportunity-section-history')}</h3></header>\n <table>\n <thead>\n <tr>\n <th>${i18next.t('field.opportunity-event-at')}</th>\n <th>${i18next.t('field.opportunity-event-actor')}</th>\n <th>${i18next.t('field.opportunity-event-action')}</th>\n <th>${i18next.t('field.opportunity-stage')}</th>\n <th class=\"number\">${i18next.t('field.opportunity-probability')}</th>\n </tr>\n </thead>\n <tbody>\n ${this.events.map(\n one => html`<tr>\n <td>${one.createdAt ? new Date(one.createdAt).toLocaleString() : ''}</td>\n <td>${one.actor?.name ?? ''}</td>\n <td>${eventWord(one.action)}${one.reason ? ` · ${one.reason}` : ''}</td>\n <td>${one.fromStage ? `${opportunityStageWord(one.fromStage)} → ` : ''}${opportunityStageWord(one.stage)}</td>\n <td class=\"number\">${one.probability}%</td>\n </tr>`\n )}\n </tbody>\n </table>\n </section>`\n }\n\n private setPicker(which: 'counterparty' | 'endCustomer', patch: Partial<Picker>) {\n this.pickers = { ...this.pickers, [which]: { ...this.pickers[which], ...patch } }\n }\n\n private chooseParty(which: 'counterparty' | 'endCustomer', party: Party | null) {\n if (!party) return\n this.form = { ...this.form, [which]: party }\n this.setPicker(which, { search: '', found: [] })\n }\n\n /** The stage's own probability comes in with it; the person may change it afterwards. */\n private chooseStage(stage: string) {\n const given = this.stages.find(one => one.stage === stage)\n this.form = { ...this.form, stage, probability: given ? String(given.probability) : this.form.probability }\n }\n\n private async readChoices() {\n try {\n const response = await client.query({\n query: gql`\n query {\n opportunityStages { stage probability open }\n opportunityOwners { id name email }\n }\n `,\n fetchPolicy: 'no-cache'\n })\n if (response.errors?.length) throw response\n this.stages = response.data.opportunityStages\n this.owners = response.data.opportunityOwners\n } catch (error) {\n this.error = error\n }\n }\n\n private async findParties(which: 'counterparty' | 'endCustomer') {\n await this.run(async () => {\n const response = await client.query({\n query: gql`\n query ($search: String, $pagination: Pagination) {\n counterparties: counterpartyChoices(search: $search, pagination: $pagination) {\n items { id name businessNumber }\n }\n }\n `,\n variables: { search: this.pickers[which].search.trim() || undefined, pagination: { page: 1, limit: 30 } },\n fetchPolicy: 'no-cache'\n })\n if (response.errors?.length) throw response\n const found: Party[] = response.data.counterparties.items ?? []\n if (found.length === 1) this.chooseParty(which, found[0])\n else this.setPicker(which, { found })\n })\n }\n\n private async load(id: string) {\n this.loading = true\n this.error = null\n try {\n const response = await client.query({\n query: gql(`query ($id: String!) { opportunity(id: $id) { ${FIELDS} } opportunityEvents(opportunityId: $id) { id action fromStage stage probability reason createdAt actor { id name } } }`),\n variables: { id },\n fetchPolicy: 'no-cache'\n })\n if (response.errors?.length) throw response\n if (!response.data.opportunity) throw new Error(i18next.t('text.opportunity-not-found'))\n this.show(response.data.opportunity, response.data.opportunityEvents)\n } catch (error) {\n this.error = error\n } finally {\n this.loading = false\n this.updateContext()\n }\n }\n\n private show(opportunity: any, events: any[]) {\n this.opportunity = opportunity\n this.events = events\n this.form = {\n name: opportunity.name,\n counterparty: opportunity.counterparty,\n endCustomer: opportunity.endCustomer,\n amount: String(opportunity.amount ?? 0),\n currency: opportunity.currency,\n expectedCloseMonth: opportunity.expectedCloseMonth,\n stage: opportunity.stage,\n probability: String(opportunity.probability),\n ownerId: opportunity.ownerId ?? '',\n description: opportunity.description ?? ''\n }\n this.reason = ''\n }\n\n private async run<T>(work: () => Promise<T>): Promise<T | undefined> {\n if (this.busy) return undefined\n this.busy = true\n try {\n return await work()\n } catch (error: any) {\n notify({ level: 'error', message: error?.graphQLErrors?.[0]?.message ?? error?.errors?.[0]?.message ?? error?.message ?? String(error) })\n return undefined\n } finally {\n this.busy = false\n }\n }\n\n private input() {\n const { name, counterparty, endCustomer, amount, currency, expectedCloseMonth, stage, probability, ownerId, description } = this.form\n return {\n name,\n counterpartyId: counterparty?.id ?? '',\n endCustomerId: endCustomer?.id ?? null,\n amount: Number(amount || 0),\n currency,\n expectedCloseMonth,\n stage,\n probability: probability === '' ? null : Number(probability),\n ownerId: ownerId || null,\n description\n }\n }\n\n private async save() {\n const id = this.opportunity?.id\n const saved = await this.run(async () => {\n const response = await client.mutate({\n mutation: gql(\n id\n ? `mutation ($id: String!, $opportunity: NewOpportunity!) { opportunity: updateOpportunity(id: $id, opportunity: $opportunity) { id } }`\n : `mutation ($opportunity: NewOpportunity!) { opportunity: createOpportunity(opportunity: $opportunity) { id } }`\n ),\n variables: { ...(id ? { id } : {}), opportunity: this.input() }\n })\n if (response.errors?.length) throw response\n return response.data.opportunity as { id: string }\n })\n if (!saved) return\n if (!id) navigate(`opportunity-editor?id=${saved.id}`)\n else await this.load(id)\n }\n\n private async lose() {\n const id = this.opportunity!.id\n const lost = await this.run(async () => {\n const response = await client.mutate({\n mutation: gql`\n mutation ($id: String!, $reason: String!) {\n loseOpportunity(id: $id, reason: $reason) { id }\n }\n `,\n variables: { id, reason: this.reason.trim() }\n })\n if (response.errors?.length) throw response\n return response.data.loseOpportunity\n })\n if (lost) await this.load(id)\n }\n}\n\nconst eventWord = (action?: string) =>\n action === 'CREATED'\n ? i18next.t('text.opportunity-event-created')\n : action === 'STAGED'\n ? i18next.t('text.opportunity-event-staged')\n : action === 'WON'\n ? i18next.t('text.opportunity-event-won')\n : action === 'LOST'\n ? i18next.t('text.opportunity-event-lost')\n : i18next.t('text.opportunity-event-updated')\n\nfunction blank(stages: { stage: string; probability: number }[] = []): Form {\n const lead = stages.find(one => one.stage === 'LEAD')\n return {\n name: '',\n counterparty: null,\n endCustomer: null,\n amount: '0',\n currency: 'KRW',\n expectedCloseMonth: thisMonth(),\n stage: 'LEAD',\n probability: lead ? String(lead.probability) : '',\n ownerId: '',\n description: ''\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"opportunity-editor.js","sourceRoot":"","sources":["../../client/pages/opportunity-editor.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/list-state/ox-page-state.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, nothing } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\n\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { notify } from '@operato/layout'\nimport { navigate, PageView } from '@operato/shell'\nimport { ButtonStyles, DocumentPageStyles, FormFieldStyles } from '@operato/styles'\nimport { currencyChoices, documentAmount, DocumentFormStyles } from '@things-factory/invoice/dist-client'\n\nimport { opportunitySection } from '../opportunity-attach'\nimport { opportunityStageWord } from '../opportunity-words'\nimport { quotationStatusWord } from '../quotation-words'\n\nconst FIELDS = `\n id name stage probability amount currency expectedCloseMonth closedOn lostReason description\n counterpartyId endCustomerId ownerId counterparty { id name } endCustomer { id name } owner { id name }\n quotations { id number version status issueDate validUntil totalAmount currency }\n`\n\ntype Party = { id: string; name: string; businessNumber?: string }\ntype Picker = { search: string; found: Party[] }\ntype Form = {\n name: string\n counterparty: Party | null\n endCustomer: Party | null\n amount: string\n currency: string\n expectedCloseMonth: string\n stage: string\n probability: string\n ownerId: string\n description: string\n}\n\nconst thisMonth = () => new Date().toLocaleDateString('en-CA').slice(0, 7)\n\n/**\n * 영업 기회 편집 — with whom, for how much, by when and how likely.\n *\n * A person moves an open opportunity through the stages; changing the stage puts that stage's probability in, and the\n * person may change it. An open one is closed as lost with the reason; a lost one is opened again by choosing an open\n * stage. Winning is the application's: it closes the opportunity when the opportunity becomes its contract.\n */\n@customElement('opportunity-editor')\nexport class OpportunityEditor extends localize(i18next)(PageView) {\n static styles = [\n FormFieldStyles,\n ButtonStyles,\n DocumentPageStyles,\n DocumentFormStyles,\n css`\n .party {\n display: flex;\n gap: var(--spacing-small);\n align-items: center;\n }\n .party input {\n flex: 1;\n }\n table {\n width: 100%;\n border-collapse: collapse;\n font-variant-numeric: tabular-nums;\n }\n th,\n td {\n text-align: left;\n padding: var(--spacing-small);\n border-bottom: 1px solid var(--ui-line-soft);\n font-size: var(--ui-t-body);\n }\n th.number,\n td.number {\n text-align: right;\n }\n td a {\n color: inherit;\n text-decoration: underline;\n }\n `\n ]\n\n @state() opportunity: any = null\n @state() form: Form = blank()\n @state() pickers: Record<'counterparty' | 'endCustomer', Picker> = { counterparty: { search: '', found: [] }, endCustomer: { search: '', found: [] } }\n @state() stages: { stage: string; probability: number; open: boolean }[] = []\n @state() owners: { id: string; name: string; email?: string }[] = []\n /** Whether the application's section is this person's to read - asked once, before it is shown. */\n @state() sectionReadable = false\n @state() events: any[] = []\n @state() reason = ''\n @state() loading = false\n @state() error: unknown = null\n @state() busy = false\n\n private isOpen(stage: string) {\n return this.stages.some(one => one.stage === stage && one.open)\n }\n\n /** Won is final; a lost one is changed only by being opened again. */\n get editable() {\n return !this.busy && this.opportunity?.stage !== 'WON' && this.isOpen(this.form.stage)\n }\n\n get context() {\n const actions: any[] = []\n if (this.editable) actions.push({ title: i18next.t('button.save'), icon: 'save', emphasis: { raised: true }, action: () => this.save() })\n return {\n title: this.opportunity ? `${i18next.t('title.opportunity')} ${this.opportunity.name}` : i18next.t('title.opportunity-new'),\n ...(this.opportunity ? { description: opportunityStageWord(this.opportunity.stage) } : {}),\n frame: 'document',\n /* Opened from the opportunity list; the menu marks it. */\n menu: 'opportunity-list',\n actions: this.error ? [] : actions\n }\n }\n\n async pageUpdated(changes: any, lifecycle: any) {\n if (!this.active || !(changes.active || changes.params)) return\n if (!this.stages.length) await this.readChoices()\n const section = opportunitySection()\n if (section && !this.sectionReadable) (section.readable?.() ?? Promise.resolve(true)).then(may => (this.sectionReadable = !!may))\n const id = lifecycle?.params?.id\n if (!id) {\n this.opportunity = null\n this.form = blank(this.stages)\n this.events = []\n this.updateContext()\n return\n }\n if (id !== this.opportunity?.id) await this.load(id)\n }\n\n render() {\n const attached = this.opportunity && this.sectionReadable ? opportunitySection() : undefined\n const editable = this.editable\n const set = (patch: Partial<Form>) => (this.form = { ...this.form, ...patch })\n const stageChoices = this.stages.filter(one => one.open || one.stage === this.opportunity?.stage)\n return html`<ox-page-state .loading=${this.loading} .error=${this.error} @retry=${() => this.opportunity && this.load(this.opportunity.id)}>\n <div class=\"page\">\n <section class=\"page-section\">\n <header class=\"page-section-header\"><h3>${i18next.t('text.opportunity-section-head')}</h3></header>\n <div class=\"form\">\n <label class=\"wide\"\n >${i18next.t('field.opportunity-name')}\n <input .value=${this.form.name} ?disabled=${!editable} @input=${(e: any) => set({ name: e.target.value })}\n /></label>\n ${this.renderParty('counterparty', i18next.t('field.opportunity-counterparty'), editable)}\n ${this.renderParty('endCustomer', i18next.t('field.opportunity-end-customer'), editable)}\n <label\n >${i18next.t('field.opportunity-amount')}\n <input type=\"number\" min=\"0\" .value=${this.form.amount} ?disabled=${!editable} @input=${(e: any) => set({ amount: e.target.value })}\n /></label>\n <label\n >${i18next.t('field.opportunity-currency')}\n <select .value=${this.form.currency} ?disabled=${!editable} @change=${(e: any) => set({ currency: e.target.value })}>\n ${currencyChoices().map((code: string) => html`<option value=${code} ?selected=${code === this.form.currency}>${code}</option>`)}\n </select>\n </label>\n <label\n >${i18next.t('field.opportunity-expected-close-month')}\n <input type=\"month\" .value=${this.form.expectedCloseMonth} ?disabled=${!editable} @input=${(e: any) => set({ expectedCloseMonth: e.target.value })}\n /></label>\n <label\n >${i18next.t('field.opportunity-owner')}\n <select .value=${this.form.ownerId} ?disabled=${!editable} @change=${(e: any) => set({ ownerId: e.target.value })}>\n ${this.form.ownerId ? nothing : html`<option value=\"\" selected>${i18next.t('text.opportunity-owner-me')}</option>`}\n ${this.owners.map(one => html`<option value=${one.id} ?selected=${one.id === this.form.ownerId}>${one.name}</option>`)}\n </select>\n </label>\n <label class=\"wide\"\n >${i18next.t('field.opportunity-description')}\n <textarea .value=${this.form.description} ?disabled=${!editable} @input=${(e: any) => set({ description: e.target.value })}></textarea>\n </label>\n </div>\n </section>\n <section class=\"page-section\">\n <header class=\"page-section-header\"><h3>${i18next.t('text.opportunity-section-stage')}</h3></header>\n <div class=\"form\">\n <label\n >${i18next.t('field.opportunity-stage')}\n <select .value=${this.form.stage} ?disabled=${this.busy || this.opportunity?.stage === 'WON'} @change=${(e: any) => this.chooseStage(e.target.value)}>\n ${stageChoices.map(one => html`<option value=${one.stage} ?selected=${one.stage === this.form.stage} ?disabled=${!one.open}>${opportunityStageWord(one.stage)}</option>`)}\n </select>\n </label>\n <label\n >${i18next.t('field.opportunity-probability')}\n <input type=\"number\" min=\"0\" max=\"100\" step=\"1\" .value=${this.form.probability} ?disabled=${!editable} @input=${(e: any) => set({ probability: e.target.value })}\n /></label>\n ${this.opportunity?.closedOn\n ? html`<label>${i18next.t('field.opportunity-closed-on')} <strong>${this.opportunity.closedOn}</strong></label>`\n : nothing}\n </div>\n </section>\n ${this.opportunity && this.isOpen(this.opportunity.stage) ? this.renderLose() : nothing}\n ${this.opportunity?.lostReason\n ? html`<section class=\"page-section\">\n <header class=\"page-section-header\"><h3>${i18next.t('field.opportunity-lost-reason')}</h3></header>\n <p>${this.opportunity.lostReason}</p>\n </section>`\n : nothing}\n ${this.opportunity ? this.renderQuotations() : nothing}\n ${attached && this.opportunity\n ? html`<section class=\"page-section\" @opportunity-changed=${() => this.load(this.opportunity.id)}>\n <header class=\"page-section-header\"><h3>${attached.heading()}</h3></header>\n ${attached.render(this.opportunity)}\n </section>`\n : nothing}\n ${this.events.length ? this.renderEvents() : nothing}\n </div>\n </ox-page-state>`\n }\n\n /** A counterparty of the domain, found by name or business number. */\n private renderParty(which: 'counterparty' | 'endCustomer', label: string, editable: boolean) {\n const picker = this.pickers[which]\n const chosen = this.form[which]\n return html`<label\n >${label}\n <span class=\"party\">\n <input\n .value=${picker.search}\n placeholder=${chosen?.name ?? i18next.t('text.opportunity-counterparty-search')}\n ?disabled=${!editable}\n @input=${(e: any) => this.setPicker(which, { search: e.target.value })}\n @keydown=${(e: KeyboardEvent) => e.key === 'Enter' && this.findParties(which)}\n />\n <button ?disabled=${!editable} @click=${() => this.findParties(which)}>${i18next.t('button.search')}</button>\n ${which === 'endCustomer' && chosen ? html`<button ?disabled=${!editable} @click=${() => (this.form = { ...this.form, endCustomer: null })}>${i18next.t('button.opportunity-clear')}</button>` : nothing}\n </span>\n ${picker.found.length\n ? html`<select ?disabled=${!editable} @change=${(e: any) => this.chooseParty(which, picker.found.find(one => one.id === e.target.value) ?? null)}>\n <option value=\"\">${chosen?.name ?? ''}</option>\n ${picker.found.map(one => html`<option value=${one.id}>${one.name}${one.businessNumber ? ` (${one.businessNumber})` : ''}</option>`)}\n </select>`\n : nothing}\n </label>`\n }\n\n private renderLose() {\n return html`<section class=\"page-section\">\n <header class=\"page-section-header\">\n <h3>${i18next.t('text.opportunity-section-lose')}</h3>\n <div class=\"page-section-actions\">\n <button ?disabled=${this.busy || !this.reason.trim()} @click=${() => this.lose()}>${i18next.t('button.opportunity-lose')}</button>\n </div>\n </header>\n <div class=\"form\">\n <label class=\"wide\"\n >${i18next.t('field.opportunity-lost-reason')}\n <input .value=${this.reason} ?disabled=${this.busy} @input=${(e: any) => (this.reason = e.target.value)}\n /></label>\n </div>\n </section>`\n }\n\n /** The quotations that answer this opportunity; a new one is written from here and answers it. */\n private renderQuotations() {\n const quotations: any[] = this.opportunity.quotations ?? []\n return html`<section class=\"page-section\">\n <header class=\"page-section-header\">\n <h3>${i18next.t('text.opportunity-section-quotations')}</h3>\n <div class=\"page-section-actions\">\n <button ?disabled=${this.busy || this.opportunity.stage === 'WON' || this.opportunity.stage === 'LOST'} @click=${() => navigate(`quotation-editor?opportunity=${this.opportunity.id}`)}>\n ${i18next.t('button.opportunity-new-quotation')}\n </button>\n </div>\n </header>\n ${quotations.length\n ? html`<table>\n <thead>\n <tr>\n <th>${i18next.t('field.quotation-number')}</th>\n <th>${i18next.t('field.quotation-version')}</th>\n <th>${i18next.t('field.quotation-status')}</th>\n <th>${i18next.t('field.quotation-issue-date')}</th>\n <th class=\"number\">${i18next.t('field.quotation-total-amount')}</th>\n </tr>\n </thead>\n <tbody>\n ${quotations.map(\n one => html`<tr>\n <td><a href=${`quotation-editor?id=${one.id}`}>${one.number}</a></td>\n <td>v${one.version}</td>\n <td>${quotationStatusWord(one.status)}</td>\n <td>${one.issueDate ?? ''}</td>\n <td class=\"number\">${documentAmount(one.totalAmount, one.currency || 'KRW')}</td>\n </tr>`\n )}\n </tbody>\n </table>`\n : nothing}\n </section>`\n }\n\n private renderEvents() {\n return html`<section class=\"page-section\">\n <header class=\"page-section-header\"><h3>${i18next.t('text.opportunity-section-history')}</h3></header>\n <table>\n <thead>\n <tr>\n <th>${i18next.t('field.opportunity-event-at')}</th>\n <th>${i18next.t('field.opportunity-event-actor')}</th>\n <th>${i18next.t('field.opportunity-event-action')}</th>\n <th>${i18next.t('field.opportunity-stage')}</th>\n <th class=\"number\">${i18next.t('field.opportunity-probability')}</th>\n </tr>\n </thead>\n <tbody>\n ${this.events.map(\n one => html`<tr>\n <td>${one.createdAt ? new Date(one.createdAt).toLocaleString() : ''}</td>\n <td>${one.actor?.name ?? ''}</td>\n <td>${eventWord(one.action)}${one.reason ? ` · ${one.reason}` : ''}</td>\n <td>${one.fromStage ? `${opportunityStageWord(one.fromStage)} → ` : ''}${opportunityStageWord(one.stage)}</td>\n <td class=\"number\">${one.probability}%</td>\n </tr>`\n )}\n </tbody>\n </table>\n </section>`\n }\n\n private setPicker(which: 'counterparty' | 'endCustomer', patch: Partial<Picker>) {\n this.pickers = { ...this.pickers, [which]: { ...this.pickers[which], ...patch } }\n }\n\n private chooseParty(which: 'counterparty' | 'endCustomer', party: Party | null) {\n if (!party) return\n this.form = { ...this.form, [which]: party }\n this.setPicker(which, { search: '', found: [] })\n }\n\n /** The stage's own probability comes in with it; the person may change it afterwards. */\n private chooseStage(stage: string) {\n const given = this.stages.find(one => one.stage === stage)\n this.form = { ...this.form, stage, probability: given ? String(given.probability) : this.form.probability }\n }\n\n private async readChoices() {\n try {\n const response = await client.query({\n query: gql`\n query {\n opportunityStages { stage probability open }\n opportunityOwners { id name email }\n }\n `,\n fetchPolicy: 'no-cache'\n })\n if (response.errors?.length) throw response\n this.stages = response.data.opportunityStages\n this.owners = response.data.opportunityOwners\n } catch (error) {\n this.error = error\n }\n }\n\n private async findParties(which: 'counterparty' | 'endCustomer') {\n await this.run(async () => {\n const response = await client.query({\n query: gql`\n query ($search: String, $pagination: Pagination) {\n counterparties: counterpartyChoices(search: $search, pagination: $pagination) {\n items { id name businessNumber }\n }\n }\n `,\n variables: { search: this.pickers[which].search.trim() || undefined, pagination: { page: 1, limit: 30 } },\n fetchPolicy: 'no-cache'\n })\n if (response.errors?.length) throw response\n const found: Party[] = response.data.counterparties.items ?? []\n if (found.length === 1) this.chooseParty(which, found[0])\n else this.setPicker(which, { found })\n })\n }\n\n private async load(id: string) {\n this.loading = true\n this.error = null\n try {\n const response = await client.query({\n query: gql(`query ($id: String!) { opportunity(id: $id) { ${FIELDS} } opportunityEvents(opportunityId: $id) { id action fromStage stage probability reason createdAt actor { id name } } }`),\n variables: { id },\n fetchPolicy: 'no-cache'\n })\n if (response.errors?.length) throw response\n if (!response.data.opportunity) throw new Error(i18next.t('text.opportunity-not-found'))\n this.show(response.data.opportunity, response.data.opportunityEvents)\n } catch (error) {\n this.error = error\n } finally {\n this.loading = false\n this.updateContext()\n }\n }\n\n private show(opportunity: any, events: any[]) {\n this.opportunity = opportunity\n this.events = events\n this.form = {\n name: opportunity.name,\n counterparty: opportunity.counterparty,\n endCustomer: opportunity.endCustomer,\n amount: String(opportunity.amount ?? 0),\n currency: opportunity.currency,\n expectedCloseMonth: opportunity.expectedCloseMonth,\n stage: opportunity.stage,\n probability: String(opportunity.probability),\n ownerId: opportunity.ownerId ?? '',\n description: opportunity.description ?? ''\n }\n this.reason = ''\n }\n\n private async run<T>(work: () => Promise<T>): Promise<T | undefined> {\n if (this.busy) return undefined\n this.busy = true\n try {\n return await work()\n } catch (error: any) {\n notify({ level: 'error', message: error?.graphQLErrors?.[0]?.message ?? error?.errors?.[0]?.message ?? error?.message ?? String(error) })\n return undefined\n } finally {\n this.busy = false\n }\n }\n\n private input() {\n const { name, counterparty, endCustomer, amount, currency, expectedCloseMonth, stage, probability, ownerId, description } = this.form\n return {\n name,\n counterpartyId: counterparty?.id ?? '',\n endCustomerId: endCustomer?.id ?? null,\n amount: Number(amount || 0),\n currency,\n expectedCloseMonth,\n stage,\n probability: probability === '' ? null : Number(probability),\n ownerId: ownerId || null,\n description\n }\n }\n\n private async save() {\n const id = this.opportunity?.id\n const saved = await this.run(async () => {\n const response = await client.mutate({\n mutation: gql(\n id\n ? `mutation ($id: String!, $opportunity: NewOpportunity!) { opportunity: updateOpportunity(id: $id, opportunity: $opportunity) { id } }`\n : `mutation ($opportunity: NewOpportunity!) { opportunity: createOpportunity(opportunity: $opportunity) { id } }`\n ),\n variables: { ...(id ? { id } : {}), opportunity: this.input() }\n })\n if (response.errors?.length) throw response\n return response.data.opportunity as { id: string }\n })\n if (!saved) return\n if (!id) navigate(`opportunity-editor?id=${saved.id}`)\n else await this.load(id)\n }\n\n private async lose() {\n const id = this.opportunity!.id\n const lost = await this.run(async () => {\n const response = await client.mutate({\n mutation: gql`\n mutation ($id: String!, $reason: String!) {\n loseOpportunity(id: $id, reason: $reason) { id }\n }\n `,\n variables: { id, reason: this.reason.trim() }\n })\n if (response.errors?.length) throw response\n return response.data.loseOpportunity\n })\n if (lost) await this.load(id)\n }\n}\n\nconst eventWord = (action?: string) =>\n action === 'CREATED'\n ? i18next.t('text.opportunity-event-created')\n : action === 'STAGED'\n ? i18next.t('text.opportunity-event-staged')\n : action === 'WON'\n ? i18next.t('text.opportunity-event-won')\n : action === 'LOST'\n ? i18next.t('text.opportunity-event-lost')\n : i18next.t('text.opportunity-event-updated')\n\nfunction blank(stages: { stage: string; probability: number }[] = []): Form {\n const lead = stages.find(one => one.stage === 'LEAD')\n return {\n name: '',\n counterparty: null,\n endCustomer: null,\n amount: '0',\n currency: 'KRW',\n expectedCloseMonth: thisMonth(),\n stage: 'LEAD',\n probability: lead ? String(lead.probability) : '',\n ownerId: '',\n description: ''\n }\n}\n"]}
|
|
@@ -38,6 +38,8 @@ export declare class QuotationEditor extends QuotationEditor_base {
|
|
|
38
38
|
amounts: Partial<DocumentValue>;
|
|
39
39
|
/** Whether this person may write invoices - an accepted quotation then makes one. */
|
|
40
40
|
invoiceWriter: boolean;
|
|
41
|
+
/** Whether the application's section is this person's to read - asked once, before it is shown. */
|
|
42
|
+
sectionReadable: boolean;
|
|
41
43
|
private grist?;
|
|
42
44
|
get editable(): boolean;
|
|
43
45
|
get context(): {
|
|
@@ -99,6 +99,8 @@ let QuotationEditor = class QuotationEditor extends localize(i18next)(PageView)
|
|
|
99
99
|
this.amounts = {};
|
|
100
100
|
/** Whether this person may write invoices - an accepted quotation then makes one. */
|
|
101
101
|
this.invoiceWriter = false;
|
|
102
|
+
/** Whether the application's section is this person's to read - asked once, before it is shown. */
|
|
103
|
+
this.sectionReadable = false;
|
|
102
104
|
}
|
|
103
105
|
static { this.styles = [
|
|
104
106
|
FormFieldStyles,
|
|
@@ -144,7 +146,7 @@ let QuotationEditor = class QuotationEditor extends localize(i18next)(PageView)
|
|
|
144
146
|
if (['SENT', 'REJECTED', 'EXPIRED'].includes(status))
|
|
145
147
|
actions.push({ title: i18next.t('button.quotation-revise'), icon: 'edit_document', action: () => this.change('reviseQuotation') });
|
|
146
148
|
if (this.quotation)
|
|
147
|
-
actions.push({ title: i18next.t('button.
|
|
149
|
+
actions.push({ title: i18next.t('button.preview'), icon: 'preview', action: () => this.preview() });
|
|
148
150
|
return {
|
|
149
151
|
title: this.quotation ? `${i18next.t('title.quotation')} ${this.quotation.number} · v${this.quotation.version}` : i18next.t('title.quotation-new'),
|
|
150
152
|
...(this.quotation ? { description: quotationStatusWord(status) } : {}),
|
|
@@ -162,6 +164,9 @@ let QuotationEditor = class QuotationEditor extends localize(i18next)(PageView)
|
|
|
162
164
|
await this.readOpportunities();
|
|
163
165
|
if (!this.defaults)
|
|
164
166
|
this.defaults = await documentDefaults();
|
|
167
|
+
const section = quotationSection();
|
|
168
|
+
if (section && !this.sectionReadable)
|
|
169
|
+
(section.readable?.() ?? Promise.resolve(true)).then(may => (this.sectionReadable = !!may));
|
|
165
170
|
hasPrivilege({ category: 'invoice', privilege: 'mutation', domainOwnerGranted: true }).then(writer => {
|
|
166
171
|
this.invoiceWriter = !!writer;
|
|
167
172
|
this.updateContext();
|
|
@@ -181,7 +186,7 @@ let QuotationEditor = class QuotationEditor extends localize(i18next)(PageView)
|
|
|
181
186
|
await this.load(id);
|
|
182
187
|
}
|
|
183
188
|
render() {
|
|
184
|
-
const attached = this.quotation ? quotationSection() : undefined;
|
|
189
|
+
const attached = this.quotation && this.sectionReadable ? quotationSection() : undefined;
|
|
185
190
|
const editable = this.editable && !this.busy;
|
|
186
191
|
return html `<ox-page-state .loading=${this.loading} .error=${this.error} @retry=${() => this.quotation && this.load(this.quotation.id)}>
|
|
187
192
|
<div class="page">
|
|
@@ -195,7 +200,7 @@ let QuotationEditor = class QuotationEditor extends localize(i18next)(PageView)
|
|
|
195
200
|
terms: this.defaults?.paymentTerms,
|
|
196
201
|
/* In the group it fills - the buyer's of a sale, the supplier's of a purchase. */
|
|
197
202
|
party: html `<label
|
|
198
|
-
>${i18next.t('field.
|
|
203
|
+
>${i18next.t('field.counterparty')}
|
|
199
204
|
<document-party-select .party=${this.party} ?disabled=${!editable} @party=${(e) => this.takeParty(e.detail)}></document-party-select>
|
|
200
205
|
</label>`
|
|
201
206
|
})}
|
|
@@ -565,7 +570,7 @@ let QuotationEditor = class QuotationEditor extends localize(i18next)(PageView)
|
|
|
565
570
|
if (!response.data?.quotationDocumentFile)
|
|
566
571
|
throw response.errors?.[0] ?? new Error(i18next.t('text.quotation-not-found'));
|
|
567
572
|
return response.data.quotationDocumentFile;
|
|
568
|
-
}, language, `${i18next.t('title.
|
|
573
|
+
}, language, `${i18next.t('title.preview')} · ${number} · v${version}`);
|
|
569
574
|
}
|
|
570
575
|
};
|
|
571
576
|
__decorate([
|
|
@@ -616,6 +621,10 @@ __decorate([
|
|
|
616
621
|
state(),
|
|
617
622
|
__metadata("design:type", Object)
|
|
618
623
|
], QuotationEditor.prototype, "invoiceWriter", void 0);
|
|
624
|
+
__decorate([
|
|
625
|
+
state(),
|
|
626
|
+
__metadata("design:type", Object)
|
|
627
|
+
], QuotationEditor.prototype, "sectionReadable", void 0);
|
|
619
628
|
__decorate([
|
|
620
629
|
query('ox-grist'),
|
|
621
630
|
__metadata("design:type", DataGrist)
|