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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
|
/**
* MDG 마이그레이션 진행되지 않은 상태라 PLM DB를 싱크해 사용했으므로, 추후 수정 필요
* PLM 쪽으로는 업데이트 불가능하므로, 최초 1회 마이그레이션한 데이터만 사용할 것임
* node-cron 으로 PLM 데이터 동기화할 필요도 없다는 얘기
*/
import { eq } from 'drizzle-orm'
import {
cmctbVendorGeneral,
cmctbVendorAddr,
cmctbVendorCompny,
cmctbVendorPorg,
cmctbVendorRepremail,
cmctbVendorInco,
type CmctbVendorGeneral,
type CmctbVendorAddr
} from '@/db/schema/NONSAP/nonsap'
import { vendors } from '@/db/schema/vendors'
import db from '@/db/db'
import { debugLog, debugError, debugWarn, debugSuccess } from '@/lib/debug-utils'
// 구매조직별 정보 타입 정의
export interface PurchasingOrgInfo {
PUR_ORG_CD: string // 구매조직 코드
PUR_ORD_CUR: string | null // 오더통화
SPLY_COND: string | null // 지급조건
DL_COND_1: string | null // 인도조건1
DL_COND_2: string | null // 인도조건2
GR_BSE_INVC_VR: string | null // GR기준송장검증
ORD_CNFM_REQ_ORDR: string | null // P/O 확인요청
CNFM_CTL_KEY: string | null // 확정제어키
PUR_HOLD_ORDR: string | null // 구매보류지시자
DEL_ORDR: string | null // 삭제지시자
AT_PUR_ORD_ORDR: string | null // 자동구매오더지시자
SALE_CHRGR_NM: string | null // 영업담당자명
VNDR_TELNO: string | null // VENDOR전화번호
PUR_HOLD_DT: string | null // 구매보류일자
PUR_HOLD_CAUS: string | null // 구매보류사유
}
// 벤더 상세 정보 타입 정의
export interface VendorDetails {
// 기본 정보
VNDRCD: string
VNDRNM_1: string | null
VNDRNM_2: string | null
VNDRNM_ABRV_1: string | null
BIZR_NO: string | null
CO_REG_NO: string | null
CO_VLM: string | null
// 대표자 정보
REPR_NM: string | null
REP_TEL_NO: string | null
REPR_RESNO: string | null
REPRESENTATIVE_EMAIL: string | null
// 사업 정보
BIZTP: string | null
BIZCON: string | null
NTN_CD: string | null
REG_DT: string | null
// 주소 정보
ADR_1: string | null
ADR_2: string | null
POSTAL_CODE: string | null
ADDR_DETAIL_1: string | null
// 이전업체코드
PREVIOUS_VENDOR_CODE: string | null
// 내외자구분 (사내협력사 정보) << 정확하지 않음. 추후 확인 필요
PRTNR_GB: string | null
// 구매조직별 정보 (배열)
PURCHASING_ORGS: PurchasingOrgInfo[]
// 상태 정보
DEL_ORDR: string | null
PUR_HOLD_ORDR: string | null
}
// 벤더 수정 데이터 타입
export interface VendorUpdateData {
// 기본 정보
VNDRNM_1?: string
VNDRNM_2?: string
VNDRNM_ABRV_1?: string
BIZR_NO?: string
CO_REG_NO?: string
CO_VLM?: string
// 대표자 정보
REPR_NM?: string
REP_TEL_NO?: string
REPR_RESNO?: string
REPRESENTATIVE_EMAIL?: string
// 사업 정보
BIZTP?: string
BIZCON?: string
NTN_CD?: string
// 주소 정보
ADR_1?: string
ADR_2?: string
POSTAL_CODE?: string
ADDR_DETAIL_1?: string
}
// 벤더 목록 아이템 타입
export interface VendorListItem {
VNDRCD: string
VNDRNM_1: string | null
VNDRNM_2: string | null
BIZR_NO: string | null
REG_DT: string | null
DEL_ORDR: string | null
PUR_HOLD_ORDR: string | null
}
export class VendorMdgService {
/**
* 벤더 ID로 벤더 코드 조회
* @param vendorId 벤더 ID
* @returns 벤더 코드 (VNDRCD)
*/
async getVendorCodeByVendorId(vendorId: string): Promise<string | null> {
debugLog(`벤더 코드 조회 시작: ID ${vendorId}`)
try {
const vendor = await db
.select({ vendorCode: vendors.vendorCode })
.from(vendors)
.where(eq(vendors.id, parseInt(vendorId)))
.limit(1)
debugLog(`vendors 테이블 조회 결과:`, {
found: vendor.length > 0,
vendorCode: vendor[0]?.vendorCode || null
})
if (vendor.length === 0) {
debugWarn(`벤더 ID ${vendorId}에 해당하는 벤더를 찾을 수 없습니다.`)
return null
}
const vendorCode = vendor[0].vendorCode
if (!vendorCode) {
debugWarn(`벤더 ID ${vendorId}의 vendor_code가 null입니다.`)
return null
}
debugSuccess(`벤더 코드 조회 성공: ID ${vendorId} -> 코드 ${vendorCode}`)
return vendorCode
} catch (error) {
debugError('벤더 코드 조회 중 오류 발생:', error)
return null
}
}
/**
* 벤더 ID로 벤더 상세 정보 조회
* @param vendorId 벤더 ID
* @returns 벤더 상세 정보 (데이터가 없어도 기본 구조 반환)
*/
async getVendorDetailsByVendorId(vendorId: string): Promise<VendorDetails | null> {
debugLog(`벤더 ID로 상세 정보 조회 시작: ${vendorId}`)
// 1. 벤더 코드 조회
const vendorCode = await this.getVendorCodeByVendorId(vendorId)
if (!vendorCode) {
debugWarn(`벤더 ID ${vendorId}에 대한 벤더 코드를 찾을 수 없습니다.`)
return null
}
// 2. 벤더 코드로 상세 정보 조회
debugLog(`벤더 코드 ${vendorCode}로 상세 정보 조회 시작`)
return await this.getVendorDetails(vendorCode)
}
/**
* 벤더 코드로 벤더 상세 정보 조회
* @param vendorCode 벤더 코드
* @returns 벤더 상세 정보 (데이터가 없어도 기본 구조 반환)
*/
async getVendorDetails(vendorCode: string): Promise<VendorDetails> {
debugLog(`벤더 정보 조회 시작: ${vendorCode}`)
try {
// 메인 쿼리: 벤더 일반 정보
debugLog(`CMCTB_VENDOR_GENERAL 테이블에서 ${vendorCode} 조회 중...`)
const vendorGeneral = await db
.select()
.from(cmctbVendorGeneral)
.where(eq(cmctbVendorGeneral.VNDRCD, vendorCode))
.limit(1)
debugLog(`CMCTB_VENDOR_GENERAL 조회 결과:`, {
found: vendorGeneral.length > 0,
count: vendorGeneral.length,
data: vendorGeneral.length > 0 ? vendorGeneral[0] : null
})
const vendor = vendorGeneral[0] || null
// 주소 정보 조회
debugLog(`CMCTB_VENDOR_ADDR 테이블에서 ${vendorCode} 조회 중...`)
const vendorAddr = await db
.select()
.from(cmctbVendorAddr)
.where(eq(cmctbVendorAddr.VNDRCD, vendorCode))
.limit(1)
debugLog(`CMCTB_VENDOR_ADDR 조회 결과:`, {
found: vendorAddr.length > 0,
count: vendorAddr.length,
data: vendorAddr.length > 0 ? vendorAddr[0] : null
})
// 회사 정보 조회 (첫 번째 회사 코드)
debugLog(`CMCTB_VENDOR_COMPNY 테이블에서 ${vendorCode} 조회 중...`)
const vendorCompany = await db
.select()
.from(cmctbVendorCompny)
.where(eq(cmctbVendorCompny.VNDRCD, vendorCode))
.limit(1)
debugLog(`CMCTB_VENDOR_COMPNY 조회 결과:`, {
found: vendorCompany.length > 0,
count: vendorCompany.length,
data: vendorCompany.length > 0 ? vendorCompany[0] : null
})
// 모든 구매조직 정보 조회
debugLog(`CMCTB_VENDOR_PORG 테이블에서 ${vendorCode}의 모든 구매조직 조회 중...`)
const vendorPorgs = await db
.select()
.from(cmctbVendorPorg)
.where(eq(cmctbVendorPorg.VNDRCD, vendorCode))
debugLog(`CMCTB_VENDOR_PORG 조회 결과:`, {
found: vendorPorgs.length > 0,
count: vendorPorgs.length,
data: vendorPorgs
})
// 사내협력사 정보 조회 (내외자구분)
debugLog(`CMCTB_VENDOR_INCO 테이블에서 ${vendorCode} 조회 중...`)
const vendorInco = await db
.select()
.from(cmctbVendorInco)
.where(eq(cmctbVendorInco.VNDRCD, vendorCode))
.limit(1)
debugLog(`CMCTB_VENDOR_INCO 조회 결과:`, {
found: vendorInco.length > 0,
count: vendorInco.length,
data: vendorInco.length > 0 ? vendorInco[0] : null
})
// 대표자 이메일 조회
debugLog(`CMCTB_VENDOR_REPREMAIL 테이블에서 ${vendorCode} 조회 중...`)
const vendorEmail = await db
.select()
.from(cmctbVendorRepremail)
.where(eq(cmctbVendorRepremail.VNDRCD, vendorCode))
.limit(1)
debugLog(`CMCTB_VENDOR_REPREMAIL 조회 결과:`, {
found: vendorEmail.length > 0,
count: vendorEmail.length,
data: vendorEmail.length > 0 ? vendorEmail[0] : null
})
const addr = vendorAddr[0] || null
const company = vendorCompany[0] || null
const inco = vendorInco[0] || null
const email = vendorEmail[0] || null
// 구매조직 정보 배열 구성
const purchasingOrgs: PurchasingOrgInfo[] = vendorPorgs.map(porg => ({
PUR_ORG_CD: porg.PUR_ORG_CD,
PUR_ORD_CUR: porg.PUR_ORD_CUR,
SPLY_COND: porg.SPLY_COND,
DL_COND_1: porg.DL_COND_1,
DL_COND_2: porg.DL_COND_2,
GR_BSE_INVC_VR: porg.GR_BSE_INVC_VR,
ORD_CNFM_REQ_ORDR: porg.ORD_CNFM_REQ_ORDR,
CNFM_CTL_KEY: porg.CNFM_CTL_KEY,
PUR_HOLD_ORDR: porg.PUR_HOLD_ORDR,
DEL_ORDR: porg.DEL_ORDR,
AT_PUR_ORD_ORDR: porg.AT_PUR_ORD_ORDR,
SALE_CHRGR_NM: porg.SALE_CHRGR_NM,
VNDR_TELNO: porg.VNDR_TELNO,
PUR_HOLD_DT: porg.PUR_HOLD_DT,
PUR_HOLD_CAUS: porg.PUR_HOLD_CAUS
}))
// 데이터 존재 여부 확인
const hasAnyData = vendor || addr || company || purchasingOrgs.length > 0 || inco || email
if (!hasAnyData) {
debugWarn(`벤더 ${vendorCode}에 대한 데이터가 전혀 없습니다. 기본 구조만 반환합니다.`)
} else {
debugSuccess(`벤더 ${vendorCode} 데이터 조회 완료`, {
general: !!vendor,
addr: !!addr,
company: !!company,
purchasingOrgs: purchasingOrgs.length,
inco: !!inco,
email: !!email
})
}
// 벤더 상세 정보 구성 (데이터가 없어도 기본 구조 제공)
const vendorDetails: VendorDetails = {
// 기본 정보 (General 테이블)
VNDRCD: vendorCode, // 항상 요청된 벤더 코드 반환
VNDRNM_1: vendor?.VNDRNM_1 || null,
VNDRNM_2: vendor?.VNDRNM_2 || null,
VNDRNM_ABRV_1: vendor?.VNDRNM_ABRV_1 || null,
BIZR_NO: vendor?.BIZR_NO || null,
CO_REG_NO: vendor?.CO_REG_NO || null,
CO_VLM: vendor?.CO_VLM || null,
// 대표자 정보
REPR_NM: vendor?.REPR_NM || null,
REP_TEL_NO: vendor?.REP_TEL_NO || null,
REPR_RESNO: vendor?.REPR_RESNO || null,
REPRESENTATIVE_EMAIL: email?.EMAIL_ADR || null,
// 사업 정보
BIZTP: vendor?.BIZTP || null,
BIZCON: vendor?.BIZCON || null,
NTN_CD: vendor?.NTN_CD || null,
REG_DT: vendor?.REG_DT || null,
// 주소 정보 (Address 테이블 우선, 없으면 General 테이블)
ADR_1: addr?.ADR_1 || vendor?.ADR_1 || null,
ADR_2: addr?.ADR_2 || vendor?.ADR_2 || null,
POSTAL_CODE: addr?.CITY_ZIP_NO || null,
ADDR_DETAIL_1: addr?.ETC_ADR_1 || null,
// 이전업체코드
PREVIOUS_VENDOR_CODE: company?.BF_VNDRCD || null,
// 내외자구분 (사내협력사 정보)
PRTNR_GB: inco?.PRTNR_GB || null,
// 구매조직별 정보 배열
PURCHASING_ORGS: purchasingOrgs,
// 상태 정보 (기본값 제공)
DEL_ORDR: vendor?.DEL_ORDR || 'N', // 기본값: 활성
PUR_HOLD_ORDR: vendor?.PUR_HOLD_ORDR || null
}
debugLog(`최종 벤더 정보 구성 완료:`, vendorDetails)
return vendorDetails
} catch (error) {
debugError('벤더 정보 조회 중 오류 발생:', error)
// 오류가 발생해도 기본 구조는 제공
debugWarn(`오류로 인해 ${vendorCode}의 기본 구조만 반환합니다.`)
return {
VNDRCD: vendorCode,
VNDRNM_1: null,
VNDRNM_2: null,
VNDRNM_ABRV_1: null,
BIZR_NO: null,
CO_REG_NO: null,
CO_VLM: null,
REPR_NM: null,
REP_TEL_NO: null,
REPR_RESNO: null,
REPRESENTATIVE_EMAIL: null,
BIZTP: null,
BIZCON: null,
NTN_CD: null,
REG_DT: null,
ADR_1: null,
ADR_2: null,
POSTAL_CODE: null,
ADDR_DETAIL_1: null,
PREVIOUS_VENDOR_CODE: null,
PRTNR_GB: null,
PURCHASING_ORGS: [],
DEL_ORDR: 'N', // 기본값: 활성
PUR_HOLD_ORDR: null
}
}
}
/**
* 벤더 기본 정보 수정
* @param vendorCode 벤더 코드
* @param updateData 수정할 데이터
* @returns 성공 여부
*/
async updateVendorBasicInfo(
vendorCode: string,
updateData: VendorUpdateData
): Promise<boolean> {
try {
// 트랜잭션으로 여러 테이블 업데이트
await db.transaction(async (tx) => {
// 1. General 테이블 업데이트
const generalUpdateData: Partial<CmctbVendorGeneral> = {}
if (updateData.VNDRNM_1 !== undefined) generalUpdateData.VNDRNM_1 = updateData.VNDRNM_1
if (updateData.VNDRNM_2 !== undefined) generalUpdateData.VNDRNM_2 = updateData.VNDRNM_2
if (updateData.VNDRNM_ABRV_1 !== undefined) generalUpdateData.VNDRNM_ABRV_1 = updateData.VNDRNM_ABRV_1
if (updateData.BIZR_NO !== undefined) generalUpdateData.BIZR_NO = updateData.BIZR_NO
if (updateData.CO_REG_NO !== undefined) generalUpdateData.CO_REG_NO = updateData.CO_REG_NO
if (updateData.CO_VLM !== undefined) generalUpdateData.CO_VLM = updateData.CO_VLM
if (updateData.REPR_NM !== undefined) generalUpdateData.REPR_NM = updateData.REPR_NM
if (updateData.REP_TEL_NO !== undefined) generalUpdateData.REP_TEL_NO = updateData.REP_TEL_NO
if (updateData.REPR_RESNO !== undefined) generalUpdateData.REPR_RESNO = updateData.REPR_RESNO
if (updateData.BIZTP !== undefined) generalUpdateData.BIZTP = updateData.BIZTP
if (updateData.BIZCON !== undefined) generalUpdateData.BIZCON = updateData.BIZCON
if (updateData.NTN_CD !== undefined) generalUpdateData.NTN_CD = updateData.NTN_CD
if (updateData.ADR_1 !== undefined) generalUpdateData.ADR_1 = updateData.ADR_1
if (updateData.ADR_2 !== undefined) generalUpdateData.ADR_2 = updateData.ADR_2
// 현재 시간 설정
generalUpdateData.CHG_DT = new Date().toISOString().slice(0, 10).replace(/-/g, '')
generalUpdateData.CHG_TM = new Date().toTimeString().slice(0, 8).replace(/:/g, '')
if (Object.keys(generalUpdateData).length > 2) { // CHG_DT, CHG_TM 외에 다른 필드가 있는 경우만 업데이트
await tx
.update(cmctbVendorGeneral)
.set(generalUpdateData)
.where(eq(cmctbVendorGeneral.VNDRCD, vendorCode))
}
// 2. Address 테이블 업데이트 (있는 경우)
if (updateData.ADR_1 || updateData.ADR_2 || updateData.POSTAL_CODE || updateData.ADDR_DETAIL_1) {
const addrUpdateData: Partial<CmctbVendorAddr> = {}
if (updateData.ADR_1 !== undefined) addrUpdateData.ADR_1 = updateData.ADR_1
if (updateData.ADR_2 !== undefined) addrUpdateData.ADR_2 = updateData.ADR_2
if (updateData.POSTAL_CODE !== undefined) addrUpdateData.CITY_ZIP_NO = updateData.POSTAL_CODE
if (updateData.ADDR_DETAIL_1 !== undefined) addrUpdateData.ETC_ADR_1 = updateData.ADDR_DETAIL_1
// 주소 레코드가 있는지 확인
const existingAddr = await tx
.select()
.from(cmctbVendorAddr)
.where(eq(cmctbVendorAddr.VNDRCD, vendorCode))
.limit(1)
if (existingAddr.length > 0) {
// 기존 주소 업데이트
await tx
.update(cmctbVendorAddr)
.set(addrUpdateData)
.where(eq(cmctbVendorAddr.VNDRCD, vendorCode))
} else {
// 새 주소 레코드 생성
await tx
.insert(cmctbVendorAddr)
.values({
VNDRCD: vendorCode,
ADR_NO: '0001',
INTL_ADR_VER_ID: '1',
...addrUpdateData
})
}
}
// 3. 대표자 이메일 업데이트 (있는 경우)
if (updateData.REPRESENTATIVE_EMAIL !== undefined) {
// 기존 이메일 레코드가 있는지 확인
const existingEmail = await tx
.select()
.from(cmctbVendorRepremail)
.where(eq(cmctbVendorRepremail.VNDRCD, vendorCode))
.limit(1)
const currentDate = new Date().toISOString().slice(0, 10).replace(/-/g, '')
if (existingEmail.length > 0) {
// 기존 이메일 업데이트
await tx
.update(cmctbVendorRepremail)
.set({
EMAIL_ADR: updateData.REPRESENTATIVE_EMAIL,
IF_DT: currentDate,
IF_TM: new Date().toTimeString().slice(0, 8).replace(/:/g, ''),
IF_STAT: '1'
})
.where(eq(cmctbVendorRepremail.VNDRCD, vendorCode))
} else if (updateData.REPRESENTATIVE_EMAIL) {
// 새 이메일 레코드 생성 (빈 문자열이 아닌 경우만)
await tx
.insert(cmctbVendorRepremail)
.values({
VNDRCD: vendorCode,
ADR_NO: '0001',
REPR_SER: '001',
VLD_ST_DT: currentDate,
EMAIL_ADR: updateData.REPRESENTATIVE_EMAIL,
IF_DT: currentDate,
IF_TM: new Date().toTimeString().slice(0, 8).replace(/:/g, ''),
IF_STAT: '1'
})
}
}
})
return true
} catch (error) {
console.error('벤더 정보 수정 중 오류 발생:', error)
throw new Error('벤더 정보를 수정할 수 없습니다.')
}
}
/**
* 벤더 목록 조회 (페이징)
* @param page 페이지 번호 (1부터 시작)
* @param limit 페이지당 개수
* @param searchTerm 검색어 (업체명 검색)
* @returns 벤더 목록과 총 개수
*/
async getVendorList(
page: number = 1,
limit: number = 20,
searchTerm?: string
): Promise<{ vendors: VendorListItem[], total: number }> {
try {
const offset = (page - 1) * limit
// 기본 조건: 활성 벤더만 조회
const whereCondition = eq(cmctbVendorGeneral.DEL_ORDR, 'N')
// 검색어가 있는 경우 업체명으로 필터링 (추후 구현 시 사용)
void searchTerm // 현재는 미사용
// 총 개수 조회
const totalResult = await db
.select({ count: cmctbVendorGeneral.VNDRCD })
.from(cmctbVendorGeneral)
.where(whereCondition)
// 벤더 목록 조회
const vendors = await db
.select({
VNDRCD: cmctbVendorGeneral.VNDRCD,
VNDRNM_1: cmctbVendorGeneral.VNDRNM_1,
VNDRNM_2: cmctbVendorGeneral.VNDRNM_2,
BIZR_NO: cmctbVendorGeneral.BIZR_NO,
REG_DT: cmctbVendorGeneral.REG_DT,
DEL_ORDR: cmctbVendorGeneral.DEL_ORDR,
PUR_HOLD_ORDR: cmctbVendorGeneral.PUR_HOLD_ORDR
})
.from(cmctbVendorGeneral)
.where(whereCondition)
.limit(limit)
.offset(offset)
return {
vendors,
total: totalResult.length
}
} catch (error) {
console.error('벤더 목록 조회 중 오류 발생:', error)
throw new Error('벤더 목록을 조회할 수 없습니다.')
}
}
/**
* 벤더 상태 변경 (활성/비활성)
* @param vendorCode 벤더 코드
* @param isActive 활성 상태 여부
* @returns 성공 여부
*/
async updateVendorStatus(vendorCode: string, isActive: boolean): Promise<boolean> {
try {
await db
.update(cmctbVendorGeneral)
.set({
DEL_ORDR: isActive ? 'N' : 'Y',
CHG_DT: new Date().toISOString().slice(0, 10).replace(/-/g, ''),
CHG_TM: new Date().toTimeString().slice(0, 8).replace(/:/g, '')
})
.where(eq(cmctbVendorGeneral.VNDRCD, vendorCode))
return true
} catch (error) {
console.error('벤더 상태 변경 중 오류 발생:', error)
throw new Error('벤더 상태를 변경할 수 없습니다.')
}
}
}
// 싱글톤 인스턴스 생성
export const vendorMdgService = new VendorMdgService()
|