Commit Graph

4526 Commits

Author SHA1 Message Date
hjjeong 7779f37c17 개발관리>PART·E-BOM Excel Import 메뉴 신설 — wace partMng 1:1 이식
PART Excel Import (M1·M2 공용):
- /partMng/openPartExcelImportPopUp.do + partParsingExcelFile.do + partUploadSave.do 1:1
- 22컬럼 파싱 + NOTE 누적 검증 (품번 필수/중복, PART_TYPE/ACCTFG/UNIT_DC commCode 매핑,
  ODRFG/LOT_FG/USE_YN/QC_FG/SETITEM_FG/REQ_FG 한글 → 코드값)
- 저장은 신규 PART_NO 만 mergePartMng INSERT (기존 IS_LAST='1' 행은 skip)
- part-regist + part-search 페이지에 Excel Upload 버튼 + 다이얼로그 연결

BOM Report Excel Import (M3 = openBomReportExcelImportPopUp = "PART 및 구조등록 Excel upload"):
- /partMng/parsingExcelFile.do + checkDuplicatePartNo.do + getBomDataForCopy.do
  + partBomApplySave.do (savePartBomMaster) 1:1
- 10컬럼 파싱 + 자품번/모품번/품명/수량 필수 검증, 모품번이 자품번 목록(Set)에 존재 검증,
  수량 숫자+>0 검증, PART_TYPE='0001788'(구매품표준) part_mng 존재 검증
- 1레벨(모품번 없는 첫 행) → 헤더 PART_NO/PART_NAME 자동 채움
- 저장 트랜잭션 (wace 1:1):
    헤더 part_bom_report INSERT(신규) / DELETE 자식트리+UPDATE(수정)
    자식 PART: part_mng IS_LAST='1' 존재 시 updatePartInfoFromCsv UPDATE, 없으면 insertpartInfo INSERT
    부모 PART: 존재 시 lookup, 없으면 "" (절대 INSERT 안 함 — wace 5359-5361)
    bom_part_qty INSERT (relatePartInfo) — 부모행 CHILD_OBJID 를 PARENT_OBJID 로 체인
- 헤더 PART_NO 중복 검사 (편집 중인 자신 제외)
- E-BOM 복사 기능 (기존 BOM → 그리드 행) + Template Download
- ebom-regist 페이지에 "E-BOM 등록(Excel)" 버튼 + 다이얼로그 연결

운영 템플릿 정적 자산:
- frontend/public/templates/PART_EXCEL_IMPORT_TEMPLATE.xlsx
- frontend/public/templates/BOM_REPORT_EXCEL_IMPORT_TEMPLATE.xlsx (.gitignore 우회 git add -f)

wace structureExcelImportPopup.jsp 는 옛 차종/제품군/사양 도메인 화면으로 운영 메뉴 트리에
서 더이상 호출되지 않아 이식 대상 제외.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 17:55:17 +09:00
hjjeong c9adfd7327 개발관리>설계변경 리스트 메뉴 신설 (PR-C) — wace partMng 1:1 이식
backend (M5, read-only):
- devEoHistoryService: list + getByObjid
- partMngHistList SQL 1:1 (NVL→COALESCE, PART_MNG.OBJID bigint cast, CODE_NAME→LEFT JOIN comm_code)
- 동적 필터 10종 (Year/contract_objid/unit_code/part_no/part_name/change_option/eo_start~end/change_type/part_type/writer_id)
- 신규등록 제외 가드: NOT (HIS_STATUS='DEPLOY' AND CHANGE_TYPE IS NULL AND REVISION='RE') + BOM_STATUS='deploy'
- 품번변경(CHANGE_OPTION=0001790) 'A->B' 머지 CASE (part_no_disp/part_name_disp/revision_disp)

frontend (M5):
- change-list/page.tsx: 16셀 그리드 + 검색 8필드 + 페이징
- PartHisDetailDialog: 모든 필드 disabled, 4 섹션 (EO/프로젝트/PART/수량)
- AdminPageRenderer dynamic 임포트 + 기존 menu_info URL 그대로 사용

개발관리 5개 메뉴 (M1~M5) baseline 완료.

본 PR 제외 (별 PR): writer SmartSelect, change_type/change_option comm_code 그룹 SmartSelect (그룹 ID 확정 후)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 16:27:37 +09:00
hjjeong 0872199b30 개발관리>E-BOM 등록·조회 메뉴 신설 (PR-B) — wace partMng 1:1 이식
backend (M3+M4):
- devBomService: list/getByObjid/updateStatus/removeMany/ascending/descending
- M3 그리드 SQL (getBOMStandardStructureGridList 1:1)
  - customer_mng 매핑 (wace SUPPLY_MNG → vexplor customer_mng.customer_code)
  - PRODUCT_NAME LEFT JOIN comm_code (CODE_NAME 함수 대체)
- M3 다중 삭제 트랜잭션 (bom_part_qty + part_bom_report CASCADE)
- M4 정/역전개 재귀 CTE (bom_part_qty 트리 + part_mng JOIN)
- vexplor 적응: M4 product_mgmt_spec/upg/vc 분기 제거 (스키마 단순화)
- PG 재귀 CTE 타입 일치: ARRAY[BP.objid::varchar] 명시 cast

frontend (M3+M4):
- ebom-regist (M3): 9셀 그리드 (제품구분·품번·품명·E-BOM·등록자·등록일·확정일·Version·상태)
- ebom-search (M4): 동적 LEVEL 컬럼 + 정/역전개 토글
- BomReportStatusDialog: 상태 변경 (create/changeDesign/deploy + version)
- AdminPageRenderer dynamic 임포트 2건 + menu_info URL spec 정렬

본 PR 제외 (별 PR): E-BOM Excel Import, 정/역전개 Excel Download, BOM_PART_QTY 수량 편집

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 16:23:10 +09:00
hjjeong ea6606da0c 개발관리>PART 등록·조회 메뉴 신설 (PR-A) — wace partMng 1:1 이식
backend (M1+M2):
- devPartService: listTemp/listRelease/getByObjid/create/update/deploy/removeMany
- partMngBaseSimple SELECT + 추가 15컬럼(acctfg/odrfg/unit_dc/unitmang_dc/lot_fg 등) 라벨/CASE
- deploy 트랜잭션 3단계 (isLastInit → part_mng_history INSERT → partMngDeploy + EO_NO 채번)
- EO_NO 분기: is_longd='1'→EOB{yy}-{seq} / else EO{yy}-{seq}
- objidUtil: wace CommonUtils.createObjId() 1:1 (bigint objid 채번)
- DDL: 9 신규 테이블 + part_mng 15컬럼 ALTER (운영판 1:1 추출)

frontend (M1+M2):
- part-regist (M1) / part-search (M2): 23셀 그리드 + 검색폼 + 액션
- PartFormDialog: 등록/수정 통합 (mode prop, 4 섹션)
- PartDetailDialog: 읽기 전용 + "수정" dispatch
- AdminPageRenderer dynamic 임포트 2건 + menu_info URL spec 정렬

본 PR 제외 (별 PR): 도면 다중 업로드, ERP 업로드, Excel Import, BOM_PART_QTY R/W

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 16:14:10 +09:00
hjjeong d8d9ad3bcc Merge pull request 'hjjeong' (#8) from hjjeong into main
Reviewed-on: https://g.wace.me/chpark/vexplor_rps/pulls/8
2026-05-12 04:47:29 +00:00
hjjeong 5c085dc69e 프로젝트 상세 정보 다이얼로그 wace 운영판 1:1 + 영업관리 판매·매출관리 연결
· 다이얼로그 디자인: 프로젝트정보 박스(주문유형/제품구분/국내해외/고객사·유무상/접수일/견적환종/견적환율) + 품목정보 테이블(No/품번/품명/S/N/요청납기/고객요청사항/반납사유)
· ProjectInfoData 정규화 props — 진행관리/판매관리/매출관리 각각 toProjectInfo 매핑으로 호출
· backend SQL 3곳 보강: exchange_rate (contract_mgmt) + customer_request (CI→CM fallback) + return_reason_name (CI CODE_NAME)
· 판매관리/매출관리 page에 columns useMemo + project_no 셀 onClick + ProjectInfoDialog state 추가
· wace 운영 URL: /salesMgmt/salesRegForm.do?saleNo=detail 1:1 매핑 (새 창 → 같은 탭 다이얼로그)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 13:44:58 +09:00
hjjeong 50669a66ee 프로젝트관리>제품구분_WBS관리 메뉴 신설 — wace WBS 템플릿 1:1 이식
· 메인 그리드 5컬럼(제품구분/제목/WBS/등록자/등록일) + 통합 팝업(트리 CRUD + 엑셀 임포트 + 템플릿 다운로드)
· 운영 매핑: pms_wbs_template(헤더) + pms_wbs_task_standard(트리) — 활성 갈래 확정 (_info/_standard2 갈래는 2021년 멈춘 레거시)
· wace mergeExcelUploadWBS 1:1: 신규=헤더+트리 INSERT, 수정=트리 일괄 DELETE→INSERT (헤더 변경 없음)
· objid 채번 gen_random_uuid()::text, 엑셀 파싱 xlsx(SheetJS), 정적 템플릿 frontend/public/templates/
· DataGrid 컬럼 단위 onClick 추가 (WBS 폴더 셀 클릭용)
· DDL: 8개 테이블 162컬럼 (docs/migration/project/ddl-extracted/200_pms_wbs.sql) / GAP: docs/migration/project/02-wbs-template.md
· 프로젝트 자동 복사/진행관리 연계는 wace도 미완성 — P2 범위 외

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 13:43:51 +09:00
hjjeong 7c4817b045 진행관리 P1.5 재작업 — PROJECT_NO 셀 클릭 시 프로젝트 정보 다이얼로그
· wace fn_openSaleRegPopup(PROJECT_NO, "detail") 의도 재해석 — read-only 상세 조회 모드
· 행 전체 클릭(onRowClick) → PROJECT_NO 컬럼 셀 클릭(cellClick)으로 좁힘 (wace 1:1)
· 판매관리 페이지 라우팅 폐기 → ProjectInfoDialog 신설 (같은 탭, list row 직접 사용, 추가 API 호출 0)
· 표시 항목: 프로젝트번호/영업번호/주문유형/제품구분/국내해외/고객사/유무상/품번/품명/S/N/수주수량/접수일/요청납기/발주일/프로젝트명/작성자
· 영업관리 변경 롤백 (SaleListFilter.project_no, useSearchParams 자동 선택, 초기화 핸들러)
· 01-progress / 01-progress-verify 문서 갱신

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 12:06:01 +09:00
chpark 945b65b870 시퀀스 관리 메뉴 + 테이블 타입관리 코멘트/검증 + 설계 문서
Build and Push Images / build-and-push (push) Has been cancelled
- 시스템 관리 > 시퀀스 관리 신규 메뉴 + 페이지(채번 룰 빌더)
- ensureSequenceMngMenu 부팅 시드
- 테이블 타입관리 → 채번 룰 드롭다운 + 의존성 자동 검증
- 표시명/코멘트 UX 개선
- 설계 문서 추가

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 11:46:11 +09:00
hjjeong 332688a441 진행관리 P1.5 행 클릭 + 검증 문서 — 판매관리 라우팅 (wace fn_openSaleRegPopup 대응)
· 진행관리 행 클릭 → /COMPANY_16/sales/sale?project_no={PROJECT_NO} 라우팅
· 판매관리 page: useSearchParams로 project_no 자동 필터 + 첫 매칭 행 자동 선택 + 초기화 핸들러 보강
· backend SaleListFilter.project_no 추가 (T.project_no = $1 단일 매칭, 기존 영업 흐름 무영향)
· wace 새창 패턴 → RPS SPA 동일 탭 라우팅으로 매핑 (의도 동일)
· docs/migration/project/01-progress.md + 01-progress-verify.md 신설 (영업관리 검증 문서 패턴)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 18:47:56 +09:00
hjjeong b4ed5f3a2a Merge pull request 'hjjeong' (#7) from hjjeong into main
Reviewed-on: https://g.wace.me/chpark/vexplor_rps/pulls/7
2026-05-11 09:26:35 +00:00
hjjeong a1ace22626 프로젝트관리>진행관리 메뉴 신설 — wace projectMgmtWbsList3 1:1 이식
· 그리드: 8그룹 18셀 평탄화 (운영판 projectMgmtWbsGridList SQL 1:1)
· 검색폼: 11필드 (년도/프로젝트번호/주문유형/고객사/제품구분/요청납기/국내해외/유무상/품번/품명/S/N)
· 영업관리 패턴 통일: PartSelect 단일 search_partObjId, customer_mng 단일 LEFT JOIN
· client_mng/supply_mng 분기 → customer_mng로 흡수, CODE_NAME() 함수 직접 사용
· 행 클릭 동작은 P1.5 별도 결정 (영업관리 OrderRegistDialog 재사용 후보)
· PMS_WBS_TASK/SETUP_WBS_TASK 의존 컬럼은 그리드 표시 컬럼에 없어 P2(WBS관리) 보류

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 18:22:06 +09:00
hjjeong b17d7b063d PR-D G11 견적 결재상신 — Amaranth 직행 (wace estimateList_new.jsp btnApproval 1:1)
G11 수주 결재상신(905d5c09)과 동일 패턴을 견적관리에 확장. target_type='CONTRACT_ESTIMATE',
target_objid=estimate_template.objid(최신 차수), formId='1162' (수주 1161과 별도 양식).

- 백엔드: salesEstimateService.startEstimateApproval + POST /sales/estimate/:id/amaranth-approval
- 견적 list SQL: LEFT JOIN amaranth_approval(CONTRACT_ESTIMATE) + APPR_STATUS 4단계 한글 라벨 + approval_required='N' fallback (wace contractMgmt.xml:513~522 1:1)
- 프론트: 견적관리 placeholder 토스트 → handleAmaranthApproval 핸들러 + sky-600 Send 버튼 (수주 페이지와 통일)
- docker-compose 3개: AMARANTH_OUT_PROCESS_CODE_CONTRACT_ESTIMATE + AMARANTH_FORM_ID_CONTRACT_ESTIMATE=1162 추가
- 가드: 행 미선택 / est_objid 없음(견적서 미작성) / inProcess+complete / notRequired+approval_required='N'
- 사전판정(checkApprovalRequired)은 G4 영역으로 분리 — 이번 PR은 단순 SSO 흐름만

검증: BEGIN/ROLLBACK으로 26C-0712(est_objid=-452406811) 4단계 상태(create→inProcess→complete→reject)
+ amaranth row 삭제 시 approval_required='N' fallback 모두 한글 라벨 정상. 문서 08-estimate-approval-verify.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 18:16:43 +09:00
hjjeong 905d5c0976 PR-D G9 수주복사 + G11 Amaranth 수주 결재상신 (wace 1:1)
[G9 수주복사 — wace copyEstimateAndOrderInfo 1:1]
- salesOrderMgmtService.copyOrder: 새 영업번호({YY}C-{NNNN}) 채번 +
  contract_mgmt 23컬럼 INSERT-SELECT(contract_result='', is_direct_order='Y' 강제) +
  contract_item + contract_item_serial 통째 복제
- POST /api/sales/order-mgmt/:id/copy 라우트
- 주문관리 그리드 "수주복사" 버튼 (Copy 아이콘) + handleCopyOrder

[G11 Amaranth 수주 결재상신 — wace ApprovalService.getAmaranthSsoUrl 1:1]
- chpark의 amaranthApprovalClient(HMAC-SHA256 + AES-128-CBC) 재사용
- amaranth_approval만 사용(자체 approval 미경유, wace 운영 패턴 동일)
- target_type='CONTRACT_ORDER', formId='1161', compSeq='1000'
- approKey 분기: 신규 / reject·delete·create는 새 approKey UPDATE / 그 외 재사용
- salesOrderMgmtService.startOrderApproval: user_info.emp_seq 조회 →
  라인 0건 가드 → 매핑 분기 → SSO URL 발급 → INSERT/UPDATE → fullUrl 반환
- POST /api/sales/order-mgmt/:id/amaranth-approval 라우트
- 주문관리 그리드 "결재상신" 버튼 (Send 아이콘, sky-600) + handleAmaranthApproval
- getList SQL에 LEFT JOIN amaranth_approval AMR_ORDER 추가 +
  order_appr_status(작성중/결재중/결재완료/반려 한글) + order_amaranth_status 노출

[DB 스키마]
- amaranth_approval.target_objid BIGINT → VARCHAR(80) (wace 운영 1:1)
  · 출처: wace 매퍼 T.OBJID::VARCHAR = AMR_ORDER.TARGET_OBJID
  · 사유: contract_mgmt.objid가 'CM-' prefix varchar라 bigint cast 불가
  · 데이터 0건 무손실, ECR/CS는 bigint→varchar 자동 cast로 무영향
- approvalTableMigration.ts 동기화

[운영 배포 환경변수 — wace Constants 1:1 default 박힘]
- AMARANTH_OUT_PROCESS_CODE=RPSPLM_00001 (wace Constants.java:81)
- AMARANTH_FORM_ID_CONTRACT_ORDER=1161 (wace orderMgmtList.jsp:558)
- AMARANTH_COMP_SEQ=1000 (wace orderMgmtList.jsp:559)
- 3개 docker-compose(deploy/onpremise, docker/deploy, docker/prod) 모두
  ${VAR:-default} 형식으로 매핑 — 호스트 .env 미설정 시 default 동작

[검증]
- G9: BEGIN/ROLLBACK으로 26C-0800(라인 3건) 복사 시뮬레이션 — 헤더 23컬럼 1:1,
  채번 26C-0803, 라인 3→3건 + seq 보존
- G11: 4단계 상태 라벨(create→inProcess→complete→reject) 모두 정상,
  VARCHAR PK(CM-... prefix) JOIN도 정상
- 문서: docs/migration/sales/06-copy-order-verify.md, 07-amaranth-approval-verify.md
- GAP: G9 , G10 (영업 GAP 아님 — Admin 도메인), G11 

[운영 트러블슈팅 노트 — 07-verify.md 트러블슈팅 섹션]
dev에서 amaranth 측이 "API Proxy 호출 시 유효한 레디스 값이 존재하지 않습니다"로
거부. 우리 코드는 정상 — 'Amaranth - 결재' accessToken을 amaranth 서버 측
Redis에 등록받아야 동작. chpark/RPS ERP 담당자 협조 영역(코드 변경 없음).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 17:44:54 +09:00
chpark a61643c216 Merge remote-tracking branch 'origin/main'
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
2026-05-11 17:00:38 +09:00
hjjeong 0208a072c2 G8 견적/주문 삭제 가드 — 프로젝트가 생성된 건은 차단 (wace deleteContractMngInfo 1:1)
- salesOrderMgmtService에 assertNoProjectExists(client, contractObjid) 신설. wace 매퍼 getProjectListBycontractObjid:3909와 동일하게 SELECT 1 FROM project_mgmt WHERE contract_objid=$1 LIMIT 1 (status 필터 없음).
- salesEstimateService.remove + salesOrderMgmtService.remove 둘 다 BEGIN 직후 가드 호출. 차단 시 AppError("프로젝트가 생성된 건은 삭제할 수 없습니다.", 409) throw.
- 컨트롤러 remove 두 곳에서 error.statusCode ?? 500으로 응답 → 409 정확히 전달.
- DB 검증: 26C-0698(project 11건) 차단, project 없는 contract 통과.

G7(contract_item UPSERT)는 사실상 이미 구현 — upsertItems 두 서비스 모두 INSERT ... ON CONFLICT (objid) DO UPDATE 패턴으로 OBJID 유지 보장 중. 별도 코드 변경 없음.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:33:28 +09:00
hjjeong 902118d46e PR-C G6 견적관리 SMTP 메일 발송 (wace sendEstimateMailCustom 1:1)
- nodemailer + pdf-lib로 실제 SMTP 발송. mail_log INSERT(is_send='N') → 발송 → 성공 시 UPDATE(is_send='Y'), 실패 시 UPDATE(error_log). SMTP_SEND_SWITCH='N'면 발송 스킵.
- SMTP 3계정(ERP/SALES/PURCHASE) host/user/pw 환경변수 분리. 견적서는 SALES. dev는 backend-node/.env, 운영은 deploy/onpremise + docker/prod + docker/deploy 3개 compose에 environment 매핑(호스트 .env에서 실값 주입).
- 다이얼로그(EstimateMailDialog): wace estimateMailFormPopup.jsp 1:1. 고객사 담당자 체크박스 + To/CC/제목/내용 자동채움(GET /sales/estimate/mail-info/:id + .../customer/:id/managers). hasBaseEst/hasAddEst 분기로 PDF 첨부 안내. 본문은 다이얼로그 plain text 입력 → <br> 변환.
- PDF 첨부: 메일 다이얼로그가 hidden iframe으로 최신 차수 template1/2 페이지를 렌더 → window.fn_generateAndUploadPdf(cb) 글로벌 → jsPDF.output('datauristring') base64 추출 → 한 요청에 전달. backend가 견적 PDF + estimate02 N건 pdf-lib로 합본 첨부.
- PDF 캡처 수신처 누락 픽스: CustomerSelect의 /sales/customers 옵션 fetch가 iframe에서 dataLoaded=true 뒤에 끝나 셀렉트 라벨이 빈 상태로 캡처되던 현상. fetchCustomers export + template1/2 setLoading(false) 직전 await + onclone에서 [role="combobox"] 라이브 DOM 텍스트 fallback.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 16:09:10 +09:00
chpark 690b85805c ECR 기능/스키마 wace_plm 일치 + 공통코드·테이블타입 화면 정리
- ECR 관리: wace 의 ecrList/Form/Detail JSP 와 동일하게 5개 필터(연도/기종/요청/작성자/상태),
  변경전/후 2분할 모달, 작성중(0000100)만 삭제·수정 허용, 컬럼 순서/라벨 wace 일치
- ECR 스키마 wace 풀세트 동기화: ecr_mng 컬럼폭 확장, product_mgmt 16컬럼, part_mng 52컬럼,
  user_info 22컬럼, comm_code 보강(id/code_cd/ext_val), code_name(varchar) 함수,
  seq_ecr_no setval(33) 정렬
- wace_plm public.comm_code 733행 시드: src/seed/wace_comm_code.sql 추출 + 부팅 시 자동 적재
  (writer='system-seed' placeholder 자동 정리, 무중단 재적재 엔드포인트 /comm-code-seed)
- wace_plm 데이터 import 풀스키마: PRODUCT(7→16), PART(6→52), USER_INFO·COMM_CODE 신규
- 공통코드 관리 화면: 제목/설명 축소, 카테고리·코드 카드 → 컴팩트 리스트, 활성 토글 점,
  계층 배지 톤다운, hover 시 액션 노출
- 테이블 타입 관리 — 좌측: 한 줄 리스트 + 알파벳 인덱스 sticky 헤더
- 테이블 타입 관리 — 우측: 타입 카드 그리드 → 그룹 셀렉트(기본/참조/자동/첨부/표시변형),
  표시이름 제거 + 코멘트(description) Textarea 신설(화면관리에서 기본 라벨로 활용),
  시스템 자동 생성 컬럼(id/company_code/writer/created_date/updated_date) 잠금,
  표시옵션/고급설정(필수·읽기·기본값·최대길이) 제거 — 화면관리로 이관

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 15:58:54 +09:00
hjjeong 81f674da15 Merge pull request 'hjjeong' (#6) from hjjeong into main
Reviewed-on: https://g.wace.me/chpark/vexplor_rps/pulls/6
2026-05-11 06:14:49 +00:00
hjjeong 0afa8b03cf 견적서 자동 채움 보강 + 시행일자 picker 형식 정정
1) getById 응답 구조 fix
   - salesEstimateService.getById는 { ...contract_mgmt 헤더, items } 평면 객체 반환
   - 페이지가 contractInfo.header.customer_objid로 잘못 접근해 고객사·환율·통화 자동 채움이 안 됐던 버그
   - contractInfo.customer_objid 직접 접근으로 수정 (template1·template2 동일)

2) /auth/me 응답에 cellPhone/tel 추가
   - AuthService.getUserInfo는 이미 두 필드 반환하나 authController가 응답에서 누락
   - 견적서 연락처가 wace MailUtil 패턴(cell_phone 우선 → tel 폴백)으로 자동 채워지도록 노출

3) 시행일자 picker 표시 형식 정정
   - input[type="date"]는 한국 Chrome이 "YYYY. MM. DD." 강제 (CSS 변경 불가)
   - text input + hidden type=date 조합: 표시는 YYYY-MM-DD, 클릭 시 hidden picker showPicker() 트리거
   - template1 executor + template2 executor_date 모두 적용

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 15:07:25 +09:00
hjjeong f88c5e3e40 견적서 담당자/연락처 자동 채움 (wace estimateTemplate1.jsp ready 1:1)
신규 작성 시 useAuth로 로그인 사용자 정보 자동 채움:
- 담당자 = "{deptName} {userName}" (wace: connectUserDeptName + connectUserName)
- 연락처 = user.tel (wace: cell_phone || tel)

조건: templateObjid 없는 신규 작성 + 사용자가 아직 입력하지 않은 빈 값에만 채움.
기존 견적서 수정 모드는 DB 값 우선 (manager_name/manager_contact).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 14:42:36 +09:00
hjjeong 8fdc42df79 PR-C G5-B 일반 견적서 PDF 다운로드 (html2canvas-pro + jspdf)
- frontend deps: html2canvas-pro@^2.0.2, jspdf@^3.0.4
- template1 페이지 "PDF 다운로드" 버튼 → wace fn_generatePdf 1:1 포팅
  · 클라이언트 dynamic import (SSR 회피)
  · html2canvas-pro 캡처 (scale 2, JPEG 0.85) → jsPDF A4 페이지 분할 → save({estimateNo}.pdf)
  · onclone 콜백에서 input/textarea/select → 텍스트 노드로 교체 (글자 잘림 방지)
  · .no-print, .btn-area, 삭제버튼은 클론에서 숨김
- html2canvas-pro 사용 이유: Tailwind 4 oklab/oklch CSS color function 지원
  (기존 html2canvas 1.4.1은 "Attempting to parse an unsupported color function 'oklab'" 에러)

장비 견적서(template2)는 wace 원본부터 PDF 다운로드 버튼이 없어 그대로 유지.
메일 발송용 PDF 합본은 G6 SMTP 묶음에서 처리.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 14:32:29 +09:00
hjjeong 844216c298 PR-C G5-A 견적작성 페이지(일반 template1 + 장비 template2) 1:1 이식
- 백엔드: saveEstimateTemplate1/2 + getTemplateById + listTemplatesByContract
- 라우트: POST /api/sales/estimate/template1·template2, GET /template/:id, /templates/:contractObjid
- 프론트 페이지 /estimate/template{1,2}/pop/[contractObjid]
  · template1: wace estimateTemplate1.jsp 1:1 (헤더·라인·합계·비고·참조사항)
  · template2: wace estimateTemplate2.jsp 1:1 (CNC + 7개 기본 카테고리 + group1 공유 subtotal + 비고 contenteditable + 카테고리 동적 추가/삭제)
  · /pop/ 세그먼트로 (main)/layout.tsx isPop 분기에 걸려 새 창에서 사이드바·탭바 우회
  · 다크모드에서 견적서 양식 검정 텍스트 강제
- 진입점: 견적관리 그리드 "견적작성" → 일반/장비 선택 다이얼로그 → window.open 새 창
- 견적현황(폴더) 컬럼 클릭 → 차수 리스트 다이얼로그 (wace fn_showEstimateList)
- 회사 도장 PNG (wace_plm/WebContent/images/company_stamp.png 1:1 복사, .gitignore *.png 우회 -f)

PDF 다운로드(html2canvas+jspdf) + 메일 PDF 합본은 G5-B 별도 PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 14:08:33 +09:00
hjjeong fa2f232924 주문관리 수주등록 폼 분기 — wace orderRegistFormPopup 1:1 별도 컴포넌트
- 견적요청에서 시작된 행(is_direct_order != 'Y')은 별도 다이얼로그(OrderRegistDialog)
  · 헤더 4개(발주번호/발주일*/견적환종/견적환율)
  · 라인은 contract_item 자동 로드, 추가/삭제 불가
  · 입력은 제품구분 + ORDER_*(수주수량/단가/공급가액/부가세/총액)만
  · 자동계산(수량×단가→공급가액, ×10%→부가세, 공급+부가세→총액)
  · Total 합계 행
- 통합폼은 항상 is_direct_order='Y' 케이스만 노출 — 토글 로직 제거
- list SQL/OrderRow에 is_direct_order 노출 (행 분기 판별용)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 11:12:23 +09:00
hjjeong 12c23d2cb6 주문관리 수주입력 보강: 자동계산 + 행 선택 시 수정 분기 + is_direct_order 따라 폼 모드
- 라인 자동계산 (wace fn_calculateItemAmount / fn_calculateFromSupplyPrice / fn_calculateTotalFromVat 이식)
  · 수량/단가 → 공급가액 = 수량×단가, 부가세 = round(공급가액×0.1), 총액 = 공급가액+부가세
  · 공급가액 직접 → 부가세/총액 재계산
  · 부가세 직접 → 총액만 재계산
  · 총액 직접 → 영향 없음 (수동)
- 수주입력 버튼 분기: selected 없으면 신규(openCreate), 있으면 수정(openEdit). 라벨 자동 토글 ("수주입력" ↔ "수주수정"). 기존 별도 "수정" 버튼 제거.
- 다이얼로그 모드 분기 (is_direct_order):
  · 'Y' (수주통합등록/수정): 라인 13컬럼 + ORDER_* 5개 + Total 합계 행
  · 'N' (견적관리에서 온 견적단계 행): 라인 8컬럼 + ORDER_* 5개·Total 숨김 (견적요청수정 폼)
- openEdit에서 product / return_reason / master_part_no/name fallback 추가

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 10:52:47 +09:00
hjjeong 0a97f2ec38 S/N 관리·연속번호생성 Dialog 모두 onInteractOutside 차단 (자식 Dialog 닫힘 시 부모 도미노 차단 완성)
이전 커밋에서 메인 등록 Dialog에만 onInteractOutside 추가 — 자식(S/N)·손자(연속번호) Dialog가 닫힐 때 이벤트가 메인까지 도미노로 전파되며 여전히 메인이 닫혔음.

해결: nested Dialog 4개(견적/주문 각각 S/N + 연속번호) 모두에 onInteractOutside={(e) => e.preventDefault()} 추가.
사용자는 X / 취소 / 확인 / 생성 버튼으로만 명시적으로 각 Dialog 닫음.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 10:39:49 +09:00
hjjeong 447090faca 견적/주문 등록 다이얼로그: 자식 S/N·연속번호 Dialog 닫힐 때 부모 Dialog까지 닫히는 현상 차단
Radix Dialog 알려진 이슈 — nested Dialog 닫힐 때 PointerDown 이벤트가 부모로 전파되어 outside click으로 인식, 부모 Dialog도 함께 닫힘.

수정:
  <DialogContent onInteractOutside={(e) => e.preventDefault()}>
  → 외부 클릭으로 부모 닫힘 차단. 사용자는 X / 취소 / 저장 버튼으로만 닫음.
  ESC는 그대로 — Radix focus stack이 자식만 먼저 닫음.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 10:35:41 +09:00
hjjeong ae5ef8f7e5 주문서 수주통합등록 다이얼로그 wace G2 1:1 재작성
기존 RPS 폼이 wace estimateAndOrderRegistFormPopup과 크게 어긋남(헤더 항목 잘못 배치 + 라인 누락). 통째 재작성.

수주통합 기본정보 — wace 헤더 9개 정확 일치:
  영업번호(자동채번) / 주문유형* / 국내해외* / 고객사* / 유무상* / 접수일* / 견적환종 / 견적환율 / 발주번호 / 발주일*
  (이전 RPS의 요청납기/통화/수주상태/담당자(PM ID)/출하방법/고객사요청사항 헤더 배치 폐지 — wace 통합폼에 없음)

품목정보 — wace 라인 13컬럼 + Total 합계 행:
  No / 제품구분* / 품번* / 품명* / S/N / 요청납기 / 고객요청사항 / 반납사유 / 수주수량* / 수주단가 / 수주공급가액 / 수주부가세 / 수주총액 / 삭제
  (이전 누락: 제품구분 / S/N / 요청납기 / 고객요청사항 / 반납사유)

추가 컴포넌트:
- 품번/품명: PartSelect (part_mng 8,176건 검색 + 자동 매핑)
- 제품구분/반납사유: CommCodeSelect (0000001 / 0001810)
- S/N: 별도 다이얼로그(테이블 + 연속번호생성) — wace fn_openItemSnPopup / fn_openItemSequentialSnPopup 1:1
- 합계: useMemo로 라인 수량/공급가액/부가세/총액 실시간 집계

EMPTY_ITEM 라인 기본값에 product/serials/due_date/return_reason/customer_request 추가.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 10:24:25 +09:00
hjjeong 7c03907000 PR-B G2: 주문관리 수주입력 = 직접등록 통합폼 (is_direct_order='Y' + order_date + approval_required)
wace 패턴(estimateAndOrderRegistFormPopup + saveEstimateAndOrderInfo) 이식.
운영 데이터 90건 중 74건이 is_direct_order='Y' — 주문 신규 등록의 기본 흐름.

변경:
- 백엔드 OrderBody: order_date / approval_required / is_direct_order 신규 (contract_date 폐지, 운영 컬럼명 일치)
- create()/update() INSERT·UPDATE에 위 3개 컬럼 추가. is_direct_order 기본값 'Y'
- 프론트 OrderBody 타입 동기화. openCreate 시 order_date=today + is_direct_order='Y' 자동
- 폼 다이얼로그 "발주일" 입력을 order_date 바인딩 (잘못 contract_date 바인딩 정정)

자동 검증 (BEGIN/ROLLBACK):
- is_direct_order='Y' INSERT, order_date 저장, ORDER_* 라인 컬럼 정상
- 견적관리 그리드 노출 차단(IS_DIRECT_ORDER!='Y' 필터), 주문관리 그리드 노출 확인

docs/migration/sales/05-direct-order-verify.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 10:17:04 +09:00
hjjeong 548d365798 Merge pull request 'hjjeong' (#5) from hjjeong into main
Reviewed-on: https://g.wace.me/chpark/vexplor_rps/pulls/5
2026-05-11 01:11:13 +00:00
hjjeong 86e3aef6f7 영업 4개 메뉴 그리드: wace JSP 주석 처리된 비활성 컬럼들 정정 (V1 보강 잘못 활성화 되돌림)
원인: wace JSP의 var columns 끝에 있는 /* 주석처리된 컬럼 */ 블록은 비활성 보존 영역(메모리 feedback_wace_jsp_columns)인데, V1 보강 커밋에서 추측으로 활성화함. 운영 화면에 노출되지 않는 컬럼이므로 원본대로 주석으로 되돌림.

비활성으로 복귀한 컬럼:
- 견적관리(estimateList_new.jsp 494~502): 제품구분 / 국내해외 / 반납사유
- 주문관리(orderMgmtList.jsp 429~434): 제품구분 / 국내해외 / 접수일
- 판매관리(salesMgmtList.jsp 503~519): 제품구분 / 국내해외 / 접수일 / 고객사요청사항 / 주문서첨부 / 출하방법 / 담당자 / 인도조건
- 매출관리(revenueMgmtList.jsp 615~632): 접수일 / 유무상 / 요청납기 / 고객사요청사항 / 수주상태 / 주문서첨부 / 출하방법 / 담당자 / 인도조건

코드는 주석 블록으로 남겨두어 필요시 활성화 가능. 백엔드 SQL은 그대로 두어 다른 메뉴에서 재사용 가능.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 10:09:09 +09:00
hjjeong 293339724c 영업 4개 메뉴 그리드 컬럼 너비 보강 (날짜·발주번호·프로젝트번호 잘림 해소)
YYYY-MM-DD 날짜 10자가 잘리던 컬럼 + 발주번호(10~13자 PO) + 프로젝트번호(한글 포함) 너비 상향.

- 견적관리: 영업번호 110→125, 접수일 100→115, 요청납기 110→160
- 주문관리: 영업번호 120→125
- 판매관리: 프로젝트번호 140→170, 발주일 100→115, 발주번호 110→140, 요청납기/출하일/접수일 100/110→115
- 매출관리: 프로젝트번호 140→170, 발주일/출하일 100→115, 발주번호 110→140, 접수일/요청납기 100/110→115

(개별 사용자 환경에서는 컬럼 드래그 리사이저 + localStorage로 추가 미세조정 가능)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 10:04:23 +09:00
hjjeong f34eddb9fc 영업관리 PartSelect·JOIN을 part_mng 전용 테이블로 분리 (item_info 혼재 데이터 해소)
배경:
  item_info에 wace 마이그레이션(numeric id 8,179건) + RPS 자체 등록(UUID 21k건)이 섞여 있어
  PartSelect/그리드 JOIN에서 잡 데이터(-20260126-, 00 등)와 RPS 자체 등록 데이터가 노출됨.
  wace 도메인 메뉴는 part_mng만 참조하도록 분리. 개발관리 등 다른 wace 메뉴도 동일 테이블 활용.

변경:
- DDL: docs/migration/sales/ddl-extracted/105_create_part_mng.sql
  (item_info의 numeric id 데이터를 part_mng로 컬럼 매핑 INSERT, 8,176건 적재)
- backend service JOIN 6곳 교체: item_info IT → part_mng PM (PM.objid::varchar = CI.part_objid)
  · salesEstimateService.ts (getList LATERAL JOIN, getById 라인 조회 — 2곳)
  · salesOrderMgmtService.ts (getList, getById, getOrderFormView, createProjectsFromContract — 4곳)
- /sales/parts endpoint: part_mng SELECT + status active/release/활성 필터.
  반환 키는 기존 호환을 위해 id/item_number/item_name으로 alias (objid::varchar/part_no/part_name).
- 자동 검증: scripts/verify-part-mng.sql (카운트·JOIN·그리드 SQL·잡 데이터 제거 검증)

영향:
- item_info는 그대로 — RPS 자체 메뉴(/sales/sales-item 등) 전용으로 유지
- ecrMngService, wacePlmDataImportService 등 RPS 다른 모듈은 이미 part_mng 사용 가정 → 자연 활성화

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 09:56:45 +09:00
hjjeong d23b305990 매출관리 그리드 V1 컬럼 9개 보강 + getRevenueList SQL JOIN 확장 + wace 1:1 검증
- getRevenueList SQL: contract_item / user_info / comm_code(CC_RES) / attach_file_info LATERAL 4개 JOIN 추가. receipt_date / payment_type / request_date / customer_request / order_status_name / manager_name / incoterms / cu01_cnt SELECT 보강
- RevenueListRow 타입: 9개 신규 필드 보강
- GRID_COLUMNS 9개 추가: 접수일/유무상/요청납기/고객사요청사항/수주상태/주문서첨부/출하방법/담당자/인도조건 (wace 35/35 일치)
- docs/migration/sales/04-revenue-verify.md, scripts/verify-revenue.sql

영업 4개 메뉴 (견적·주문·판매·매출) 모두 구조적 검증 1차 종결.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 09:42:21 +09:00
hjjeong a0f6e0fa26 판매관리 그리드 V1 컬럼 8개 보강 + cu01_cnt 실데이터 + wace 1:1 검증 문서·자동 검증 SQL
- getList SQL: attach_file_info LATERAL JOIN으로 cu01_cnt(주문서첨부) 실데이터 (contract_mgmt.objid 기반, doc_type IN FTC_ORDER/ORDER)
- SaleListRow 타입: product_type_name/nation_name/receipt_date/customer_request/manager_name/payment_type_name/cu01_cnt 보강
- GRID_COLUMNS 8개 추가: 제품구분/국내해외/접수일/고객사요청사항/주문서첨부/출하방법/담당자/인도조건 (wace 36/36 일치)
- docs/migration/sales/03-sale-verify.md: wace ↔ RPS 매핑 / 갭 처리
- scripts/verify-sale.sql: BEGIN/ROLLBACK 2개 시나리오 (그리드 V1 / 판매상태 wace 로직)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 09:38:57 +09:00
hjjeong 13b4efd2fe 주문관리 그리드 V1 컬럼 보강(제품구분·국내해외·접수일) + wace 1:1 검증 문서·자동 검증 SQL
- getList SQL: 라인 집계에 product_summary 추가, PRODUCT_NAME을 COALESCE(line, header)로 변경 (운영 contract_mgmt.product NULL 패턴 대응)
- GRID_COLUMNS 3개 추가: 제품구분/국내해외/접수일 (wace 27/27 일치)
- OrderRow 타입: product_name / area_name 보강
- searchForm.search_partName 키 추가(초기화 포함, UI 이미 PartSelect mode=partName 존재)
- docs/migration/sales/02-order-verify.md: wace ↔ RPS 항목 매핑 / 운영 데이터 / 갭 처리 결과
- scripts/verify-order.sql: BEGIN/ROLLBACK 4개 시나리오 (그리드 V1 / G1 / 수주취소 / 채번) 자동 검증

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 09:35:11 +09:00
hjjeong 12ea68616d 견적관리 그리드 V1 컬럼 보강(제품구분·국내해외·반납사유) + wace 1:1 검증 문서·자동 검증 SQL
- getList SQL: 라인 집계에 product_summary(=PRODUCT_NAME, contract_item.product distinct join) / return_reason_summary 추가. wace는 헤더 product 폐지·라인으로 이동(운영 90건 contract_mgmt.product NULL) → 라인 집계로 그리드 표시
- GRID_COLUMNS 3개 추가: 제품구분 / 국내해외 / 반납사유
- searchForm.search_partName 필드 추가(초기화 포함). 검색 폼 UI는 PartSelect mode=partName 이미 존재
- docs/migration/sales/01-estimate-verify.md: wace ↔ RPS 항목 매핑 / 운영 데이터 코드 체계 / 갭 우선순위
- scripts/verify-estimate.sql: BEGIN/ROLLBACK 5개 시나리오 (등록·수정·G1·수주취소·그리드) 자동 검증

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 09:29:43 +09:00
hjjeong 7cbf938345 Merge pull request 'hjjeong' (#4) from hjjeong into main
Reviewed-on: https://g.wace.me/chpark/vexplor_rps/pulls/4
2026-05-09 07:55:51 +00:00
hjjeong 66e2a63dfa 영업관리 G1 수주확정→프로젝트 자동생성 + 견적요청등록 wace 1:1 이식
- G1: salesOrderMgmtService.updateStatus 트랜잭션화 + project_mgmt 자동생성 (project_no 채번/Machine 분기/contract_item 라인별 INSERT)
- 수주확정 다이얼로그(상태 select 팝업) + 수주취소 다이얼로그(라인별 cancel_qty)·POST /sales/order-mgmt/:id/cancel-qty 신설
- 견적요청등록 폼: estimate_template 분리, 헤더 8(주문유형/국내해외/고객사/유무상/접수일/견적환종/견적환율/결재여부) + 라인 8(제품구분/품번/품명/S/N/견적수량/요청납기/반납사유/고객요청사항) wace 운영 화면과 1:1
- S/N 관리 다이얼로그(테이블+연속번호생성), PartSelect/CommCodeSelect/CustomerSelect 셀렉트박스 + ✕(선택해제), 수주확정된 행 라인 추가/삭제 차단
- DataGrid 체크박스 모드 (영업번호 No → 체크박스, 행 어디 클릭이나 단일 선택)
- 식별자 정합성: contract_mgmt.customer_objid를 customer_mng.customer_code 기반(C_xxxx)으로 통일, contract_no 채번 {YY}C-{NNNN} 운영 패턴 일치, contract_item.quantity ::integer 캐스트

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 16:48:25 +09:00
chpark 575098698c 배치 편집 conditional 매핑 평가 필드 UX 개선
- 평가 필드 미선택 시 select 에 빨간 테두리 + ring 강조 (한눈에 누락 식별)
- 라벨에 * 필수 마크 + placeholder 를 '조건을 평가할 API 필드 선택 (필수)' 로 변경
- 안내 텍스트 추가: 'status 컬럼에 enrlFg 의 J01→active 변환 시 평가 필드=enrlFg' 예시
- 저장된 apiField 가 fromApiFields 옵션에 없을 때 동적으로 (저장값) 라벨로 추가
  → 응답 미리보기 안 한 편집 모드에서도 기존 값 보존되어 그대로 저장 가능
- cn 유틸 import 추가 (조건부 클래스 적용 시 ReferenceError 방지)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 18:24:12 +09:00
chpark 4007042311 ECR · 고객 CS · 결재 시스템 + Amaranth 전자결재 RestAPI 연계 + wace_plm 데이터 import
[ECR(Engineering Change Request) 관리]
- ecr_mng / product_mgmt / part_mng 테이블 + seq_ecr_no 시퀀스
- 설변요청 코드(0000090) 자식 코드 시드 (설계오류/품질개선/원가절감/고객요청/법규대응/부품단종)
- API: 목록/상세/등록·수정(merge)/조치완료/삭제 + 옵션(작성자/제품/부품/공통코드)
- 화면: 필터바, 그리드, 등록·수정 모달, 상세 모달, 조치완료 모달

[고객 CS 관리]
- customer_cs_mng 테이블 (기존 customer_mng 거래처 마스터와 충돌 회피)
- 공통코드 5종 카테고리(0000200~0000204) 자동 시드: 관리유형/제품구분/담당자/조치유형/CS상태
- API: 목록/상세/등록·수정/삭제/대시보드(요약·상태별·관리유형별·제품구분별)
- 화면: 요약 카드 4종, 10종 필터바, 14컬럼 그리드, 등록·수정·상세 모달

[결재(APPROVAL) 시스템 — wace_plm ApprovalService 포팅]
- approval / route / inboxtask / approval_target / approval_kind / amaranth_approval 6개 테이블
- 라이프사이클: 상신(startApproval) → 결재함(listInbox) → 승인/반려(approveTask/rejectTask)
  → 다음 결재자 ready 자동 전달, 마지막이면 route+approval+target 일괄 complete
- target_type 별 도메인 status 동기화 훅 (ECR_MNG/CUSTOMER_MNG)
- API: /api/wace-approval/{inbox,start,inbox/:id/approve|reject,by-target,:id,:id/amaranth-link}

[Amaranth(Wehago) 전자결재 RestAPI 연계]
- 외부 커넥션 'Amaranth - 결재' 자동 시드 (auth_config: callerName/accessToken/hashKey/groupSeq/aesKey)
- amaranthApprovalClient: 자바 AmaranthApprovalApiClient 1:1 포팅
  HMAC-SHA256 wehago-sign / AES-128-CBC empSeq 암호화 / HTTPS / JSON 파싱
- 6개 endpoint: 인증토큰/결재함/문서목록/문서상세/SSO URL/문서상신
- 하드코딩 0건 — DB 외부 커넥션의 인증 정보를 매 호출 시 로드
- 통신 검증 완료 (dummy empSeq 로 응답 정상 수신)
- 프록시 라우트 /api/amaranth-approval/{box,docs,docs/:id,sso,submit,auth-token}

[wace_plm 데이터 import]
- WacePlmDataImportService: source PG 클라이언트 → 우리 DB ON CONFLICT DO NOTHING idempotent
- 환경변수 WACE_PLM_DB_* 만 읽음 (운영 비번 코드 0건, 미설정 시 명시적 에러)
- /api/wace-import/{all,ecr,cs,masters,approval} (SUPER_ADMIN 전용)

[Bugfix]
- 배치 편집 conditional 매핑 silent drop 방지 — 평가 필드/규칙 누락 시
  어느 컬럼이 어떤 이유로 빠졌는지 toast 로 명시 + 저장 차단
- 시드 topup 강화 — extra_auth_config(aesKey 등) 누락된 기존 레코드 자동 보강

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 17:01:56 +09:00
hjjeong 10e9996249 DataGrid 컬럼 너비 마우스 드래그 리사이저 + localStorage 영구 저장
- 헤더 우측 6px 영역 드래그 핸들 (col-resize 커서 + hover 강조)
- mousedown→document mousemove/mouseup으로 너비 계산 (최소 40px)
- columnWidths state로 inline width 적용 (Tailwind w-[Xpx]는 fallback)
- gridId prop이 있으면 localStorage에 영구 저장 → 새로고침 후 유지
- 컬럼 순서 드래그(@dnd-kit)와 충돌 안 하도록 핸들 영역 분리

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 14:53:08 +09:00
hjjeong b7a6816ef2 영업관리 GAP 분석 문서 신설 + README 다음 작업 갱신
00-gap.md: wace_plm 원본 흐름 vs vexplor_rps 이식본 GAP 매트릭스. 다음 PR 우선순위(A: 수주확정→프로젝트 자동생성, B: 직접등록 통합폼, C: 결재·메일·PDF) 합의 문서.
README.md: §7 다음 작업 항목을 완료 처리하고 00-gap.md 우선 합의로 재정렬.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 14:48:24 +09:00
hjjeong 2d9f30ebab 영업관리 첨부파일 모달·주문서 뷰 + DataGrid frozen 컬럼
- 공통 AttachmentDialog 컴포넌트 신설 (목록/업로드/다운로드/삭제, doc_type 단일·배열 지원)
- 견적 add_est_cnt(클립) → AttachmentDialog (estimate02)
- 주문 cu01_cnt(클립) → AttachmentDialog (FTC_ORDER,ORDER), has_order_data(폴더) → OrderFormViewDialog
- OrderFormViewDialog 신설 — wace orderFormView 한국 표준 주문서 양식 + 인쇄
- 백엔드 fileController.getFileList docType 콤마 멀티값 지원, salesOrderMgmt.getOrderFormView API 추가
- DataGrid 확장: column.onClick / frozen prop / table-fixed / sticky-left + selected·hover 일관 처리
- 4개 메뉴 첫 컬럼 frozen 적용 (영업번호/프로젝트번호)
- 주문서관리 발주일·발주번호·요청납기 컬럼 너비 확장

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 14:48:13 +09:00
hjjeong acc2b8a88f Merge pull request '영업관리 4개 메뉴 검색폼 wace 일치 + 공통 UX(초기화·date input) 정비' (#3) from hjjeong into main
Reviewed-on: https://g.wace.me/chpark/vexplor_rps/pulls/3
2026-05-08 01:43:09 +00:00
hjjeong 489fa50d11 영업관리 4개 메뉴 검색폼 wace 일치 + 공통 UX(초기화·date input) 정비
- 검색 폼 정합성: wace JSP `<!-- 주석처리된 검색필터 -->` 블록까지 잘못 이식했던 부분 정정
  - 견적: 11→7개 (제품구분/국내해외/유무상/요청납기 제거)
  - 주문: 13→9개 (제품구분/국내해외/유무상/견적환종 제거)
  - 매출: 10→11개 (출하지시상태 제거 + 제품구분·국내/해외 추가, JSP 순서로 재배치)
  - 판매: 변경 없음 (원본 그대로 일치)
- 매출 백엔드: SaleListFilter에 productType/nation 추가, getRevenueList에 partObjId/serialNo/orderDate/productType/nation 5개 필터 처리
- 공통 UX
  - 초기화 버튼을 4개 메뉴 동일하게 통일 (variant=ghost, 버튼 영역 끝)
  - <Input type="date">는 빈 값 placeholder 숨김 + 캘린더 아이콘 숨김 + 영역 클릭으로 picker 자동(showPicker)
- 신규 공통 컴포넌트: CommCodeSelect/CustomerSelect/CustomerSearchDialog/PartSelect/ItemSearchDialog + backend salesCommonRoutes
- 문서: 01/02/04 검색 폼 표를 활성/비활성 분리 형식으로 정정, README에 8. 공통 UX 규칙 섹션 신설

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 10:42:16 +09:00
chpark 4c3ea194a0 권한 그룹 코드 자동 생성 + 대시보드 API URL 환경변수 우선
- RoleFormModal: 권한 코드 입력 필드 제거. 생성 시 ROLE_<base36 timestamp>
  형태로 자동 부여 (시스템 내부 키, UI 비노출). 수정 모드에서도
  authCode 는 기존 값 유지하고 입력 받지 않음.
- dashboard.ts getApiBaseUrl: NEXT_PUBLIC_API_URL 환경변수가 있으면 우선 사용.
  fallback 포트를 8080 → 8090 (compose 외부 노출 포트)으로 정정해
  '데이터를 불러올 수 없습니다 / Failed to fetch' 해결.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 09:07:40 +09:00
chpark 442f4dc115 Merge backup/ui-compact-e9d6a701 (관리자 화면 컴팩트 리디자인 + Docker 프로젝트 분리) 2026-05-07 19:33:47 +09:00
chpark 638543b37a Merge feature/rps-rebrand-pipeline-design (사이드바 SUPER_ADMIN + NewRoomModal 가드)
# Conflicts:
#	backend-node/src/services/adminService.ts
#	frontend/components/messenger/NewRoomModal.tsx
2026-05-07 19:33:41 +09:00
chpark c17086f8c4 Merge origin/feature/rps-rebrand-pipeline-design into main (영업관리 + wace-migration)
# Conflicts:
#	frontend/components/messenger/MessageInput.tsx
#	frontend/components/messenger/NewRoomModal.tsx
2026-05-07 19:32:41 +09:00