@dssp/dkpi 1.0.0-alpha.81 → 1.0.0-alpha.84

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 (40) hide show
  1. package/dist-client/components/kpi-lookup-chart.js +45 -12
  2. package/dist-client/components/kpi-lookup-chart.js.map +1 -1
  3. package/dist-client/entries/auth/checkin.js +7 -2
  4. package/dist-client/entries/auth/checkin.js.map +1 -1
  5. package/dist-client/pages/kpi-admin/kpi-system-guide.d.ts +1 -1
  6. package/dist-client/pages/kpi-admin/kpi-system-guide.js +29 -21
  7. package/dist-client/pages/kpi-admin/kpi-system-guide.js.map +1 -1
  8. package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.js +1 -1
  9. package/dist-client/pages/kpi-dashboard/kpi-dashboard-map.js.map +1 -1
  10. package/dist-client/pages/project-complete-tabs/pc-tab1-plan.d.ts +5 -0
  11. package/dist-client/pages/project-complete-tabs/pc-tab1-plan.js +38 -20
  12. package/dist-client/pages/project-complete-tabs/pc-tab1-plan.js.map +1 -1
  13. package/dist-client/pages/sv-project-completed-list.js +3 -3
  14. package/dist-client/pages/sv-project-completed-list.js.map +1 -1
  15. package/dist-client/pages/sv-project-detail.js +22 -16
  16. package/dist-client/pages/sv-project-detail.js.map +1 -1
  17. package/dist-client/pages/sv-project-list.d.ts +1 -0
  18. package/dist-client/pages/sv-project-list.js +3 -3
  19. package/dist-client/pages/sv-project-list.js.map +1 -1
  20. package/dist-client/pages/sv-project-update.d.ts +5 -0
  21. package/dist-client/pages/sv-project-update.js +81 -261
  22. package/dist-client/pages/sv-project-update.js.map +1 -1
  23. package/dist-client/route.d.ts +1 -1
  24. package/dist-client/shared/complete-api.js +4 -1
  25. package/dist-client/shared/complete-api.js.map +1 -1
  26. package/dist-client/shared/geo-group-mapping.d.ts +25 -0
  27. package/dist-client/shared/geo-group-mapping.js +189 -0
  28. package/dist-client/shared/geo-group-mapping.js.map +1 -0
  29. package/dist-client/tsconfig.tsbuildinfo +1 -1
  30. package/dist-client/viewparts/menu-tools.js +39 -37
  31. package/dist-client/viewparts/menu-tools.js.map +1 -1
  32. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js +22 -11
  33. package/dist-server/service/kpi-metric-value/kpi-metric-value-mutation.js.map +1 -1
  34. package/dist-server/service/kpi-metric-value/kpi-metric-value-query.d.ts +5 -0
  35. package/dist-server/service/kpi-metric-value/kpi-metric-value-query.js +7 -10
  36. package/dist-server/service/kpi-metric-value/kpi-metric-value-query.js.map +1 -1
  37. package/dist-server/service/kpi-value/kpi-value-query.js +16 -3
  38. package/dist-server/service/kpi-value/kpi-value-query.js.map +1 -1
  39. package/dist-server/tsconfig.tsbuildinfo +1 -1
  40. package/package.json +5 -5
@@ -10,10 +10,11 @@ import { client } from '@operato/graphql';
10
10
  import { notify } from '@operato/layout';
11
11
  import { OxPrompt } from '@operato/popup';
12
12
  import gql from 'graphql-tag';
13
- import { SITE_TYPE_DISPLAY } from '@dssp/project/dist-client/pages/project/project-list';
13
+ import { SiteType } from '@dssp/project/dist-client/pages/project/project-list';
14
14
  import '@dssp/project/dist-client/pages/lib/select2-component';
15
15
  import './component/project-update-header';
16
16
  import { isProjectTypeDomain, tenantHeaders } from '@dssp/project/dist-client/shared/domain-context';
17
+ import { inferGeoGroupFromPostalCode } from '../shared/geo-group-mapping';
17
18
  let SvProjectUpdate = class SvProjectUpdate extends ScopedElementsMixin(PageView) {
18
19
  constructor() {
19
20
  super(...arguments);
@@ -81,7 +82,7 @@ let SvProjectUpdate = class SvProjectUpdate extends ScopedElementsMixin(PageView
81
82
  };
82
83
  }
83
84
  render() {
84
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25;
85
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z;
85
86
  return html `
86
87
  <dkpi-project-update-header
87
88
  .projectId=${this.project.id || ''}
@@ -106,25 +107,6 @@ let SvProjectUpdate = class SvProjectUpdate extends ScopedElementsMixin(PageView
106
107
  ></md-outlined-text-field>
107
108
  </span>
108
109
  </div>
109
- <div row>
110
- <span>프로젝트 문서 네이밍</span>
111
- <span>
112
- <md-outlined-text-field
113
- type="text"
114
- name="documentNaming"
115
- project
116
- .value=${this.project.documentNaming || ''}
117
- @input=${this._onInputChange}
118
- placeholder="프로젝트 문서 네이밍"
119
- ></md-outlined-text-field>
120
- </span>
121
- </div>
122
- <div row>
123
- <span></span>
124
- <span>
125
- <div document-preview>📄 문서 생성 예시: <br />${this.project.documentNaming} 검측 제01-00001호</div>
126
- </span>
127
- </div>
128
110
  <div row>
129
111
  <span>프로젝트 주소</span>
130
112
  <span class="address-row">
@@ -146,28 +128,14 @@ let SvProjectUpdate = class SvProjectUpdate extends ScopedElementsMixin(PageView
146
128
  </span>
147
129
  </div>
148
130
  <div row>
149
- <span>위도</span>
150
- <span>
151
- <md-outlined-text-field
152
- type="text"
153
- name="latitude"
154
- numeric
155
- building-complex
156
- .value=${((_e = (_d = (_c = this.project) === null || _c === void 0 ? void 0 : _c.buildingComplex) === null || _d === void 0 ? void 0 : _d.latitude) === null || _e === void 0 ? void 0 : _e.toString()) || ''}
157
- @input=${this._onInputChange}
158
- ></md-outlined-text-field>
159
- </span>
160
- </div>
161
- <div row>
162
- <span>경도</span>
131
+ <span>우편번호</span>
163
132
  <span>
164
133
  <md-outlined-text-field
165
134
  type="text"
166
- name="longitude"
167
- numeric
168
- building-complex
169
- .value=${((_h = (_g = (_f = this.project) === null || _f === void 0 ? void 0 : _f.buildingComplex) === null || _g === void 0 ? void 0 : _g.longitude) === null || _h === void 0 ? void 0 : _h.toString()) || ''}
170
- @input=${this._onInputChange}
135
+ name="postalCode"
136
+ project
137
+ .value=${this.project.postalCode || ''}
138
+ @input=${this._onPostalCodeChange}
171
139
  ></md-outlined-text-field>
172
140
  </span>
173
141
  </div>
@@ -179,27 +147,13 @@ let SvProjectUpdate = class SvProjectUpdate extends ScopedElementsMixin(PageView
179
147
  name="area"
180
148
  numeric
181
149
  building-complex
182
- .value=${((_l = (_k = (_j = this.project) === null || _j === void 0 ? void 0 : _j.buildingComplex) === null || _k === void 0 ? void 0 : _k.area) === null || _l === void 0 ? void 0 : _l.toString()) || ''}
150
+ .value=${((_e = (_d = (_c = this.project) === null || _c === void 0 ? void 0 : _c.buildingComplex) === null || _d === void 0 ? void 0 : _d.area) === null || _e === void 0 ? void 0 : _e.toString()) || ''}
183
151
  @input=${this._onInputChange}
184
152
  suffix-text="㎡"
185
153
  ></md-outlined-text-field>
186
154
  </span>
187
155
  </div>
188
156
 
189
- <div row>
190
- <span>건폐율</span>
191
- <span align-end>
192
- <md-outlined-text-field
193
- type="text"
194
- name="coverageRatio"
195
- numeric
196
- building-complex
197
- .value=${((_p = (_o = (_m = this.project) === null || _m === void 0 ? void 0 : _m.buildingComplex) === null || _o === void 0 ? void 0 : _o.coverageRatio) === null || _p === void 0 ? void 0 : _p.toString()) || ''}
198
- @input=${this._onInputChange}
199
- suffix-text="%"
200
- ></md-outlined-text-field>
201
- </span>
202
- </div>
203
157
  <div row>
204
158
  <span>용적률</span>
205
159
  <span align-end>
@@ -208,29 +162,13 @@ let SvProjectUpdate = class SvProjectUpdate extends ScopedElementsMixin(PageView
208
162
  name="floorAreaRatio"
209
163
  numeric
210
164
  building-complex
211
- .value=${((_s = (_r = (_q = this.project) === null || _q === void 0 ? void 0 : _q.buildingComplex) === null || _r === void 0 ? void 0 : _r.floorAreaRatio) === null || _s === void 0 ? void 0 : _s.toString()) || ''}
165
+ .value=${((_h = (_g = (_f = this.project) === null || _f === void 0 ? void 0 : _f.buildingComplex) === null || _g === void 0 ? void 0 : _g.floorAreaRatio) === null || _h === void 0 ? void 0 : _h.toString()) || ''}
212
166
  @input=${this._onInputChange}
213
167
  suffix-text="%"
214
168
  ></md-outlined-text-field>
215
169
  </span>
216
170
  </div>
217
171
 
218
- <div row>
219
- <span>현장유형</span>
220
- <span
221
- ><md-filled-select name="siteType" building-complex @change=${this._onInputChange}>
222
- ${Object.entries(SITE_TYPE_DISPLAY).map(([key, display]) => {
223
- var _a, _b;
224
- return html `
225
- <md-select-option ?selected=${((_b = (_a = this.project) === null || _a === void 0 ? void 0 : _a.buildingComplex) === null || _b === void 0 ? void 0 : _b.siteType) === key} .value=${key}>
226
- <div slot="headline">${display}</div>
227
- </md-select-option>
228
- `;
229
- })}
230
- </md-filled-select>
231
- </span>
232
- </div>
233
-
234
172
  <div row>
235
173
  <span>착공일정 ~ 준공일정</span>
236
174
  <span
@@ -253,74 +191,90 @@ let SvProjectUpdate = class SvProjectUpdate extends ScopedElementsMixin(PageView
253
191
  />
254
192
  </span>
255
193
  </div>
194
+
256
195
  <div row>
257
- <span>발주처</span>
196
+ <span>유형</span>
258
197
  <span
259
- ><md-outlined-text-field
260
- type="text"
261
- name="clientCompany"
262
- building-complex
263
- .value=${((_u = (_t = this.project) === null || _t === void 0 ? void 0 : _t.buildingComplex) === null || _u === void 0 ? void 0 : _u.clientCompany) || ''}
264
- @input=${this._onInputChange}
265
- ></md-outlined-text-field>
198
+ ><md-filled-select name="sectorType" project @change=${this._onInputChange}>
199
+ <md-select-option ?selected=${!this.project.sectorType} value="">
200
+ <div slot="headline">선택</div>
201
+ </md-select-option>
202
+ <md-select-option ?selected=${this.project.sectorType === 'PUBLIC'} value="PUBLIC">
203
+ <div slot="headline">공공</div>
204
+ </md-select-option>
205
+ <md-select-option ?selected=${this.project.sectorType === 'PRIVATE'} value="PRIVATE">
206
+ <div slot="headline">민간</div>
207
+ </md-select-option>
208
+ </md-filled-select>
266
209
  </span>
267
210
  </div>
268
211
  <div row>
269
- <span>건설사</span>
212
+ <span>용도</span>
270
213
  <span
271
- ><md-outlined-text-field
272
- type="text"
273
- name="constructionCompany"
274
- building-complex
275
- .value=${((_w = (_v = this.project) === null || _v === void 0 ? void 0 : _v.buildingComplex) === null || _w === void 0 ? void 0 : _w.constructionCompany) || ''}
276
- @input=${this._onInputChange}
277
- ></md-outlined-text-field>
214
+ ><md-filled-select name="buildingUsage" project @change=${this._onInputChange}>
215
+ <md-select-option ?selected=${!this.project.buildingUsage} value="">
216
+ <div slot="headline">선택</div>
217
+ </md-select-option>
218
+ <md-select-option
219
+ ?selected=${this.project.buildingUsage === 'RESIDENTIAL'}
220
+ value="RESIDENTIAL"
221
+ >
222
+ <div slot="headline">주거</div>
223
+ </md-select-option>
224
+ <md-select-option
225
+ ?selected=${this.project.buildingUsage === 'NON_RESIDENTIAL'}
226
+ value="NON_RESIDENTIAL"
227
+ >
228
+ <div slot="headline">비주거</div>
229
+ </md-select-option>
230
+ </md-filled-select>
278
231
  </span>
279
232
  </div>
233
+
280
234
  <div row>
281
- <span>설계사</span>
235
+ <span>발주처</span>
282
236
  <span
283
237
  ><md-outlined-text-field
284
238
  type="text"
285
- name="designCompany"
239
+ name="clientCompany"
286
240
  building-complex
287
- .value=${((_y = (_x = this.project) === null || _x === void 0 ? void 0 : _x.buildingComplex) === null || _y === void 0 ? void 0 : _y.designCompany) || ''}
241
+ .value=${((_k = (_j = this.project) === null || _j === void 0 ? void 0 : _j.buildingComplex) === null || _k === void 0 ? void 0 : _k.clientCompany) || ''}
288
242
  @input=${this._onInputChange}
289
243
  ></md-outlined-text-field>
290
244
  </span>
291
245
  </div>
292
246
  <div row>
293
- <span>감리사</span>
247
+ <span>건설사</span>
294
248
  <span
295
249
  ><md-outlined-text-field
296
250
  type="text"
297
- name="supervisoryCompany"
251
+ name="constructionCompany"
298
252
  building-complex
299
- .value=${((_0 = (_z = this.project) === null || _z === void 0 ? void 0 : _z.buildingComplex) === null || _0 === void 0 ? void 0 : _0.supervisoryCompany) || ''}
253
+ .value=${((_m = (_l = this.project) === null || _l === void 0 ? void 0 : _l.buildingComplex) === null || _m === void 0 ? void 0 : _m.constructionCompany) || ''}
300
254
  @input=${this._onInputChange}
301
255
  ></md-outlined-text-field>
302
256
  </span>
303
257
  </div>
304
258
  <div row>
305
- <span>건설구분</span>
259
+ <span>설계사</span>
306
260
  <span
307
261
  ><md-outlined-text-field
308
262
  type="text"
309
- name="constructionType"
263
+ name="designCompany"
310
264
  building-complex
311
- .value=${((_2 = (_1 = this.project) === null || _1 === void 0 ? void 0 : _1.buildingComplex) === null || _2 === void 0 ? void 0 : _2.constructionType) || ''}
265
+ .value=${((_p = (_o = this.project) === null || _o === void 0 ? void 0 : _o.buildingComplex) === null || _p === void 0 ? void 0 : _p.designCompany) || ''}
312
266
  @input=${this._onInputChange}
313
267
  ></md-outlined-text-field>
314
268
  </span>
315
269
  </div>
316
270
  <div row>
317
- <span>구조 유형</span>
271
+ <span>감리사</span>
318
272
  <span
319
273
  ><md-outlined-text-field
320
274
  type="text"
321
- name="structureType"
275
+ name="supervisoryCompany"
322
276
  building-complex
323
- .value=${((_4 = (_3 = this.project) === null || _3 === void 0 ? void 0 : _3.buildingComplex) === null || _4 === void 0 ? void 0 : _4.structureType) || ''}
277
+ .value=${((_r = (_q = this.project) === null || _q === void 0 ? void 0 : _q.buildingComplex) === null || _r === void 0 ? void 0 : _r.supervisoryCompany) || ''}
324
278
  @input=${this._onInputChange}
325
279
  ></md-outlined-text-field>
326
280
  </span>
@@ -331,7 +285,7 @@ let SvProjectUpdate = class SvProjectUpdate extends ScopedElementsMixin(PageView
331
285
  <span>
332
286
  <ox-input-image
333
287
  name="mainPhoto"
334
- value=${((_6 = (_5 = this.project) === null || _5 === void 0 ? void 0 : _5.mainPhoto) === null || _6 === void 0 ? void 0 : _6.fullpath) || ''}
288
+ value=${((_t = (_s = this.project) === null || _s === void 0 ? void 0 : _s.mainPhoto) === null || _t === void 0 ? void 0 : _t.fullpath) || ''}
335
289
  @change=${this.onCreateAttachment.bind(this)}
336
290
  ></ox-input-image>
337
291
  </span>
@@ -344,7 +298,7 @@ let SvProjectUpdate = class SvProjectUpdate extends ScopedElementsMixin(PageView
344
298
  name="constructionCost"
345
299
  numeric
346
300
  building-complex
347
- .value=${((_9 = (_8 = (_7 = this.project) === null || _7 === void 0 ? void 0 : _7.buildingComplex) === null || _8 === void 0 ? void 0 : _8.constructionCost) === null || _9 === void 0 ? void 0 : _9.toString()) || ''}
301
+ .value=${((_w = (_v = (_u = this.project) === null || _u === void 0 ? void 0 : _u.buildingComplex) === null || _v === void 0 ? void 0 : _v.constructionCost) === null || _w === void 0 ? void 0 : _w.toString()) || ''}
348
302
  @input=${this._onInputChange}
349
303
  suffix-text="억원"
350
304
  ></md-outlined-text-field>
@@ -358,7 +312,7 @@ let SvProjectUpdate = class SvProjectUpdate extends ScopedElementsMixin(PageView
358
312
  name="workerCount"
359
313
  numeric
360
314
  building-complex
361
- .value=${((_12 = (_11 = (_10 = this.project) === null || _10 === void 0 ? void 0 : _10.buildingComplex) === null || _11 === void 0 ? void 0 : _11.workerCount) === null || _12 === void 0 ? void 0 : _12.toString()) || ''}
315
+ .value=${((_z = (_y = (_x = this.project) === null || _x === void 0 ? void 0 : _x.buildingComplex) === null || _y === void 0 ? void 0 : _y.workerCount) === null || _z === void 0 ? void 0 : _z.toString()) || ''}
362
316
  @input=${this._onInputChange}
363
317
  suffix-text="명"
364
318
  ></md-outlined-text-field>
@@ -405,164 +359,6 @@ let SvProjectUpdate = class SvProjectUpdate extends ScopedElementsMixin(PageView
405
359
  </div>
406
360
  </div>
407
361
 
408
- <div project>
409
- <h3>프로젝트 현황</h3>
410
- <div row separate-container>
411
- <div>
412
- <span>전체 진행현황</span>
413
- <span>
414
- <md-outlined-text-field
415
- type="text"
416
- numeric
417
- project
418
- name="totalProgress"
419
- .value=${((_13 = this.project.totalProgress) === null || _13 === void 0 ? void 0 : _13.toString()) || ''}
420
- @input=${this._onInputChange}
421
- suffix-text="%"
422
- ></md-outlined-text-field>
423
- </span>
424
- </div>
425
- <div>
426
- <span>검측/통과비율</span>
427
- <span>
428
- <md-outlined-text-field
429
- type="text"
430
- numeric
431
- project
432
- name="inspPassRate"
433
- .value=${((_14 = this.project.inspPassRate) === null || _14 === void 0 ? void 0 : _14.toString()) || ''}
434
- @input=${this._onInputChange}
435
- suffix-text="%"
436
- ></md-outlined-text-field>
437
- </span>
438
- </div>
439
- </div>
440
- <div row separate-container>
441
- <div>
442
- <span>주간 진행현황</span>
443
- <span>
444
- <md-outlined-text-field
445
- type="text"
446
- numeric
447
- project
448
- name="weeklyProgress"
449
- .value=${((_15 = this.project.weeklyProgress) === null || _15 === void 0 ? void 0 : _15.toString()) || ''}
450
- @input=${this._onInputChange}
451
- suffix-text="%"
452
- ></md-outlined-text-field>
453
- </span>
454
- </div>
455
- <div>
456
- <span>로봇작업진행율</span>
457
- <span>
458
- <md-outlined-text-field
459
- type="text"
460
- numeric
461
- project
462
- name="robotProgressRate"
463
- .value=${((_16 = this.project.robotProgressRate) === null || _16 === void 0 ? void 0 : _16.toString()) || ''}
464
- @input=${this._onInputChange}
465
- suffix-text="%"
466
- ></md-outlined-text-field>
467
- </span>
468
- </div>
469
- </div>
470
- <div row separate-container>
471
- <div>
472
- <span>KPI</span>
473
- <span
474
- ><md-outlined-text-field
475
- type="text"
476
- numeric
477
- project
478
- name="kpi"
479
- .value=${((_17 = this.project.kpi) === null || _17 === void 0 ? void 0 : _17.toString()) || ''}
480
- @input=${this._onInputChange}
481
- suffix-text="%"
482
- ></md-outlined-text-field>
483
- </span>
484
- </div>
485
- <div>
486
- <span>구조안전도</span>
487
- <span
488
- ><md-outlined-text-field
489
- type="text"
490
- numeric
491
- project
492
- name="structuralSafetyRate"
493
- .value=${((_18 = this.project.structuralSafetyRate) === null || _18 === void 0 ? void 0 : _18.toString()) || ''}
494
- @input=${this._onInputChange}
495
- suffix-text="%"
496
- ></md-outlined-text-field>
497
- </span>
498
- </div>
499
- </div>
500
-
501
- <div row separate-container>
502
- <div>
503
- <span>로봇 작업 대수</span>
504
- <span
505
- ><md-outlined-text-field
506
- type="text"
507
- numeric
508
- project
509
- name="robotCount"
510
- .value=${((_19 = this.project.robotCount) === null || _19 === void 0 ? void 0 : _19.toString()) || ''}
511
- @input=${this._onInputChange}
512
- ></md-outlined-text-field>
513
- </span>
514
- </div>
515
- </div>
516
-
517
- <hr />
518
-
519
- <div row separate-container>
520
- <div>
521
- <span>설계 변경 횟수</span>
522
- <span
523
- ><md-outlined-text-field
524
- type="text"
525
- numeric
526
- building-complex
527
- name="designChangeCount"
528
- .value=${((_21 = (_20 = this.project.buildingComplex) === null || _20 === void 0 ? void 0 : _20.designChangeCount) === null || _21 === void 0 ? void 0 : _21.toString()) || ''}
529
- @input=${this._onInputChange}
530
- ></md-outlined-text-field>
531
- </span>
532
- </div>
533
- <div>
534
- <span>계획 공정률</span>
535
- <span
536
- ><md-outlined-text-field
537
- type="text"
538
- numeric
539
- building-complex
540
- name="plannedProgress"
541
- .value=${((_23 = (_22 = this.project.buildingComplex) === null || _22 === void 0 ? void 0 : _22.plannedProgress) === null || _23 === void 0 ? void 0 : _23.toString()) || ''}
542
- @input=${this._onInputChange}
543
- suffix-text="%"
544
- ></md-outlined-text-field>
545
- </span>
546
- </div>
547
- </div>
548
-
549
- <div row separate-container>
550
- <div>
551
- <span>실제 공정률</span>
552
- <span
553
- ><md-outlined-text-field
554
- type="text"
555
- numeric
556
- building-complex
557
- name="actualProgress"
558
- .value=${((_25 = (_24 = this.project.buildingComplex) === null || _24 === void 0 ? void 0 : _24.actualProgress) === null || _25 === void 0 ? void 0 : _25.toString()) || ''}
559
- @input=${this._onInputChange}
560
- suffix-text="%"
561
- ></md-outlined-text-field>
562
- </span>
563
- </div>
564
- </div>
565
- </div>
566
362
 
567
363
  </div>
568
364
  </div>
@@ -611,6 +407,10 @@ let SvProjectUpdate = class SvProjectUpdate extends ScopedElementsMixin(PageView
611
407
  }
612
408
  name
613
409
  documentNaming
410
+ sectorType
411
+ buildingUsage
412
+ postalCode
413
+ geoGroup
614
414
  startDate
615
415
  endDate
616
416
  mainPhoto {
@@ -727,6 +527,7 @@ let SvProjectUpdate = class SvProjectUpdate extends ScopedElementsMixin(PageView
727
527
  return obj;
728
528
  }
729
529
  async _saveProject() {
530
+ var _a;
730
531
  // 첨부 파일 필드 제거 (첨부 파일은 {filename}Upload 로 전송)
731
532
  delete this.project.mainPhoto;
732
533
  delete this.project.buildingComplex.drawing;
@@ -737,6 +538,13 @@ let SvProjectUpdate = class SvProjectUpdate extends ScopedElementsMixin(PageView
737
538
  // state 는 raw 값('10'/'20')으로 로드되지만 ProjectPatch 는 enum 키 기대 — 일반
738
539
  // save 에서는 state 변경 의도 없으므로 patch 에서 제외. (state 변경은 _onUnfinalize 별도)
739
540
  delete this.project.state;
541
+ // buildingComplex.siteType 가 SiteType enum 외 값 ('BUILDING' 같은 옛 잔재) 이면
542
+ // mutation validation 실패. enum 에 없으면 null 로 정정.
543
+ const validSiteTypes = new Set(Object.values(SiteType));
544
+ if (((_a = this.project.buildingComplex) === null || _a === void 0 ? void 0 : _a.siteType) &&
545
+ !validSiteTypes.has(this.project.buildingComplex.siteType)) {
546
+ this.project.buildingComplex.siteType = null;
547
+ }
740
548
  const response = await client.mutate({
741
549
  mutation: gql `
742
550
  mutation UpdateProject($project: ProjectPatch!) {
@@ -949,6 +757,18 @@ let SvProjectUpdate = class SvProjectUpdate extends ScopedElementsMixin(PageView
949
757
  this.project = Object.assign({}, this.project);
950
758
  }
951
759
  // Input 요소의 값이 변경될 때 호출되는 콜백 함수
760
+ /**
761
+ * 우편번호 입력 핸들러 — postalCode 갱신과 동시에 앞 2자리 prefix 로 geoGroup
762
+ * best-guess 자동 매핑. 매핑 안 되면 기존 값 유지.
763
+ */
764
+ _onPostalCodeChange(event) {
765
+ const target = event.target;
766
+ const value = target.value;
767
+ this.project.postalCode = value;
768
+ const inferred = inferGeoGroupFromPostalCode(value);
769
+ if (inferred)
770
+ this.project.geoGroup = inferred;
771
+ }
952
772
  _onInputChange(event, idx) {
953
773
  const target = event.target;
954
774
  let inputVal = target.value;