@things-factory/tax-invoice 6.2.147 → 6.2.149

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/client/pages/tax-invoice-send/company-list-popup.ts +3 -0
  2. package/client/pages/tax-invoice-send/tax-invoice-send-page.ts +9 -898
  3. package/client/pages/tax-invoice-send/tax-invoice-send.ts +951 -0
  4. package/dist-client/pages/tax-invoice-send/company-list-popup.d.ts +3 -0
  5. package/dist-client/pages/tax-invoice-send/company-list-popup.js +3 -0
  6. package/dist-client/pages/tax-invoice-send/company-list-popup.js.map +1 -1
  7. package/dist-client/pages/tax-invoice-send/tax-invoice-send-page.d.ts +2 -79
  8. package/dist-client/pages/tax-invoice-send/tax-invoice-send-page.js +8 -796
  9. package/dist-client/pages/tax-invoice-send/tax-invoice-send-page.js.map +1 -1
  10. package/dist-client/pages/tax-invoice-send/tax-invoice-send.d.ts +112 -0
  11. package/dist-client/pages/tax-invoice-send/tax-invoice-send.js +869 -0
  12. package/dist-client/pages/tax-invoice-send/tax-invoice-send.js.map +1 -0
  13. package/dist-client/route.d.ts +1 -1
  14. package/dist-client/tsconfig.tsbuildinfo +1 -1
  15. package/dist-server/service/index.js +1 -0
  16. package/dist-server/service/index.js.map +1 -1
  17. package/dist-server/service/tax-invoice/tax-invoice-mutation.js +0 -4
  18. package/dist-server/service/tax-invoice/tax-invoice-mutation.js.map +1 -1
  19. package/dist-server/service/tax-invoice/tax-invoice-query.js +18 -6
  20. package/dist-server/service/tax-invoice/tax-invoice-query.js.map +1 -1
  21. package/dist-server/service/tax-invoice/tax-invoice-type.js +4 -0
  22. package/dist-server/service/tax-invoice/tax-invoice-type.js.map +1 -1
  23. package/dist-server/service/tax-invoice/tax-invoice-util.js +1 -0
  24. package/dist-server/service/tax-invoice/tax-invoice-util.js.map +1 -1
  25. package/dist-server/service/tax-invoice/tax-invoice.js +5 -0
  26. package/dist-server/service/tax-invoice/tax-invoice.js.map +1 -1
  27. package/dist-server/service/unipost-api/test-data.js +3812 -0
  28. package/dist-server/service/unipost-api/test-data.js.map +1 -0
  29. package/dist-server/tsconfig.tsbuildinfo +1 -1
  30. package/package.json +2 -2
  31. package/server/service/index.ts +1 -0
  32. package/server/service/tax-invoice/tax-invoice-mutation.ts +0 -3
  33. package/server/service/tax-invoice/tax-invoice-query.ts +19 -7
  34. package/server/service/tax-invoice/tax-invoice-type.ts +3 -0
  35. package/server/service/tax-invoice/tax-invoice-util.ts +1 -0
  36. package/server/service/tax-invoice/tax-invoice.ts +4 -0
@@ -3,103 +3,16 @@ import '@operato/data-grist'
3
3
  import { CommonButtonStyles, CommonGristStyles, ScrollbarStyles } from '@operato/styles'
4
4
  import { PageView } from '@operato/shell'
5
5
  import { css, html } from 'lit'
6
- import { customElement, property, query, state } from 'lit/decorators.js'
6
+ import { customElement, state } from 'lit/decorators.js'
7
7
  import { ScopedElementsMixin } from '@open-wc/scoped-elements'
8
8
  import { client } from '@operato/graphql'
9
9
  import { i18next, localize } from '@operato/i18n'
10
10
  import { notify } from '@operato/layout'
11
11
  import gql from 'graphql-tag'
12
- import { BUSINESS_REGISTRATION_CATEGORY, BusinessRegistrationCategory, Category, INVOICE_TYPE, InvoiceType, PURPOSE, Purpose } from '../tax-invoice/tax-invoice-list-page'
13
- import { openPopup } from '@operato/layout'
12
+ import { BusinessRegistrationCategory, Category, InvoiceType, Purpose } from '../tax-invoice/tax-invoice-list-page'
14
13
  import { CompanyListPopup } from './company-list-popup'
15
-
16
- const SHORT_INVOICE_TYPE = {
17
- TAX_INVOICE: {
18
- [InvoiceType.TAX_INVOICE]: '일반',
19
- [InvoiceType.SMALL_BUSINESS_TAX_INVOICE]: '영세율',
20
- [InvoiceType.CONSIGNMENT_TAX_INVOICE]: '위수탁',
21
- [InvoiceType.SMALL_BUSINESS_CONSIGNMENT_TAX_INVOICE]: '위수탁영세율'
22
- },
23
- INVOICE: {
24
- [InvoiceType.INVOICE]: '일반',
25
- [InvoiceType.CONSIGNMENT_INVOICE]: '위수탁'
26
- // [InvoiceType.IMPORT_INVOICE]: INVOICE_TYPE[IMPORT_INVOICE],
27
- }
28
- }
29
-
30
- const SHORT_BUSINESS_REGISTRATION_CATEGORY = {
31
- [BusinessRegistrationCategory.BUSINESS_REGISTRATION_NUMBER]: '사업자',
32
- [BusinessRegistrationCategory.RESIDENT_REGISTRATION_NUMBER]: '개인',
33
- [BusinessRegistrationCategory.FOREIGNER_REGISTRATION_NUMBER]: '외국인'
34
- }
35
-
36
- export interface Supplier {
37
- supplierBusinessRegistrationCategory: string
38
- supplierBusinessRegistrationNumber: string
39
- supplierBranchIdentification?: string
40
- supplierBusinessName: string
41
- supplierRepresentativeName: string
42
- supplierAddress?: string
43
- supplierBusinessType?: string
44
- supplierIndustryType?: string
45
- supplierDepartment?: string
46
- supplierContactName?: string
47
- supplierContactPhone?: string
48
- supplierContactEmail?: string
49
- supplierContactCellPhone?: string
50
- }
51
- interface Buyer {
52
- buyerBusinessRegistrationCategory: BusinessRegistrationCategory
53
- buyerBusinessRegistrationNumber: string
54
- buyerBranchIdentification?: string
55
- buyerBusinessName: string
56
- buyerRepresentativeName: string
57
- buyerAddress?: string
58
- buyerBusinessType?: string
59
- buyerIndustryType?: string
60
- buyer1stDepartment?: string
61
- buyer1stContactName?: string
62
- buyer1stContactPhone?: string
63
- buyer1stContactEmail?: string
64
- buyer1stContactCellPhone?: string
65
- buyer2ndDepartment?: string
66
- buyer2ndContactName?: string
67
- buyer2ndContactPhone?: string
68
- buyer2ndContactEmail?: string
69
- buyer2ndContactCellPhone?: string
70
- }
71
- interface TaxInvoice {
72
- category: Category
73
- issueNo?: string
74
- approvalNo?: string
75
- originalApprovalNo?: string
76
- issueDate: string
77
- signatureDate?: string
78
- invoiceType: InvoiceType
79
- purpose: Purpose
80
- remark0?: string
81
- remark1?: string
82
- remark2?: string
83
- paymentAmountCash?: number
84
- paymentAmountCheck?: number
85
- paymentAmountPromissoryNote?: number
86
- paymentAmountAccountsReceivable?: number
87
- supplyAmount: number
88
- taxAmount: number
89
- totalAmount: number
90
- // revisedReason?: RevisedReason
91
- }
92
- interface TaxInvoiceItem {
93
- sequence: number
94
- supplyDate: string
95
- itemName: string
96
- specification: string
97
- quantity: number
98
- unitPrice: number
99
- supplyPrice: number
100
- taxPrice: number
101
- remark?: string
102
- }
14
+ import { Supplier, Buyer, TaxInvoice, TaxInvoiceItem } from './tax-invoice-send'
15
+ import './tax-invoice-send'
103
16
 
104
17
  @customElement('tax-invoice-send-page')
105
18
  export class TaxInvoiceSendPage extends localize(i18next)(ScopedElementsMixin(PageView)) {
@@ -109,261 +22,6 @@ export class TaxInvoiceSendPage extends localize(i18next)(ScopedElementsMixin(Pa
109
22
  css`
110
23
  :host {
111
24
  display: flex;
112
- flex-direction: column;
113
- overflow-y: auto;
114
- overflow-x: hidden;
115
-
116
- width: 100%;
117
- min-width: 850px;
118
- padding: 0 40px 40px 40px;
119
-
120
- --grid-record-emphasized-background-color: red;
121
- --grid-record-emphasized-color: yellow;
122
- }
123
-
124
- .flex-row {
125
- display: flex;
126
- flex-direction: row;
127
- }
128
- .flex-column {
129
- display: flex;
130
- flex-direction: column;
131
- }
132
-
133
- input[type='text'],
134
- input[type='date'],
135
- input[type='number'] {
136
- width: 85%;
137
- max-width: calc(100% - 12px);
138
- height: 14px;
139
- margin: 0;
140
- padding: 4px 5px 5px;
141
- line-height: 14px;
142
- border: 1px solid #bbb;
143
- background: #fff;
144
- letter-spacing: 0.5px;
145
- }
146
- input[type='date'] {
147
- width: auto;
148
- }
149
- input[readonly],
150
- input:disabled {
151
- background-color: #eee;
152
- }
153
-
154
- div.invoice-type {
155
- font-size: 18px;
156
- margin-top: 15px;
157
- }
158
-
159
- table {
160
- border: solid;
161
- border-width: 2px 0;
162
- border-collapse: collapse;
163
- border-spacing: 0;
164
- }
165
-
166
- .title table {
167
- border-color: #d3dbe5;
168
- width: 100%;
169
- height: 33px;
170
- margin-top: 10px;
171
- font-size: 12px;
172
-
173
- th {
174
- font-size: 13px;
175
- background-color: #e9edf6;
176
- min-width: 140px;
177
- }
178
- td {
179
- width: 50%;
180
- padding-left: 10px;
181
-
182
- & > * {
183
- vertical-align: middle;
184
- }
185
- & > input {
186
- margin: 0 5px 0 1px;
187
- }
188
- }
189
- }
190
-
191
- div.body {
192
- margin-top: 15px;
193
- font-size: 14px;
194
-
195
- div.data {
196
- display: flex;
197
- margin-top: 5px;
198
-
199
- table {
200
- flex: 1;
201
-
202
- td,
203
- th {
204
- padding: 5px;
205
- min-width: 60px;
206
- }
207
- td {
208
- padding-left: 8px;
209
- }
210
- th.target {
211
- width: 25px;
212
- writing-mode: vertical-rl;
213
- min-width: unset;
214
- }
215
-
216
- &.supplier {
217
- border-color: #f64843;
218
-
219
- td,
220
- th {
221
- background-color: #fef5f7;
222
- border: solid 1.5px #f5b1b1;
223
- }
224
- th.target {
225
- background-color: #fedbde;
226
- }
227
- }
228
- &.buyer {
229
- border-color: #007ed9;
230
-
231
- td,
232
- th {
233
- background-color: #f7f7ff;
234
- border: solid 1.5px #a7bcff;
235
- }
236
- th.target {
237
- background-color: #c6daf6;
238
- }
239
- }
240
- }
241
- }
242
-
243
- div.header {
244
- display: flex;
245
-
246
- span {
247
- flex: 1;
248
- }
249
- }
250
-
251
- div.info {
252
- margin-top: 15px;
253
- border: solid;
254
- border-color: #000;
255
- border-width: 2px 0px 0px 0px;
256
-
257
- div.flex-row div {
258
- border: solid #c4d2ff;
259
- border-width: 0px 1.5px 1.5px 1.5px;
260
- margin-right: -1px;
261
- padding: 5px;
262
- text-align: center;
263
-
264
- &.title {
265
- background-color: #e9edf5;
266
- font-weight: bold;
267
- flex: 1;
268
- }
269
- &.value {
270
- flex: 3;
271
- text-align: left;
272
-
273
- .desc {
274
- font-size: 11px;
275
- color: #c90000;
276
- }
277
- }
278
- }
279
- }
280
-
281
- div.items,
282
- div.summary {
283
- margin-top: 20px;
284
-
285
- table {
286
- width: 100%;
287
- border-color: #000;
288
- border-width: 2px 0px 0px 0px;
289
-
290
- th {
291
- background-color: #e9edf5;
292
- }
293
- th,
294
- td {
295
- border: solid 1.5px #c4d2ff;
296
- padding: 5px;
297
- text-align: center;
298
- }
299
- }
300
- }
301
-
302
- div.summary {
303
- display: flex;
304
-
305
- & > table {
306
- flex: 6.7;
307
- }
308
- & > div {
309
- flex: 3.2;
310
- display: flex;
311
- justify-content: center;
312
- align-items: center;
313
- border: 1.5px solid #c4d2ff;
314
- border-top: 2px solid #000;
315
- }
316
-
317
- span.type-wrapper {
318
- margin: 0 10px;
319
-
320
- & > div {
321
- display: flex;
322
- justify-content: center;
323
- align-items: center;
324
- gap: 4px;
325
-
326
- input[type='radio' i] {
327
- margin: 0px;
328
- }
329
- }
330
- }
331
- }
332
-
333
- div.items {
334
- div.desc {
335
- font-weight: 400;
336
- font-size: 12px;
337
- margin-bottom: 5px;
338
- }
339
- div.desc-date {
340
- color: #005d98;
341
- }
342
- button {
343
- font-size: 13px;
344
- height: 25px;
345
- cursor: pointer;
346
- text-align: center;
347
- font-weight: 600;
348
- border-radius: 2px;
349
- border-color: #ccc;
350
- }
351
- .btn-add {
352
- color: #333;
353
- background-color: #f9f9f9;
354
- }
355
- .btn-delete {
356
- color: #fff;
357
- background-color: #5c636e;
358
- border: none;
359
- }
360
- }
361
-
362
- *[required]::before {
363
- content: '*';
364
- color: red;
365
- margin-right: 2px;
366
- }
367
25
  }
368
26
  `
369
27
  ]
@@ -376,7 +34,6 @@ export class TaxInvoiceSendPage extends localize(i18next)(ScopedElementsMixin(Pa
376
34
 
377
35
  // 오늘 날짜 YYYY-MM-DD 형식으로 뽑기
378
36
  private today: string = new Intl.DateTimeFormat('fr-CA', { timeZone: 'Asia/Seoul' }).format(new Date())
379
- private isTaxFree = false
380
37
 
381
38
  private defaultSupplier = {
382
39
  supplierBusinessRegistrationCategory: '01',
@@ -393,7 +50,7 @@ export class TaxInvoiceSendPage extends localize(i18next)(ScopedElementsMixin(Pa
393
50
  buyerBusinessName: '',
394
51
  buyerRepresentativeName: ''
395
52
  }
396
- @property({ type: Object }) buyer: Buyer = this.defaultBuyer
53
+ @state() buyer: Buyer = this.defaultBuyer
397
54
 
398
55
  private defaultTaxInvoice = {
399
56
  invoiceType: InvoiceType.TAX_INVOICE,
@@ -404,7 +61,7 @@ export class TaxInvoiceSendPage extends localize(i18next)(ScopedElementsMixin(Pa
404
61
  taxAmount: 0,
405
62
  totalAmount: 0
406
63
  }
407
- @property({ type: Object }) taxInvoice: TaxInvoice = this.defaultTaxInvoice
64
+ @state() taxInvoice: TaxInvoice = this.defaultTaxInvoice
408
65
 
409
66
  private defaultTaxInvoiceItem = {
410
67
  sequence: new Date().getTime(), // 구분용 임시 값 (중복되면 안되니 생성 마다 넣어주기)
@@ -416,7 +73,7 @@ export class TaxInvoiceSendPage extends localize(i18next)(ScopedElementsMixin(Pa
416
73
  supplyPrice: 0,
417
74
  taxPrice: 0
418
75
  }
419
- @property({ type: Array }) taxInvoiceItems: TaxInvoiceItem[] = [{ ...this.defaultTaxInvoiceItem }]
76
+ @state() taxInvoiceItems: TaxInvoiceItem[] = [{ ...this.defaultTaxInvoiceItem }]
420
77
 
421
78
  get context() {
422
79
  return {
@@ -433,333 +90,7 @@ export class TaxInvoiceSendPage extends localize(i18next)(ScopedElementsMixin(Pa
433
90
  }
434
91
 
435
92
  render() {
436
- return html`
437
- <div class="invoice-type">
438
- * ${INVOICE_TYPE[this.taxInvoice?.invoiceType]} (${SHORT_BUSINESS_REGISTRATION_CATEGORY[this.buyer.buyerBusinessRegistrationCategory]})
439
- </div>
440
-
441
- <div class="title">
442
- <table>
443
- <tr>
444
- <th>${i18next.t('field.short invoice type')}</th>
445
- <td>
446
- ${Object.keys(SHORT_INVOICE_TYPE['TAX_INVOICE']).map(key => {
447
- const disabled: boolean = key !== InvoiceType.TAX_INVOICE && key !== InvoiceType.SMALL_BUSINESS_TAX_INVOICE
448
- const checked: boolean = key === InvoiceType.TAX_INVOICE
449
- return html`
450
- <label for="${'tax_' + key}">${SHORT_INVOICE_TYPE['TAX_INVOICE'][key]}</label>
451
- <input
452
- type="radio"
453
- id="${'tax_' + key}"
454
- .value="${key}"
455
- name="invoiceType"
456
- ?checked=${checked}
457
- ?disabled=${disabled}
458
- @change=${this._onInputTaxInvoice}
459
- />
460
- `
461
- })}
462
- </td>
463
- <th>${i18next.t('field.tax invoice buyer registration category')}</th>
464
- <td>
465
- ${Object.keys(BUSINESS_REGISTRATION_CATEGORY).map(key => {
466
- const disabled: boolean = key !== BusinessRegistrationCategory.BUSINESS_REGISTRATION_NUMBER
467
- const checked: boolean = key === BusinessRegistrationCategory.BUSINESS_REGISTRATION_NUMBER
468
- return html`
469
- <label for="${'tax_' + key}">${BUSINESS_REGISTRATION_CATEGORY[key]}</label>
470
- <input type="radio" id="${'tax_' + key}" value="${key}" name="buyerBusinessRegistrationCategory" ?checked=${checked} ?disabled=${disabled} />
471
- `
472
- })}
473
- </td>
474
- </tr>
475
- </table>
476
- </div>
477
-
478
- <div class="body">
479
- <div class="header">
480
- <span><button @click=${this._openSupplierPopup}>공급처 선택</button></span>
481
- <span><button @click=${this._openBuyerPopup}>공급받는자 선택</button></span>
482
- </div>
483
-
484
- <div class="data">
485
- <table class="supplier">
486
- <colgroup>
487
- <col width="150px" />
488
- <col width="18%" />
489
- <col width="32%" />
490
- <col width="18%" />
491
- <col width="32%" />
492
- </colgroup>
493
- <tr>
494
- <th rowspan="6" class="target">${i18next.t('field.tax invoice supplier')}</th>
495
- <th required>${i18next.t('field.short business registration number')}</th>
496
- <td>${this.supplier?.supplierBusinessRegistrationNumber?.replace(/(\S{3})(\S{2})(\S{5})/g, '$1-$2-$3')}</td>
497
- <th>${i18next.t('field.short branch identification')}</th>
498
- <td>${this.supplier?.supplierBranchIdentification}</td>
499
- </tr>
500
- <tr>
501
- <th required>${i18next.t('field.short tax invoice business name')}</th>
502
- <td><input type="text" name="supplierBusinessName" .value=${this.supplier?.supplierBusinessName || ''} @input=${this._onInputTaxInvoice} /></td>
503
- <th required>${i18next.t('field.tax invoice representative name')}</th>
504
- <td>
505
- <input type="text" name="supplierRepresentativeName" .value=${this.supplier?.supplierRepresentativeName || ''} @input=${this._onInputTaxInvoice} />
506
- </td>
507
- </tr>
508
- <tr>
509
- <th>${i18next.t('field.address')}</th>
510
- <td colspan="3">${this.supplier?.supplierAddress}</td>
511
- </tr>
512
- <tr>
513
- <th>${i18next.t('field.business type')}</th>
514
- <td><input type="text" name="supplierBusinessType" .value=${this.supplier?.supplierBusinessType || ''} @input=${this._onInputTaxInvoice} /></td>
515
- <th>${i18next.t('field.industry type')}</th>
516
- <td><input type="text" name="supplierIndustryType" .value=${this.supplier?.supplierIndustryType || ''} @input=${this._onInputTaxInvoice} /></td>
517
- </tr>
518
- <tr>
519
- <th rowspan="2">${i18next.t('field.email')}</th>
520
- <td rowspan="2" colspan="3">
521
- <input type="text" name="supplierContactEmail" .value=${this.supplier?.supplierContactEmail || ''} @input=${this._onInputTaxInvoice} />
522
- </td>
523
- </tr>
524
- <tr></tr>
525
- </table>
526
-
527
- <table class="buyer">
528
- <colgroup>
529
- <col width="150px" />
530
- <col width="18%" />
531
- <col width="32%" />
532
- <col width="18%" />
533
- <col width="32%" />
534
- </colgroup>
535
- <tr>
536
- <th rowspan="6" class="target">${i18next.t('field.tax invoice buyer')}</th>
537
- <th required>${i18next.t('field.short business registration number')}</th>
538
- <td>
539
- <input
540
- type="text"
541
- maxlength="10"
542
- name="buyerBusinessRegistrationNumber"
543
- .value=${this.buyer?.buyerBusinessRegistrationNumber || ''}
544
- @input=${this._onInputTaxInvoice}
545
- />
546
- </td>
547
- <th>${i18next.t('field.short branch identification')}</th>
548
- <td><input type="text" name="buyerBranchIdentification" .value=${this.buyer?.buyerBranchIdentification || ''} @input=${this._onInputTaxInvoice} /></td>
549
- </tr>
550
- <tr>
551
- <th required>${i18next.t('field.short tax invoice business name')}</th>
552
- <td><input type="text" name="buyerBusinessName" .value=${this.buyer?.buyerBusinessName || ''} @input=${this._onInputTaxInvoice} /></td>
553
- <th required>${i18next.t('field.tax invoice representative name')}</th>
554
- <td><input type="text" name="buyerRepresentativeName" .value=${this.buyer?.buyerRepresentativeName || ''} @input=${this._onInputTaxInvoice} /></td>
555
- </tr>
556
- <tr>
557
- <th>${i18next.t('field.address')}</th>
558
- <td colspan="3"><input type="text" name="buyerAddress" .value=${this.buyer?.buyerAddress || ''} @input=${this._onInputTaxInvoice} /></td>
559
- </tr>
560
- <tr>
561
- <th>${i18next.t('field.business type')}</th>
562
- <td><input type="text" name="buyerBusinessType" .value=${this.buyer?.buyerBusinessType || ''} @input=${this._onInputTaxInvoice} /></td>
563
-
564
- <th>${i18next.t('field.industry type')}</th>
565
- <td><input type="text" name="buyerIndustryType" .value=${this.buyer?.buyerIndustryType || ''} @input=${this._onInputTaxInvoice} /></td>
566
- </tr>
567
- <tr>
568
- <th>${i18next.t('field.email')}</th>
569
- <td colspan="3"><input type="text" name="buyer1stContactEmail" .value=${this.buyer?.buyer1stContactEmail || ''} @input=${this._onInputTaxInvoice} /></td>
570
- </tr>
571
- <tr>
572
- <th>${i18next.t('field.email')}</th>
573
- <td colspan="3"><input type="text" name="buyer2ndContactEmail" .value=${this.buyer?.buyer2ndContactEmail || ''} @input=${this._onInputTaxInvoice} /></td>
574
- </tr>
575
- </table>
576
- </div>
577
-
578
- <div class="info flex-column">
579
- <div class="flex-row">
580
- <div class="title" required>${i18next.t('field.issue date')}</div>
581
- <div class="value">
582
- <input type="date" name="issueDate" .value=${this.taxInvoice.issueDate} @input=${this._onInputTaxInvoice} />
583
- <span class="desc">※ 작성일자는 공급 연월일을 의미함</span>
584
- </div>
585
- <div class="title">${i18next.t('field.remark0')}</div>
586
- <div class="value"><input type="text" name="remark0" .value=${this.taxInvoice?.remark0 || ''} @input=${this._onInputTaxInvoice} /></div>
587
- </div>
588
- <div class="flex-row">
589
- <div class="title">${i18next.t('field.total amount')}</div>
590
- <div class="value">${this._numberFormat(this.taxInvoice?.totalAmount)}</div>
591
- <div class="title">${i18next.t('field.supply amount')}</div>
592
- <div class="value">${this._numberFormat(this.taxInvoice?.supplyAmount)}</div>
593
- <div class="title">${i18next.t('field.tax amount')}</div>
594
- <div class="value">${this._numberFormat(this.taxInvoice?.taxAmount)}</div>
595
- </div>
596
- </div>
597
-
598
- <div class="items">
599
- <div class="desc desc-date">
600
- ※ 아래 '품목'의 '월'은 상단 '작성일자'의 '월'이 자동 반영됩니다. 합계의 '계산' 버튼은 금액을 공급가액과 세액으로 계산할 수 있습니다.
601
- </div>
602
- <div class="desc"><button class="btn-add" @click=${this._onAddInvoiceItem}>품목추가</button> 품목은 최대 16개까지 추가, 삭제 가능</div>
603
-
604
- <table>
605
- <colgroup>
606
- <col width="5%" />
607
- <col width="5%" />
608
- <col width="14%" />
609
- <col width="7%" />
610
- <col width="7%" />
611
- <col width="12%" />
612
- <col width="12%" />
613
- <col width="12%" />
614
- <col width="16%" />
615
- <col width="8%" />
616
- </colgroup>
617
- <tr>
618
- <th>${i18next.t('field.tax invoice month')}</th>
619
- <th required>${i18next.t('field.tax invoice day')}</th>
620
- <th required>${i18next.t('field.tax invoice item name')}</th>
621
- <th>${i18next.t('field.tax invoice ea')}</th>
622
- <th required>${i18next.t('field.tax invoice quantity')}</th>
623
- <th required>${i18next.t('field.tax invoice price')}</th>
624
- <th>${i18next.t('field.supply amount')}</th>
625
- <th>${i18next.t('field.tax amount')}</th>
626
- <th>${i18next.t('field.remark0')}</th>
627
- <th>${i18next.t('field.delete')}</th>
628
- </tr>
629
-
630
- ${this.taxInvoiceItems.map(
631
- (item, idx) => html`
632
- <tr>
633
- <input type="hidden" name="sequence" value=${item.sequence} />
634
- <td>${this.taxInvoice.issueDate.split('-')[1]}</td>
635
- <td><input type="text" numeric maxlength="2" name="supplyDate" @input=${e => this._onInputItem(e, idx)} /></td>
636
- <td><input type="text" name="itemName" .value=${item.itemName} @input=${e => this._onInputItem(e, idx)} /></td>
637
- <td><input type="text" name="specification" .value=${item.specification} @input=${e => this._onInputItem(e, idx)} /></td>
638
- <td><input type="text" numeric name="quantity" .value=${this._numberFormat(item.quantity)} @input=${e => this._onInputItem(e, idx)} /></td>
639
- <td><input type="text" numeric name="unitPrice" .value=${this._numberFormat(item.unitPrice)} @input=${e => this._onInputItem(e, idx)} /></td>
640
- <td><input type="text" numeric name="supplyPrice" .value=${this._numberFormat(item.supplyPrice)} @input=${e => this._onInputItem(e, idx)} /></td>
641
- <td>
642
- <input
643
- type="text"
644
- numeric
645
- name="taxPrice"
646
- .value=${this._numberFormat(item.taxPrice)}
647
- @input=${e => this._onInputItem(e, idx)}
648
- .disabled=${this.isTaxFree}
649
- />
650
- </td>
651
- <td><input type="text" name="remark" .value=${item.remark || ''} @input=${e => this._onInputItem(e, idx)} /></td>
652
- <td><button class="btn-delete" @click=${e => this._onRemoveInvoiceItem(e, item.sequence)}>삭제</button></td>
653
- </tr>
654
- `
655
- )}
656
- </table>
657
- </div>
658
-
659
- <div class="summary">
660
- <table>
661
- <colgroup>
662
- <col width="25%" />
663
- <col width="25%" />
664
- <col width="25%" />
665
- <col width="25%" />
666
- </colgroup>
667
- <tr>
668
- <th>${i18next.t('field.tax invoice payment cash')}</th>
669
- <th>${i18next.t('field.tax invoice payment check')}</th>
670
- <th>${i18next.t('field.tax invoice payment promissory note')}</th>
671
- <th>${i18next.t('field.tax invoice payment accounts receivable')}</th>
672
- </tr>
673
- <tr>
674
- <td><input type="text" numeric name="paymentAmountCash" .value=${this.taxInvoice?.paymentAmountCash || ''} @input=${this._onInputTaxInvoice} /></td>
675
- <td><input type="text" numeric name="paymentAmountCheck" .value=${this.taxInvoice?.paymentAmountCheck || ''} @input=${this._onInputTaxInvoice} /></td>
676
- <td>
677
- <input
678
- type="text"
679
- numeric
680
- name="paymentAmountPromissoryNote"
681
- .value=${this.taxInvoice?.paymentAmountPromissoryNote || ''}
682
- @input=${this._onInputTaxInvoice}
683
- />
684
- </td>
685
- <td>
686
- <input
687
- type="text"
688
- numeric
689
- name="paymentAmountAccountsReceivable"
690
- .value=${this.taxInvoice?.paymentAmountAccountsReceivable || ''}
691
- @input=${this._onInputTaxInvoice}
692
- />
693
- </td>
694
- </tr>
695
- </table>
696
- <div>
697
- ${i18next.t('text.prev tax invoice description payment') + ' ('}
698
- <span class="type-wrapper">
699
- <div>
700
- <input type="radio" id="purpose_20" name="purpose" .value=${Purpose.INVOICE} @change=${this._onInputTaxInvoice} checked />
701
- <label for="purpose_20">${PURPOSE[Purpose.INVOICE]}</label>
702
- </div>
703
- <div>
704
- <input type="radio" id="purpose_10" name="purpose" .value=${Purpose.RECEIPT} @change=${this._onInputTaxInvoice} />
705
- <label for="purpose_10">${PURPOSE[Purpose.RECEIPT]}</label>
706
- </div>
707
- </span>
708
- ${') ' + i18next.t('text.next tax invoice description payment')}
709
- </div>
710
- </div>
711
- </div>
712
- `
713
- }
714
-
715
- async pageInitialized(lifecycle: any) {
716
- this._fetchSupplier()
717
- }
718
-
719
- async _fetchSupplier() {
720
- const response = await client.query({
721
- query: gql`
722
- query taxInvoiceDefaultCompany {
723
- response: taxInvoiceDefaultCompany {
724
- businessRegistrationNumber
725
- branchIdentification
726
- businessName
727
- representativeName
728
- address
729
- businessType
730
- industryType
731
- department
732
- contactName
733
- contactPhone
734
- contactEmail
735
- contactCellPhone
736
- }
737
- }
738
- `
739
- })
740
-
741
- const supplier = response.data.response
742
- this.supplier = {
743
- supplierBusinessRegistrationCategory: supplier.businessRegistrationCategory,
744
- supplierBusinessRegistrationNumber: supplier.businessRegistrationNumber,
745
- supplierBranchIdentification: supplier.branchIdentification,
746
- supplierBusinessName: supplier.businessName,
747
- supplierRepresentativeName: supplier.representativeName,
748
- supplierAddress: supplier.address,
749
- supplierBusinessType: supplier.businessType,
750
- supplierIndustryType: supplier.industryType,
751
- supplierDepartment: supplier.department,
752
- supplierContactName: supplier.contactName,
753
- supplierContactPhone: supplier.contactPhone,
754
- supplierContactEmail: supplier.contactEmail,
755
- supplierContactCellPhone: supplier.contactCellPhone
756
- }
757
- }
758
-
759
- async pageUpdated(changes: any, lifecycle: any) {
760
- if (this.active) {
761
- // do something here when this page just became as active
762
- }
93
+ return html` <tax-invoice-send></tax-invoice-send> `
763
94
  }
764
95
 
765
96
  async _sendTaxInvoice() {
@@ -825,227 +156,7 @@ export class TaxInvoiceSendPage extends localize(i18next)(ScopedElementsMixin(Pa
825
156
  this.taxInvoice = this.defaultTaxInvoice
826
157
  this.supplier = this.defaultSupplier
827
158
  this.buyer = this.defaultBuyer
828
- this.taxInvoiceItems = []
829
- }
830
- }
831
-
832
- private _numberFormat(value: number): string {
833
- return !value ? '' : new Intl.NumberFormat('en-US').format(value) || ''
834
- }
835
-
836
- // Input 요소의 값이 변경될 때 호출되는 콜백 함수
837
- private _onInputTaxInvoice(event: InputEvent) {
838
- const target = event.target as HTMLInputElement
839
-
840
- // 숫자 타입은 다른 문자 입력 제거
841
- if (target.hasAttribute('numeric')) {
842
- target.value = target.value.replace(/\D/g, '')
159
+ this.taxInvoiceItems = [{ ...this.defaultTaxInvoiceItem }]
843
160
  }
844
-
845
- if (target.name.startsWith('supplier')) {
846
- this.supplier[target.name] = target.value
847
- } else if (target.name.startsWith('buyer')) {
848
- this.buyer[target.name] = target.value
849
- } else {
850
- // 날짜 체크가 오늘 날짜를 넘어가면 값 변경 되면 안됨
851
- if (target.name === 'issueDate' && target.value > this.today) {
852
- target.value = this.taxInvoice['issueDate']
853
- alert('작성일자는 현재일까지 입력하시기 바랍니다.')
854
- return
855
- }
856
-
857
- // 세금이 없는 영세율이 선택 시 모든 아이템의 세금 0원으로 초기화
858
- if (target.name === 'invoiceType' && target.value === InvoiceType.SMALL_BUSINESS_TAX_INVOICE) {
859
- this.isTaxFree = true
860
- this.taxInvoice = { ...this.taxInvoice, taxAmount: 0 }
861
- this.taxInvoiceItems = this.taxInvoiceItems.map(item => ({ ...item, taxPrice: 0 }))
862
- }
863
-
864
- // 변경시에는 아이템 변경도 리 렌더가 필요해서 데이터 갱신
865
- this.taxInvoice[target.name] = target.value
866
- this.taxInvoice = { ...this.taxInvoice }
867
- }
868
- }
869
-
870
- // Input 요소의 값이 변경될 때 호출되는 콜백 함수
871
- private _onInputItem(e: InputEvent, idx: number) {
872
- const target = e.target as HTMLInputElement
873
- let inputVal: any = target.value
874
-
875
- // 숫자 타입은 다른 문자 입력 제거
876
- if (target.hasAttribute('numeric')) {
877
- inputVal = Number(inputVal.replace(/\D/g, ''))
878
- target.value = inputVal
879
- }
880
-
881
- // 공급일자 케이스 시 => 세금계산서의 작성일자의 YYYY-MM + 아이템의 입력된 DD
882
- if (target.name === 'supplyDate') {
883
- const itemDate = this.taxInvoice.issueDate.substring(0, 8) + inputVal.toString().padStart(2, '0')
884
- if (itemDate > this.taxInvoice.issueDate) {
885
- alert('품목의 일자는 작성일자보다 클 수 없습니다.')
886
- target.value = ''
887
- }
888
- inputVal = itemDate
889
- }
890
-
891
- // 수량, 단가 수정시 공급가액/세액 자동 계산
892
- if (target.name == 'quantity' || target.name == 'unitPrice') {
893
- const supplyPrice = target.name == 'quantity' ? Number(inputVal) * this.taxInvoiceItems[idx]['unitPrice'] : Number(inputVal) * this.taxInvoiceItems[idx]['quantity']
894
- this.taxInvoiceItems[idx]['supplyPrice'] = supplyPrice
895
- this.taxInvoiceItems[idx]['taxPrice'] = this.isTaxFree ? 0 : Math.floor(supplyPrice / 10)
896
- }
897
-
898
- // 인풋에 값 넣기
899
- this.taxInvoiceItems[idx][target.name] = inputVal
900
-
901
- // 아이템 금액에 관련된 필드 수정시 합계 계산
902
- if (['quantity', 'unitPrice', 'supplyPrice', 'taxPrice'].includes(target.name)) {
903
- this.taxInvoiceItems = [...this.taxInvoiceItems]
904
- this._setTaxInvoiceSummaryCalc()
905
- }
906
- }
907
-
908
- private async _openSupplierPopup() {
909
- const response = await client.query({
910
- query: gql`
911
- query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
912
- responses: taxInvoiceApis(filters: $filters, pagination: $pagination, sortings: $sortings) {
913
- items {
914
- id
915
- name: provider
916
- businessRegistrationNumber
917
- branchIdentification
918
- businessName
919
- representativeName
920
- address
921
- businessType
922
- industryType
923
- department
924
- contactName
925
- contactPhone
926
- contactEmail
927
- contactCellPhone
928
- }
929
- }
930
- }
931
- `
932
- })
933
-
934
- const items = response.data.responses.items || []
935
- openPopup(
936
- html`
937
- <company-list-popup
938
- .companyList=${items}
939
- @selected=${e => {
940
- this.supplier = {
941
- supplierBusinessRegistrationCategory: BusinessRegistrationCategory.BUSINESS_REGISTRATION_NUMBER,
942
- supplierBusinessRegistrationNumber: e.detail.businessRegistrationNumber || '',
943
- supplierBranchIdentification: e.detail.branchIdentification || '',
944
- supplierBusinessName: e.detail.businessName || '',
945
- supplierRepresentativeName: e.detail.representativeName || '',
946
- supplierAddress: e.detail.address || '',
947
- supplierBusinessType: e.detail.businessType || '',
948
- supplierIndustryType: e.detail.industryType || '',
949
- supplierDepartment: e.detail.department || '',
950
- supplierContactName: e.detail.contactName || '',
951
- supplierContactPhone: e.detail.contactPhone || '',
952
- supplierContactEmail: e.detail.contactEmail || '',
953
- supplierContactCellPhone: e.detail.contactCellPhone || ''
954
- }
955
-
956
- history.back()
957
- }}
958
- >
959
- </company-list-popup>
960
- `,
961
- {
962
- backdrop: true,
963
- size: 'large',
964
- title: i18next.t('title.company list popup')
965
- }
966
- )
967
- }
968
-
969
- private async _openBuyerPopup() {
970
- const response = await client.query({
971
- query: gql`
972
- query TaxInvoiceBuyerList {
973
- responses: taxInvoiceBuyerList {
974
- id
975
- name
976
- businessRegistrationNumber
977
- branchIdentification
978
- businessName
979
- representativeName
980
- address
981
- businessType
982
- industryType
983
- department
984
- contactName
985
- contactPhone
986
- contactEmail
987
- contactCellPhone
988
- }
989
- }
990
- `
991
- })
992
-
993
- const items = response.data.responses || []
994
- openPopup(
995
- html`
996
- <company-list-popup
997
- .companyList=${items}
998
- @selected=${e => {
999
- this.buyer = {
1000
- buyerBusinessRegistrationCategory: BusinessRegistrationCategory.BUSINESS_REGISTRATION_NUMBER,
1001
- buyerBusinessRegistrationNumber: e.detail.businessRegistrationNumber || '',
1002
- buyerBranchIdentification: e.detail.branchIdentification || '',
1003
- buyerBusinessName: e.detail.businessName || '',
1004
- buyerRepresentativeName: e.detail.representativeName || '',
1005
- buyerAddress: e.detail.address || '',
1006
- buyerBusinessType: e.detail.businessType || '',
1007
- buyerIndustryType: e.detail.industryType || '',
1008
- buyer1stDepartment: e.detail.department || '',
1009
- buyer1stContactName: e.detail.contactName || '',
1010
- buyer1stContactPhone: e.detail.contactPhone || '',
1011
- buyer1stContactEmail: e.detail.contactEmail || '',
1012
- buyer1stContactCellPhone: e.detail.contactCellPhone || ''
1013
- }
1014
-
1015
- history.back()
1016
- }}
1017
- >
1018
- </company-list-popup>
1019
- `,
1020
- {
1021
- backdrop: true,
1022
- size: 'large',
1023
- title: i18next.t('title.company list popup')
1024
- }
1025
- )
1026
- }
1027
-
1028
- private _onAddInvoiceItem(e: Event) {
1029
- e.preventDefault()
1030
- if (this.taxInvoiceItems.length >= 16) {
1031
- alert('품목은 최대 16개까지 추가 가능합니다.')
1032
- return
1033
- }
1034
-
1035
- this.taxInvoiceItems = [...this.taxInvoiceItems, { ...this.defaultTaxInvoiceItem, sequence: new Date().getTime() }]
1036
- }
1037
-
1038
- private _onRemoveInvoiceItem(e: Event, sequence: number) {
1039
- e.preventDefault()
1040
- this.taxInvoiceItems = [...this.taxInvoiceItems.filter(item => item.sequence != sequence)]
1041
- this._setTaxInvoiceSummaryCalc()
1042
- }
1043
-
1044
- private _setTaxInvoiceSummaryCalc() {
1045
- const supplyPrice: number = this.taxInvoiceItems.reduce((prev, item) => prev + Number(item.supplyPrice), 0) || 0
1046
- const taxPrice: number = this.isTaxFree ? 0 : this.taxInvoiceItems.reduce((prev, item) => prev + Number(item.taxPrice), 0) || 0
1047
- const totalAmount: number = supplyPrice + taxPrice
1048
-
1049
- this.taxInvoice = { ...this.taxInvoice, supplyAmount: supplyPrice, taxAmount: taxPrice, totalAmount: totalAmount }
1050
161
  }
1051
162
  }