@things-factory/tax-invoice 7.0.0-alpha.1 → 7.0.0-alpha.18

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 (58) hide show
  1. package/client/pages/tax-invoice/tax-invoice-detail-popup.ts +13 -1
  2. package/client/pages/tax-invoice/tax-invoice-list-page.ts +58 -37
  3. package/client/pages/tax-invoice-api/tax-invoice-api-page.ts +47 -110
  4. package/client/pages/tax-invoice-send/tax-invoice-send-page.ts +860 -0
  5. package/client/route.ts +1 -1
  6. package/dist-client/pages/tax-invoice/tax-invoice-detail-popup.js +13 -1
  7. package/dist-client/pages/tax-invoice/tax-invoice-detail-popup.js.map +1 -1
  8. package/dist-client/pages/tax-invoice/tax-invoice-list-page.d.ts +20 -6
  9. package/dist-client/pages/tax-invoice/tax-invoice-list-page.js +56 -35
  10. package/dist-client/pages/tax-invoice/tax-invoice-list-page.js.map +1 -1
  11. package/dist-client/pages/tax-invoice-api/tax-invoice-api-page.d.ts +2 -4
  12. package/dist-client/pages/tax-invoice-api/tax-invoice-api-page.js +47 -101
  13. package/dist-client/pages/tax-invoice-api/tax-invoice-api-page.js.map +1 -1
  14. package/dist-client/pages/tax-invoice-send/tax-invoice-send-page.d.ts +106 -0
  15. package/dist-client/pages/tax-invoice-send/tax-invoice-send-page.js +776 -0
  16. package/dist-client/pages/tax-invoice-send/tax-invoice-send-page.js.map +1 -0
  17. package/dist-client/route.js +1 -1
  18. package/dist-client/route.js.map +1 -1
  19. package/dist-client/tsconfig.tsbuildinfo +1 -1
  20. package/dist-server/service/tax-invoice/tax-invoice-mutation.js +10 -88
  21. package/dist-server/service/tax-invoice/tax-invoice-mutation.js.map +1 -1
  22. package/dist-server/service/tax-invoice/tax-invoice-query.js +23 -0
  23. package/dist-server/service/tax-invoice/tax-invoice-query.js.map +1 -1
  24. package/dist-server/service/tax-invoice/tax-invoice-type.js +14 -3
  25. package/dist-server/service/tax-invoice/tax-invoice-type.js.map +1 -1
  26. package/dist-server/service/tax-invoice/tax-invoice-util.js +93 -0
  27. package/dist-server/service/tax-invoice/tax-invoice-util.js.map +1 -0
  28. package/dist-server/service/tax-invoice/tax-invoice.js +7 -7
  29. package/dist-server/service/tax-invoice/tax-invoice.js.map +1 -1
  30. package/dist-server/service/tax-invoice-api/tax-invoice-api-mutation.js +176 -21
  31. package/dist-server/service/tax-invoice-api/tax-invoice-api-mutation.js.map +1 -1
  32. package/dist-server/service/tax-invoice-api/tax-invoice-api-query.js +4 -25
  33. package/dist-server/service/tax-invoice-api/tax-invoice-api-query.js.map +1 -1
  34. package/dist-server/service/tax-invoice-api/tax-invoice-api-type.js +17 -1
  35. package/dist-server/service/tax-invoice-api/tax-invoice-api-type.js.map +1 -1
  36. package/dist-server/service/tax-invoice-api/tax-invoice-api.js +7 -1
  37. package/dist-server/service/tax-invoice-api/tax-invoice-api.js.map +1 -1
  38. package/dist-server/service/tax-invoice-item/tax-invoice-item-type.js +2 -2
  39. package/dist-server/service/tax-invoice-item/tax-invoice-item-type.js.map +1 -1
  40. package/dist-server/service/unipost-api/tax-invoice-inquiry.js +5 -5
  41. package/dist-server/service/unipost-api/tax-invoice-inquiry.js.map +1 -1
  42. package/dist-server/service/unipost-api/tax-invoice-send.js +34 -0
  43. package/dist-server/service/unipost-api/tax-invoice-send.js.map +1 -0
  44. package/dist-server/tsconfig.tsbuildinfo +1 -1
  45. package/package.json +5 -5
  46. package/server/service/tax-invoice/tax-invoice-mutation.ts +10 -89
  47. package/server/service/tax-invoice/tax-invoice-query.ts +20 -2
  48. package/server/service/tax-invoice/tax-invoice-type.ts +14 -2
  49. package/server/service/tax-invoice/tax-invoice-util.ts +223 -0
  50. package/server/service/tax-invoice/tax-invoice.ts +21 -21
  51. package/server/service/tax-invoice-api/tax-invoice-api-mutation.ts +203 -34
  52. package/server/service/tax-invoice-api/tax-invoice-api-query.ts +4 -21
  53. package/server/service/tax-invoice-api/tax-invoice-api-type.ts +11 -0
  54. package/server/service/tax-invoice-api/tax-invoice-api.ts +7 -15
  55. package/server/service/tax-invoice-item/tax-invoice-item-type.ts +2 -2
  56. package/server/service/unipost-api/tax-invoice-inquiry.ts +5 -5
  57. package/server/service/unipost-api/tax-invoice-send.ts +32 -0
  58. package/translations/ko.json +6 -1
@@ -66,10 +66,15 @@ export class TaxInvoiceDetailPopup extends localize(i18next)(LitElement) {
66
66
  td,
67
67
  th {
68
68
  padding: 5px;
69
+ min-width: 60px;
70
+ }
71
+ td {
72
+ padding-left: 8px;
69
73
  }
70
74
  th.target {
71
75
  width: 25px;
72
76
  writing-mode: vertical-rl;
77
+ min-width: unset;
73
78
  }
74
79
 
75
80
  &.supplier {
@@ -149,7 +154,7 @@ export class TaxInvoiceDetailPopup extends localize(i18next)(LitElement) {
149
154
  <table>
150
155
  <tr>
151
156
  <th>${i18next.t('field.approval no')}</th>
152
- <td>${this.detail?.approvalNo?.replace(/(\d{8})(\d{8})(\d{8})/g, '$1-$2-$3')}</td>
157
+ <td>${this.detail?.approvalNo?.replace(/(\S{8})(\S{8})(\S{8})/g, '$1-$2-$3')}</td>
153
158
  </tr>
154
159
  </table>
155
160
  </div>
@@ -196,6 +201,13 @@ export class TaxInvoiceDetailPopup extends localize(i18next)(LitElement) {
196
201
  </table>
197
202
 
198
203
  <table class="buyer">
204
+ <colgroup>
205
+ <col width="150px" />
206
+ <col width="18%" />
207
+ <col width="32%" />
208
+ <col width="18%" />
209
+ <col width="32%" />
210
+ </colgroup>
199
211
  <tr>
200
212
  <th rowspan="6" class="target">${i18next.t('field.tax invoice buyer')}</th>
201
213
  <th>${i18next.t('field.short business registration number')}</th>
@@ -16,9 +16,9 @@ import gql from 'graphql-tag'
16
16
  import './tax-invoice-detail-popup'
17
17
 
18
18
  export enum Category {
19
- EXPORT = '10', // 매출
20
- IMPORT = '20', // 매입
21
- NTS = '30' // NTS
19
+ EXPORT = '10',
20
+ IMPORT = '20',
21
+ NTS = '30'
22
22
  }
23
23
  export const CATEGORY = {
24
24
  [Category.EXPORT]: '매출',
@@ -44,26 +44,41 @@ export enum InvoiceType {
44
44
  'REVISED_IMPORT_INVOICE' = '0404'
45
45
  }
46
46
  export const INVOICE_TYPE = {
47
- [InvoiceType.TAX_INVOICE]: '일반 세금계산서',
48
- [InvoiceType.SMALL_BUSINESS_TAX_INVOICE]: '영세율 세금계산서',
49
- [InvoiceType.CONSIGNMENT_TAX_INVOICE]: '위수탁 세금계산서',
50
- [InvoiceType.SMALL_BUSINESS_CONSIGNMENT_TAX_INVOICE]: '영세율 위수탁 세금계산서',
51
- [InvoiceType.REVISED_TAX_INVOICE]: '수정 일반 세금계산서',
52
- [InvoiceType.REVISED_SMALL_BUSINESS_TAX_INVOICE]: '수정 영세율 세금계산서',
53
- [InvoiceType.REVISED_CONSIGNMENT_TAX_INVOICE]: '수정 위수탁 세금계산서',
54
- [InvoiceType.REVISED_IMPORT_TAX_INVOICE]: '수정 수입 세금계산서',
55
- [InvoiceType.REVISED_SMALL_BUSINESS_CONSIGNMENT_TAX_INVOICE]: '수정 영세율 위수탁 세금계산서',
56
- [InvoiceType.INVOICE]: '일반 계산서',
57
- [InvoiceType.CONSIGNMENT_INVOICE]: '위수탁 계산서',
58
- [InvoiceType.IMPORT_INVOICE]: '수입 계산서',
59
- [InvoiceType.REVISED_INVOICE]: '수정 일반 계산서',
60
- [InvoiceType.REVISED_CONSIGNMENT_INVOICE]: '수정 위수탁 계산서',
61
- [InvoiceType.REVISED_IMPORT_INVOICE]: '수정 수입 계산서'
47
+ [InvoiceType.TAX_INVOICE]: '일반 전자세금계산서',
48
+ [InvoiceType.SMALL_BUSINESS_TAX_INVOICE]: '영세율 전자세금계산서',
49
+ [InvoiceType.CONSIGNMENT_TAX_INVOICE]: '위수탁 전자세금계산서',
50
+ [InvoiceType.SMALL_BUSINESS_CONSIGNMENT_TAX_INVOICE]: '영세율 위수탁 전자세금계산서',
51
+ [InvoiceType.REVISED_TAX_INVOICE]: '수정 일반 전자세금계산서',
52
+ [InvoiceType.REVISED_SMALL_BUSINESS_TAX_INVOICE]: '수정 영세율 전자세금계산서',
53
+ [InvoiceType.REVISED_CONSIGNMENT_TAX_INVOICE]: '수정 위수탁 전자세금계산서',
54
+ [InvoiceType.REVISED_IMPORT_TAX_INVOICE]: '수정 수입 전자세금계산서',
55
+ [InvoiceType.REVISED_SMALL_BUSINESS_CONSIGNMENT_TAX_INVOICE]: '수정 영세율 위수탁 전자세금계산서',
56
+ [InvoiceType.INVOICE]: '일반 전자계산서',
57
+ [InvoiceType.CONSIGNMENT_INVOICE]: '위수탁 전자계산서',
58
+ [InvoiceType.IMPORT_INVOICE]: '수입 전자계산서',
59
+ [InvoiceType.REVISED_INVOICE]: '수정 일반 전자계산서',
60
+ [InvoiceType.REVISED_CONSIGNMENT_INVOICE]: '수정 위수탁 전자계산서',
61
+ [InvoiceType.REVISED_IMPORT_INVOICE]: '수정 수입 전자계산서'
62
62
  }
63
63
 
64
+ export enum Purpose {
65
+ RECEIPT = '01',
66
+ INVOICE = '02'
67
+ }
64
68
  export const PURPOSE = {
65
- '01': '영수',
66
- '02': '청구'
69
+ [Purpose.RECEIPT]: '영수',
70
+ [Purpose.INVOICE]: '청구'
71
+ }
72
+
73
+ export enum BusinessRegistrationCategory {
74
+ BUSINESS_REGISTRATION_NUMBER = '01', // 사업자등록번호
75
+ RESIDENT_REGISTRATION_NUMBER = '02', // 주민등록번호
76
+ FOREIGNER_REGISTRATION_NUMBER = '03' // 외국인등록번호
77
+ }
78
+ export const BUSINESS_REGISTRATION_CATEGORY = {
79
+ [BusinessRegistrationCategory.BUSINESS_REGISTRATION_NUMBER]: '사업자등록번호',
80
+ [BusinessRegistrationCategory.RESIDENT_REGISTRATION_NUMBER]: '주민등록번호',
81
+ [BusinessRegistrationCategory.FOREIGNER_REGISTRATION_NUMBER]: '외국인'
67
82
  }
68
83
 
69
84
  @customElement('tax-invoice-list-page')
@@ -97,6 +112,7 @@ export class TaxInvoiceListPage extends localize(i18next)(ScopedElementsMixin(Pa
97
112
  align-items: center;
98
113
  justify-content: center;
99
114
  height: 35px;
115
+ font-weight: bold;
100
116
  }
101
117
  span.value {
102
118
  padding-left: 10px;
@@ -109,7 +125,7 @@ export class TaxInvoiceListPage extends localize(i18next)(ScopedElementsMixin(Pa
109
125
  ]
110
126
 
111
127
  @property({ type: Object }) gristConfig: any
112
- @state() summary: { count: number; total: number; supply: number; tax: number } | null = null
128
+ @state() summary: { cnt: number; total_amount: number; supply_amount: number; tax_amount: number } | null = null
113
129
 
114
130
  @query('ox-grist') private grist!: DataGrist
115
131
 
@@ -134,17 +150,18 @@ export class TaxInvoiceListPage extends localize(i18next)(ScopedElementsMixin(Pa
134
150
 
135
151
  render() {
136
152
  const mode = 'GRID'
153
+ const summary = this.summary
137
154
 
138
155
  return html`
139
156
  <div class="summary">
140
157
  <span class="title">${i18next.t('field.summary total count')}</span>
141
- <span class="value">${this._numberFormat(this.summary?.count)}</span>
158
+ <span class="value">${this._numberFormat(summary?.cnt)}</span>
142
159
  <span class="title">${i18next.t('field.summary total amount')}</span>
143
- <span class="value">${this._numberFormat(this.summary?.total)}</span>
160
+ <span class="value">${this._numberFormat(summary?.total_amount)}</span>
144
161
  <span class="title">${i18next.t('field.summary supply amount')}</span>
145
- <span class="value">${this._numberFormat(this.summary?.supply)}</span>
162
+ <span class="value">${this._numberFormat(summary?.supply_amount)}</span>
146
163
  <span class="title">${i18next.t('field.summary tax amount')}</span>
147
- <span class="value">${this._numberFormat(this.summary?.tax)}</span>
164
+ <span class="value">${this._numberFormat(summary?.tax_amount)}</span>
148
165
  </div>
149
166
 
150
167
  <ox-grist .mode=${mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)}>
@@ -199,6 +216,10 @@ export class TaxInvoiceListPage extends localize(i18next)(ScopedElementsMixin(Pa
199
216
  type: 'select',
200
217
  value: Category.EXPORT,
201
218
  options: () => [
219
+ {
220
+ display: '전체',
221
+ value: ''
222
+ },
202
223
  {
203
224
  display: '매출',
204
225
  value: Category.EXPORT
@@ -297,7 +318,7 @@ export class TaxInvoiceListPage extends localize(i18next)(ScopedElementsMixin(Pa
297
318
  header: i18next.t('field.approval no'),
298
319
  record: {
299
320
  align: 'center',
300
- renderer: value => value.replace(/(\d{8})(\d{8})(\d{8})/g, '$1-$2-$3')
321
+ renderer: value => value.replace(/(\S{8})(\S{8})(\S{8})/g, '$1-$2-$3')
301
322
  },
302
323
  width: 200
303
324
  },
@@ -381,8 +402,8 @@ export class TaxInvoiceListPage extends localize(i18next)(ScopedElementsMixin(Pa
381
402
  async fetchHandler({ page = 1, limit = 100, sortings = [], filters = [] }: FetchOption) {
382
403
  const response = await client.query({
383
404
  query: gql`
384
- query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
385
- responses: taxInvoices(filters: $filters, pagination: $pagination, sortings: $sortings) {
405
+ query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!], $summaryFilters: [Filter!]) {
406
+ taxInvoices(filters: $filters, pagination: $pagination, sortings: $sortings) {
386
407
  items {
387
408
  id
388
409
  memo
@@ -410,25 +431,25 @@ export class TaxInvoiceListPage extends localize(i18next)(ScopedElementsMixin(Pa
410
431
  }
411
432
  total
412
433
  }
434
+ taxInvoicesSummary(filters: $summaryFilters) {
435
+ summary
436
+ }
413
437
  }
414
438
  `,
415
439
  variables: {
416
440
  filters,
417
441
  pagination: { page, limit },
418
- sortings
442
+ sortings,
443
+ summaryFilters: filters
419
444
  }
420
445
  })
421
446
 
422
- this.summary = {
423
- count: response.data.responses.total || 0,
424
- supply: response.data.responses.total || 0,
425
- tax: response.data.responses.total || 0,
426
- total: response.data.responses.total || 0
427
- }
447
+ // 합계 필드 갱신
448
+ this.summary = response.data.taxInvoicesSummary.summary
428
449
 
429
450
  return {
430
- total: response.data.responses.total || 0,
431
- records: response.data.responses.items || []
451
+ total: response.data.taxInvoices.total || 0,
452
+ records: response.data.taxInvoices.items || []
432
453
  }
433
454
  }
434
455
 
@@ -9,7 +9,6 @@ import { DataGrist, FetchOption } from '@operato/data-grist'
9
9
  import { client } from '@operato/graphql'
10
10
  import { i18next, localize } from '@operato/i18n'
11
11
  import { notify } from '@operato/layout'
12
- import { OxPrompt } from '@operato/popup'
13
12
  import { isMobileDevice } from '@operato/utils'
14
13
  import gql from 'graphql-tag'
15
14
 
@@ -27,6 +26,10 @@ export class TaxInvoiceApiPage extends localize(i18next)(ScopedElementsMixin(Pag
27
26
  --grid-record-emphasized-background-color: red;
28
27
  --grid-record-emphasized-color: yellow;
29
28
  }
29
+
30
+ ox-grist {
31
+ margin-top: 15px;
32
+ }
30
33
  `
31
34
  ]
32
35
 
@@ -44,11 +47,6 @@ export class TaxInvoiceApiPage extends localize(i18next)(ScopedElementsMixin(Pag
44
47
  title: i18next.t('button.save'),
45
48
  action: this._updateTaxInvoiceApi.bind(this),
46
49
  ...CommonButtonStyles.save
47
- },
48
- {
49
- title: i18next.t('button.delete'),
50
- action: this._deleteTaxInvoiceApi.bind(this),
51
- ...CommonButtonStyles.delete
52
50
  }
53
51
  ]
54
52
  }
@@ -57,15 +55,7 @@ export class TaxInvoiceApiPage extends localize(i18next)(ScopedElementsMixin(Pag
57
55
  render() {
58
56
  const mode = this.mode || (isMobileDevice() ? 'CARD' : 'GRID')
59
57
 
60
- return html`
61
- <ox-grist .mode=${mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)}>
62
- <div slot="headroom">
63
- <div id="filters">
64
- <ox-filters-form autofocus></ox-filters-form>
65
- </div>
66
- </div>
67
- </ox-grist>
68
- `
58
+ return html` <ox-grist .mode=${mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)}> </ox-grist> `
69
59
  }
70
60
 
71
61
  async pageInitialized(lifecycle: any) {
@@ -85,7 +75,6 @@ export class TaxInvoiceApiPage extends localize(i18next)(ScopedElementsMixin(Pag
85
75
  editable: true,
86
76
  classifier: () => ({ emphasized: ['#D1E8FF', '#000'] })
87
77
  },
88
- filter: 'search',
89
78
  sortable: true,
90
79
  width: 150
91
80
  },
@@ -271,126 +260,74 @@ export class TaxInvoiceApiPage extends localize(i18next)(ScopedElementsMixin(Pag
271
260
  rows: {
272
261
  selectable: {
273
262
  multiple: true
274
- }
275
- },
276
- sorters: [
277
- {
278
- name: 'name'
279
- }
280
- ]
281
- }
282
- }
283
-
284
- async pageUpdated(changes: any, lifecycle: any) {
285
- if (this.active) {
286
- this.grist.fetch()
263
+ },
264
+ appendable: false
265
+ }
287
266
  }
288
267
  }
289
268
 
290
269
  async fetchHandler({ page = 1, limit = 100, sortings = [], filters = [] }: FetchOption) {
291
270
  const response = await client.query({
292
271
  query: gql`
293
- query ($filters: [Filter!], $pagination: Pagination, $sortings: [Sorting!]) {
294
- responses: taxInvoiceApis(filters: $filters, pagination: $pagination, sortings: $sortings) {
295
- items {
272
+ query TaxInvoiceApi {
273
+ response: taxInvoiceApi {
274
+ id
275
+ name
276
+ description
277
+ apiKey
278
+ apiAccountId
279
+ apiAccountPassword
280
+ businessRegistrationNumber
281
+ branchIdentification
282
+ businessName
283
+ representativeName
284
+ address
285
+ businessType
286
+ industryType
287
+ department
288
+ contactName
289
+ contactPhone
290
+ contactEmail
291
+ contactCellPhone
292
+ attributes
293
+ updater {
296
294
  id
297
295
  name
298
- description
299
- apiKey
300
- apiAccountId
301
- apiAccountPassword
302
- businessRegistrationNumber
303
- branchIdentification
304
- businessName
305
- representativeName
306
- address
307
- businessType
308
- industryType
309
- department
310
- contactName
311
- contactPhone
312
- contactEmail
313
- contactCellPhone
314
- attributes
315
- updater {
316
- id
317
- name
318
- }
319
- updatedAt
320
296
  }
321
- total
297
+ updatedAt
322
298
  }
323
299
  }
324
- `,
325
- variables: {
326
- filters,
327
- pagination: { page, limit },
328
- sortings
329
- }
300
+ `
330
301
  })
331
302
 
332
- return {
333
- total: response.data.responses.total || 0,
334
- records: response.data.responses.items || []
335
- }
336
- }
337
-
338
- async _deleteTaxInvoiceApi() {
339
- if (
340
- await OxPrompt.open({
341
- title: i18next.t('text.are_you_sure'),
342
- text: i18next.t('text.sure_to_x', { x: i18next.t('text.delete') }),
343
- confirmButton: { text: i18next.t('button.confirm') },
344
- cancelButton: { text: i18next.t('button.cancel') }
345
- })
346
- ) {
347
- const ids = this.grist.selected.map(record => record.id)
348
- if (ids && ids.length > 0) {
349
- const response = await client.mutate({
350
- mutation: gql`
351
- mutation ($ids: [String!]!) {
352
- deleteTaxInvoiceApis(ids: $ids)
353
- }
354
- `,
355
- variables: {
356
- ids
357
- }
358
- })
303
+ const records = response.data.response ? [response.data.response] : [{}]
359
304
 
360
- if (!response.errors) {
361
- this.grist.fetch()
362
- notify({
363
- message: i18next.t('text.info_x_successfully', { x: i18next.t('text.delete') })
364
- })
365
- }
366
- }
305
+ return {
306
+ total: 1,
307
+ records: records
367
308
  }
368
309
  }
369
310
 
370
311
  async _updateTaxInvoiceApi() {
371
- let patches = this.grist.dirtyRecords
372
- if (patches && patches.length) {
373
- patches = patches.map(patch => {
374
- let patchField: any = patch.id ? { id: patch.id } : {}
375
- const dirtyFields = patch.__dirtyfields__
376
- for (let key in dirtyFields) {
377
- patchField[key] = key === 'type' ? Number(dirtyFields[key].after) : dirtyFields[key].after
378
- }
379
- patchField.cuFlag = patch.__dirty__
380
-
381
- return patchField
382
- })
312
+ let patch = this.grist.dirtyRecords[0]
313
+ if (patch) {
314
+ let patchField: any = patch.id ? { id: patch.id } : {}
315
+ const dirtyFields = patch.__dirtyfields__
316
+ for (let key in dirtyFields) {
317
+ patchField[key] = key === 'type' ? Number(dirtyFields[key].after) : dirtyFields[key].after
318
+ }
319
+ patchField.cuFlag = patch.id ? 'M' : '+'
383
320
 
384
321
  const response = await client.mutate({
385
322
  mutation: gql`
386
- mutation ($patches: [TaxInvoiceApiPatch!]!) {
387
- updateMultipleTaxInvoiceApis(patches: $patches) {
323
+ mutation ($patch: TaxInvoiceApiPatch!) {
324
+ updateMultipleTaxInvoiceApi(patch: $patch) {
388
325
  name
389
326
  }
390
327
  }
391
328
  `,
392
329
  variables: {
393
- patches
330
+ patch: patchField
394
331
  }
395
332
  })
396
333