Compare commits

534 Commits

Author SHA1 Message Date
김보곤
4a3d14a591 feat: [payroll] 급여명세서 이메일을 PDF 첨부파일로 변경
- 이메일 본문에 급여 내역 직접 노출 → PDF 첨부파일로 전환 (보안 강화)
- barryvdh/laravel-dompdf 패키지 추가
- 이메일 본문은 간단한 안내 메시지로 변경
- dompdf에서 한글 렌더링을 위해 Noto Sans KR 폰트 적용
2026-03-10 09:12:25 +09:00
김보곤
01493c90f5 fix: [rd] 가이드레일 높이 오픈H+150 → 오픈H+100으로 변경 2026-03-10 07:33:23 +09:00
김보곤
2b1e8b559c fix: [rd] 스크린 가이드레일 립 절곡방향 수정 (안쪽→개구부 방향)
- 2D 평면도: 사이드월 길이 분리(swLen=bodyD-lp), 립이 개구부 방향으로 절곡
- 3D 렌더링: bodyShape/hole의 립 Y좌표 반전(-lp, 벽쪽→개구부쪽)
- 치수선, 씰, 슬랫, 클립 위치 업데이트
2026-03-10 01:41:22 +09:00
김보곤
85d52c9bc0 fix: [rd] 방화셔터 가이드레일 높이 계산 수정 (오픈H + 150mm)
- 기존: 표준 재고길이(3305mm) 선택 방식 → 오픈H + 305mm 표시
- 수정: 오픈H + 150mm 계산 (실제 가이드레일 높이)
- 3D 렌더링 레일 높이도 +100 → +150 수정
2026-03-10 01:28:34 +09:00
김보곤
4c2a905a94 feat: [payroll] 이메일 발송 후 '발송' 라벨 표시 기능
- payrolls 테이블 options JSON에 email_sent_at/email_sent_to 저장
- 이메일 아이콘 아래 '발송' 텍스트 표시 (서버 렌더링 + JS 즉시 반영)
- Payroll 모델에 options 컬럼 추가
2026-03-10 01:21:28 +09:00
김보곤
dfa193f369 fix: [payroll] 급여명세서 이메일 버튼 Blade 파싱 오류 수정
- @json() 내부 (int) 캐스팅이 Blade 파서 괄호 매칭 혼란 유발
- @php 블록에서 데이터를 미리 준비하고 @json($var)로 전달
2026-03-10 01:12:21 +09:00
김보곤
5ac4495d6b feat: [payroll] 급여명세서 이메일 발송 기능 추가
- PayslipMail Mailable 클래스 생성 (admin@codebridge-x.com 발송)
- 급여명세서 이메일 템플릿 (전통 한국식 양식)
- 이메일 발송 API 엔드포인트 추가 (POST /payrolls/{id}/send-payslip)
- 목록 테이블에 이메일 발송 아이콘 버튼 추가
- 급여명세서 미리보기 모달 + 인쇄 기능
2026-03-10 01:06:48 +09:00
김보곤
2fc4754dd6 fix: [leave-promotions] 단일 상태열 제거, 1차/2차 통지열에 결재상태 뱃지 통합 2026-03-10 00:51:15 +09:00
김보곤
36ca51afc3 feat: [leave-promotions] 통지서 미리보기 모달 기능 추가
- 1차/2차 통지 눈 아이콘 클릭 시 통지서 문서 모달 팝업
- 결재 상태 뱃지, 발송일시, 인쇄, 결재문서 링크 포함
2026-03-10 00:45:01 +09:00
김보곤
0ef6b72d8e feat: [hr] 연차촉진 관리에 1차/2차 촉진기간 컬럼 추가
- 근로기준법 제61조 기준 입사일 기반 촉진기간 자동 계산
- 1차 촉진기간: 연차만료 6개월 전 ~ +10일
- 2차 촉진기간 마감: 연차만료 2개월 전
- 잔여일수 다음에 촉진기간 표시
2026-03-10 00:37:33 +09:00
김보곤
694646158d feat: [approval] 결재서명란에 참조자 표시 추가
- 결재 테이블 하단에 참조자 녹색 칩 표시
- reference step_type 필터링하여 존재 시에만 표시
2026-03-10 00:16:42 +09:00
김보곤
fcdffa66db feat: [hr] 휴가관리 참조자 선택 기능 추가
- 휴가 신청 모달에 참조자 검색/선택 UI 추가 (Alpine.js)
- 부서별 사용자 목록에서 참조자 검색 및 녹색 칩 표시
- LeaveController 참조 배열 유효성 검증 추가
- LeaveService에서 결재선 steps에 참조자 자동 병합
2026-03-10 00:10:16 +09:00
김보곤
2a82797926 fix: [hr] 급여관리 접근 권한 사용자 변경 (이경호 → 이의찬) 2026-03-10 00:10:16 +09:00
김보곤
b92a538cad feat: [fire-shutter] 스크린형 가이드레일/평면도 등 develop 미반영분 통합
- 스크린형 가이드레일 3D 구조, 평면도 전면 재설계
- 연기차단재/슬롯 개방/LIP 방향 수정
- 벽체 토글, Undo 기능, 셔터박스 개선 등
2026-03-09 23:47:57 +09:00
김보곤
a6d93f7c02 fix: [database] codebridge 모델 cross-DB 관계 오류 수정
- samdb 공유 모델에 $connection = 'mysql' 명시적 선언
- codebridge 모델에서 eager-load 시 connection 상속 방지
- 영향 모델: User, Tenant, Department, Process, File(2), Approval, AiQuotationModule, InterviewProject
2026-03-09 23:35:44 +09:00
김보곤
12427326df Reapply "feat: [database] codebridge DB 분리 재적용 - 55개 MNG 전용 모델만 설정"
This reverts commit 7371dda5a1.
2026-03-09 23:18:02 +09:00
김보곤
2e0f8ddb9b Reapply "feat: [database] Equipment 하위 4개 모델 codebridge connection 추가"
This reverts commit 1d5062a0b6.
2026-03-09 23:18:02 +09:00
7371dda5a1 Revert "feat: [database] codebridge DB 분리 재적용 - 55개 MNG 전용 모델만 설정"
This reverts commit 48aa4505f5.
2026-03-09 21:22:03 +09:00
1d5062a0b6 Revert "feat: [database] Equipment 하위 4개 모델 codebridge connection 추가"
This reverts commit ea5f064574.
2026-03-09 21:21:58 +09:00
김보곤
ea5f064574 feat: [database] Equipment 하위 4개 모델 codebridge connection 추가
- EquipmentInspection, EquipmentInspectionDetail, EquipmentInspectionTemplate, EquipmentRepair
- equipments 테이블과 FK 참조 관계 → 동일 DB(codebridge)에서 관리
2026-03-09 20:58:44 +09:00
김보곤
48aa4505f5 feat: [database] codebridge DB 분리 재적용 - 55개 MNG 전용 모델만 설정
- API 사용 테이블 22개(23개 모델) 제외하고 55개 모델만 $connection = 'codebridge' 적용
- config/database.php에 codebridge connection 재추가
- 제외 대상: Barobill 12개, ESign 4개, Audit 2개, DevTools 1개, System 2개, HR 1개
2026-03-09 20:02:38 +09:00
김보곤
47ce1aaac6 fix: [fire-shutter] const p 중복 선언 제거 2026-03-09 11:41:04 +09:00
김보곤
e81eb67e85 feat: [fire-shutter] 셔터박스 조립식 철판 구조, 라벨 오픈폭/오픈H 변경 2026-03-09 11:39:20 +09:00
김보곤
0d913b3f9e fix: [fire-shutter] 벽체 기본값 변경 (날개벽 600, 두께 600) 2026-03-09 11:33:27 +09:00
김보곤
71da28e26a fix: [fire-shutter] hw 변수명 충돌 해결 (whw로 변경) 2026-03-09 11:30:30 +09:00
김보곤
0560b99617 fix: [fire-shutter] 벽체 기둥+인방 U자 일체형으로 이음새 제거 2026-03-09 11:29:18 +09:00
김보곤
59a0af1884 fix: [fire-shutter] 벽체 기둥-인방 겹침(z-fighting) 해결 2026-03-09 11:15:05 +09:00
김보곤
3d01649e4f feat: [fire-shutter] 상단 설정 변경 시 3D 렌더링 동적 갱신 2026-03-09 11:09:49 +09:00
김보곤
4790433c64 refactor: [fire-shutter] 설정 영역을 전체 폭 상단바로 이동 2026-03-09 11:06:06 +09:00
김보곤
3ea2430e2e fix: [fire-shutter] 상세설정 토글 버튼 $ 참조 오류 수정 2026-03-09 10:59:26 +09:00
김보곤
f6bbf65a00 fix: [finance] 거래처 등록 필수값 개선 (거래처명+사업자번호만 필수)
- 백엔드: bizNo 필수 검증 추가, trade_type/status null-safe 처리
- 프론트엔드: 사업자번호 필수 검증 + 라벨에 * 표시 추가
- 나머지 필드 비어있어도 저장 가능하도록 NOT NULL 컬럼 기본값 보장
2026-03-09 10:54:24 +09:00
김보곤
22bbab22e1 fix: [finance] 거래처 등록/수정 시 NOT NULL 컬럼 기본값 누락 수정
- type, category 컬럼이 NOT NULL인데 빈 값 전달 시 null 변환되어 DB 오류 발생
- store: null 대신 DB 기본값(vendor, 기타) 적용
- update: null 대신 기존 값 유지
2026-03-09 10:50:05 +09:00
김보곤
edffdfc501 refactor: [fire-shutter] 좌측패널 UI 구조 개선 - 4탭→3탭+상단 설정바 2026-03-09 10:28:07 +09:00
김보곤
8136fbe6b6 fix: [rd] 셔터박스 Z 오프셋을 샤프트 기반으로 변경
- 샤프트 앞면이 가이드레일(Z=0) 바로 뒤에 위치하도록 계산
- 철재: boxZOffset=-65mm (기존 -195mm), 스크린: -45mm (기존 -125mm)
- frontRatio 방식 제거, 샤프트 직경 기반 계산
2026-03-09 10:17:36 +09:00
김보곤
c6609018b9 feat: [rd] 방화셔터 제품별 셔터박스 기본 치수 + 비대칭 Z 오프셋
- 철재: 650×550mm, 스크린: 500×380mm 기본값 적용
- 제품 타입 전환 시 셔터박스 높이/깊이/샤프트경 자동 업데이트
- 비대칭 Z 오프셋: 가이드레일(Z=0) 기준 후면으로 더 돌출
  - 철재: frontRatio 0.20 (앞 130mm, 뒤 520mm)
  - 스크린: frontRatio 0.25 (앞 125mm, 뒤 375mm)
- 샤프트/모터/슬랫롤 Z 위치를 박스 중심에 동기화
2026-03-09 10:06:51 +09:00
김보곤
ef88d4044d fix: [rd] 모터 Z 오프셋 절반 축소 + 중복 체인 박스 제거
- 모터 이격거리: 150mm → 75mm (motorZ: -270 → -195)
- 체인 직선 두께 박스(csTop/csBot) 제거, Line 경로만 유지
2026-03-09 09:48:11 +09:00
김보곤
920f858574 fix: [rd] 방화셔터 모터 Z 오프셋 150mm 추가 (슬랫 감김 간섭 방지) 2026-03-09 09:42:47 +09:00
김보곤
99cc6f24cd feat: [rd] 방화셔터 3D 단품 보기(Isolation) 기능 추가
- 우클릭 컨텍스트 메뉴: 객체 클릭 시 '단품 보기', 빈 공간 시 '전체 보기'
- Raycaster 기반 객체 감지 (Group 자식까지 추적)
- 단품 보기 시 카메라 자동 포커스 (BoundingBox 기반)
- 상태 배지 표시 (클릭으로 전체 보기 복원)
- 재빌드 시 단품 상태 유지
2026-03-09 09:38:43 +09:00
김보곤
2b8f0c680e fix: [rd] 방화셔터 체인/스프로켓 시각화 수정
- 샤프트 스프로켓 반지름 130→70mm (브라켓 180mm 내 수용)
- 모터 스프로켓 반지름 45.5→30mm
- 양쪽 스프로켓에 톱니바퀴 메시 추가 (18/10개 톱니)
- 체인 직선 구간 기울기 회전 적용
2026-03-09 09:31:51 +09:00
김보곤
4e1de76f15 fix: [rd] 모터측 브라켓 앞 큰 스프로켓 디스크+허브 제거
- 샤프트 스프로켓 메시(ø260) 및 허브 메시 삭제
- 스프로켓 좌표는 체인 경로 계산용으로만 유지
2026-03-09 09:15:41 +09:00
김보곤
e1120c28f6 fix: [rd] 모터측 큰 플랜지 삭제, 3인치 연결관→브라켓 직결
- 모터측 플랜지(flangeMT) 삭제 (실제 없는 부품)
- 3인치 연결관이 샤프트 끝에서 복주머니까지 직접 연결
- 비모터측 플랜지만 유지
2026-03-09 08:53:56 +09:00
김보곤
75d9148b5b feat: [rd] 모터측 샤프트 ASSY 구현 (3인치 연결관+복주머니)
- 모터측: 메인샤프트 → 플랜지 → 3인치 연결관(ø76) → 복주머니 → 브라켓
- 복주머니: 브라켓과 직접 결합되는 특수 플랜지 (연결관보다 약간 큼)
- 비모터측: 기존 환봉 구조 유지
2026-03-09 08:41:36 +09:00
김보곤
be2dde6b1d fix: [rd] 플랜지 외경 = 샤프트 내경 - 1mm 공차
- 샤프트 관 두께 4mm 정의
- 플랜지 외경 = shaftR - 4mm(관두께) - 0.5mm(공차)
- 플랜지가 샤프트 안으로 삽입되는 실제 구조 반영
2026-03-09 08:30:22 +09:00
김보곤
619c0885d2 fix: [rd] 플랜지 외경=샤프트 동일 + 초기 탭 3D로 변경
- 플랜지: 샤프트 끝에 딱 들어가는 형태 (외경=샤프트 외경)
- 초기 탭: Settings → 3D 렌더링으로 변경
2026-03-09 08:28:47 +09:00
김보곤
1fff76ee2e fix: [rd] 샤프트 길이 축소 + 양쪽 환봉 노출
- 샤프트 관: W1-400mm (양쪽 환봉 200mm씩 노출)
- 환봉: ø30, 200mm 밖으로 보임 (전체 300mm 중 100mm는 플랜지 내부)
- 모터측에도 환봉 추가
- 플랜지 위치를 샤프트 끝 바깥으로 수정
- slat roll 길이도 샤프트에 맞춤
2026-03-09 08:25:10 +09:00
김보곤
caec5bf854 feat: [rd] 샤프트 ASSY 구조 구현 (환봉+플랜지)
- 비모터측 브라켓: 환봉(stub pin ø30) 중앙 돌출
- 양쪽 샤프트 끝: 플랜지 디스크 (샤프트 용접)
- 구조: 브라켓→환봉→플랜지→샤프트관 (실제 조립 구조)
2026-03-09 08:19:33 +09:00
김보곤
c429e6f183 fix: [rd] 비모터측 브라켓 도면 치수 적용 (180×180mm)
- 비모터측: 180×180mm 두께 18mm (도면 기준)
- 모터측: 380×180mm 두께 18mm (기존 유지)
- 계산값(height*0.7, depth*0.6) → 실측 치수로 변경
2026-03-09 08:12:23 +09:00
김보곤
dc59b0e3b4 fix: [rd] 모터를 샤프트와 수평(Z방향)으로 재배치
- 모터가 가이드레일쪽(Y-) 배치 → 셔터박스 깊이방향(Z-) 수평 배치
- 슬랫과의 간섭 해소
- 브라켓 380mm를 Z방향으로 설정 (샤프트~모터 수용)
- 체인 경로를 YZ 수평 루프로 변경
2026-03-09 08:06:49 +09:00
김보곤
3103535d47 fix: [rd] slat roll을 단일 실린더로 변경 (접시 모양 제거)
- 디스크/링 제거, 샤프트 전체에 감기는 하나의 실린더로 표현
- 최소 두께 8mm 보장 (적은 감김에서도 보이도록)
- 나선형 표면 라인으로 감긴 질감 표현
2026-03-09 07:59:01 +09:00
김보곤
0a32bba5d9 fix: [rd] 방화셔터 slat roll 시각화 개선
- 모터 Y 위치 수정 (스프로켓 겹침 해소)
- slat roll 색상/형태 개선 (양쪽 디스크, 나선형 표면 라인)
- 재빌드 후 토글 visibility 동기화 추가
2026-03-09 07:52:37 +09:00
김보곤
48688cf81b fix: [rd] 복주머니+플랜지를 모터 그룹으로 이동
- 모터 숨기면 복주머니+플랜지도 함께 숨김
- 샤프트는 복주머니 없이 자기 구간까지만 표시
- 모터 ON: 브라켓 ← 모터 ← 출력축 ← 복주머니 ← 샤프트
- 모터 OFF: 샤프트만 남음 (비모터측 브라켓+환봉까지)
2026-03-08 22:12:48 +09:00
김보곤
1166c5ebc7 fix: [rd] 모터측 브라켓을 모터 그룹에 추가
- 모터측 브라켓은 모터 그룹 소속 (모터 숨기면 함께 숨김)
- 구조: 벽 ← 브라켓 ← 모터 ← 출력축 ← 복주머니 ← 샤프트
- 비모터측: 벽 ← 브라켓 ← 환봉 ← 샤프트
2026-03-08 22:09:51 +09:00
김보곤
03e17d2a3d fix: [rd] 모터측 브라켓 제거 — 모터가 복주머니로 샤프트에 직접 결합
- 모터측 브라켓 제거 (비모터측에만 브라켓 존재)
- 복주머니가 셔터박스 끝에서 직접 시작
- 모터 → 출력축 → 복주머니 → 샤프트 직결 구조
- 주축 길이 재계산 (모터측 브라켓 두께 제외)
2026-03-08 22:06:30 +09:00
김보곤
9da1823750 feat: [rd] 모터 형상 실제 DH-150K 스타일로 재설계
- 은색 본체 실린더 + 냉각 핀 리브 3줄
- 파란색 기어박스 (본체보다 넓음, 복주머니 쪽)
- 기어박스 전면 플랜지 (복주머니 결합면)
- 후면 마감판
- 마운팅 베이스 플레이트 + 3개 다리 (브라켓 위에 안착)
- 출력축 (기어박스 → 복주머니 방향)
2026-03-08 22:03:37 +09:00
김보곤
85a3c8de47 fix: [rd] 모터 방향 수정 — 브라켓 안쪽(샤프트 방향)으로 배치
- 모터를 브라켓 바깥(벽쪽)에서 안쪽(복주머니 옆)으로 이동
- 돌출축이 복주머니 방향으로 향하도록 수정
- 마감판은 바깥(샤프트 반대편)에 위치
2026-03-08 21:51:54 +09:00
김보곤
f4a39afe12 feat: [rd] 모터 구조 개선 — 샤프트 1.2배 크기 + 돌출축-복주머니 결합
- 모터 크기를 샤프트 직경의 1.2배로 조정
- 모터 돌출축 (output shaft) 추가
- 복주머니 플랜지 링 추가 (모터축-샤프트 결합면)
- 모터 후면 마감판 (end cap) 추가
- 모터를 브라켓 바깥에 배치 (돌출축이 복주머니와 결합)
2026-03-08 21:47:19 +09:00
김보곤
18e47ffc69 fix: [rd] 벽체 구조 수정 — 통 기둥 + 인방 분리
- 좌/우 기둥을 하나의 통 박스로 통합 (분리 안 됨)
- 인방을 셔터박스 윗면부터만 생성 (셔터박스 내부 침범 제거)
- 개구부 뒤쪽 벽 제거 (통과 가능)
2026-03-08 21:42:36 +09:00
김보곤
3cdecc7b82 fix: [rd] 벽체 개구부 통과 구조로 변경
- 뒷벽을 좌/우 분리 + 상부 인방으로 3조각 구성
- 개구부(셔터 영역)는 뚫려서 통과 가능
- 셔터 열렸을 때 실제 건물처럼 통행 가능한 구조
2026-03-08 21:37:24 +09:00
김보곤
c0b670ce1c feat: [rd] 3D 벽체 설정 기능 추가
- 3면 벽체 구조 (좌/우 날개벽 + 뒷벽)
- 날개벽 폭, 벽 두께, 상단 여유 슬라이더 조절
- 벽체 투명도 슬라이더 (0~100%)
- 색상 프리셋 6종 (콘크리트/벽돌/흰색/커튼월/갈색/ALC) + 직접 선택
- 벽체 와이어프레임 윤곽선 표시
2026-03-08 21:34:00 +09:00
김보곤
625790a78a fix: [rd] 철재 슬랫 감김 두께 수정 (72mm→10mm)
- 72mm는 슬랫 폭이지 감김 두께가 아님
- ㄷ자 슬랫 감김 시 실제 적층 두께 ~10mm로 수정
2026-03-08 21:24:11 +09:00
김보곤
16d10c614d feat: [rd] 3D 샤프트 슬랫 감김 롤 표현
- 셔터 올라간 만큼 샤프트 주위에 감긴 롤 원통 표시
- 철재: ㄷ자 72mm 피치 (두꺼운 감김) + 골 링 라인 표현
- 스크린: 1mm 피치 (얇은 감김)
- 개폐 슬라이더 조작 시 롤 두께 실시간 변화
2026-03-08 21:21:01 +09:00
김보곤
0f96834214 fix: [rd] 3D 개폐 조절 시 카메라 시점 유지
- 셔터 개폐 슬라이더 조작 시 카메라 위치가 리셋되던 문제 수정
- 최초 빌드 시에만 카메라 초기화, 이후 재빌드에서는 현재 시점 유지
2026-03-08 21:12:07 +09:00
김보곤
4206111a13 fix: [rd] 모터 위치/형상 수정 — 브라켓 안쪽에 3개 다리로 안착
- 모터를 벽쪽(바깥)에서 샤프트 방향(안쪽)으로 이동
- 원통형 모터 본체로 변경
- 3개 마운팅 다리 추가 (브라켓 위에 안착)
2026-03-08 21:09:37 +09:00
김보곤
664b561edf feat: [rd] 방화셔터 3D 샤프트 조립 구조 구현
- 가이드레일 높이 수정: 셔터박스 상단까지 → 샤프트 아래 100mm까지
- 브라켓 양쪽 추가 (BoxGeometry)
- 비모터측 환봉 (thin cylinder) 추가
- 모터측 복주머니 커플링 (wider cylinder) 추가
- 주축 샤프트를 환봉~복주머니 사이로 단축
- 모터 위치를 브라켓 바깥으로 이동
2026-03-08 20:59:15 +09:00
김보곤
74ed1c83a7 fix: [fire-shutter] 셔터박스 기본값 수정(2210/520/10), 정면도 샤프트/슬랫을 브래킷 연결 수평바 형태로 변경 2026-03-08 20:48:26 +09:00
김보곤
f34c7c5473 fix: [fire-shutter] 가이드레일 기본값 수정(120/75/1.55/0.8), 횡단면→평면도 용어 변경 2026-03-08 20:40:53 +09:00
김보곤
7cf6bcabc3 fix: [fire-shutter] HEAD BOX→셔터박스(CASE) 용어 수정, 3D 슬랫 라인 좌표를 로컬 좌표로 변환 2026-03-08 20:31:34 +09:00
김보곤
c05b7813d0 fix: [fire-shutter] SVG 미리보기 미표시 수정 (wrapper div 크기 명시, displaySvg 헬퍼 통합) 2026-03-08 20:24:24 +09:00
김보곤
069d981850 refactor: [fire-shutter] 3:7 가로 레이아웃 적용 (설정패널 좌측 30%, 미리보기 우측 70%) 2026-03-08 20:17:39 +09:00
김보곤
9f4bf7e0c3 fix: [rd] 방화셔터 3D 셔터박스 위치 오류 수정
- wireframe이 case 자식으로 추가되면서 위치가 2배 적용되던 버그 수정
- boxLine.position 제거 (부모 case의 transform을 상속하므로 불필요)
2026-03-08 20:07:00 +09:00
김보곤
865fe60850 fix: [rd] 방화셔터 3D 패널 극한 압축
- 슬라이더 라벨+값+슬라이더를 한 행으로 통합
- 부품 토글 4열 grid로 변경 (2행으로 압축)
- 조명 프리셋 버튼 제거, 조명색 color picker로 교체
- 배경색 버튼 14px로 축소, 조명+배경 한 행 배치
- 전체 패딩/간격 최소화
2026-03-08 20:03:14 +09:00
김보곤
c6bad98440 fix: [rd] 방화셔터 3D 탭 컨트롤 패널 압축
- 부품 표시 2열 grid로 변경 (7항목이 4행으로 압축)
- 배경색 선택 인라인 소형 버튼 (20px)으로 변경
- 조명 프리셋 한 줄 인라인 배치
- 토글 스위치 크기 축소 (2.5rem→2rem)
- 슬라이더 라벨 인라인화, 전체 여백 축소
2026-03-08 19:48:16 +09:00
김보곤
a30ab9251a feat: [rd] 방화셔터 도면생성 기능 구현
- 4탭 구성: 설정 / 가이드레일 / 셔터박스 / 3D 렌더링
- 가이드레일 C-채널 SVG 단면도 (횡단면/정면도)
- 셔터박스 SVG 단면도 (정면/측면, 내부 부품 ON/OFF)
- Three.js 3D 조립체 렌더링 (셔터 개폐 애니메이션, 투명도, 부품 토글)
- DXF/PNG/JSON 내보내기, localStorage 프리셋 관리
- 제품 유형별(강판/스크린) 기본값 자동 적용
2026-03-08 19:30:44 +09:00
김보곤
ef3870f3a3 feat: [rd] 자동도면 생성 메뉴 추가
- 레거시 전개도 시뮬레이터를 MNG 환경으로 마이그레이션
- RdController에 autoDrawing 메서드 추가 (HX-Request 체크 포함)
- 라우트: GET /rd/auto-drawing
- R&D 대시보드에 자동도면 생성 카드 추가
- 레거시 PHP 코드 제거 (세션, API키, 서버기록 등)
- Three.js 3D 렌더링, SVG 미리보기, DXF 도면 생성 기능 유지
2026-03-08 17:56:09 +09:00
김보곤
877a60e0fb fix: [sound-logo] 시퀀서/AI BGM 상호 배타적 재생 구조 적용
- AI BGM 있으면 시퀀서(수동/프리셋) 음표 제외
- 시퀀서 모드에서는 AI BGM 제외
- TTS 음성은 양쪽 모두 공통 재생
- exportWav도 동일 로직 적용 + 오프라인 컴프레서 추가
2026-03-08 14:53:37 +09:00
김보곤
94147cce56 fix: [sound-logo] 오디오 합성 시 클리핑 소음 방지
- DynamicsCompressor 마스터 노드 추가 (threshold:-6dB, ratio:12)
- 모든 오디오 출력(시퀀서/음성/BGM)을 컴프레서 경유로 변경
- 다중 소스 합산 시 진폭 초과로 인한 디지털 클리핑 방지
2026-03-08 14:47:44 +09:00
김보곤
17ee94ff72 fix: [sound-logo] Lyria WebSocket 메시지 키 형식 수정
- client_content → clientContent (camelCase)
- music_generation_config 중첩 제거 → musicGenerationConfig 최상위
- playback_control 중첩 제거 → playbackControl 최상위
- WAV 헤더 감지 시 decodeAudioData fallback 추가
2026-03-08 14:39:12 +09:00
김보곤
c1619af390 feat: [sound-logo] Lyria BGM WebSocket 디버그 로깅 추가 2026-03-08 14:35:04 +09:00
김보곤
d208faa7d3 fix: [sound-logo] 음성 기본 텍스트에 ~ 추가 2026-03-08 14:31:10 +09:00
김보곤
4d033ae758 fix: [sound-logo] Lyria WebSocket Blob 데이터를 텍스트로 변환 후 JSON 파싱
- Blob 무시 대신 text()로 변환하여 JSON 파싱 시도
- Lyria API가 오디오 청크를 Blob 바이너리 프레임으로 전송하는 경우 대응
2026-03-08 14:28:01 +09:00
김보곤
7d86a1f30c fix: [sound-logo] Alpine 표현식 에러 + WebSocket Blob 파싱 에러 수정
- x-text 속성에서 이스케이프된 따옴표 제거 (Blade 빌드 시 깨짐 방지)
- WebSocket onmessage에서 Blob 바이너리 데이터 수신 시 JSON.parse 건너뛰기
2026-03-08 14:20:12 +09:00
김보곤
88e9364e2c fix: [sound-logo] 음성 카테고리 기반 선택으로 재구성
- 여성/남성/아이 카테고리 탭으로 1차 분류 (성별 확실한 전달)
- 공식 문서 기반 음성 성별 정보 수정 (Gacrux=여성, Sadachbia=남성 등)
- 아이 카테고리: 젊은 음성 + 'young child, high-pitched' Director's Note 지시문
- 스타일 옵션에서 아이/청소년 제거 (카테고리로 이동)
- 프롬프트 형식을 Director's Note 형식으로 개선
2026-03-08 14:13:14 +09:00
김보곤
0c2c14c39e feat: [sound-logo] 아이 목소리 옵션 + 말하기 속도 조절 추가
- 스타일 옵션에 어린이(5~7세), 초등학생(8~12세), 청소년(13~18세) 추가
- 말하기 속도 슬라이더 추가 (매우느리게~매우빠르게 5단계)
- 속도와 스타일을 TTS 프롬프트 지시문으로 조합하여 Gemini API에 전달
- 음성 목록 여성/남성/중성 순서로 정렬
2026-03-08 14:05:37 +09:00
김보곤
5a6fa180e4 feat: [sound-logo] TTS 음성 옵션 확장 + 잡음 문제 수정
- PCM 디코딩 endianness 수정 (big-endian → little-endian, Gemini TTS는 s16le)
- 16종 음성 선택 옵션 추가 (남성/여성/중성, 성격 설명)
- 9종 발화 스타일 옵션 추가 (밝고 활기차게, 차분하고 신뢰감 등)
- 음성/스타일을 컨트롤러에 전달하여 Gemini API에 적용
- 기본 텍스트: '우리들의 솔루션 쌤, 쌤, 쌤'
2026-03-08 13:59:07 +09:00
김보곤
584961ca18 fix: [sound-logo] UX 개선 - 중앙 toast 안내 시스템 + transport bar 레이아웃 수정
- toast를 화면 중앙에 표시하고 info/warn/error 유형별 색상 분리
- 모든 기능에 조건 미충족 시 가이드 메시지 추가 (음표/음성/배경음악 미생성 안내)
- 에러 발생 시 console 대신 사용자 친화적 toast로 알림
- transport bar 하단 잘림 수정 (height 계산 + margin 보정)
2026-03-08 13:53:43 +09:00
김보곤
904cde62cf feat: [rd] 사운드 로고 생성기 도움말 모달 추가
- 툴바에 ? 아이콘 추가 → 클릭 시 사용법 모달 표시
- 4개 탭(수동/프리셋/AI생성/AI배경음악) 상세 사용법 안내
- 음성 오버레이, 재생/내보내기, 3중 합성 구조 설명 포함
- ESC 키/외부 클릭으로 모달 닫기 지원
2026-03-08 13:44:00 +09:00
김보곤
37b40c8513 feat: [rd] AI 배경음악 생성 기능 추가 (Google Lyria RealTime)
- Lyria RealTime WebSocket 연동으로 다중 악기 배경음악 실시간 생성
- BPM, 밀도, 밝기, 스케일 컨트롤 지원
- 시퀀서 + 음성 + 배경음악 3중 합성 (playAll, exportWav)
- 서버 API 키 보호 엔드포인트 (lyria-config)
- 빠른 프롬프트 10종 제공
2026-03-08 13:37:42 +09:00
김보곤
7ef8971b93 feat: [rd] 사운드로고/나레이션 AI 토큰 사용량 기록 추가
- RdController: 사운드로고-AI생성, 사운드로고-TTS 토큰 기록
- CmSongController: 나레이션-가사생성, 나레이션-TTS 토큰 기록
- AI 토큰 사용량 UI에 사운드로고/나레이션 카테고리 분류 추가
2026-03-08 12:57:48 +09:00
김보곤
c2ddb625fb fix: [rd] TTS 500 에러 수정 및 AI 응답 파싱 개선
- 짧은 텍스트(4자 미만) TTS 요청 시 따옴표 래핑으로 Gemini TTS 인식률 개선
- TTS API 에러 시 실제 에러 메시지 반환 (기존: 일괄 500)
- AI 생성 temperature 0.9→0.7, maxOutputTokens 2048→4096으로 응답 안정성 개선
- 프롬프트에 name/desc 길이 제한 추가하여 JSON 잘림 방지
2026-03-08 12:51:30 +09:00
김보곤
ff2296d4d8 feat: [sound-logo] TTS 음성 오버레이 기능 추가
- Gemini TTS API 연동 (한국어 Kore 음성)
- 사이드바에 음성 오버레이 컨트롤: 텍스트 입력, 시작 시점, 볼륨
- 재생/WAV 내보내기 시 신스 + 음성 자동 합성
- POST /rd/sound-logo/tts 엔드포인트 추가
- L16 PCM → AudioBuffer 디코더 구현
2026-03-08 12:44:22 +09:00
김보곤
85304bdfbc feat: [sound-logo] Phase 2 AI 어시스트 모드 추가
- Gemini API 연동: 프롬프트 → 음표 시퀀스 JSON 자동 생성
- AI 탭 UI: 프롬프트 입력, 카테고리/길이 선택, 빠른 프롬프트 10종
- AI 결과 미리보기: 음표 시각화, 미리듣기, 시퀀서 로드
- POST /rd/sound-logo/generate 엔드포인트 추가
2026-03-08 12:34:59 +09:00
김보곤
92e2bddf50 feat: [sound-logo] 프리셋 10종 → 50종 확장 + 카테고리 필터 추가
- 8개 카테고리: 기업시그널, 알림/메시지, 상태/피드백, 전환효과, 게임효과, UI인터랙션, 브랜드징글, 방송/미디어
- 카테고리별 필터 탭 UI 추가
2026-03-08 12:28:13 +09:00
김보곤
c37d73c5bb feat: [rd] 사운드 로고 생성기 Phase 1 MVP 구현
- Web Audio API 기반 사운드 합성 엔진
- 4종 신스(sine/square/triangle/sawtooth) + ADSR 엔벨로프
- 노트 시퀀서 UI (비주얼 바 + 드롭다운 편집)
- 10종 프리셋 (알림, 로고, 시작음, 성공 등)
- WAV 내보내기, JSON import/export, localStorage 저장
2026-03-08 12:15:54 +09:00
김보곤
441a20a5d2 feat: [design-insight] AI 프롬프트 복사 버튼 추가
- 카드 상세 모달 편집 버튼 옆에 AI 프롬프트 버튼 추가
- 패턴 정보/구성요소/가이드라인을 AI 프롬프트로 변환 후 클립보드 복사
- 복사한 프롬프트를 AI에 붙여넣으면 해당 스타일로 코드 생성 가능
2026-03-08 11:11:11 +09:00
김보곤
4bc4e83340 feat: [design-insight] UI 패턴 50종 → 100종 확장
- 프리셋 템플릿 50개 추가 (51~100번)
- CSS 와이어프레임 50개 추가
- 버튼/토스트/다이얼로그 텍스트 100종으로 수정
2026-03-08 11:02:21 +09:00
김보곤
d490db2dc0 fix: [design-insight] 인기 UI 패턴 20종 → 50종 문구 수정 2026-03-08 10:47:45 +09:00
김보곤
ad564c0771 feat: [design-insight] 50종 UI 패턴 와이어프레임 미리보기 추가
- 로그인/인증 5종: 클래식 로그인, 소셜 SSO, 2FA, 비밀번호 재설정, 회원가입
- 보고서 5종: 인쇄용, 인보이스/견적서, 분석 리포트, 업무 보고서, PDF 리포트
- 대시보드 4종: 위젯, 실시간 모니터링, 멀티 차트, 데이터 시각화
- 목록 3종: 무한 스크롤, 그룹/섹션, 벌크 액션
- 폼 3종: 인라인 편집, 리치 텍스트 에디터, 프로필 카드
- 모달 4종: 확인 다이얼로그, 라이트박스, 알림 센터, 날짜 선택기
- 네비게이션 3종: 메가 메뉴, 모바일 하단바, 다단계 드롭다운
- 기타 3종: 드래그 정렬, 스켈레톤 로딩, 알림 배지
2026-03-08 10:41:44 +09:00
김보곤
2b64f41b39 feat: [rd] 디자인 인사이트 카드 미리보기 모달 + 와이어프레임 20종
- 카드 클릭 시 미리보기 모달 (좌: 와이어프레임, 우: 정보 패널)
- 패턴 카드 20종 CSS 와이어프레임 자동 생성
- KPI 대시보드, 데이터 테이블, 칸반, Command Palette,
  사이드바, 모달 폼, 설정, 타임라인, 트리 분할뷰,
  온보딩 스테퍼, 토스트, Empty State, 검색 자동완성,
  탭 레이아웃, 카드 그리드, 가격표, 캘린더, 채팅,
  파일 업로드, 브레드크럼
- 미리보기에서 편집 모달로 전환 가능
2026-03-08 10:27:26 +09:00
김보곤
2fc9242019 feat: [rd] 디자인 인사이트 인기 UI 패턴 20종 프리셋 추가
- 웹서비스 인기 UI 패턴 20종 프리셋 템플릿
- KPI 대시보드, 데이터 테이블, 칸반, Command Palette,
  사이드바, 모달 폼, 설정 페이지, 타임라인, 트리 분할뷰,
  온보딩 스테퍼, 토스트, Empty State, 검색 자동완성,
  탭 레이아웃, 카드 그리드, 가격표, 캘린더, 채팅,
  파일 업로드, 브레드크럼
- 빈 상태 및 내보내기 메뉴에서 불러오기 버튼 제공
- 각 패턴별 구성 요소, 가이드라인, 참고 서비스 포함
2026-03-08 10:12:32 +09:00
김보곤
ce9747a129 fix: [rd] 디자인 인사이트 'SAM ERP' → 'SAM' 용어 수정 2026-03-08 10:07:56 +09:00
김보곤
4b28a868ac feat: [rd] 디자인 인사이트 도움말 모달 추가
- ? 버튼 클릭 시 7개 탭 도움말 모달 표시
- 개요, 툴바, 카드 유형, 뷰 모드, 사이드바, 단축키, 워크플로우
- 각 기능별 상세 설명 및 빠른 시작 가이드
2026-03-08 10:02:57 +09:00
김보곤
5898a29077 feat: [rd] 디자인 인사이트 메뉴 Phase 1 MVP 구현
- GET /rd/design-insight 라우트 + 컨트롤러 추가
- Alpine.js 단일 파일 SPA (localStorage 기반)
- 4종 카드: 레퍼런스, 분석(CRAP), 패턴, Before/After
- 3종 뷰: 보드, 갤러리, 리스트
- Ctrl+V 클립보드 이미지 붙여넣기
- 프로젝트 CRUD, 태그/카테고리 필터, 검색
- JSON 내보내기/가져오기
2026-03-08 09:56:01 +09:00
김보곤
9e8f240f41 fix: [planning-design] 이미지 블록 업로드를 더블클릭으로 변경
- 단일 클릭 시 드래그 이동 중 파일 창이 뜨는 문제 해결
- @click.stop → @dblclick.stop 변경
2026-03-08 09:23:32 +09:00
김보곤
863cc16735 feat: [planning-design] 작업 영역 극대화 (패널 접기/펼치기)
- 좌측 메뉴트리 패널 접기/펼치기 토글 버튼 추가
- Description 패널 접기/펼치기 토글 바 추가
- 사이드바 접힘 시 스토리보드 페이지 폭 1100→1400px 자동 확장
- sb-editor padding 24→12px 축소
2026-03-08 09:19:34 +09:00
김보곤
e24be0f43e feat: [planning-design] 사이드바 접기/펼치기 버튼 추가
- 좌측 패널 탭 바에 접기(<<) 버튼 추가
- 사이드바 접힘 시 좌측 가장자리에 펼치기(>) 버튼 표시
- 캔버스 작업 공간 극대화 지원
2026-03-08 09:08:41 +09:00
김보곤
01310cda0f fix: [planning-design] 블록 서식(글자색/크기/굵기 등) 자식 요소에 상속 적용
- 자식 요소(.sb-blk-text, .sb-blk-heading 등)에 하드코딩된 color가 있어 부모 스타일 무시됨
- CSS attribute selector로 부모에 style이 설정된 경우 color/font-size/font-weight/font-style/text-align inherit 적용
2026-03-08 01:26:22 +09:00
김보곤
997ae6f46c feat: [planning-design] 블록 서식 툴바 + 우클릭 컨텍스트 메뉴 추가
- 블록 선택 시 Notion 스타일 플로팅 서식 툴바 표시
- 글자색, 배경색, 글자 크기, 굵게, 기울임, 정렬 설정
- 앞/뒤로 보내기 (z-index), 서식 초기화
- 우클릭 컨텍스트 메뉴: 복제/잘라내기/삭제/서식/레이어
- 서브메뉴로 글자색/배경색 직접 선택 가능
- 블록별 style 속성 저장 (localStorage 영속)
- HTML 내보내기/인쇄에 서식 반영
2026-03-08 01:22:28 +09:00
김보곤
ad98929978 feat: [planning-design] 좌표 기반 인쇄 기능 추가 + HTML 내보내기 블록 좌표 배치 개선 2026-03-08 00:51:26 +09:00
김보곤
08dbab9912 feat: [planning-design] Description 패널 리사이즈 + 번호 뱃지 마커 블록 (드래그&드롭/툴바) 2026-03-08 00:41:48 +09:00
김보곤
fb9c6e1de5 fix: [planning-design] Ctrl+X 후 Ctrl+Z 복구 안 되는 문제 수정 2026-03-08 00:34:25 +09:00
김보곤
60c370370c feat: [planning-design] Ctrl+X 잘라내기 기능 추가 (단일/다중) 2026-03-08 00:31:20 +09:00
김보곤
c37adb1a7e fix: [planning-design] 올가미 선택 동작 안 되는 문제 수정 2026-03-08 00:29:14 +09:00
김보곤
7e0c99a9b3 feat: [planning-design] 올가미(마퀴) 다중 선택 + 그룹 이동/복사/삭제 기능 추가 2026-03-08 00:26:40 +09:00
김보곤
889c527154 feat: [planning-design] 메뉴/캔버스 경계 드래그 리사이즈 기능 추가 2026-03-08 00:20:56 +09:00
김보곤
e5e5b69ad8 fix: [planning-design] 블록 툴바를 단위업무 상단으로 이동 2026-03-08 00:17:20 +09:00
김보곤
35d092f065 fix: [planning-design] placeholder 색상 더 옅게 + italic 스타일 적용 2026-03-07 23:54:31 +09:00
김보곤
c6b6bbdf92 feat: [planning-design] 스토리보드 페이지 복사 기능 추가 2026-03-07 23:52:05 +09:00
김보곤
3e3ea03139 feat: [planning-design] 스토리보드 블록 Undo/Redo 기능 추가 (Ctrl+Z/Y) 2026-03-07 23:49:56 +09:00
김보곤
abebf0e452 feat: [planning-design] 블록 Ctrl+C/V 복사 붙여넣기 및 Delete 삭제
- Ctrl+C: 선택된 블록 클립보드 복사
- Ctrl+V: 클립보드 블록 붙여넣기 (24px 오프셋)
- Delete/Backspace: 선택된 블록 삭제
- 연속 Ctrl+V 시 오프셋 누적으로 겹침 방지
2026-03-07 23:43:33 +09:00
김보곤
049e66e426 feat: [planning-design] 블록 자유 배치 캔버스 (PPT 스타일)
- 블록을 드래그하여 자유롭게 위치 이동
- 오른쪽/아래/대각선 리사이즈 핸들로 크기 조절
- 더블클릭으로 편집 모드 진입
- 그리드 도트 배경으로 위치 인지 용이
- 선택 시 크기 표시 (w × h)
- 블록 기본 크기를 유형별로 최적화
- 템플릿 삽입 시 자동 세로 배치
2026-03-07 23:40:30 +09:00
김보곤
d9fa80fc03 fix: [planning-design] 템플릿 패널 잘림 현상 수정
- position: absolute → fixed로 변경 (부모 overflow 영향 제거)
- 버튼 위치 기준으로 JS 동적 좌표 계산
- 화면 경계 밖 방지 (좌/우/하단 overflow 체크)
2026-03-07 23:34:50 +09:00
김보곤
8c734bbf2d feat: [planning-design] 스토리보드 블록 템플릿 시스템 추가
- 기본 프리셋 9종: 검색+목록, 상세폼, CRUD, 대시보드, 결재폼,
  탭 레이아웃, 팝업/모달, 로그인, 빈 페이지
- 내 템플릿 저장/삽입/삭제 (localStorage 영구 보관)
- 템플릿 검색 필터, 프리셋/커스텀 탭 분리
- 현재 페이지 블록을 한 번에 템플릿으로 저장하여 재활용
2026-03-07 23:29:31 +09:00
김보곤
2f9ef0d0a2 feat: [planning-design] 스토리보드 블록 편집기 구현
- 노션 스타일 블록 기반 화면 설계 편집기
- 15종 블록: 제목(H1/H2), 텍스트, 테이블, 콜아웃, 체크리스트,
  코드, 버튼, 입력필드, 셀렉트, 카드, 뱃지, 이미지, 구분선
- 드래그 앤 드롭 블록 순서 변경
- 블록 복제, 위/아래 이동, 삭제 지원
- HTML 내보내기에 블록 렌더링 반영
2026-03-07 23:19:29 +09:00
김보곤
90c03b3f14 feat: [planning-design] 메뉴 트리 편집 모달 UI 추가
- JSON prompt 방식 → 트리구조 모달 UI로 개선
- 상위/하위 메뉴 추가, 삭제, 이름 편집 지원
- 드래그 앤 드롭으로 메뉴 순서 변경 가능
- 접기/펼치기 토글 지원
2026-03-07 23:07:37 +09:00
김보곤
f16d078359 feat: [planning-design] 스토리보드 뷰 통합 완성
- loadProject()에서 sb 데이터 복원 추가
- newProject()에서 sb 초기화 추가
- init()에서 sbInitPages() 호출 추가
2026-03-07 22:55:56 +09:00
김보곤
439d80b09a fix: [rd] 기획디자인 연결선 화살표 제거, 단순 곡선으로 변경 2026-03-07 22:32:18 +09:00
김보곤
7b9ce99541 feat: [rd] 기획디자인 연결선 삭제 + 스페이스바 패닝 기능 추가
- 연결선 클릭 선택 → Delete/Backspace로 삭제
- 우클릭 컨텍스트 메뉴에 '연결선 삭제' 항목 추가
- 스페이스바 누른 채 마우스 드래그로 캔버스 이동 (Figma/FigJam 방식)
- 패닝 중 커서 grab/grabbing 변경
2026-03-07 22:28:54 +09:00
김보곤
b0a70481e8 fix: [rd] 기획디자인 연결선 렌더링 수정 (SVG namespace 문제 해결)
- Alpine.js <template x-for>가 SVG 내부에서 path 요소 생성 불가 문제
- SVG 요소를 createElementNS로 직접 생성하는 renderConnections() 도입
- x-effect + _connTick 카운터로 노드 이동/연결 변경 시 자동 리렌더
2026-03-07 22:22:51 +09:00
김보곤
98f7b94516 feat: [rd] 기획디자인 7대 기능 추가 (칸반/모달/체크리스트/담당자/필터/검색/리스트뷰)
- 칸반 보드: 상태별 컬럼 드래그앤드롭으로 상태 전환
- 노드 상세 모달: 더블클릭으로 전체 편집 (Notion 스타일)
- 체크리스트: 모달 내 하위 작업 관리, 진행률 프로그레스 바
- 담당자/마감일 필드: 노드별 배정, 기한 초과 빨간 표시
- 필터 바: 상태/우선순위/유형/텍스트 필터링 (Ctrl+F)
- 리스트/테이블 뷰: 정렬 가능한 전체 노드 목록
- autoSave toast 제거 (UX 방해 요소)
2026-03-07 22:17:08 +09:00
김보곤
d0f997321e feat: [rd] 기획디자인 플래닝 캔버스 페이지 추가
- 연구개발 > 기획디자인 메뉴 라우트/컨트롤러/뷰 추가
- Alpine.js 기반 캔버스 도구 (노드 배치, 연결, 줌/팬)
- 16종 노드 타입 (기획/분석/구조/산출물 카테고리)
- 타임라인/플로우 뷰 모드, 프로젝트 저장/불러오기
- 실행취소/재실행, 키보드 단축키 지원
2026-03-07 22:06:27 +09:00
김보곤
2150d236b8 fix: [approval] 결재선 인원 목록에서 미배정/퇴사/외주 사용자 제외
- 부서 미배정(department_id NULL) 사용자 목록에서 제외
- 코드브릿지엑스(tenant_id=1) 테넌트에서 영업팀(외주) 제외
2026-03-07 21:53:39 +09:00
김보곤
64a9c0556e feat: [approval] 결재선 요약 카드 가로 2분할 (결재선 | 참조선 분리 표시)
- 기안 작성 페이지 결재선 요약 영역을 좌우 2분할 레이아웃으로 변경
- 좌측: 결재선 (결재/합의 카드), 우측: 참조선 (참조 카드)
- 참조자가 없으면 결재선만 전체 너비로 표시
2026-03-07 20:58:14 +09:00
김보곤
089808a5ba fix: [menus] 메뉴 관리 페이지 기본 행 표시 500개 고정
- 공통 pagination_per_page 쿠키 대신 menu_per_page 전용 쿠키 사용
- 다른 페이지에서 200개로 설정해도 메뉴 관리는 항상 500개 기본
2026-03-07 19:51:09 +09:00
김보곤
c309d70a7e feat: [claude-code] 벤치마크 이름 hover 시 설명 툴팁 추가 (SWE-bench, GPQA, ARC-AGI 등) 2026-03-07 19:29:49 +09:00
김보곤
48bb0a5ae0 fix: [claude-code] 모델 비교 카드 날짜 뱃지 inline style로 변경 (Tailwind bg-opacity 미적용 문제) 2026-03-07 19:29:49 +09:00
김보곤
b1e5d54020 fix: [claude-code] 모델 비교 카드 날짜 텍스트 색상 수정 (흰배경에 흰글자 → 명시적 text-white) 2026-03-07 19:29:49 +09:00
김보곤
6958d18938 fix: [claude-code] 발전과정 리서치 데이터 보강 및 오류 수정
- Opus 4.1 (2025.08.05) 모델 추가 (SWE 74.5%, GPQA 80.9%)
- Haiku 4.5 SWE-bench 73.3% 벤치마크 추가
- Opus 4.5 가격 수정 ($15/$75 → $5/$25)
- Opus 4 GPQA 수정 (79.6% → 76.9%), 출시일 수정 (09 → 05)
- Claude Code GA 날짜 정정 (2025.04 → 2025.05.22)
- Claude Code $1B 런레이트 매출 달성 정보 추가
- SWE-bench 성장 바 차트에 Opus 4.1, Haiku 4.5 추가
2026-03-07 19:29:49 +09:00
김보곤
cfe1e924c5 feat: [claude-code] 발전과정 페이지 대폭 강화 - 모델 비교 탭 추가
- 새 '모델 비교' 탭: 각 모델별 특징 카드, 벤치마크 바 차트, 핵심 스펙
- Opus 4.6/4.5, Sonnet 4.6/4.5, 4 Opus/Sonnet, 3.7/3.5, Haiku 4.5 상세
- SWE-bench, GPQA Diamond, ARC-AGI 2, OSWorld 벤치마크 수치 반영
- Opus 4.6 vs Sonnet 4.6 직접 비교표 추가
- 모델 진화 탭: 세대별 비교표 10개 모델로 확장, SWE-bench 성장 바 차트
- 타임라인 탭: Opus 4.5(2025.11) 노드 추가, 정확한 출시일 반영
- 히어로 수치 업데이트 (9세대 모델, SWE-bench 80.8%)
2026-03-07 19:29:49 +09:00
김보곤
0f5b123a2c feat: [claude-code] 발전과정 페이지 추가 (타임라인/핵심혁신/모델진화/생태계) 2026-03-07 19:29:49 +09:00
김보곤
6a25389164 feat: [china-tech] 중국 AI기술 발전과정 페이지 추가 2026-03-07 19:27:15 +09:00
김보곤
348b22c296 feat: [help] 도움말 > 바로빌 연동 가이드 페이지 추가
- 7탭 구성: 전체 구조, 초기 설정, 세금계산서, 계좌/카드, 홈택스 연동, 카카오톡/SMS, 메뉴 맵
- BarobillGuideController + HX-Redirect 패턴 적용
- 테넌트 필수 설정, 바로빌↔SAM 연동 구조, FAQ 포함
2026-03-07 19:03:06 +09:00
김보곤
594ae575a5 feat: [help] 도움말 > 연차휴가/근태관리 페이지 추가
- 7탭 구성: 전체 흐름도, 연차 발생/계산, 휴가 신청/결재, 근태 기록, 연차촉진제도, 급여 연동, 메뉴 맵
- AttendanceGuideController + HX-Redirect 패턴 적용
- 근로기준법 기반 연차 발생 기준, 촉진 타임라인, 급여 연동 로직 포함
2026-03-07 18:51:09 +09:00
김보곤
33f0a9b808 feat: [help] 도움말 > 회계동작원리 페이지 추가
- 6탭 구성: 전체 흐름도, 일상 업무, 월간 업무, 세금/부가세, 정산/결산, 메뉴 맵
- AccountingGuideController + HX-Redirect 패턴 적용
- 중소기업 회계담당자를 위한 SAM 재무/회계 가이드
2026-03-07 18:36:51 +09:00
김보곤
f8e5a4df75 Revert "feat: [database] codebridge DB 분리 - 118개 MNG 전용 테이블 connection 설정"
This reverts commit 8291cdc39b.
2026-03-07 11:37:39 +09:00
김보곤
8291cdc39b feat: [database] codebridge DB 분리 - 118개 MNG 전용 테이블 connection 설정
- config/database.php에 codebridge connection 추가
- 78개 MNG 전용 모델에 $connection = 'codebridge' 설정
  - Admin (15): PM, 로드맵, API Explorer
  - Sales (16): 영업파트너, 수수료, 가망고객
  - Finance (9): 법인카드, 자금관리, 홈택스
  - Barobill (12): 은행/카드 동기화 관리
  - Interview (1), ESign (6), Equipment (2)
  - AI (3), Audit (3), 기타 (11)
2026-03-07 11:31:27 +09:00
b67bc20f1b chore: 기타 모델/설정 보완
- PayrollSetting 모델 수정
- PptxController 수정

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 03:05:19 +09:00
9e69c64024 feat: [품질검사] 제품검사 요청서 템플릿 시더 + Pretendard 폰트
- ProductInspectionRequestTemplateSeeder (template ID 66)
- Pretendard 폰트 + TCPDF 폰트 파일 추가

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 03:05:14 +09:00
3e1d1ffc33 feat: [문서인쇄] 스냅샷 출력 + 절곡 전용 렌더링
- print.blade.php rendered_html 스냅샷 우선 출력
- bending-inspection-data, bending-worklog 파셜 추가
- documents/show.blade.php 개선
- DocumentTemplateSection 모델 보완

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 03:05:07 +09:00
김보곤
d9be4e2400 feat: [hr] 연차촉진 관리 페이지 추가
- LeavePromotionController: 대상자 목록 조회 + 일괄 통지 발송
- LeaveService: getPromotionCandidates(), sendPromotionNotices() 메서드 추가
- 통지 현황 추적 (미발송/1차 발송/완료)
- 일괄 선택 + 결재 문서 자동 생성 + 상신
2026-03-07 00:46:31 +09:00
김보곤
b708f473d1 fix: [approval] 연차사용촉진 통지서 Employee 모델 속성 수정
- departments->first() → department? (BelongsTo 단수 관계)
- $emp->name → $emp->display_name
- $emp->position → $emp->position_key
- $emp->id → $emp->user_id
- LeaveService에 department eager load 추가
2026-03-07 00:33:55 +09:00
김보곤
e95598acad feat: [approval] 연차사용촉진 통지서 1차/2차 양식 추가
- 1차 통지서: 직원 선택, 연차 현황(발생/사용/잔여), 제출기한, 법적 문구
- 2차 통지서: 직원 선택, 잔여연차, 회사 지정 휴가일(다건), 법적 문구
- create/edit/show 통합 완료
- 미리보기/인쇄 기능 포함
2026-03-07 00:29:39 +09:00
김보곤
8f287149ef fix: [approval] 공문서 양식에 샘플 데이터 기본값 추가 2026-03-06 23:53:42 +09:00
김보곤
d43cb4bc9b feat: [approval] 공문서 양식 추가
- 공문서 전용 폼/조회 파셜 추가
- create/edit/show 페이지에 공문서 통합
- 문서번호, 수신, 참조, 제목, 본문, 붙임 입력
- 발신자 정보 테넌트에서 자동 로드
- 미리보기/인쇄 기능 (공문서 형식)
2026-03-06 23:39:13 +09:00
김보곤
5f1a211722 feat: [approval] 견적서 양식 추가
- 견적서 전용 폼/조회 파셜 추가
- create/edit/show 페이지에 견적서 통합
- Alpine.js 동적 품목 테이블 (자동 세액 계산)
- 공급자 정보 테넌트에서 자동 로드
- 미리보기/인쇄 기능
2026-03-06 23:22:21 +09:00
김보곤
05321c8839 feat: [approval] 이사회의사록 양식 추가
- 이사회의사록 전용 폼(_board-minutes-form.blade.php) 생성
- 이사회의사록 읽기전용 뷰(_board-minutes-show.blade.php) 생성
- Alpine.js 의안/서명란 동적 추가/삭제 기능
- 테넌트 정보에서 회사명/대표자 자동 채움
- create/edit/show 페이지 통합
- 미리보기/인쇄 기능 포함
- 인사/근태 카테고리에 배치
2026-03-06 23:00:39 +09:00
김보곤
f149a987c9 feat: [approval] 위임장 양식 추가
- 위임장 전용 폼(_delegation-form.blade.php) 생성
- 위임장 읽기전용 뷰(_delegation-show.blade.php) 생성
- create/edit/show 페이지에 위임장 통합
- 미리보기/인쇄 기능 포함
- 인사/근태 카테고리에 배치
2026-03-06 22:25:17 +09:00
김보곤
33f02379e4 feat: [finance] 경조사비 관리 페이지 추가
- 거래처 경조사비 관리대장 CRUD (등록/수정/삭제)
- 축의/부조 구분, 부조금(현금/계좌이체/카드), 선물(종류/금액) 관리
- 연도별 필터, 구분별 필터, 거래처/내역 검색
- 통계 카드 (총건수, 총금액, 부조금 합계, 선물 합계, 축의/부조 비율)
- CSV 내보내기
- 라우트: /finance/condolence-expenses
2026-03-06 21:39:19 +09:00
김보곤
bf802d6af3 feat: [approvals] 결재선/참조선 2영역 분리 UI
- 결재선 에디터를 결재선(결재/합의)과 참조선으로 분리
- 좌측 인원 목록에 '결재' / '참조' 두 버튼 제공
- 결재선: 드래그 정렬, 결재/합의 유형 선택
- 참조선: 칩(태그) 형태로 표시, 상신 즉시 열람 가능
- show 페이지에 참조자 목록 표시 추가
- getStepsData()에서 결재선+참조선 합산하여 기존 API 호환 유지
2026-03-06 21:18:48 +09:00
김보곤
20c4e9d879 fix: [approvals] 사용인감계 create 폼/미리보기 인감비교 형식 반영
- create.blade.php: buildSealUsagePreviewHtml 인감비교 레이아웃 적용
- create.blade.php: saveApproval formContent에서 seal_type/remarks 제거, attachment_desc 추가
- _seal-usage-form.blade.php: 인감비교 2열 레이아웃 + 용도/제출처/첨부서류 필드
- _seal-usage-show.blade.php: 읽기전용 인감비교 레이아웃
2026-03-06 21:09:42 +09:00
김보곤
ae367e733e fix: [approvals] 사용인감계 미리보기를 인감비교 형식으로 통일
- edit/show 페이지의 buildSealUsagePreviewHtml을 법인인감|사용인감 비교 레이아웃으로 교체
- 구 테이블 형식(인감종류/비고 필드) 제거
- create 페이지와 동일한 확약문구, 일자 포맷, 회사정보 레이아웃 적용
2026-03-06 21:03:31 +09:00
김보곤
c96a92bcb5 feat: [approvals] 사용인감계 양식 추가
- 증명서 카테고리에 사용인감계(seal_usage) 양식 등록
- 입력 폼: 사용일자, 인감종류, 용도, 제출처, 비고
- 회사 정보 자동 로드 (테넌트 정보 기반)
- 미리보기/인쇄 기능 (원본 DOCX 유사 레이아웃)
- create/edit/show 3개 페이지 모두 지원
2026-03-06 20:48:19 +09:00
김보곤
da20e3552f feat: [org-chart] 부서 숨기기 상태 DB 저장
- departments.options JSON 컬럼에 orgchart_hidden 플래그 저장
- 숨기기/복원 시 API 호출하여 영구 저장
- 페이지 로드 시 DB에서 숨김 상태 복원
2026-03-06 20:28:25 +09:00
김보곤
eeb56ae206 fix: [org-chart] 대표이사 미배치 제외 및 숨긴 부서 연결선 제거
- 대표이사/사장/회장 등 임원직 미배치 목록에서 제외
- ceoName과 일치하는 직원도 미배치에서 제외
- 숨긴 부서의 상위 연결선(vertical connector) 제거
- rootDepts getter에서도 숨긴 부서 필터링
2026-03-06 20:20:29 +09:00
김보곤
3e47402d3e feat: [org-chart] 부서 숨기기 기능 추가
- 부서 헤더 더블클릭 시 숨기기 버튼 표시
- 숨긴 부서와 하위 부서 트리에서 제거, 연결선 자동 조정
- 숨겨진 부서 패널에서 눈 아이콘 클릭으로 복원
2026-03-06 20:16:11 +09:00
김보곤
3ace66065e fix: [org-chart] 연결선 'ㄱ'자 형상 수정 및 드롭존 숨김 처리
- 수평 연결선 위치: top:12px → top:0 (수직선과 정확히 접합)
- 하위 부서 드롭존: 기본 숨김, 드래그 시에만 표시
2026-03-06 20:10:09 +09:00
김보곤
48a41e535b fix: [org-chart] 부서 드래그 정렬 버그 수정 및 계층 이동, 직책 표시 개선
- SortableJS+Alpine 충돌 해결: 수동 DOM 렌더링으로 전환
- 부서 드래그로 다른 부서 하위로 이동 가능 (parent_id 변경)
- 순환 참조 방지 (자기 자신/하위로 이동 불가)
- 재귀 렌더링으로 무제한 depth 지원
- 직책이 이름 앞에 표시 ("사원 김보곤")
- 빈 하위 드롭존: 드래그 시에만 표시
2026-03-06 20:05:48 +09:00
김보곤
8111910d6c feat: [org-chart] 조직도 최상단 노드 색상 수정 및 부서 드래그 정렬 기능 추가
- 최상단 회사 노드: Tailwind gradient → inline style로 변경 (글씨 안보이는 문제 수정)
- 부서 카드 드래그 앤 드롭 정렬: SortableJS handle 기반
- 1단계/2단계 부서 모두 드래그 정렬 가능
- sort_order 변경 즉시 서버 저장 (reorder-depts API)
- 부서 헤더에 드래그 아이콘 추가
2026-03-06 19:51:01 +09:00
김보곤
11d5fb57a7 feat: [rd] 조직도 클래식 하향식 트리 형태로 개편
- 회사(대표이사) → 1단계 부서 → 2단계 → 3단계 하향식 트리 구조
- 부서 간 수직/수평 연결선으로 계층 시각화
- 미배치 직원 패널을 상단 접이식으로 변경
- 부서 카드 클릭 시 하위 부서 펼침/접기
- drag & drop 배치 기능 유지
2026-03-06 19:42:37 +09:00
김보곤
a164410791 fix: [rd] 조직도 Blade 템플릿 ParseError 수정
- @json 내 화살표 함수를 컨트롤러로 이동
- Blade 컴파일러와 배열 구문 충돌 해결
2026-03-06 19:37:22 +09:00
김보곤
3fccd7414c feat: [rd] 조직도 관리 화면 추가
- SortableJS 기반 drag & drop 부서 배치 UI
- 미배치 직원 패널 + 부서 트리 (3단계 계층 지원)
- 직원 배치/해제 API 엔드포인트
- 실시간 저장 및 인원수 표시
2026-03-06 19:35:06 +09:00
김보곤
08bf255480 fix: [approvals] 근태신청 기간 표시에서 T 제거 (2026-03-12T14:00 → 2026-03-12 14:00) 2026-03-06 17:59:13 +09:00
김보곤
c8223a63b5 fix: [approvals] 사직서 주민번호 마스킹 제거 2026-03-06 17:48:51 +09:00
김보곤
a474c26675 fix: [approvals] 근태신청 종료일도 종료일시(datetime-local)로 변경 2026-03-06 17:46:52 +09:00
김보곤
47fcaaa3a3 feat: [approvals] 근태신청 시작일에 시간 선택 기능 추가
- 근태신청(attendance_request) 선택 시 시작일 input을 datetime-local로 전환
- 라벨도 '시작일' → '시작일시'로 변경
- 휴가/사유서는 기존 date 유지
2026-03-06 17:44:41 +09:00
김보곤
43862e26c6 fix: [approvals] 위촉증명서 PDF 상단 여백 축소 (전체 위치 상향) 2026-03-06 17:41:08 +09:00
김보곤
eb47351af1 fix: [approvals] 위촉증명서 주민번호 마스킹 제거 2026-03-06 17:35:58 +09:00
김보곤
0649802ffd fix: [approvals] 재직/경력증명서 주민번호 전체 표시 (마스킹 제거)
- 재직증명서: 주민번호 뒷자리 ****** 마스킹 제거, 전체 표시
- 경력증명서: 주민등록번호 필드 추가 (폼/조회/미리보기/PDF)
- EmploymentCertService: maskedResident 로직 제거
- CareerCertService: resident_number 반환 추가, PDF 행 추가
2026-03-06 15:59:05 +09:00
김보곤
017e2882a9 feat: [approvals] 구매품의서에 지급방법(법인카드/계좌이체) 선택 추가 2026-03-06 15:39:03 +09:00
김보곤
fa96b8e013 feat: [approvals] 비용정산품의서 지급방법을 각 행별 선택으로 변경
- 하단 일괄 radio 제거, 각 내역행에 지급방법 select 추가
- tfoot에 법인카드/개인선지출 합계표 추가
- 조회 화면에도 지급방법 컬럼 및 합계표 반영
2026-03-06 15:28:34 +09:00
김보곤
520406a06c fix: [sidebar] 즐겨찾기 섹션에 메뉴 뱃지 표시 동기화 2026-03-06 15:22:04 +09:00
김보곤
2906825c33 feat: [sidebar] 사이드바 메뉴 즐겨찾기 기능 추가
- MenuFavorite 모델 생성 (menu_favorites 테이블)
- SidebarMenuService에 즐겨찾기 CRUD 메서드 추가
- MenuFavoriteController 생성 (toggle/reorder API)
- 사이드바 상단에 즐겨찾기 섹션 표시
- 메뉴 아이템에 별 아이콘 추가 (hover 시 표시, 토글)
- 최대 10개 제한, 리프 메뉴만 대상
2026-03-06 14:34:46 +09:00
김보곤
53fb5103ac fix: [approval] 결재선 인원 목록에서 퇴사자 제외
- tenant_user_profiles.employee_status = 'resigned' 필터 추가
- search(), list() 두 엔드포인트 모두 적용
2026-03-06 14:32:08 +09:00
김보곤
033e8b12cc fix: [approvals] 지출품의서 '사용일자' → '지출일자' 라벨 변경 2026-03-06 13:43:03 +09:00
김보곤
bf3ec57095 feat: [approvals] 양식 선택 2단계 구조 (분류 → 양식)
- 1단계: 분류 선택 (일반/인사·근태/증명서/품의/재무)
- 2단계: 해당 분류 내 양식만 필터링하여 표시
- 분류별 아이콘 표시 (📄📜📋💰👤)
- edit 화면에서 기존 양식의 분류 자동 선택
2026-03-06 13:18:58 +09:00
김보곤
7679c2b99b feat: [approvals] 전체 양식 설명 카드 추가
- 업무기안서, 휴가신청, 근태신청, 사유서 등 8개 양식 설명 추가
- 재직/경력/위촉증명서, 사직서 포함 전체 14종 양식 설명 완비
- 양식별 고유 아이콘/색상으로 시각적 구분
2026-03-06 13:08:22 +09:00
김보곤
12239866db feat: [approvals] 양식 선택 시 설명 카드 표시
- 지출결의서/품의서 5종 선택 시 우측에 설명 카드 노출
- 드롭다운 30% + 설명 카드 70% 레이아웃
- 양식별 아이콘/색상/설명 텍스트 (사전승인 vs 사후보고 등)
- create/edit 동일 적용
2026-03-06 12:55:07 +09:00
김보곤
406d47bc93 feat: [approvals] 품의서 5종 분리 (지출/계약체결/구매/출장/비용정산)
- 기존 단일 품의서(purchase_request)를 5가지 전문 양식으로 분리
- pr_expense: 지출품의서 (항목/금액/비고)
- pr_contract: 계약체결품의서 (계약상대방/기간/금액/조건)
- pr_purchase: 구매품의서 (품목/수량/단가/납품정보)
- pr_trip: 출장품의서 (일정표/경비내역)
- pr_settlement: 비용정산품의서 (사용일자/항목/지급방법)
- Alpine.js 단일 컴포넌트로 5종 동적 전환
- show/create/edit 모두 pr_ prefix 코드 자동 감지
2026-03-06 11:41:08 +09:00
김보곤
cba91713ee feat: [approvals] 품의서 양식 추가
- 품의서(purchase_request) 전용 폼/뷰 partial 추가
- 지출결의서 기반, 지출방법(카드/계좌) 제거, 구매목적 필드 추가
- 테이블: 품명/수량/단가/금액/업체명/비고 (수량×단가 자동계산)
- 희망 납기일, 요청부서/요청자, 첨부파일 지원
- create/edit/show 모두 분기 처리
2026-03-06 11:28:28 +09:00
김보곤
e02f1daf0a fix: [approvals] 위촉증명서 테이블 2열 행 텍스트 넘침 수정
- table-layout:fixed + colgroup(18%/32%/18%/32%)로 열 너비 고정
- td에 white-space:nowrap 추가하여 텍스트 줄바꿈 방지
- th width 고정값 제거 → colgroup 비율로 제어
- "위촉(재직)기간" → "위촉기간"으로 라벨 축소
- padding 18px→14px, font 16px→15px로 미세 조정
2026-03-06 10:56:24 +09:00
김보곤
36fa02132c fix: [approvals] 사직서 레이아웃 개선 - A4 용지 내 안정된 수직 배분
- HTML: @page A4 설정, cert-page wrapper(padding 100px), th/td 16px 18px, font 16px
- PDF: 상단여백 40mm+Ln20, rowHeight 8→12, 본문 10→12pt, 문구 12→14pt, 회사 14→16pt
- 섹션 간격 대폭 확대 (테이블↔문구 30mm, 신청인↔회사 30mm)
- create/show 동일 적용
2026-03-06 10:40:41 +09:00
김보곤
f7bb375bea fix: [approvals] 경력증명서 증명문구 재직/퇴직 분기 처리
- 퇴직일 있음: "위 사람은 당사에 재직(근무) 하였음을 증명합니다."
- 퇴직일 없음(현재 재직): "위 사람은 당사에서 재직(근무) 하고 있음을 증명합니다."
- HTML 미리보기(create/show) + PDF 모두 적용
2026-03-06 10:35:54 +09:00
김보곤
f83986aec3 fix: [approvals] 재직증명서 레이아웃 개선 - A4 용지 내 수직 배분 조정
- HTML 미리보기: @page A4 설정, cert-page wrapper, padding/font-size 증가
- PDF(TCPDF): 상단여백 추가, 섹션간격 확대, rowHeight 8→10, 본문 10→11pt
- 증명문구/날짜 12→14pt, 회사명 14→16pt
- create/show 동일 적용
2026-03-06 10:26:11 +09:00
김보곤
f00eee7f12 fix: [approvals] 위촉증명서 레이아웃 개선 - 테이블 행 높이/글자크기 증가
- HTML 미리보기: th/td padding 16px 18px, font-size 16px, th width 140px
- PDF(TCPDF): rowHeight 8→12, 본문 폰트 10→12, 증명문구/날짜 12→14, 회사명 14→16
- create/show 동일하게 적용
2026-03-06 10:19:21 +09:00
김보곤
b60f2109af feat: [document] 양식 디자이너(Block Builder) Phase 2 - 블록 런타임 렌더러
- BlockRendererService: view/edit/print 3모드 렌더링 지원
  - edit 모드: 폼 필드(input/select/textarea/checkbox) 생성
  - view 모드: 읽기 전용 데이터 표시
  - print 모드: 인쇄 최적화 레이아웃
- 데이터 바인딩: block.binding → document_data.field_key 매핑
- 체크박스 그룹: 콤마 구분 값으로 저장/복원
- 테이블 셀 편집: tbl_{blockId}_r{row}_c{col} 키로 EAV 저장
- edit.blade.php: 블록 빌더 서식 분기 (blockFormContainer)
- show.blade.php: 블록 빌더 조회 모드 분기
- DocumentController: renderBlockHtml() 메서드 추가
2026-03-06 10:16:50 +09:00
김보곤
10b3490d9c fix: [approvals] 위촉증명서 인쇄/PDF A4 레이아웃 수직 배분 개선
- 인쇄 CSS: @page A4 적용, 상단 padding 100px로 확대
- HTML 미리보기: 제목/테이블/증명문구/날짜/서명 간격 확대
- PDF: 상단 여백 및 섹션 간 Ln 값 증가 (A4 수직 균등 배분)
2026-03-06 10:09:15 +09:00
김보곤
b05daffedb fix: [approvals] 재직증명서 양식에 대표자명/회사주소 누락 수정
- 재직증명서 폼/제출/미리보기/PDF에 ceo_name, company_address 추가
- tenants 테이블에서 가져온 회사 정보를 모든 기안 양식에 통일 적용
- 경력/위촉/사직서는 이미 정상 처리, 재직증명서만 누락되어 있었음
2026-03-06 09:19:57 +09:00
김보곤
d9c905ca9a feat: [approval] 사직서 양식 추가
- ResignationService 생성 (정보 조회 + PDF 생성)
- 사직서 전용 폼/조회 파셜 추가
- create/show 블레이드에 사직서 JS 로직 통합
- 컨트롤러 resignationInfo/resignationPdf 메서드 추가
- API 라우트 resignation-info, resignation-pdf 등록
2026-03-06 00:13:38 +09:00
김보곤
2dc559d190 feat: [approval] 위촉증명서 기안/조회/PDF 기능 추가
- AppointmentCertService: 사원 위촉정보 조회 + TCPDF PDF 생성
- 기안 작성 폼: 사원 선택, 인적/위촉/발급 정보, 미리보기
- 상세 조회: 읽기전용 렌더링 + 미리보기/PDF 다운로드
- API: appointment-cert-info, appointment-cert-pdf 엔드포인트
2026-03-05 23:58:07 +09:00
김보곤
7c03aba203 fix: [approval] 전용 폼 선택 시 제목을 항상 양식명으로 설정 2026-03-05 23:46:53 +09:00
김보곤
4daca61007 feat: [approval] 경력증명서 기안/조회/PDF 기능 추가
- CareerCertService: 사원 경력정보 조회 + TCPDF PDF 생성
- 기안 작성 폼: 사원 선택, 인적/경력/발급 정보, 미리보기
- 상세 조회: 읽기전용 렌더링 + 미리보기/PDF 다운로드
- API: career-cert-info, career-cert-pdf 엔드포인트
2026-03-05 23:41:45 +09:00
김보곤
8cdedae07e feat: [corporate-card] 카드분리 기능 추가
- 결제 내역 수정 모달에 카드분리 버튼 추가
- 카드별 배분금액 직접 입력 UI
- 균등 배분 / 비율 배분 / 해제 버튼
- 배분 합계 검증 (일치해야 저장 가능)
- card_splits 데이터 JSON 저장 (기존 items 확장)
- cardDeductions 로직: card_splits 우선 적용, 없으면 기존 비율 배분
2026-03-05 23:19:41 +09:00
김보곤
dab120eacd fix: [sidebar] 메뉴 검색 결과 텍스트 색상 가독성 개선 2026-03-05 22:11:45 +09:00
김보곤
cb88c02ae5 fix: [rd] 중대재해처벌법 진단 개요 너비 20% 확대 및 체크리스트 전체 너비 사용 2026-03-05 22:08:39 +09:00
김보곤
e7e0f55a27 feat: [rd] 중대재해처벌법 실무 점검 대시보드 추가
- 6개 카테고리 34개 점검항목 인터랙티브 체크리스트
- Chart.js 도넛/막대 차트 실시간 통계
- React 기반 SPA 대시보드
2026-03-05 21:57:21 +09:00
김보곤
53a851740a feat: [juil] 업무 Workflow 분기형 UI 구현
- 입찰 참여 기업 / 수의계약 기업 두 경로로 분기
- A경로: 영업 → 견적서 작성 → 입찰 참여 → 수주/계약
- B경로: 영업 → 견적서 작성 → 수주/계약 (입찰 생략)
- 분기/합류 시각적 연결선으로 표현
- 수주/계약 이후 공통 프로세스로 합류
2026-03-05 21:28:07 +09:00
김보곤
106e654cbd fix: [juil] 업무 Workflow 프로세스 순서 수정
- 영업/수주 → 영업 (수주는 견적 이후로 이동)
- 순서 변경: 영업 → 입찰 참여 → 견적서 작성 → 수주/계약
- 입찰 참여를 선택적 단계로 변경 (소규모/수의계약 시 생략 가능)
- 분기 표시: 대형/공공 vs 소규모/수의계약 경로 안내
2026-03-05 21:18:56 +09:00
김보곤
6de7ff21e4 fix: [sidebar] 메뉴 검색 닫기 시 스크롤 위치가 초기화되는 문제 수정
- 검색 닫기 시 매칭된 메뉴 위치로 스크롤 유지
- 부모 그룹 자동 펼침으로 해당 메뉴 바로 확인 가능
2026-03-05 21:06:08 +09:00
김보곤
8e4be54e3e fix: [bank-account] 보유계좌관리 테이블에 테넌트ID 열 추가 2026-03-05 21:01:15 +09:00
김보곤
2b98ac56dd fix: [approval] 지출결의서 출금계좌 목록 테넌트 필터링 수정
- BankAccount 글로벌 스코프 의존 → 명시적 tenant_id 필터로 변경
- CorporateCard와 동일한 패턴으로 통일
2026-03-05 20:29:07 +09:00
김보곤
a96cb35068 feat: [tenant] 테넌트 편집에 인쇄용 회사 표시명 필드 추가
- 테넌트 편집 페이지에 '인쇄용 회사명' 입력 필드 추가
- 저장 시 tenant_settings 테이블에 display_company_name 저장
- 재직증명서 등 문서에서 표시명 우선 적용
2026-03-05 20:20:48 +09:00
김보곤
5ae9db5842 feat: [cm-song] 나레이션 제작 시 자동 저장
- 저장 버튼 제거, 제작 완료 시 서버에 자동 저장
- 자동 저장 상태 표시 (저장 중.../자동 저장됨/저장 실패)
- 불필요한 나레이션은 목록에서 삭제하는 방식으로 변경
2026-03-05 20:13:48 +09:00
김보곤
e28077745f feat: [juil] 업무 Workflow 상세 모달 추가
- 각 워크플로우 단계 클릭 시 상세 업무 모달 표시
- 서브플로우 4단계 (단계별 아코디언 펼침)
- Input/Output, 담당자, 소요시간, TIP 정보 포함
- 미니 서브플로우 다이어그램으로 단계 간 이동 가능
2026-03-05 20:00:04 +09:00
김보곤
5c24a70a87 fix: [routes] /settings 리다이렉트 제거 (기존 시스템 설정 route 충돌 방지) 2026-03-05 19:48:36 +09:00
김보곤
d5abdfbe6b fix: [routes] /settings → /tenant-settings 리다이렉트 추가 2026-03-05 19:44:33 +09:00
김보곤
2658b44618 feat: [juil] 업무 Workflow 플로우차트 메뉴 추가
- 주일기업 기획 하위 '업무 Workflow' 메뉴 추가
- 11단계 업무처리과정 인터랙티브 플로우차트 구현
- 각 단계 클릭 시 상세정보(담당부서, 필요서류, SAM 연동) 표시
2026-03-05 19:41:43 +09:00
김보곤
72c93a47fa feat: [tenant-settings] 회사 표시명 설정 추가
- 테넌트 설정에 '인쇄용 회사명' 입력 필드 추가
- 재직증명서 등 문서 인쇄 시 표시명 우선 적용
- 비워두면 기본 company_name 사용
2026-03-05 19:37:03 +09:00
김보곤
7f73c054d5 refactor: [approval] 재직증명서 DOCX 생성을 제거하고 content JSON 저장 + PDF 다운로드 방식으로 변경
- 상신 시 DOCX 생성 API 호출 제거, content JSON만 저장
- show 페이지에 PDF 다운로드 버튼 추가
- TCPDF 기반 PDF 생성 (기존 Pretendard 한글 폰트 활용)
- EmploymentCertService에서 generateDocx/createFileRecord 제거
2026-03-05 19:29:38 +09:00
김보곤
b82cba0cc9 fix: [approval] 재직증명서 DOCX 생성을 PhpWord 직접 생성으로 변경
- 외부 템플릿 파일(employment_cert.docx) 의존성 제거
- PhpWord로 테이블/텍스트 직접 생성하여 서버 배포 시 템플릿 누락 문제 해결
2026-03-05 19:17:33 +09:00
김보곤
62e9a9b8a2 feat: [approval] 재직증명서 미리보기 및 인쇄 기능 추가
- create/edit: 미리보기 버튼 + 모달 (실제 증명서 양식 레이아웃)
- show: 증명서 미리보기 버튼 + 모달 (content 데이터 기반)
- 인쇄 버튼으로 새 창에서 바로 인쇄 가능
2026-03-05 19:14:11 +09:00
김보곤
f405c690a4 fix: [tenant] TenantScope에 session selected_tenant_id fallback 추가
- users 테이블에 tenant_id 컬럼이 없어 글로벌 스코프 미작동
- session('selected_tenant_id') fallback으로 테넌트 필터링 정상화
- 결재 양식 등 모든 BelongsToTenant 모델에 영향
2026-03-05 19:08:25 +09:00
김보곤
dde0acad72 feat: [approval] 재직증명서 기안 기능 추가
- EmploymentCertService: 사원 정보 조회, DOCX 생성, 파일 레코드 생성
- API 엔드포인트: cert-info/{userId}, generate-cert-docx
- _certificate-form: 인적사항/재직사항/발급정보 입력 폼
- _certificate-show: 재직증명서 읽기전용 표시 파셜
- create/edit/show에 employment_cert 양식 분기 처리
- phpoffice/phpword 패키지 추가
2026-03-05 18:54:03 +09:00
김보곤
5ed34ca27b feat: [approval] 결재함/참조함/완료함 페이지 사이즈 선택, 체크박스 선택삭제 기능 추가
- 기안함과 동일한 UI 패턴 적용
- 페이지당 표시 건수 선택 (15/50/100/200/500)
- 전체선택/개별선택 체크박스 + 선택삭제
- 슈퍼관리자 영구삭제 컬럼 추가
2026-03-05 17:46:27 +09:00
김보곤
27f520d303 feat: [approval] 기안함 페이지 사이즈 선택, 체크박스 선택삭제 기능 추가
- 페이지당 표시 건수 선택 (15/50/100/200/500, 기본 15)
- 첫 번째 열 체크박스 추가 (전체선택/개별선택)
- 선택삭제 버튼 및 bulk-delete API 엔드포인트 추가
2026-03-05 17:23:31 +09:00
김보곤
b74c8f8930 fix: [hr] 잔여연차 탭에서 영업팀+제외 사원 필터링 적용 2026-03-05 17:08:55 +09:00
김보곤
add05c6546 fix: [approval] 영구삭제 File 모델 네임스페이스 오류 수정
- App\Models\File → App\Models\Commons\File 수정
2026-03-05 16:57:51 +09:00
김보곤
d0d5a7acd9 feat: [hr] 근태관리 영업팀 및 제외 사원 필터링 적용
- 근태 목록/통계/요약/초과근무에서 영업팀+제외 사원 제외
- 근태관리 부서 드롭다운에서 영업팀 제외
- 활성 사원 목록(드롭다운)에서 영업팀+제외 사원 제외
2026-03-05 16:54:44 +09:00
김보곤
b0f821423d fix: [approval] 영구삭제 시 첨부파일/하위문서 정리 및 에러 로깅 추가
- 첨부파일(files 테이블) soft delete 처리
- 하위 문서(parent_doc_id) 참조 해제
- DB 트랜잭션으로 원자성 보장
- catch 블록에 report() 추가로 에러 로깅
2026-03-05 16:51:13 +09:00
김보곤
86fce5e67f feat: [payroll] 엑셀 export에 추가공제 항목 동적 열 포함
- 전 사원의 deductions JSON에서 고유 항목명 수집
- 개인별 추가공제 항목을 동적 열로 확장 출력
- 추가공제 열 헤더 보라색, 데이터 영역 연보라 배경 구분
- 추가공제 없는 사원은 해당 열 0 표시
2026-03-05 16:29:09 +09:00
김보곤
975a90d1f8 feat: [approval] 기안함 작성자 열 추가 및 슈퍼관리자 영구삭제 기능
- 기안함 테이블에 작성자 열 추가
- 슈퍼관리자: 전체 기안문서 조회 + 영구삭제 버튼
- forceDestroy API 엔드포인트 추가 (연관 Leave/Steps 함께 삭제)
- 기안함에서 휴가신청 시 Leave 자동 생성 로직 추가
2026-03-05 16:22:11 +09:00
김보곤
1b85a26f1d fix: [leave] 휴가신청 탭 기본 종료일을 연말로 변경
- 미래 날짜 휴가가 기본 필터에서 제외되는 문제 수정
- date_to 기본값: today → endOfYear
2026-03-05 16:06:31 +09:00
김보곤
810242ecdf feat: [dashboard] 비본사/영업팀/소속없음 사용자는 주간 날씨만 표시
- HQ(코드브릿지엑스) 테넌트가 아닌 경우 날씨 카드만 노출
- 소속 부서가 없거나 영업팀만 소속인 경우 날씨 카드만 노출
- Quick Actions, 달력, 일정 모달은 본사 직원만 표시
2026-03-05 16:00:10 +09:00
김보곤
a63b501964 feat: [approval] 기안함 휴가신청 → 휴가관리 연동
- 기안함에서 휴가/근태신청/사유서 양식 선택 시 전용 입력 폼 표시
- 양식코드별 유형 필터링 (leave/attendance_request/reason_report)
- saveApproval()에서 content에 구조화된 데이터 포함
- handleApprovalCompleted()에서 Leave 없을 시 자동 생성
- createLeaveFromApproval() 메서드 추가
2026-03-05 15:57:57 +09:00
김보곤
7b9c101065 feat: [business-card] 명함신청 화면에 제작 일정 안내 배너 추가
- 그라데이션 배경 + SVG 장식 배너 디자인
- 신청 마감/제작 소요/배송 기간 일정 안내
- 컬러 아이콘 활용 시각적 구분
2026-03-05 15:28:14 +09:00
김보곤
3f799308ed fix: [receivable] 거래처별 요약 거래건수에 입금 건수 포함되는 오류 수정
- transactionCount가 차변+대변 전체를 카운트하여 실제 매출 건수의 2배로 표시됨
- 차변(매출 발생) 건수만 카운트하도록 수정
2026-03-05 15:27:10 +09:00
김보곤
dd9b534162 feat: [hr] 휴가관리 잔여연차 탭에도 재직상태 필터 추가 2026-03-05 15:23:08 +09:00
김보곤
8af1647173 feat: [hr] 연차잔여 탭에 재직상태 필터 추가 (전체/재직자/퇴직자)
- 필터 기본값: 재직자 (active + leave)
- 퇴직자 선택 시 resigned만 표시
- 전체 선택 시 모든 상태 표시
2026-03-05 15:17:12 +09:00
김보곤
013df2592f feat: [hr] 사원관리 영업팀 제외 및 강제 제외 기능 추가
- 영업팀 포함 부서 사원 기본 제외 (외부직원)
- json_extra.is_excluded 플래그로 강제 제외/복원 토글
- 필터에 '제외 사원 표시' 체크박스 추가
- 제외 사원 시각적 구분 (주황 배경, 제외 뱃지)
2026-03-05 15:16:31 +09:00
김보곤
9192291400 feat: [layout] Remix Icon CDN 추가
- R&D 페이지에서 ri-* 아이콘이 렌더링되지 않던 문제 해결
2026-03-05 14:59:50 +09:00
김보곤
da1fc41acb fix: [cm-song] 나레이션 제작 TTS 오디오 재생 버튼 미표시 수정
- TTS try-catch 블록 누락 수정 (JS 구문 오류 해결)
- audioReady display:flex 명시적 설정 (hidden 제거 후 레이아웃 보장)
2026-03-05 14:56:56 +09:00
김보곤
3bba48e443 refactor: [rd] CM송 → 나레이션 명칭 변경 + 결과 자동 스크롤
- 모든 UI 텍스트 CM송 → 나레이션으로 변경
- 버튼: 나레이션 제작
- 제작 시 결과 패널로 자동 스크롤
- 프롬프트, 다운로드 파일명, 저장 메시지 모두 변경
2026-03-05 14:51:22 +09:00
김보곤
446d0ff60b fix: [rd] CM송 저장 시 tenant_id를 session에서 가져오도록 수정 2026-03-05 14:48:17 +09:00
김보곤
135d88e812 fix: [rd] CM송 제작 입력 필드 기본값 설정 2026-03-05 14:46:20 +09:00
김보곤
272df31501 feat: [rd] CM송 길이 슬라이더, 다운로드, 저장/목록 기능 추가
- 10~60초 5초 간격 길이 선택 슬라이더
- 음성 파일 WAV 다운로드
- 생성 결과 DB 저장 + 목록/상세/삭제 관리
- CmSong 모델 + tenant 스토리지 연동
2026-03-05 14:37:29 +09:00
김보곤
0e9f1297b8 feat: [rd] AI CM송 제작 기능 추가
- Gemini API 기반 CM송 가사 생성 + TTS 음성 생성
- 연구개발 대시보드에 CM송 제작 카드 추가
- 서버사이드 API 프록시로 API 키 보호
2026-03-05 14:13:59 +09:00
김보곤
9727a092e6 feat: [approval] 반려 이력 관리 기능 추가
- rejection_history JSON 컬럼으로 반려 이력 누적 저장
- 재상신 시 반려자, 사유, 일시를 이력에 기록
- 상세 페이지에 반려 이력 섹션 표시 (빨간 테두리)
- 수정 페이지에 이전 반려 이력 표시 (주황 배경)
2026-03-05 13:51:16 +09:00
김보곤
5fd69830ca feat: [approval] 기안함/완료함/대기함에 재상신 구분 열 추가
- resubmit_count 필드로 재상신 횟수 추적
- 반려 후 재상신 시 카운트 증가
- 보라색 뱃지로 재상신/재상신(N차) 표시
2026-03-05 13:06:58 +09:00
김보곤
61e77346de fix: [approval] 완료함 확인 상태 컬럼 추가 및 개별 읽음 처리로 변경
- 일괄 읽음 처리 제거 → 상세 페이지 열람 시에만 개별 읽음 처리
- 확인 컬럼 추가: 확인전(주황) / 확인(회색) 뱃지 표시
- 미확인 행 배경 하이라이트(주황) + 제목 볼드 처리
- 기안자 본인 문서만 확인 상태 표시, 타인 문서는 - 표시
2026-03-05 12:54:09 +09:00
김보곤
280367170a feat: [approval] 완료함 미읽음 알림 뱃지 기능 추가
- approvals 테이블에 drafter_read_at 컬럼 추가 (API 마이그레이션)
- 승인/반려/전결 완료 시 drafter_read_at = null 설정
- getBadgeCounts()에 completed_unread 카운트 추가
- 사이드메뉴 완료함에 미읽음 뱃지 표시 (주황색)
- 완료함 페이지 진입 시 일괄 읽음 처리
- 상세 페이지 열람 시 개별 읽음 처리
2026-03-05 11:38:05 +09:00
999cbad667 chore: [infra] Slack 알림 채널 분리 — product_infra → deploy_mng
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 11:35:24 +09:00
김보곤
2e999114ae fix: [approval] 결재서명란 테이블 크기 확대 (150% 너비, 130% 글씨)
- 셀 패딩 10px→16px, min-width 64px→96px
- 기본 폰트 12px→15px, 도장 32px→42px
- 결재 헤더 13px→16px, 이름/날짜 비례 확대
2026-03-05 11:29:29 +09:00
김보곤
daa7d40f4e feat: [approval] 결재서명란 테이블 추가 (전통 결재 양식)
- 문서 상세 우측 상단에 결재서명란 테이블 배치
- 작성자 + 결재자 컬럼, 직급/이름/서명/날짜 표시
- 승인/반려/보류/전결 상태별 도장 아이콘
- 기존 원형 타임라인 결재 진행 제거, 결재 의견만 유지
2026-03-05 11:23:48 +09:00
김보곤
76aabebc6e fix: [approval] 거래처 검색 키보드 방향키 내비게이션 버그 수정
- moveDown/moveUp 시 debounce 타이머 클리어하여 search 재실행 방지
2026-03-05 11:16:21 +09:00
김보곤
dcbeafd92c fix: [approvals] 완료함에 기안자 본인의 완료 문서도 표시
- 기존: 결재자로 처리한 문서만 조회
- 수정: 내가 기안한 완료/반려/회수 문서 + 결재자로 처리한 문서 모두 조회
2026-03-05 11:08:17 +09:00
김보곤
29c41165cc fix: [approvals] 거래처 선택 후 드롭다운이 다시 열리는 문제 수정
- 선택 시 selected 플래그 설정 + blur로 포커스 해제
- onInput/onFocus에서 selected 상태면 검색 차단
- 다시 직접 타이핑 시 selected 해제되어 검색 재개
2026-03-05 11:05:24 +09:00
김보곤
447c2152d2 fix: [approvals] 거래처 검색 드롭다운을 순수 DOM으로 body에 직접 렌더링
- x-teleport 대신 document.body.appendChild로 드롭다운 생성
- position:fixed + z-index:99999로 모든 레이아웃 위에 표시
- mousedown으로 blur 전 선택 처리
2026-03-05 10:58:13 +09:00
김보곤
75b359cec6 fix: [approvals] 거래처 검색 드롭다운이 레이아웃에 가려지는 문제 수정
- x-teleport로 body에 렌더링하여 overflow 영향 제거
- position:fixed + getBoundingClientRect로 정확한 위치 계산
2026-03-05 10:55:23 +09:00
김보곤
a29d246330 feat: [approvals] 지출결의서 업체명에 거래처 검색 기능 추가
- 업체명 input을 거래처 검색 자동완성으로 교체
- 기존 trading_partners 검색 API 활용 (/barobill/tax-invoice/search-partners)
- 거래처명/사업자번호로 검색, 드롭다운에서 선택
- 키보드 탐색 지원 (위/아래 화살표, Enter, Escape)
- vendor_id, vendor_biz_no 추가 저장
2026-03-05 10:53:03 +09:00
김보곤
011446bab5 fix: [approvals] 불러오기 버튼을 양식 선택 옆으로 이동 2026-03-05 10:46:24 +09:00
김보곤
8226552da5 feat: [approvals] 지출결의서 불러오기 기능 추가
- 기안 작성 시 '불러오기' 버튼으로 기존 지출결의서 불러오기
- 지출결의서 이력 API 엔드포인트 추가 (/expense-history)
- 선택한 지출결의서의 내용을 새 폼에 복사 (날짜는 오늘로 초기화)
2026-03-05 10:27:07 +09:00
김보곤
0d0e458d63 fix: [approvals] 지출부서 기본값 경리부로 변경, 복지카드 옵션 삭제 2026-03-05 10:20:29 +09:00
김보곤
7528113fc3 fix: [approvals] 결재일자 기본값을 현재일자로 설정 2026-03-05 10:17:56 +09:00
김보곤
eae39be233 feat: [approvals] 지출결의서 양식 필드 추가
- 지출형식에 '자동이체 출금' 라디오버튼 추가
- 세금계산서 종류에 '없음' 옵션 추가
- 작성일자 옆에 '결재일자' 날짜 입력 필드 추가
- 저장/수정 로직(getFormData)에 신규 필드 반영
- 읽기전용 표시(_expense-show)에도 반영
2026-03-05 10:15:53 +09:00
김보곤
74d406fceb fix: [leaves] 휴가관리 삭제/영구삭제 함수 누락 수정 2026-03-04 23:09:35 +09:00
김보곤
d431fc3637 fix: [approval] 파일 업로드 시 display_name 누락 오류 수정 2026-03-04 21:32:10 +09:00
김보곤
7b81f954d7 feat: [approval] 지출형식별 내역 테이블 동적 전환
- 법인카드: 지급은행/계좌/예금주 → 결제카드 컬럼 (선택 카드 자동표시)
- 송금: 선택 계좌 정보 자동 채움 (녹색 배경)
- 현금/가지급정산, 복지카드: 기존 수동입력 유지
- getFormData()에서 저장 시 카드/계좌 정보 items에 반영
2026-03-04 21:29:24 +09:00
김보곤
871b470ff2 fix: [approval] 법인카드 tenant_id 세션 조회, 하이패스카드 제외 2026-03-04 21:11:11 +09:00
김보곤
5c652e6b21 fix: [approval] 계좌 조회 tenant 중복조건 제거, 관리링크 모달 변경 2026-03-04 21:00:40 +09:00
김보곤
fa4132c946 fix: [approval] 카드/계좌 1개일 때 자동 선택 2026-03-04 20:54:17 +09:00
김보곤
33fcec9c9c fix: [approval] 카드/계좌 관리 페이지 링크 수정 2026-03-04 20:42:44 +09:00
김보곤
e006f25427 feat: [approval] 지출결의서 법인카드/송금 계좌 선택 기능
- 법인카드 선택 시 카드 목록 패널 슬라이드-다운 표시
- 송금 선택 시 출금 계좌 목록 표시, 대표계좌 자동 선택
- 선택된 카드/계좌 정보를 content JSON에 스냅샷 저장
- 상세 페이지에서 선택된 카드/계좌 정보 읽기전용 표시
2026-03-04 20:29:48 +09:00
김보곤
087ad1c7b9 feat: [approval] 지출결의서 첨부파일 업로드/다운로드 기능 추가
- 첨부파일 업로드 API (GCS 연동, 20MB 제한)
- 첨부파일 삭제/다운로드 API 추가
- 지출결의서 폼에 드래그&드롭 멀티 파일 업로드 UI 추가
- ApprovalService에 linkAttachments 메서드 추가 (is_temp 플래그 관리)
- show 페이지에 첨부파일 목록 표시 및 다운로드 링크
- 지출부서 기본값 '본사', 로그인 사용자 이름 자동입력, 제목 필드 제거
2026-03-04 20:08:16 +09:00
김보곤
beff55cabb fix: [approval] 기안 작성 폼 가로 폭 제한 제거
- max-width: 960px 제거하여 전체 너비 사용
2026-03-04 15:19:17 +09:00
김보곤
9beda571a4 feat: [approval] 지출결의서 전용 폼 UI 추가
- Alpine.js 기반 지출결의서 전용 폼 컴포넌트 (_expense-form.blade.php)
- 지출형식/세금계산서 라디오, 내역 테이블(동적 행 추가/삭제), 금액 자동합계
- 양식 code === 'expense' 시 Quill 대신 전용 폼 표시 (create/edit)
- content JSON 구조화 저장, show 페이지 읽기전용 테이블 렌더링
- 기존 Quill 방식 하위 호환 유지
2026-03-04 15:14:42 +09:00
김보곤
aa8ae86f1d feat: [approval] 양식 선택 시 제목 자동 설정 기능 추가
- applyBodyTemplate에서 제목 필드가 비어있으면 양식명 자동 입력
- create/edit 공통 적용
2026-03-04 14:51:43 +09:00
김보곤
0593700e40 fix: [approval] 결재선 요약 카드 XSS 방어 추가
- updateApprovalLineSummary의 innerHTML에 escapeHtml 함수 적용
- user_name, position, stepLabel 출력 시 HTML 이스케이프 처리
2026-03-04 14:21:27 +09:00
김보곤
25b6470555 feat: [approval] 결재선 드롭다운 직접 배치 및 양식 본문 자동 채움
- 새기안/수정 화면에 결재선 드롭다운 추가 (모달 없이 빠른 선택)
- 양식 선택 시 body_template HTML 자동 채움 (편집기 자동 활성화)
- 모달 닫을 때 외부 드롭다운 동기화
- ApprovalForm 모델 fillable에 body_template 추가
2026-03-04 14:19:18 +09:00
김보곤
a8b6a781bd fix: [eaccount] 부분 월 조회 시 무한루프 크래시 수정
- splitDateRangeMonthly()에서 endDate가 월 중간인 경우
  cursor가 같은 달 1일로 되돌아가 무한루프 발생
- cursor 이동 로직 수정: chunkEnd+1일→월초 대신 chunkStart+1월→월초
- 부분 월, 전체 월, 다중 월 모든 케이스 테스트 완료
2026-03-04 13:26:27 +09:00
김보곤
322442aef6 fix: [roadmap] 개발서버 문서 경로 설정 가능하도록 개선
- config/roadmap.php 추가 (ROADMAP_DOCS_BASE 환경변수)
- RoadmapController에서 config 기반 경로 사용
- 로컬: base_path('../docs') 기본값 유지
- 서버: .env에서 ROADMAP_DOCS_BASE 설정
2026-03-04 13:21:56 +09:00
김보곤
1da6ae7841 fix: [barobill] 전체 바로빌 컨트롤러 WSDL 캐싱 활성화
- EcardController, HometaxController, EtaxController
- WSDL_CACHE_NONE → WSDL_CACHE_BOTH (불필요한 WSDL 재다운로드 방지)
2026-03-04 13:16:15 +09:00
김보곤
94ae19e14a fix: [eaccount] SOAP 호출 크래시 방지 — WSDL 캐싱 + 소켓 타임아웃 + 진단 로깅
- WSDL_CACHE_NONE → WSDL_CACHE_BOTH (매 요청 WSDL 재다운로드 방지)
- default_socket_timeout 60→120초 연장
- register_shutdown_function으로 Fatal Error 감지/로깅
- callSoap에 SOAP 호출 소요시간 로깅 추가
2026-03-04 13:14:59 +09:00
김보곤
367b81d504 fix: [eaccount] 운영서버 500 에러 디버깅 — set_time_limit 안전 처리 + 상세 에러 메시지 2026-03-04 13:03:48 +09:00
김보곤
06cd50d1a6 fix: [ecard] 기간 검색 stale closure 문제 수정
- loadTransactions/loadSplits/loadJournalStatuses에 명시적 날짜 파라미터 추가
- 조회 버튼 클릭 시 현재 날짜 직접 전달
- 편의 버튼(이번달/지난달/D-N월) 클릭 시 자동 검색 트리거
2026-03-04 12:57:54 +09:00
김보곤
6188762f8c fix: [eaccount] 기간 검색 시 stale closure 문제 수정
- loadTransactions/loadSplits에 명시적 날짜 파라미터 추가
- 조회 버튼 클릭 시 TransactionTable prop의 최신 날짜 직접 전달
- 편의 버튼(이번달/지난달/D-N월) 클릭 시 자동 검색 트리거
2026-03-04 12:51:02 +09:00
김보곤
d77b9615b3 fix: [journal] 계좌 출처 전표 일반전표에서 수정 허용
- 카드/세금계산서 출처 → 잠금 유지 (원본에서 수정)
- 계좌(bank_transaction) 출처 → 일반전표에서 수정 허용
- 프론트엔드 UI + 백엔드 update 메서드 동시 수정
2026-03-04 12:42:47 +09:00
김보곤
fc63ea80ff fix: [eaccount] 12월분 조회 타임아웃 오류 수정
- PHP set_time_limit(120) 추가 (SOAP 다건 호출 시 기본 30초 초과 방지)
- 프론트엔드 응답 상태/빈 응답 체크 추가 (에러 원인 구체화)
2026-03-04 12:39:49 +09:00
김보곤
ec388df7b3 feat: [china-tech] 유니트리 왕싱싱 5번째 탭 추가
- 공급망 혁신 인터랙티브 비교 (기존 vs 유니트리 수직 계열화)
- H1/G1 휴머노이드 제어 알고리즘 탭 전환 UI
- 시장 점유율 도넛 차트, 가격 파괴 현황 Bar 차트
- ut- 접두사로 외부 함수 충돌 방지
2026-03-04 11:17:27 +09:00
김보곤
4a72368107 fix: [payables] JournalEntry 모델 use 문 누락 수정 2026-03-04 11:17:10 +09:00
김보곤
f5e7e6c2a8 fix: [payables] 전표 삭제 500 에러 수정
- Accept: application/json 헤더 추가 (HTML 응답 방지)
- findOrFail → find + 수동 404 처리 (에러 메시지 개선)
- try-catch 추가로 상세 에러 메시지 반환
2026-03-04 11:15:05 +09:00
김보곤
f8f9619258 fix: [payables] 전표 삭제 라우트 순서 수정
- journal-entry/{id}를 /{id}보다 위로 이동하여 라우트 충돌 해결
2026-03-04 11:07:52 +09:00
김보곤
32e680dce8 feat: [payables] 미지급금관리 전표 삭제 기능 추가
- 일반전표 상세 행에 삭제 버튼(휴지통 아이콘) 추가
- DELETE /finance/payables/journal-entry/{id} API 추가
- journal_entry_id 필드를 프론트에 전달하도록 쿼리 수정
- 삭제 후 데이터 자동 새로고침
2026-03-04 11:02:27 +09:00
김보곤
7ee3c9398a feat: [china-tech] DeepSeek 량원펑 4번째 탭 추가
- 개요&기원, V3 핵심기술 MoE, 비용효율성, 오픈소스 생태계 4개 내부 탭
- MoE 라우팅 인터랙티브 시뮬레이션 데모
- 훈련 비용 비교 Bar 차트 (DeepSeek vs Llama vs GPT-4)
- 내부 탭 네비게이션 ds- 접두사로 외부 충돌 방지
2026-03-04 11:01:15 +09:00
김보곤
3b7e493b19 feat: [journal] 일반전표입력 테이블에 전표번호 컬럼 추가
- 날짜 다음에 전표번호(entry_no) 컬럼 추가
- 운영서버에서 전표 식별/비교 용이하도록 개선
2026-03-04 10:48:09 +09:00
김보곤
4dc445aaf1 feat: [china-tech] 양즈린 Kimi LLM 기술 리서치 탭 추가
- 세 번째 탭: Moonshot AI 양즈린 분석 콘텐츠
- 타임라인 카드 인터랙션, 문맥 길이 바 차트, 투자 도넛 차트
2026-03-04 10:40:19 +09:00
김보곤
f8bfb9dfa6 fix: [big-tech] Agibot 비전 섹션 가독성 개선
- 다크 배경(slate-900) → 밝은 배경(indigo-50)으로 변경
- 텍스트 색상 대비 강화 (slate-200 → slate-700)
- 비전 탭 버튼/콘텐츠 박스 밝은 테마 적용
2026-03-04 10:36:03 +09:00
김보곤
c79e33063e fix: [big-tech] Agibot 비교 테이블 레이아웃 깨짐 수정
- grid-cols-3 균등 분배 → table 요소로 교체 (컬럼 비율 제어)
- 테이블+차트를 flex 레이아웃으로 나란히 배치
- min-width 설정으로 좁은 화면에서 텍스트 줄바꿈 방지
2026-03-04 10:32:47 +09:00
김보곤
4ecd34e767 feat: [ecard] 변경사항 저장 시 기존 분개 금액 자동 갱신
- 카드 금액 수정 후 저장 시 기존 분개의 차변/대변 금액도 연동 갱신
- 공제/불공제 유형별 라인 구조 보존하면서 금액만 업데이트
- 기존 계정과목, 적요, 거래처 정보 유지
2026-03-04 10:23:33 +09:00
김보곤
d149af95b7 feat: [china-tech] Agibot 휴머노이드 로봇 정보 탭 추가
- 두 번째 탭: Agibot 원정 A1 분석 콘텐츠
- 탭 전환 시 차트 지연 초기화 (lazy init)
- 비전 단계별 인터랙티브 UI
2026-03-04 10:13:17 +09:00
김보곤
706393ea4b fix: [ecard] 분개 모달에서 수정된 카드 금액 자동 반영
- 기존 분개 로드 시 카드 금액과 불일치하면 자동으로 새 금액 기준 라인 갱신
- 불일치 경고를 자동 갱신 안내 메시지로 변경
2026-03-04 10:12:51 +09:00
김보곤
38484c464d fix: [ecard] 분리/분개 모달에서 수정된 금액 반영
- SplitModal의 originalAmount를 effectiveSupplyAmount + effectiveTax로 변경
- 분리 저장 시 백엔드 검증도 수정된 금액 기준으로 전달
2026-03-04 09:43:19 +09:00
김보곤
ed2ac18518 feat: [china-tech] 중국의 기술도약 > 5대 신흥빅테크 페이지 추가
- BigTechController 생성 (HX-Redirect 패턴 적용)
- 5개 탭 UI 구현 (첫 번째 탭: 천텐스, 캄브리콘 AI 반도체 분석)
- Chart.js 차트 3개 (주가, 매출 비중, 성능 레이더)
2026-03-04 09:31:08 +09:00
김보곤
9f45a82940 feat: [hr] 슈퍼관리자 근태/신청 삭제 및 영구삭제 기능 추가
- AttendanceService: forceDeleteAttendance 메서드 추가
- LeaveService: deleteLeave(모든 상태), forceDeleteLeave 메서드 추가
- Controller: force 파라미터 + 슈퍼관리자 권한 분기
- 근태 테이블: 슈퍼관리자에게 삭제/영구삭제 버튼 표시
- 신청 테이블: 슈퍼관리자에게 삭제/영구삭제 버튼 표시
2026-03-04 00:15:56 +09:00
김보곤
6b7eb29ebe fix: [hr] 통합 근태관리 탭2/3 컨테이너 HTML 추가 및 정렬 지원 2026-03-04 00:06:18 +09:00
김보곤
092bcbd66c fix: [hr] 통합 근태관리 JS API URL에 /api 접두사 추가 2026-03-04 00:02:58 +09:00
김보곤
36add4d889 feat: [hr] 근태등록 + 휴가관리 통합 시스템 구현
- Leave 모델 확장: 6개 유형 추가 (출장/재택/외근/조퇴/지각사유서/결근사유서)
- LeaveService: 유형별 결재양식 자동 선택, 유형별 Attendance 반영 분기
- ApprovalService: 콜백 3개 결재양식코드로 확장
- AttendanceIntegratedController: 통합 화면 컨트롤러
- 통합 UI: 근태현황/신청결재/연차잔여 3탭 + 신규 신청 드롭다운
- AttendanceRequest 모델/서비스/컨트롤러/뷰 삭제 (Leave로 일원화)
- AttendanceService: deductLeaveBalance 제거 (Leave 시스템으로 일원화)
2026-03-03 23:52:41 +09:00
김보곤
6674df1b64 fix: [attendance] 근태관리 승인 탭 제거
- 결재관리에서 처리하므로 승인 탭 불필요
- 탭 네비게이션, 승인 탭 콘텐츠, 승인 신청 모달 제거
- 승인/반려 JS 함수 및 탭 전환 로직 제거
2026-03-03 23:04:54 +09:00
김보곤
e8ea3375ad feat: [leave] 결재선 없을 때 빠른 생성 기능 추가
- 결재선 0개 시 경고 메시지 + '결재선 바로 생성' 버튼 표시
- 결재선 있을 때 '새 결재선 추가' 링크 표시
- 빠른 결재선 생성 모달 (z-[60]): 인원 목록 / 결재선 편집 2단 레이아웃
- 부서별 펼침/접기, 이름 검색, SortableJS 드래그 순서 변경
- 저장 후 드롭다운 동적 갱신 + 새 결재선 자동 선택
2026-03-03 22:50:51 +09:00
김보곤
511bfa3ec5 feat: [leave] 휴가 신청 시 결재선 선택 기능 추가
- 휴가 신청 모달에 결재선 드롭다운 + 미리보기 UI 추가
- 선택된 결재선으로 결재 생성 (미선택 시 기본결재선 fallback)
- 휴가 목록에 결재진행 컬럼 추가 (원형 아이콘: ✓승인/✗반려/숫자대기/파랑현재)
- approval.steps.approver eager load 추가
2026-03-03 22:36:30 +09:00
김보곤
81b64f25aa feat: [hr] 사원관리 퇴직자 영구삭제 기능 추가
- 슈퍼관리자만 퇴직 상태 사원을 영구삭제 가능
- 관련 첨부파일도 함께 삭제
- DELETE /admin/hr/employees/{id}/force 엔드포인트 추가
2026-03-03 21:46:56 +09:00
김보곤
614cbaef15 fix: [eaccount] 계좌 입출금내역 적요 중복 표시 수정
- BankTransaction::cleanSummary() 메서드 추가: 상대계좌예금주명(cast) 중복 제거
- parseTransactionLogs: 적요 표시 시 remark2 중복 제거 적용
- cacheApiTransactions: DB 저장 시에도 중복 제거 적용
- 기존 DB 데이터 45건 정리 완료
2026-03-03 21:11:52 +09:00
김보곤
9b36052a8f fix: [user] 사용자 영구삭제 시 FK 제약 위반 500 에러 수정
- users.id를 참조하는 모든 FK를 information_schema에서 동적 조회
- NULLABLE FK → NULL 설정, NOT NULL FK → 관련 행 삭제
- 기존 5개 테이블만 처리하던 것을 전체 FK 대응으로 확장
2026-03-03 19:58:07 +09:00
김보곤
8762882b54 fix: [hr] 사업소득자 임금대장 행 삭제 후 일괄저장 실패 수정
- 모든 행 삭제 시 "저장할 데이터가 없습니다" 오류 → 확인 후 서버 전송으로 변경
- 백엔드 validation: required|array → present|array (빈 배열 허용)
- 서버의 orphan draft 자동 삭제 로직이 정상 동작하도록 수정
2026-03-03 19:30:41 +09:00
김보곤
60291e08f1 fix: [sidebar] 메뉴 검색 시 대분류 그룹도 검색 대상에 포함
- 그룹 헤더(대분류/서브그룹)도 검색어 매칭 대상으로 추가
- 그룹 헤더 매칭 시 하위 전체 메뉴 표시 + 하이라이트 적용
2026-03-03 16:08:20 +09:00
김보곤
25795f8612 feat: [ai-quotation] 제조 견적서 자동 생성 기능 추가
- AI 2단계 분석: 고객 인터뷰 → 요구사항 추출 → 견적 산출
- 모델 확장: AiQuotation(모드/견적번호), AiQuotationItem(규격/단가/금액)
- AiQuotePriceTable 모델 신규 생성
- Create 페이지: 모듈/제조 모드 탭, 제품 카테고리, 고객 정보 입력
- Show 페이지: 제조 모드 분기 렌더링 (품목/금액/고객정보)
- Edit 페이지: 품목 인라인 편집, 할인/부가세/조건 입력
- Document: 한국 표준 제조업 견적서 양식 템플릿
- Controller/Route: update 엔드포인트, edit 라우트 추가
2026-03-03 15:58:16 +09:00
김보곤
3962d4b35c fix: [journal] 카드거래 수정 금액이 일반전표에 미반영되는 문제 수정
- 통합 목록 출금액: approvalAmount(원본) → supplyAmount+taxAmount(수정값) 사용
- 카드 분개 모달: 동일하게 수정된 금액 사용
- 외국결제 수수료 포함 금액 등 사용자 수정값이 정상 반영됨
2026-03-03 15:13:20 +09:00
김보곤
6a5976cc5d feat: [journal] 카드/은행 출처 전표 읽기 전용 적용
- update() 메서드에 source_type 가드 추가 (403 반환)
- 통합 목록에서 카드/은행 분개완료 행에 잠금 아이콘 표시
- handleEditEntry에 출처 전표 방어 가드 추가
- show() 응답에 source_type 필드 추가
2026-03-03 14:54:49 +09:00
김보곤
2ac4c188d5 feat: [hr] 사업소득자 임금대장 동적 행 입력 리디자인
- earner 고정 행 → 동적 행 추가/삭제 구조로 변경
- 상호/성명 datalist 콤보박스 (드롭다운 선택 + 직접 입력)
- display_name/business_reg_number 컬럼 직접 저장
- bulkSave: payment_id 기반 upsert + 미제출 draft 자동 삭제
- confirmed/paid 행 수정/삭제 불가 유지
- 엑셀 내보내기 display_name 직접 사용으로 단순화
2026-03-03 14:21:06 +09:00
김보곤
e431ab1fbd fix: [payroll] 급여목록 정렬 기준을 입사일 오름차순으로 변경 2026-03-03 11:35:41 +09:00
68a96e32a7 fix: [deploy] Google Storage credentials 심링크 추가
- 배포 시 shared/storage/credentials → storage/credentials 심링크 생성
- Google Cloud 서비스 계정 JSON 파일 접근 보장

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 10:21:10 +09:00
9281bb64b9 fix: [deploy] 배포 시 .env 권한 640 보장 추가
- Production 배포 스크립트에 chmod 640 추가
- vi 편집으로 인한 .env 권한 변경(600) 방지
- 2026-03-03 장애 재발 방지 (PHP-FPM이 .env 읽기 실패 → 500)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 10:21:10 +09:00
김보곤
099d08e49e chore: [ai] Gemini 모델 gemini-2.0-flash → gemini-2.5-flash 마이그레이션
- config/services.php fallback 기본값 변경
- AiConfig DEFAULT_MODELS 상수 + getActiveGemini() fallback 변경
- NotionService fallback 변경
- AI 설정 관리 UI placeholder/기본값 변경
- Google Cloud AI 가이드 서비스 현황 모델명 변경
- 환경변수 관리 아카데미 예시 변경
2026-03-03 08:09:28 +09:00
김보곤
3216bb98bc feat: [approval] 결재관리 삭제 권한 기능 추가
- 관리자/슈퍼관리자 모든 상태 결재 문서 삭제 가능
- 일반 사용자는 기존대로 draft + 본인 기안만 삭제
- 진행 중 문서 삭제 시 휴가 연동 취소 처리
- 삭제 API 403 권한 검증 추가
- 상세 페이지 삭제 버튼 + 2중 확인 다이얼로그
2026-03-03 07:36:24 +09:00
김보곤
420b80e45a feat: [ai-quotation] 견적서 5종 템플릿 선택 시스템 추가
- classic(클래식), modern(모던), blue(블루), dark(다크), colorful(컬러풀) 5종
- 문서 상단 미리보기 카드 클릭으로 즉시 디자인 전환
- URL 쿼리 파라미터 ?template=xxx 방식, 기본값 classic
- 인쇄/PDF 시 선택 UI 자동 숨김 (no-print)
- 기존 디자인은 classic 템플릿으로 100% 보존
2026-03-02 19:28:01 +09:00
김보곤
1fa2e0ca34 fix: [ai-quotation] 견적서 대표이사명 수정 (이의찬) 2026-03-02 19:14:17 +09:00
김보곤
a26e66bb8e feat: [ai-quotation] 제조업 표준 견적서 문서 뷰 추가
- 인쇄 전용 standalone 레이아웃 (layouts/document.blade.php) 생성
- 한국 제조업 표준 견적서 양식 문서 뷰 생성 (A4 인쇄/PDF 최적화)
- RdController에 documentQuotation 메서드 추가
- /rd/ai-quotation/{id}/document 라우트 등록
- 상세 페이지에 "견적서 보기" 버튼 추가 (완료 상태만 표시)
- 한글 금액 변환, VAT 자동 계산, 비고란 포함
2026-03-02 19:11:53 +09:00
김보곤
2e3dc556d1 feat: [credit] 신용평가 개발문서 페이지 추가
- 쿠콘(KooCon) API 연동 가이드 10개 섹션 구성
- 라우트, 컨트롤러, Blade 뷰 추가
2026-03-02 18:40:08 +09:00
김보곤
d17b46fe80 feat: [rd] AI 견적 생성 폼에 샘플 인터뷰 자동입력 버튼 추가
- 번개 아이콘 버튼 클릭 시 제목 + 인터뷰 내용 샘플 자동 입력
- 데모/설명용 기능
2026-03-02 18:16:00 +09:00
김보곤
dda94f4db8 fix: [rd] API 호출 URL /admin → /api/admin 수정
- index, create, show 뷰의 fetch URL을 /api/admin/rd/... 로 수정
- api.php 라우트는 api/ prefix가 자동 적용됨
2026-03-02 18:16:00 +09:00
김보곤
44f139f757 feat: [rd] AI 견적 엔진 Phase 1 구현
- 모델 3개: AiQuotationModule, AiQuotation, AiQuotationItem
- AiQuotationService: Gemini/Claude 2단계 AI 파이프라인
- RdController: R&D 대시보드 + AI 견적 Blade 화면
- AiQuotationController: AI 견적 API (생성/목록/상세/재분석)
- Blade 뷰: 대시보드, 목록, 생성, 상세, HTMX 테이블
- 라우트: /rd/* (web), /admin/rd/* (api)
2026-03-02 18:16:00 +09:00
김보곤
85ec94f07f feat: [barobill] 회원사 필수 설정 가이드 섹션 추가
- 파트너사/회원사 구조 설명 (코드브릿지엑스 → 회원사)
- 6단계 설정 가이드: 회원사등록, 공동인증서, 계좌, 카드, 서비스활성화, 충전
- 회원사가 바로빌 사이트에서 직접 수행해야 할 작업 명시
- 체크리스트 포함, 기존 섹션 번호 2~10 → 3~11로 조정
2026-03-02 17:52:44 +09:00
김보곤
6b411f173e feat: [barobill] 바로빌 개발문서 페이지 추가
- 라우트, 컨트롤러, Blade 뷰 생성
- 10개 섹션: 서비스 소개, 과금 구조, 시스템 구조, 트러블슈팅 등
- 기존 카카오톡 가이드 스타일 준용
2026-03-02 17:40:11 +09:00
김보곤
d2cde3d1a7 fix: [menu-sync] 대분류 메뉴 push 시 null URL validation 오류 수정
- import validation에서 url 필드를 required → nullable로 변경
- push/getChildrenData에서 null URL을 빈 문자열로 대체
- importMenu에서 빈 URL을 null로 저장
- push 에러 응답에 원격 서버 에러 메시지 포함
2026-03-02 16:35:37 +09:00
김보곤
ea14de3814 fix: [roadmap] 로드맵 문서 마크다운 렌더링 스타일 개선
- Tailwind prose 클래스 → 커스텀 .markdown-body CSS로 변경
- 테이블 보더, 코드 블록, 제목 계층, 인용문 스타일 추가
2026-03-02 16:19:35 +09:00
김보곤
626d634767 feat: [roadmap] AI 견적서 자동생성 엔진 개발 계획 문서 추가 2026-03-02 16:14:39 +09:00
김보곤
f94213fb39 feat: [roadmap] 로드맵 문서 페이지 추가
- sam/docs 중장기 계획 문서를 렌더링하는 전용 페이지
- 비전&전략, 프로젝트 런칭, 제품 설계, 시스템 개요 4개 카테고리
- Markdown → HTML 변환 (Str::markdown)
- /roadmap/documents 목록 + /roadmap/documents/{slug} 상세
2026-03-02 16:03:08 +09:00
김보곤
f7a9575655 feat: [roadmap] 중장기 계획 메뉴 및 전용 페이지 개발
- 모델: AdminRoadmapPlan, AdminRoadmapMilestone
- 서비스: RoadmapPlanService, RoadmapMilestoneService
- FormRequest: Store/Update Plan/Milestone 4개
- 컨트롤러: Blade(RoadmapController), API(Plan/Milestone) 3개
- 라우트: web.php, api.php에 roadmap 라우트 추가
- Blade 뷰: 대시보드, 목록, 생성, 수정, 상세, 파셜 테이블 6개
- HTMX 기반 필터링/페이지네이션, 마일스톤 인라인 추가/토글
2026-03-02 15:50:43 +09:00
김보곤
84befa546d feat: [google-cloud] AI 활용 가이드 PPTX 다운로드 기능 추가
- AiGuideController에 download() 메서드 추가
- AI 활용 가이드 PPTX 다운로드 라우트 추가
- 뷰에 PPTX 다운로드 버튼 추가
- 7장 슬라이드 HTML → PPTX 변환 파일 포함
2026-03-02 15:15:29 +09:00
김보곤
9fdbee5f0f feat: [google-cloud] AI 활용 가이드 페이지 추가
- AiGuideController 생성 (HX-Redirect 패턴)
- STT, Speaker Diarization, 회의록, 음성녹음, Gemini, GCS, AI Config 정보 페이지
- Google Cloud 메뉴 하위에 라우트 등록
2026-03-02 14:48:58 +09:00
김보곤
71d1c6dd85 fix: [menu] 메뉴 관리 페이지 기본 행 표시 개수를 500으로 변경 2026-03-02 14:31:12 +09:00
김보곤
5bdf133194 feat: [google-cloud] Gemini 2.0 모델 2026.06.01 중단 안내 추가
- 모델 테이블에 중단 예정 뱃지 및 취소선 표시
- 마이그레이션 가이드 경고 박스 추가 (2.0→2.5 권장)
- 바 차트에서 중단 모델 흐림(opacity) 처리
2026-03-02 14:15:08 +09:00
김보곤
1d9725c666 feat: [google-cloud] Google Cloud 메뉴 섹션 추가
- Workspace 정책: 계정관리, 2단계인증, 감사로그, 데이터보존
- Workspace 요금: 4티어 비교, 기능비교, 예상비용, 인상히스토리
- Cloud API 요금: Gemini 모델 단가, 추가기능, Storage, 비용시뮬레이션
- 컨트롤러 3개 + 뷰 3개 + 라우트 그룹 추가
2026-03-02 14:07:38 +09:00
김보곤
31e9b5d605 feat: [claude-code] 활용방안 PPTX 다운로드 기능 추가
- UsagePlanController에 download 메서드 추가
- 라우트에 /usage-plan/download 추가
- 뷰 헤더에 PPTX 다운로드 버튼 추가
- 7장 슬라이드 PPTX 파일 배치
2026-03-02 13:24:58 +09:00
김보곤
fce349392d feat: [claude-code] SAM 활용방안 페이지 추가
- 컨트롤러, 뷰, 라우트 생성
- 7개 섹션: 핵심요약, Before/After, 프로세스플로우, 80%공통화론, 멀티테넌시, AI자동화, 로드맵
- HX-Redirect 패턴 적용
2026-03-02 12:33:10 +09:00
김보곤
143418dc71 feat: [claude-code] Cowork 소개 페이지 추가
- Claude Code vs Cowork 핵심 차이 비교 테이블
- SAM 직무별 활용 시나리오 (영업/관리/생산)
- 업무 유형별 도구 선택 가이드
- Cowork 시작 3단계 안내
2026-03-02 11:40:23 +09:00
김보곤
e1289e0f82 feat: [claude-code] 요금정책 PPTX 다운로드 기능 추가
- 7페이지 상세 PPTX 생성 (표지/API단가/비용비교/팀비용/상세비교/전환가이드/결론)
- PricingController download 메서드 추가
- 페이지 헤더에 PPTX 다운로드 버튼 추가
- .gitignore에 public/downloads/*.pptx 예외 추가
2026-03-02 11:25:43 +09:00
김보곤
d9cd5d3526 feat: [claude-code] 요금정책 비교 분석 페이지 추가
- API 토큰 단가 테이블 (Sonnet/Opus/Haiku)
- 사용 강도별 Max 20x vs Max 5x+API 비용 비교 (시각적 바 차트)
- 5인 팀 기준 총 비용 비교 (현재/Max/Team Premium)
- 최종 결론: Team Premium 연간 결제 추천
2026-03-02 11:08:04 +09:00
김보곤
da334f0ee7 fix: [claude-code] body_html_ko 미존재 시 fallback 처리 2026-03-02 10:57:17 +09:00
김보곤
bec0df29e1 feat: [claude-code] 뉴스 페이지 한/영 토글 기능 추가
- Google Translate API 연동으로 릴리즈 노트 한국어 자동 번역
- 코드 블록 보호 처리 (번역 대상에서 제외)
- 긴 텍스트 단락 분할 번역 지원
- Alpine.js 한국어/English 토글 버튼 (localStorage 저장)
- 기본값: 한국어
2026-03-02 10:55:46 +09:00
김보곤
ab042cb132 feat: [claude-code] Claude Code 뉴스 페이지 추가
- GitHub Releases API 연동 서비스 (1시간 캐싱)
- 뉴스 컨트롤러 + Blade 뷰 (릴리즈 카드 목록)
- /claude-code/news 라우트 그룹 등록
2026-03-02 10:42:18 +09:00
김보곤
511fe69593 fix: [interview] 대분류 하위 '+ 중분류 추가' 버튼 개선
- 기존 '+' 단일문자 → '+ 중분류 추가' 텍스트 버튼으로 변경
- children 목록 하단에 항상 표시되도록 위치 이동
2026-02-28 21:34:04 +09:00
김보곤
43127c9c4f feat: [interview] 카테고리 계층 구조(대분류/중분류) 지원
- InterviewCategory 모델에 parent/children 관계 추가
- Service: getTree, getProjectTree 루트+children eager loading
- Service: createCategory에 parent_id 지원
- Service: cloneMaster 2단계 계층 복제
- Controller: storeCategory validation에 parent_id 추가
- UI: CategorySidebar/DomainSidebar 트리 뷰 렌더링
- UI: findCategory 헬퍼로 트리 내 카테고리 검색
2026-02-28 21:23:59 +09:00
김보곤
974a356f39 feat: [payroll] 전표 생성 도움말 모달 추가
- 전표 생성 버튼 옆에 i 도움말 아이콘 버튼 추가
- 분개 구조, 전표일자/번호, 주의사항, 수정/삭제 안내 포함
2026-02-28 20:31:31 +09:00
김보곤
daaf09bedc fix: [document-templates] 양식 디자이너 미리보기 렌더러 분기 처리
- builder_type=block 템플릿은 buildBlockPreviewHtml() 사용
- 레거시 템플릿은 기존 buildDocumentPreviewHtml() 유지
2026-02-28 20:16:52 +09:00
김보곤
0cf15923dc fix: [document] '블록 빌더' → '양식 디자이너' 명칭 변경 2026-02-28 20:11:59 +09:00
김보곤
47578da428 feat: [payroll] 급여 일반전표 자동 생성 기능
- PayrollController에 generateJournalEntry() 메서드 추가
- 해당월 급여 합산 → 분개 행 자동 구성 (차변 801 급여, 대변 207/205)
- 중복 체크 (source_type=payroll, source_key=payroll-YYYY-MM)
- 0원 항목 행 제외, 차대 균형 검증
- 급여관리 페이지에 전표 생성 버튼 추가
2026-02-28 20:06:18 +09:00
김보곤
f74bd8960b feat: [interview] 인터뷰 시나리오 고도화 Phase 1 구현
- InterviewProject/Attachment/Knowledge 모델 3개 신규
- 기존 모델 확장 (Question, Answer, Session, Category)
- 서비스 확장: 프로젝트 CRUD, 첨부파일, 지식 관리
- 컨트롤러 확장: 프로젝트/첨부/지식 API 엔드포인트
- 라우트 20개 추가 (프로젝트, 첨부, 지식)
- InterviewQuestionMasterSeeder: 8개 도메인 80개 질문
- UI 확장: 프로젝트 모드/기존 모드 전환
  - 프로젝트 선택 바, 상태 바, 도메인 사이드바
  - 탭 구조 (질문편집/인터뷰/첨부파일/추출지식)
  - 구조화 답변 입력 (테이블, 수식, 다중선택 등)
  - 첨부파일 업로드/관리
  - 지식 수동 추가/검증/필터링
2026-02-28 20:03:14 +09:00
김보곤
0706617463 fix: [document] 블록 빌더 Blade 이스케이프 오류 수정
- {{today}} → @{{today}} (Blade가 PHP 상수로 해석하는 문제)
2026-02-28 19:54:50 +09:00
김보곤
97bdc5fbb3 feat: [document] 범용 블록 빌더 Phase 1 구현
- block-editor.blade.php: 3패널 UI (Palette + Canvas + Properties)
- Alpine.js blockEditor() 컴포넌트 (CRUD, Undo/Redo, SortableJS)
- 기본 Block 6종: heading, paragraph, table, columns, divider, spacer
- 폼 필드 Block 7종: text, number, date, select, checkbox, textarea, signature
- BlockRendererService: JSON → HTML 렌더링 서비스
- 컨트롤러 분기: builder_type = 'block' → 블록 빌더 뷰
- 라우트 추가: block-create, block-edit
- API store/update에 schema JSON 처리 추가
- index 페이지에 블록 빌더 진입 버튼 추가
- 목록에 builder_type 뱃지 표시
2026-02-28 19:32:16 +09:00
김보곤
cf5b62ba06 feat: [payroll] 급여계산 도움말 모달 추가
- 급여관리 제목 옆 i 아이콘 버튼 추가
- 모달 내용: 전체 흐름, 지급항목, 4대보험, 세금, 실수령액, 예시, 상태 흐름, 팁
- 현재 설정된 요율/상하한 값을 동적으로 반영
2026-02-28 18:30:55 +09:00
김보곤
b4348d393d feat: [payroll] 급여명세서 엑셀 내보내기 CSV → XLSX 변환
- 제목행 병합 + 14pt 굵게 가운데 정렬
- 남색(#1F3864) 헤더 + 흰색 글씨 + wrapText
- 금액 열(D~O) #,##0 천단위 서식 + 오른쪽 정렬
- 합계행 SUM 수식 + 회색 배경 + 굵게
- 빈 행 포함 최소 10행까지 전체 테두리
- 파일명: 급여명세서_{year}년{month}월_{Ymd}.xlsx
2026-02-28 18:24:48 +09:00
김보곤
36992d5c23 fix: [barobill] SVG viewBox/path 속성 이중 인코딩 오류 수정
- &quot; 로 이스케이프된 SVG HTML을 component prop에 직접 전달하면
  sanitizeComponentAttribute()가 이중 인코딩하여 SVG 파서 에러 발생
- @php 블록에서 변수로 정의 후 prop 전달 방식으로 변경
- 영향 파일: settings, etax, hometax 바로빌 페이지 3개
2026-02-28 17:53:16 +09:00
김보곤
eba34ed009 fix: [hr] 사업소득자 임금대장 버튼 라벨 CSV→엑셀 내보내기 변경 2026-02-28 17:48:11 +09:00
김보곤
20e82049a8 fix: [hr] XLSX 내보내기 Color 객체 → argb 배열로 수정
- applyFromArray()에 Color 객체 직접 전달 시 TypeError 발생
- font/fill/border color를 ['argb' => 'FF...'] 배열 형태로 변경
2026-02-28 17:43:31 +09:00
김보곤
f5bbec4ce6 feat: [hr] 사업소득자 임금대장 CSV→XLSX 내보내기 변환
- PhpSpreadsheet로 스타일링된 XLSX 생성 (제목, 남색 헤더, 테두리)
- 금액 열 천 단위 구분(#,##0), 지급일자 빨간색
- earner 프로필 일괄 로드로 사업자등록번호/주민번호 표시
2026-02-28 17:13:20 +09:00
김보곤
63bc2f1cab docs: [equipment] 설비관리 도움말 업데이트 - 관리자 정/부, QR 모바일 점검, 다주기 점검 내용 추가
- 담당자 → 관리자 정/부 용어 전체 변경
- QR 코드 생성/다운로드/인쇄 안내 추가
- QR 모바일 점검 섹션 신규 추가 (흐름, 특징, 팁)
- 6단계 점검 주기(일일~반년) 안내 추가
- 휴일/주말 일일점검 제한 설명 추가
- 점검 데이터 초기화 안내 추가
- FAQ 2건 추가 (QR 모바일 점검, 데이터 초기화)
2026-02-28 16:23:19 +09:00
김보곤
947e1d1993 feat: [equipment] 설비 목록에 관리자 정/부 열 분리 및 QR 코드 열 추가
- 담당자 단일 열 → 관리자 정, 관리자 부 2열로 분리
- QR 코드 아이콘 열 추가 (클릭 시 모달로 QR 표시)
- QR PNG 다운로드 기능 포함
2026-02-28 16:17:42 +09:00
김보곤
080e6b13e5 fix: [mobile] 모바일 점검 페이지 담당자 → 관리자 정/부 라벨 변경
- 담당: → 관리자 정: 으로 변경
- 관리자 부 표시 추가
2026-02-28 16:15:19 +09:00
김보곤
e0980702a6 fix: [leaves] 최종결재자 조회 시 reorder() 적용
- steps() 관계의 기본 orderBy(ASC)와 충돌 방지
- reorder('step_order', 'desc')로 마지막 승인자 정확히 조회
2026-02-28 16:03:28 +09:00
김보곤
f6803e40d6 fix: [equipment] 담당자 → 관리자 정/부 라벨 변경 및 sub_manager_id 저장 버그 수정
- 설비 등록/수정 폼 라벨: 정 담당자 → 관리자 정, 부 담당자 → 관리자 부
- 상세보기(basic-info) 라벨 동일 변경
- StoreEquipmentRequest, UpdateEquipmentRequest에 sub_manager_id 검증 규칙 추가
- 기존에 sub_manager_id가 validated()에서 누락되어 저장되지 않던 버그 수정
2026-02-28 16:03:22 +09:00
김보곤
603767cb0e fix: [leaves] 결재 승인 시 최종결재자 ID 조회 수정
- $approval->steps (캐시된 컬렉션) → $approval->steps() (fresh 쿼리)로 변경
- 트랜잭션 내에서 업데이트된 step이 정확히 반영되도록 수정
2026-02-28 16:01:49 +09:00
김보곤
34b8a75b08 feat: [leaves] 휴가신청 → 전자결재 자동 연동
- LeaveService: 휴가 신청 시 결재 자동 생성+상신
- LeaveService: approveByApproval/rejectByApproval 메서드 추가
- LeaveService: deletePendingLeave 시 연결된 결재 자동 취소
- ApprovalService: 승인/반려/회수/전결 시 휴가 상태 자동 동기화
- Leave 모델: approval_id, approval() 관계 추가
- UI: pending 휴가에 결재 상세 링크 추가, 승인/반려 버튼 제거
2026-02-28 15:54:59 +09:00
김보곤
4aea02b085 fix: [equipment] 휴일/주말 차단을 일일 점검에만 적용
- 주간~반년 점검은 열이 기간을 대표하므로 비근무일 차단 제거
- 그리드 헤더, 셀 클릭, 판정 계산 모두 $isDaily 조건 추가
- toggleDetail/setResult 서버 차단도 daily에서만 적용
2026-02-28 15:50:52 +09:00
김보곤
2971401501 feat: [equipment] 점검 데이터 초기화 기능 추가
- 개별 설비 초기화: 장비명 하단 초기화 아이콘 클릭 → 확인 → 해당 월 점검 삭제
- 전체 초기화: 조회 버튼 옆 '전체 초기화' 버튼 → 확인 → 전체 설비 점검 삭제
- DELETE /inspections/reset (개별), /inspections/reset-all (전체) API
- canInspect 권한 체크 적용 (개별 초기화)
- SweetAlert 확인 모달로 실수 방지
2026-02-28 15:46:17 +09:00
김보곤
5f24d01780 feat: [approval] 결재 알림 드롭다운을 모달로 전환 + 로그인 시 자동 팝업
- 380px 드롭다운 → 560px 전체 화면 모달로 확장
- 로그인 시 미처리 결재 있으면 자동 팝업 (세션당 1회)
- ESC키/backdrop 클릭으로 모달 닫기 지원
- 모달 내 결재 카드: 긴급뱃지, 기안자, 양식, 날짜, 결재하기 링크
- 60초 뱃지 갱신 유지, per_page 10→20으로 확대
2026-02-28 15:33:24 +09:00
김보곤
ba792a0fcc fix: [equipment] 점검표 휴일 표시 및 주간 1주 저장 버그 수정
- 점검 그리드에 holidays 테이블 기반 휴일 표시 (빨간 배경)
- 휴일/주말 셀 클릭 차단 (UI + 서버 양쪽)
- 자동 판정에서 휴일 제외 (기존 주말만 제외 → 주말+휴일)
- 주간 1주 열 저장 누락 수정 (resolvePeriod에서 isoWeekYear 사용)
- toggleDetail, setResult에 비근무일 검증 추가
- 범례에 '휴일/주말 (점검 불가)' 안내 추가
2026-02-28 15:30:11 +09:00
김보곤
69718e7c18 fix: [approvals] 기안함 뱃지를 진행중 상태 건수로 변경
- 기존: draft(임시저장) 상태 건수 표시
- 변경: pending(진행중) 상태의 내 기안 건수 표시
2026-02-28 15:23:27 +09:00
김보곤
350394820b fix: [approvals] 뱃지 데이터 View::share 덮어쓰기 문제 수정
- AppServiceProvider와 ViewServiceProvider에서 각각 View::share 호출하여 덮어쓰기 발생
- ViewServiceProvider 한 곳에서 영업+결재 뱃지를 통합 관리하도록 수정
- AppServiceProvider에서 뱃지 로직 제거
2026-02-28 15:21:32 +09:00
김보곤
b6b16fcbd1 feat: [equipment] 설비 QR 코드 점검 시스템 추가
- 설비 상세 basic-info 탭에 QR 코드 표시 (qrcode.js CDN)
- QR PNG 다운로드/인쇄 기능
- 모바일 전용 레이아웃 (layouts/mobile.blade.php)
- 모바일 점검 페이지 (/m/inspect/{id})
- setResult API (PATCH /inspections/set-result)
- 4버튼 직접 결과 설정 (양호/이상/수리/취소)
- 전체 양호 일괄 처리
- 주기 탭 전환 (활성 주기만 표시)
2026-02-28 15:18:01 +09:00
김보곤
ee1a2d6633 feat: [approvals] 사이드바 결재 뱃지 색상 함별 차별화
- 결재함: 빨간색(#ef4444), 기안함: 파란색(#3b82f6), 참조함: 초록색(#10b981)
- 뱃지 데이터에 color 속성 추가, menu-item에서 inline style로 적용
2026-02-28 15:17:09 +09:00
김보곤
215aa2bec4 fix: [approvals] 사이드바 뱃지 Blade 컴포넌트 스코프 격리 문제 수정
- View::with() → View::share()로 변경하여 <x-sidebar.menu-item> 컴포넌트에서 $menuBadges 접근 가능하도록 수정
2026-02-28 15:13:32 +09:00
김보곤
d1911265f4 feat: [approvals] 결재 알림 뱃지 시스템 구현
- 사이드바: 결재 대기/기안함/참조함 메뉴에 빨간 뱃지 표시
- 헤더: 알림 벨 클릭 시 결재 대기 목록 드롭다운 표시
- 드롭다운: 제목/기안자/양식/긴급 여부/일시 표시, 클릭 시 상세 이동
- 뱃지 건수 60초 자동 갱신 (API: /api/admin/approvals/badge-counts)
2026-02-28 15:08:57 +09:00
김보곤
9d939a6a6a feat: [approvals] 결재선 카드 드래그 앤 드롭 순서 변경
- SortableJS로 결재선 요약 카드 드래그 앤 드롭 지원
- 순서 변경 시 Alpine 데이터 동기화 및 카드 라벨 자동 갱신
- hover/grab/ghost/chosen 시각 피드백 CSS 추가
- 2명 이상 시 '드래그하여 순서를 변경할 수 있습니다' 힌트 표시
- CSS ::after로 카드 간 화살표 표시 (드래그 시 자연스럽게 이동)
2026-02-28 14:55:31 +09:00
김보곤
b4283ccf85 fix: [approvals] 결재선 요약을 제목 아래로 이동, 카드형 표시
- 결재선 요약 바를 본문 아래에서 제목 아래로 위치 변경
- 표시 형식을 '1차 결재 / 직책 / 이름' 카드형으로 변경
- 결재/합의/참조별 색상 구분 (파랑/초록/회색)
2026-02-28 14:48:32 +09:00
김보곤
2816a6b4f4 fix: [equipment] 점검표 판정 로직 - 오늘까지 도래한 날짜만 검사
- 미래 날짜는 판정에서 제외
- 일일: 오늘까지의 평일만 검사
- 기타 주기: check_date가 오늘 이전인 열만 검사
2026-02-28 14:42:00 +09:00
김보곤
cfdb1044fb feat: [approvals] 기안 작성/수정 결재선을 모달로 전환
- 2열 레이아웃(양식 50% + 결재선 50%)을 1열 풀와이드로 변경
- 결재선 편집기를 모달로 이동, 메인 화면에 요약 바만 표시
- ESC 키로 모달 닫기 지원
- edit 페이지 로드 시 기존 결재선 요약 즉시 표시
2026-02-28 14:41:56 +09:00
김보곤
40534498b3 feat: [equipment] 점검표 판정란 자동 합격/불합격 로직 추가
- 일일점검: 주말 제외, 전체 셀 good/repaired → 합격
- 기타 주기: 전체 열 good/repaired → 합격
- 공백 또는 X(bad) 존재 시 불합격 표시
2026-02-28 14:37:25 +09:00
김보곤
b486dbdc5e fix: [approvals] 결재 상세 메타 정보 열 구분선 추가 (가독성 개선) 2026-02-28 14:27:11 +09:00
김보곤
81f33978af fix: [approvals] Quill.js CDN URL 수정 (cdn.quilljs.com → cdn.jsdelivr.net) 2026-02-28 14:21:13 +09:00
김보곤
c58ca65dc7 feat: [approvals] 기안 본문 Quill.js 편집기 토글 기능 추가
- create/edit: 본문 라벨 옆 편집기 체크박스 + Quill.js v2 WYSIWYG 에디터
- edit: 기존 HTML body 자동 감지 → 편집기 자동 활성화
- show: HTML body 안전 렌더링 (strip_tags), plain text는 기존 방식 유지
- textarea ↔ Quill 토글 시 내용 상호 이관
2026-02-28 14:18:34 +09:00
김보곤
60aef7992b feat: [equipment] 점검항목 다른 주기로 복사 기능 추가
- 서비스: copyTemplatesToCycles 메서드 추가 (중복 항목 스킵)
- 컨트롤러: copyTemplates API 엔드포인트 추가
- UI: 다른 주기에 복사 버튼 + 체크박스 모달
2026-02-28 14:17:37 +09:00
김보곤
090275e133 fix: [approvals] 기본 결재선 템플릿 드롭다운 선택 표시 수정
- selectedLineId 타입을 숫자로 초기화하여 option value와 일치시킴
2026-02-28 14:10:02 +09:00
김보곤
f1be22f062 feat: [approvals] 기안 작성 시 기본 결재선 템플릿 자동 선택
- is_default=true인 결재선 템플릿을 자동으로 선택하고 steps 로드
2026-02-28 13:57:38 +09:00
김보곤
cd0afb9c6e feat: [equipment] 다중 점검주기 + 정/부 담당자 체계 구현
- InspectionCycle enum: 6종 점검주기 상수, 열 라벨, check_date 계산
- Equipment 모델: subManager 관계, canInspect() 권한 체크
- Template/Inspection 모델: inspection_cycle fillable 추가
- EquipmentInspectionService: 주기별 점검 조회/토글/권한 체크
- 점검표 UI: 주기 탭, 동적 필터(월/연도), 주기별 그리드 열
- 점검항목 템플릿: 주기별 탭 그룹핑, 모달에 주기 선택
- 설비 등록/수정/상세: 부 담당자 필드 추가
- 권한 없는 장비 셀 비활성(cursor-not-allowed, opacity-50)
2026-02-28 12:37:59 +09:00
김보곤
b2d639265c feat: [users] 사용자 수정 화면에 소속 부서 선택 기능 추가
- UserController: profile 쿼리에 department_id 추가
- edit.blade.php: 소속 부서 select 드롭다운 UI 추가
- UpdateUserRequest: department_id 유효성 검증 규칙 추가
- UserService: tenant_user_profiles에 department_id 저장 로직 추가
2026-02-28 12:14:35 +09:00
김보곤
162f630051 fix: [approvals] 결재선 저장 시 직책(job_title) fallback 추가
- enrichLineSteps: position_label → job_title_label fallback
- saveApprovalSteps: 동일 fallback 적용
- position_key가 NULL이고 job_title_key만 있는 사용자 대응
2026-02-28 09:25:37 +09:00
김보곤
c877704575 fix: [approvals] 결재선 인원 목록 직급순 정렬 적용
- 부서 내 정렬: 직급(pos_rank) → 직책(pos_title) → 이름 순
- COALESCE로 직급/직책 없는 사용자는 하단 배치
2026-02-28 09:20:41 +09:00
김보곤
8971ec1595 style: [approvals] 결재선 관리 모달 Toss 스타일 리디자인
- CSS 변수 기반 Toss 디자인 시스템 적용
- backdrop blur + slide-up 애니메이션
- 카드 기반 결재선 목록 (arrow flow 표시)
- 커스텀 step type select, pill 버튼
- 모달/인풋/버튼 전체 톤앤매너 통일
2026-02-28 09:15:10 +09:00
김보곤
af7334dc79 feat: [approvals] 결재선 템플릿 CRUD 기능 추가
- POST/PUT/DELETE /api/admin/approvals/lines 라우트 추가
- ApprovalApiController storeLine/updateLine/destroyLine 메서드
- ApprovalService createLine/updateLine/deleteLine + enrichLineSteps 헬퍼
- 기안함 화면에 결재선 관리 버튼 + 모달 UI (목록/편집 2-state)
2026-02-28 09:07:33 +09:00
김보곤
0845720a01 feat: [menu-sync] 순서 동기화 Push + 되돌리기 기능 추가
- pushOrder: 로컬 메뉴 순서를 원격 서버에 일괄 반영
- undoOrder: 순서 동기화 취소하여 이전 상태로 복원
- reorder: 외부 API 엔드포인트 (이름 기반 매칭)
- 세션 기반 스냅샷으로 되돌리기 지원
2026-02-28 08:41:20 +09:00
김보곤
e5ea72ed2a feat: [users] 재직/휴직/퇴직 상태 검색 필터 추가
- index.blade.php에 employee_status 필터 select 추가
- UserService에 tenant_user_profiles 기반 필터링 로직 추가
2026-02-28 08:31:29 +09:00
김보곤
90e2f23f18 feat: [menus] 최상위 그룹 상단/하단 이동 버튼 추가
- depth=0 메뉴에만 이동 버튼(↕) 표시
- 클릭 시 드롭다운으로 상단/하단 이동 선택
- 기존 reorder API 재사용하여 sort_order 일괄 변경
2026-02-28 08:24:55 +09:00
김보곤
cf7244a30c feat: [users] 재직상태(재직/휴직/퇴직) 표시 및 수정 기능 추가
- 사용자 목록 테이블에 재직상태 컬럼 추가 (재직/휴직/퇴직 배지)
- 사용자 수정 화면에 재직상태 select 필드 추가
- UserService.getUsers()에 employee_status 서브쿼리 추가
- UserService.updateUser()에서 tenant_user_profiles에 employee_status 저장
- UpdateUserRequest에 employee_status validation 추가
2026-02-28 08:23:33 +09:00
김보곤
9f7c107970 fix: [users] 직급/직책 툴팁이 항상 표시되는 문제 수정
- Tailwind invisible/group-hover 클래스가 빌드에 누락되어 항상 표시됨
- inline style(display:none) + onmouseenter/onmouseleave로 변경
2026-02-28 08:13:42 +09:00
김보곤
4528147b26 feat: [users] 직급/직책 label에 info 툴팁 아이콘 추가
- 직급: "조직 내 서열" 설명 (사원, 대리, 과장 등)
- 직책: "맡은 역할/책임" 설명 (팀장, 실장 등)
- hover 시 tooltip 표시 (group/invisible 패턴)
2026-02-28 08:11:19 +09:00
김보곤
691a8bae55 feat: [users] 사용자 관리에 직급/직책 입력 UI 추가
- 사용자 수정/생성 화면에 직급(position_key), 직책(job_title_key) 선택 필드 추가
- HR 사원관리의 position-add-modal 재사용 ([+] 버튼으로 새 직급/직책 추가)
- UserService에서 tenant_user_profiles 테이블에 저장 (updateOrInsert)
- UpdateUserRequest, StoreUserRequest에 validation 규칙 추가
2026-02-28 08:07:42 +09:00
김보곤
5c5402e61a feat: [approvals] 결재선 에디터 2패널 UI/UX 개선
- 좌측 패널: 부서별 인원 목록 (접이식 그룹핑, 검색 필터)
- 우측 패널: 결재선 (SortableJS 드래그앤드롭 순서 변경)
- 부서별 전체 인원 API 추가 (GET /api/admin/tenant-users/list)
- 결재/합의/참조 유형별 요약 바 추가
- position_key → positions 테이블 조인으로 직위 라벨 표시
2026-02-28 07:45:54 +09:00
김보곤
0be540ff83 fix: [approvals] 결재자 검색 API 응답 필드 수정
- department_name → department 필드명 변경 (프론트엔드 호환)
- tenant_user_profiles 조인으로 position(직급) 데이터 추가
- 부서명 검색 지원 추가
2026-02-28 00:56:27 +09:00
김보곤
5b31822453 fix: [approvals] Alpine.js v3 호환 결재선 데이터 접근 방식 수정
- __x.$data (v2 문법) → _x_dataStack[0] (v3 문법)으로 변경
- 에디터에 id="approval-line-editor" 추가하여 정확한 요소 선택
- create.blade.php, edit.blade.php 동시 수정
2026-02-28 00:45:27 +09:00
김보곤
c39a59e082 fix: [approval] whereColumn → where 서브쿼리 비교 오류 수정
- getPendingForMe, getBadgeCounts에서 whereColumn에 Closure 전달 오류
- whereColumn은 두 컬럼 비교용, 서브쿼리 비교는 where 사용
2026-02-27 23:48:13 +09:00
김보곤
9b96a3cad1 feat: [approval] Phase 2 결재관리 고급 기능 구현
- 보류/해제: 현재 결재자가 문서를 보류하고 해제
- 전결: 이후 모든 결재를 건너뛰고 최종 승인
- 회수 강화: 회수 사유 입력, 첫 결재자 미처리 시에만 허용
- 복사 재기안: 완료/반려/회수 문서를 복사하여 새 draft 생성
- 참조 열람 추적: 미열람/열람 필터, mark-read API
- ApprovalDelegation 모델 생성 (Phase 3 위임 대결 준비)
- 뱃지 카운트에 reference_unread 추가
2026-02-27 23:42:12 +09:00
김보곤
12c9ad620a feat: [approval] 결재관리 Phase 1 MVP 구현
- 모델 4개: Approval, ApprovalStep, ApprovalForm, ApprovalLine
- ApprovalService: 목록/CRUD/워크플로우(상신/승인/반려/회수) 비즈니스 로직
- ApprovalApiController: JSON API 엔드포인트 (기안함/결재함/완료함/참조함)
- ApprovalController: Blade 뷰 컨트롤러 (HX-Redirect 처리)
- 뷰 8개: drafts, pending, completed, references, create, edit, show
- partials: _status-badge, _step-progress, _approval-line-editor
- api.php/web.php 라우트 등록
2026-02-27 23:17:41 +09:00
김보곤
bcb45c9362 feat: [payroll] 급여 확정 취소 기능 추가
- 확정 상태에서 작성중으로 되돌리는 기능 추가
- Model: isUnconfirmable() 상태 헬퍼 추가
- Service: unconfirmPayroll() 메서드 추가
- Controller: unconfirm() 엔드포인트 추가
- Route: POST /{id}/unconfirm 라우트 추가
- View: 확정 취소 버튼 및 JS 함수 추가
2026-02-27 22:17:34 +09:00
김보곤
30973d1772 feat: [hr] 사업소득자 임금대장 입력 기능 구현
- BusinessIncomePayment 모델 (소득세3%/지방소득세0.3% 자동계산)
- BusinessIncomePaymentService (일괄저장/통계/CSV내보내기)
- 웹/API 컨트롤러 (ALLOWED_PAYROLL_USERS 접근 제한)
- 스프레드시트 UI (인라인 편집, 실시간 세금 계산)
- HTMX 연월 변경 갱신, CSV 내보내기
2026-02-27 20:22:28 +09:00
김보곤
cd61dc8366 fix: [payroll] 전월 복사/일괄 생성 시 SoftDeletes 유니크 제약 충돌 수정
- exists() 대신 withTrashed()->first()로 soft-deleted 레코드 포함 체크
- soft-deleted 레코드 존재 시 forceDelete() 후 재생성
- copyFromPreviousMonth(), bulkGenerate() 양쪽 동일 수정
2026-02-27 18:00:18 +09:00
김보곤
53c7f00340 feat: [payroll] 급여관리 페이지 접근 제한 (이름 기반)
- 허용 사용자: 이경호, 전진선, 김보곤
- 웹 컨트롤러: 미허용 시 안내 뷰 반환
- API 컨트롤러: 모든 엔드포인트에 403 반환
- restricted.blade.php 안내 페이지 생성
2026-02-27 18:00:08 +09:00
김보곤
732d021b6d fix: [payroll] 전월 복사 후 테이블 새로고침 함수명 수정
- refreshPayrollTable → refreshTable (실제 함수명)
2026-02-27 17:38:12 +09:00
김보곤
57b58a2297 feat: [payroll] 전월 급여 복사 등록 기능 추가
- PayrollService에 copyFromPreviousMonth() 메서드 추가
- PayrollController에 copyFromPrevious() 액션 추가
- 전월 지급/공제 금액을 그대로 복사 (요율 재계산 없음)
- 이미 존재하는 사원/연월은 스킵 처리
2026-02-27 17:30:26 +09:00
김보곤
df8707776c fix: [esign] 서명/도장 이미지 원본 비율 유지하여 PDF 합성
- overlayImage()에서 원본 이미지 가로세로 비율 계산
- 필드 영역 내 contain 방식 배치 (비율 유지 + 중앙 정렬)
- getimagesize 실패 시 기존 방식 폴백
2026-02-27 17:22:36 +09:00
김보곤
88b73a0c3c chore: 운영 배포 재트리거 2026-02-27 17:07:33 +09:00
김보곤
e35fbb26ff fix: [esign] 운영서버 PDF 미리보기 필드값 누락 수정
- TCPDF K_PATH_FONTS를 storage/fonts/tcpdf/로 설정하여 vendor 쓰기 권한 문제 해결
- 사전 생성된 Pretendard 폰트 정의 파일 포함 (런타임 생성 불필요)
- downloadDocument() 에러 로깅 상세화 (trace 포함)
2026-02-27 16:59:09 +09:00
김보곤
3f27c2f7c0 fix: [payroll] 수정 모드에서 공제항목 자동 재계산 방지
- 수정 모드(editingPayrollId)에서는 /calculate API 호출 생략
- 기본급 등 변경 시 총지급액/실수령액만 로컬 재합산
- 재계산 버튼 클릭 시에만 최신 요율로 서버 계산 실행
2026-02-27 16:56:45 +09:00
김보곤
a88774339c fix: [payroll] 급여 수정 시 요율 재계산 제거
- updatePayroll()에서 calculateAmounts() 호출 제거
- 저장된 공제 금액을 그대로 유지 (요율 변경 영향 없음)
- 수동 수정(deduction_overrides)만 반영
- 총지급액/총공제액/실수령액은 재합산
2026-02-27 16:44:19 +09:00
김보곤
0383ef8ec0 feat: [esign] 완료 알림톡 템플릿 2종 선택 및 버튼 URL 도메인 치환
- 발송 UI에 서명 요청 + 완료 알림톡 템플릿 각각 선택 가능
- 선택한 완료 템플릿명을 DB에 저장하여 서명 완료 시 사용
- 버튼 URL 도메인을 현재 환경의 app.url로 자동 치환 (개발/운영 환경 대응)
2026-02-27 16:29:24 +09:00
김보곤
710b61f887 feat: [hr] 사원 상세화면에 고용형태 표시 추가 2026-02-27 16:19:44 +09:00
김보곤
64a9bcefce fix: [payroll] 급여 수정 모달 총 지급액 계산 오류 수정
- decimal:0 캐스트로 인해 금액이 문자열로 전달되어 문자열 연결 발생
- Number()로 명시적 숫자 변환 추가
2026-02-27 16:19:36 +09:00
김보곤
6fd59b4b44 feat: [hr] 사원 등록/수정 폼에 고용형태 선택 추가
- Employee 모델에 EMPLOYMENT_TYPES 상수 정의 (정규직/계약직/일용직/프리랜서)
- create/edit 뷰에 고용형태 select 드롭다운 추가
2026-02-27 16:00:36 +09:00
김보곤
2a29d966f5 fix: [payroll] 공제항목 수정 후 이전값 표시 문제 수정
- deduction_overrides validation에서 min:0 제거 (마이너스 허용)
- 수정 모달에서 calculate API 대신 DB 저장값 직접 표시
2026-02-27 15:55:34 +09:00
김보곤
bcef17d731 fix: [payroll] 중복 급여 등록 시 자동으로 수정 모드 전환
- store 시 동일 사원/기간 레코드가 존재하면 updatePayroll로 전환
- 기존 INSERT 실패(500) 대신 정상 수정 처리
2026-02-27 15:51:40 +09:00
김보곤
e43bb8df4e fix: [payroll] 급여 등록 중복 체크 Race Condition 수정
- 중복 체크를 트랜잭션 내부로 이동 + lockForUpdate()
- UniqueConstraintViolationException 방어 처리 (500→422)
2026-02-27 15:48:47 +09:00
김보곤
01f6ea469b feat: [payroll] 추가 공제 항목 마이너스 금액 입력 허용
- formatMoneyInput: 음수 부호(-) 유지하도록 수정
- doRecalculate/submitPayroll: amount > 0 → amount !== 0 조건 변경
- Controller validation: deductions.*.amount에서 min:0 제약 제거
- 연말정산 환급 등 음수 공제 항목 지원
2026-02-27 15:41:04 +09:00
김보곤
5f0b2ae798 fix: [payroll] 수정 모달 공제항목 자동계산값으로 표시하도록 변경
- 수정 모달 열 때 DB 저장값 대신 자동계산값으로 공제항목 표시
- 계산 방식 변경(round→floor, 구상수→DB조회)으로 인한 수동표시 오작동 해결
- 비교 API 호출에 user_id 추가하여 가족수 반영
2026-02-27 14:20:42 +09:00
김보곤
b11de7e294 fix: [payroll] 공제 항목 전체 원단위 절삭(10원 단위) 적용
- 건강보험, 장기요양보험, 국민연금, 고용보험: round() → floor(x/10)*10
- 고소득 구간 근로소득세 공식 계산도 10원 단위 절삭 적용
- 지방소득세는 이전 커밋에서 이미 적용됨
2026-02-27 14:10:44 +09:00
김보곤
62e8040304 feat: [payroll] 근로소득세 간이세액표 기반 자동 계산 기능
- IncomeTaxBracket 모델 생성 (DB 조회 방식)
- PayrollService: calculateIncomeTax DB 기반으로 리팩토링
- 10,000천원 초과 구간 공식 계산 (calculateHighIncomeTax)
- 지방소득세 10원 단위 절삭 적용
- 공제대상가족수(1~11명) 반영 (본인 + 피부양자)
- calculate API에 user_id 파라미터 추가
- 사원 select에 data-dependents 속성 추가
- 모달에 공제대상가족수 표시
2026-02-27 13:59:30 +09:00
김보곤
61a0cc2480 feat: [hr] 사업소득자관리 메뉴 신설
- BusinessIncomeEarner 모델 생성 (worker_type 글로벌 스코프)
- Employee 모델에 worker_type 글로벌 스코프 추가 (기존 사원 격리)
- BusinessIncomeEarnerService 생성 (등록/수정/삭제/조회)
- Web/API 컨트롤러 생성 (CRUD + 파일 업로드)
- 라우트 추가 (web.php, api.php)
- View 5개 생성 (index, create, show, edit, partials/table)
- 사업장등록정보 6개 필드 (사업자등록번호, 상호, 대표자명, 업태, 종목, 소재지)
2026-02-27 13:47:10 +09:00
김보곤
c3bb357513 feat: [leave] 잔여연차 퇴사자 포함 및 퇴사일 기준 연차 계산
- getBalanceSummary에 resigned 상태 포함
- 퇴사자 연차는 퇴사일까지만 산출
- 퇴사자 1년 미만 재계산 대상 제외
- 상태 컬럼 추가 (재직/휴직/퇴사 배지)
- 퇴사자 행 회색 배경 시각적 구분
- 근속 계산: 퇴사자는 입사일~퇴사일 기준
2026-02-27 13:16:26 +09:00
김보곤
b0c22f6efd feat: [leave] 잔여연차 테이블에 퇴사일 컬럼 추가 2026-02-27 13:10:15 +09:00
김보곤
52a0ef7899 feat: [leave] 잔여연차 테이블 헤더 클릭 정렬 기능 추가
- 사원, 부서, 입사일, 부여, 사용, 잔여, 소진율 컬럼 정렬 지원
- 기본 정렬: 입사일 오름차순 (빠른 순)
- 활성 정렬 컬럼 파란색 강조 + 방향 화살표 표시
2026-02-27 13:09:04 +09:00
김보곤
494454ce1d fix: [leave] 1년 미만 직원 연차 부여를 월별 발생 방식으로 수정
- 입사일~오늘 완료 월수 기준으로 연차 산출 (기존: 연말까지 선부여)
- 잔여연차 조회 시 1년 미만 직원 total_days 자동 재계산
- 도움말 가이드 연차 산출 방식 설명 갱신
2026-02-27 12:58:04 +09:00
김보곤
2f6ee8e698 fix: [employee] 부양가족 삭제가 서버에서 반영되지 않는 문제 수정
- hx-put → hx-post + _method=PUT (method spoofing) 변경
  서버 Nginx/PHP-FPM에서 PUT body 파싱 이슈 방지
- dependents_submitted 히든 마커 추가
  모든 부양가족 삭제 시 dependents 키가 폼에 없어도 서버에서 인식
- Controller에서 마커 확인 후 빈 배열로 처리하여 삭제 반영
2026-02-27 12:56:25 +09:00
김보곤
d8cd953f87 fix: [employee] 부양가족 피부양자/장애인 체크박스 저장 안되는 문제 수정
- Alpine.js :value 반응형 바인딩 대신 hidden+checkbox 표준 패턴 적용
- hidden input value=0 (기본값) + checkbox name+value=1 (체크 시 덮어쓰기)
- HTMX form 직렬화 시 Alpine.js 동기화 타이밍 문제 해결
2026-02-27 12:33:18 +09:00
김보곤
207c2a7e6b fix: [employee] 부양가족 체크박스(장애인/피부양자) 값 저장·표시 오류 수정
- Alpine x-model + hidden input 패턴 개선 (동적 :value 바인딩)
- JSON 로드 시 boolean 정규화로 체크 상태 정확히 복원
- 서비스 레이어에서 filter_var BOOLEAN 캐스팅 추가
- show 페이지 표시 로직 filter_var로 강화
2026-02-27 12:33:18 +09:00
김보곤
4b2c6a2730 feat: [leave] 잔여연차 탭 도움말 기능 추가
- 휴가관리가이드.md 마크다운 콘텐츠 작성 (연차 산출 방식, 촉진 제도 등)
- 잔여연차 탭 헤더에 도움말(?) 버튼 추가
- help-modal.blade.php 생성 (sales 패턴 재사용)
- LeaveController에 helpGuide() 메서드 추가
- 도움말 라우트 등록
2026-02-27 12:33:18 +09:00
김보곤
6b5a20e857 feat: [esign] 알림톡 템플릿명 환경별 분기 (운영: 원본, 개발: _DEV)
- resolveTemplateName() 헬퍼 메서드 추가 (두 컨트롤러)
- production 환경: 전자계약_서명요청, 전자계약_완료, 전자계약_리마인드
- 개발 환경: 전자계약_서명요청_DEV, 전자계약_완료_DEV, 전자계약_리마인드_DEV
- config('app.url')은 이미 환경별 도메인 자동 사용
2026-02-27 12:33:18 +09:00
김보곤
8ec45c85ae fix: [settlement] Alpine @click에서 clearAllCheckboxes 참조 오류 수정 2026-02-27 12:33:18 +09:00
김보곤
d6633a773a fix: [settlement] 구독료 수당(매니저/파트너) 로직 3가지 버그 수정
- 매니저 미지정 시 구독료가 소실되던 버그 → 파트너 수당으로 편입
- deposit/balance 양쪽에서 구독료 이중 계상 → deposit에서만 1회 기록
- 파트너별 결산 탭에 +구독 배지 추가, select에 manager_user_id 포함
2026-02-27 12:33:18 +09:00
김보곤
ef943381bf fix: [leave] 근속 기간 표시 형식 개선
- 소수점 float 대신 "1년 3개월", "2개월" 형태로 표시
- 1개월 미만인 경우 "1개월 미만" 표시
2026-02-27 11:27:56 +09:00
김보곤
ed3ae025c2 fix: [payroll] 식대 비과세 처리 + 국민연금 상한/하한 적용 개선
- 식대(bonus)를 과세표준에서 제외하여 4대보험/세금 산출 시 비과세 처리
- 라벨 '식대' → '식대(비과세)'로 변경 (등록/수정/상세/엑셀)
- 합계 영역에 과세표준(식대 제외) 표시 추가
- 국민연금은 기존대로 settings의 상한액/하한액 적용 (과세표준 기준으로 변경)
2026-02-27 11:22:54 +09:00
김보곤
c116551090 feat: [leave] 잔여연차 탭 전체 직원 자동 표시 + 연차일수 자동 산출
- 사원관리 재직/휴직 직원 전체가 잔여연차 탭에 자동 표시
- balance 레코드 없는 직원은 insertOrIgnore로 자동 생성
- 입사일 기반 근속년수로 연차일수 자동 산출 (근로기준법 제60조)
- 테이블에 입사일/근속 컬럼 추가 (6→8컬럼)
2026-02-27 11:22:54 +09:00
김보곤
ec2bf35fe0 fix: [payroll] 급여 수정 모달에 공제항목 데이터 전달 누락 수정
- table.blade.php의 수정 버튼에서 pension, health_insurance, long_term_care,
  employment_insurance, income_tax, resident_tax 필드를 json_encode에 추가
2026-02-27 11:07:39 +09:00
김보곤
b5329eab3f feat: [payroll] 공제항목 수동 수정 기능 추가 및 상여금→식대 변경
- 공제 6개 항목(국민연금/건강보험/장기요양/고용보험/소득세/지방소득세) 수동 수정 가능
- 수동 수정 시 노란색 배경으로 시각적 구분, 재계산 버튼으로 초기화
- 서버사이드 deduction_overrides 유효성 검증 및 적용 로직 추가
- 수정 모달에서 기존 공제값 복원 및 자동계산 비교로 수동 표시
- 상여금 → 식대 라벨 변경 (등록/상세/CSV)
2026-02-27 11:00:29 +09:00
김보곤
5314777c46 feat: [payroll] 급여 등록 모달 금액 입력 콤마 자동 포맷팅
- 숫자 입력 시 천단위 콤마 자동 표시
- 0인 필드에 포커스 시 공백으로 표시, blur 시 0으로 복원
- 수당/공제 동적 행에도 동일하게 적용
2026-02-27 10:14:06 +09:00
김보곤
50e5139ff4 feat: [payroll] 급여 설정 상한액/하한액 콤마 포맷팅 적용
- 국민연금 상한액/하한액 입력에 콤마 자동 표시
- 0일 때 포커스 시 공백, blur 시 0 복원
- 설정 저장 시 콤마 제거하여 서버 전송
2026-02-27 10:09:16 +09:00
김보곤
2d7fc3a83a feat: [payroll] 장기요양보험 공제항목 추가
- 건강보험에서 장기요양보험 분리하여 별도 항목으로 표시
- 급여등록/수정/일괄생성/상세보기/CSV 내보내기 모두 반영
- 공제순서: 국민연금-건강보험-장기요양보험-고용보험-근로소득세-지방소득세
2026-02-27 10:09:16 +09:00
김보곤
b292a98136 fix: [payroll] tenant_id null 오류 수정
- session('selected_tenant_id')에 기본값 1 추가
- PayrollSetting::getOrCreate, scopeForTenant 수정
- PayrollService 전체 tenant_id 조회에 기본값 적용
- Payroll 모델 scopeForTenant 동일 패턴 적용
2026-02-27 10:09:16 +09:00
김보곤
5435f805c4 fix: [attendance] 근태현황 HTMX 부분 로드 시 스크립트 미실행 오류 수정
- index 메서드에 HX-Redirect 추가하여 전체 페이지 로드 보장
- 근태관리→근태현황 이동 시 switchTab null 참조 에러 해결
2026-02-27 09:56:55 +09:00
김보곤
273fecaf8b fix: [payroll] soft-deleted 레코드로 인한 중복 등록 에러 수정
- withTrashed()로 삭제된 레코드 포함하여 중복 체크
- 삭제된 레코드 존재 시 forceDelete 후 재등록 허용
2026-02-27 09:56:55 +09:00
김보곤
8309d457b5 fix: [payroll] 급여 등록 500 에러 수정
- 중복 급여 등록 시 유니크 제약 위반 대신 422 응답 반환
- tenant_id null 방어 처리 (세션 값이 null인 경우 기본값 적용)
2026-02-27 09:56:55 +09:00
김보곤
857e4af147 fix: [payroll] tenant_id null 오류 수정
- session('selected_tenant_id')에 기본값 1 추가
- PayrollSetting::getOrCreate, scopeForTenant 수정
- PayrollService 전체 tenant_id 조회에 기본값 적용
- Payroll 모델 scopeForTenant 동일 패턴 적용
2026-02-27 09:56:55 +09:00
김보곤
d84f6745a3 fix: [payroll] 급여등록 용어 및 공제항목 순서 변경
- 초과근무수당 → 고정연장근로수당 명칭 변경
- 소득세 → 근로소득세, 주민세 → 지방소득세 명칭 변경
- 공제항목 순서: 국민연금-건강보험-고용보험-근로소득세-지방소득세
- CSV 내보내기 헤더 및 데이터 순서 동일 적용
2026-02-27 09:56:55 +09:00
김보곤
cdef14659e revert: [attendance] MNG 마이그레이션 정책 변경 되돌림
- MNG 마이그레이션 파일 삭제 (API에서 관리)
- CLAUDE.md DB 아키텍처 규칙 원래대로 복원
- 마이그레이션은 API 프로젝트에서만 관리
2026-02-27 09:37:08 +09:00
김보곤
cb0bc1a545 feat: [attendance] attendance_requests 마이그레이션 MNG에 추가
- API 운영 배포 중지 기간 동안 MNG에서 마이그레이션 관리
- Schema::hasTable() 가드로 중복 실행 방지
- CLAUDE.md DB 아키텍처 정책 업데이트
2026-02-27 09:24:33 +09:00
김보곤
8f6911121c feat: [payroll] 급여관리 기능 구현
- Payroll, PayrollSetting 모델 생성
- PayrollService 구현 (CRUD, 자동계산, 간이세액표, 일괄생성)
- Web/API 컨트롤러 생성 (HTMX/JSON 이중 응답)
- 급여 목록, 통계 카드, 급여 설정 뷰 생성
- 라우트 추가 (web.php, api.php)
- 상태 흐름: draft → confirmed → paid
2026-02-27 09:13:10 +09:00
김보곤
5283487f7e feat: [attendance] 근태현황/근태관리 메뉴 분리
- 근태현황(/hr/attendances): 조회 전용 (목록/캘린더/요약)
- 근태관리(/hr/attendances/manage): CRUD + 승인 관리
- table-manage.blade.php: 관리용 테이블 (체크박스/수정/삭제)
- table.blade.php: 조회용 테이블 (GPS 포함, CRUD 제거)
- API 컨트롤러 view 파라미터로 테이블 분기
2026-02-27 09:10:43 +09:00
김보곤
4462646550 fix: [attendance] 주간 근무시간 계산 UNSIGNED 오버플로우 수정
- CAST(... AS UNSIGNED)에서 음수값 시 2^64-1로 오버플로우되던 버그
- CAST(... AS SIGNED) + COALESCE + GREATEST(0, ...)로 안전하게 변경
- getOvertimeAlerts(), getEmployeeMonthlySummary() 두 곳 수정
2026-02-27 09:10:43 +09:00
김보곤
84bc7e6005 fix: [attendance] User 모델에 tenantProfiles 관계 추가로 500 에러 수정
- User 모델에 tenantProfiles() HasMany 관계 추가 (tenant_user_profiles 테이블)
- eager loading에 department 관계도 포함하여 N+1 방지
2026-02-27 09:10:43 +09:00
김보곤
b4ba431a23 fix: [attendance] cal_days_in_month → Carbon endOfMonth 대체로 500 에러 수정
- PHP calendar 확장 미설치 환경에서 cal_days_in_month 함수 호출 시 500 에러 발생
- getMonthlyStats, getMonthlyCalendarData, getEmployeeMonthlySummary 3곳 수정
2026-02-27 09:10:43 +09:00
김보곤
82513645e7 fix: [leave] 휴가 신청 422 에러 메시지 표시 개선 2026-02-27 09:06:52 +09:00
김보곤
3577ddd630 fix: [leave] HTMX 사이드바 네비게이션 시 HX-Redirect 적용 2026-02-27 09:06:52 +09:00
김보곤
8c4b6a2786 feat: [leave] 휴가관리 Phase 1 구현
- Leave, LeavePolicy, LeaveGrant 모델 생성
- LeaveBalance 헬퍼 메서드 추가 (useLeave, restoreLeave, canUse)
- LeaveService 핵심 로직 (신청, 승인, 반려, 취소, 잔여연차, 통계)
- API 컨트롤러 (목록, 등록, 승인/반려/취소, 잔여연차, 통계, CSV 내보내기)
- 뷰 컨트롤러 + 라우트 등록 (web, api)
- Blade 뷰 (index + 3개 탭 partials: table, balance, stats)
2026-02-27 09:06:52 +09:00
김보곤
2f739d0d55 feat: [hr] 입퇴사자 현황 페이지 구현
- EmployeeService에 근속기간 조회/통계/CSV 내보내기 메서드 추가
- API 컨트롤러에 tenure/tenureExport 엔드포인트 추가
- EmployeeTenureController 뷰 컨트롤러 생성
- 통계 카드 6개 (전체/재직/퇴직/평균근속/올해입사/올해퇴사)
- HTMX 테이블 (사원/부서/직책/상태/입사일/퇴사일/근속기간/근속일수)
- 필터: 이름검색, 부서, 상태, 입사기간 범위, 정렬
- CSV 엑셀 다운로드 기능
2026-02-27 09:04:07 +09:00
김보곤
57a2012a85 fix: [esign] 완료 알림톡 버튼 URL 및 이메일 PDF 서명 누락 수정
- 완료 알림톡 버튼이 서명페이지로 연결되던 문제 → 문서 다운로드 URL로 강제 변경
- 계약 완료 상태에서 signed_file_path 없을 때 서명 PDF 재생성 로직 추가
- mergeSignatures 실패 시 상세 trace 로그 추가
2026-02-26 23:31:59 +09:00
김보곤
e8514929f5 fix: [esign] MNG EsignSigner 모델에 역할/상태 상수 추가
- ROLE_CREATOR, ROLE_COUNTERPART 상수 추가
- STATUS_WAITING~STATUS_REJECTED 상수 추가
- 운영서버 Undefined constant 오류 수정
2026-02-26 23:15:41 +09:00
김보곤
4769953422 fix: [esign] 서명 요청/다음 서명자 알림에 역할 기반 분기 적용
- dispatchNotification: 상대방(counterpart)만 알림톡, 본사(creator)는 이메일
- 순차 서명 시 다음 서명자 알림도 동일 역할 기반 분기 적용
- 다음 서명자 알림에서 getKakaotalkChannelId/getTemplateData 헬퍼 활용
- 알림톡 실패 시 이메일 자동 폴백 로직 통일
2026-02-26 23:11:30 +09:00
김보곤
308dc38875 feat: [esign] 서명 완료 시 상대방에게 카카오톡 알림톡으로 PDF 계약서 전달
- sendCompletionAlimtalk: 승인된 '전자계약_완료' 템플릿 조회 후 변수 치환 발송
- 버튼 URL에 PDF 다운로드 링크(/api/document) 포함
- 상대방(counterpart)만 알림톡 발송, 본사(creator)는 이메일 유지
- 알림톡 실패 시 이메일 자동 폴백 처리
- 발송 후 3초 대기하여 전달 결과 확인 로직 추가
- getKakaotalkChannelId, getTemplateData 헬퍼 메서드 추가
2026-02-26 23:11:30 +09:00
김보곤
a6d5abf229 fix: [esign] OTP SMS 발송 조건을 tenant_id 대신 서명자 역할 기반으로 변경
- 기존: tenant_id != 1 조건으로 본사 테넌트 전체 SMS 차단
- 변경: signer->role === counterpart 조건으로 상대방만 SMS 수신
- 본사(creator)는 이메일 OTP 유지, 상대방(counterpart)은 SMS OTP 수신
2026-02-26 23:11:30 +09:00
김보곤
7ca820295f fix: [deploy] Jenkinsfile storage/logs 처리 및 PdfSignatureService 폰트 등록 간소화
- Jenkinsfile: storage/logs 심링크 대신 디렉토리 생성 + chown 방식으로 변경
- PdfSignatureService: 폰트 캐시 로직 간소화 (registerKoreanFont 제거)
2026-02-26 21:45:42 +09:00
김보곤
adc587292f feat: [attendance] 근태관리 2차 고도화 8개 기능 구현
- 월간 캘린더 뷰 (사원별 필터, 날짜 클릭 등록, HTMX 월 이동)
- 일괄 등록 (다수 사원 체크박스 선택 후 일괄 등록, upsert 처리)
- 사원별 월간 요약 (상태별 카운트 + 총 근무시간 집계 테이블)
- 초과근무 알림 (주 48h 경고 / 52h 위험 배너)
- 근태 승인 워크플로우 (신청→승인→근태 레코드 자동 생성)
- 자동 결근 처리 (매일 23:50 스케줄러, 주말 제외)
- 연차 관리 연동 (휴가 등록 시 leave_balances 자동 차감)
- GPS 출퇴근 UI (테이블 GPS 아이콘 + 상세 모달)
- 탭 네비게이션 (목록/캘린더/요약/승인) HTMX 기반 전환
2026-02-26 21:29:25 +09:00
김보곤
402e264290 feat: [attendance] 근태현황 Phase 1 구현
- 1-1: 등록/수정 버그 수정 (created_by 덮어쓰기 방지)
- 1-2: 엑셀(CSV) 다운로드 기능 추가
- 1-3: 체크박스 일괄 삭제 기능 추가
- 1-4: 월간 통계 연/월 선택 기능 추가
2026-02-26 21:29:25 +09:00
김보곤
607593ff3f feat: [hr] 근태현황 MNG 프론트엔드 구현
- Attendance 모델 (attendances 테이블, 상태/색상 매핑, check_in/check_out accessor)
- AttendanceService (목록/월간통계/CRUD, 부서/사원 드롭다운)
- API 컨트롤러 (HTMX+JSON 이중 응답, stats/index/store/update/destroy)
- 페이지 컨트롤러 (index 페이지 렌더링)
- 웹/API 라우트 등록 (hr/attendances, api/admin/hr/attendances)
- index.blade.php (통계카드+필터+등록/수정 모달)
- partials/table.blade.php (HTMX 부분 로드 테이블)
2026-02-26 21:29:25 +09:00
김보곤
d2c3ce678a feat: [journal] 일반전표입력에 카드사용내역 분개 기능 추가
- JournalEntryController에 cardTransactions/storeFromCard/cardJournals/deleteCardJournal 메서드 추가
- 카드거래 분개 라우트 4개 추가 (card-transactions, store-from-card, card-journals, delete-card-journal)
- JournalEntryList에 카드거래 탭/필터/통계 통합
- CardJournalEntryModal 컴포넌트 추가 (공제/불공제에 따른 기본 분개 라인 자동 생성)
- source_type=ecard_transaction 호환 (기존 ecard 페이지 분개와 동일 키)
2026-02-26 21:18:08 +09:00
김보곤
e86b7869b9 refactor: [hr] 사원 첨부파일을 GCS 듀얼 저장 방식으로 변경
- 업로드: 로컬 + GCS 동시 저장 (gcs_object_name, gcs_uri 기록)
- 다운로드: GCS Signed URL 우선, 로컬 폴백
- 삭제: GCS + 로컬 모두 삭제, soft delete 처리
- DashboardCalendarController 패턴 준용
2026-02-26 20:21:24 +09:00
김보곤
2edce0d282 feat: [hr] 사원등록 기능 확장
- 기본정보에 주민등록번호 필드 추가
- 급여이체정보 섹션 추가 (이체은행, 예금주, 계좌번호)
- 부양가족 정보 섹션 추가 (동적 행 추가/삭제)
- 첨부파일 업로드/다운로드/삭제 기능 추가
- 은행 목록 config/banks.php 설정 파일 생성
- show 페이지 주민등록번호 뒷자리 마스킹 처리
2026-02-26 20:21:24 +09:00
김보곤
5e06f53d2d feat: [employee] 입사일/퇴직일 컬럼 헤더에 정렬 아이콘 추가
- 입사일/퇴직일 컬럼 클릭 시 오름차순/내림차순 토글
- 현재 정렬 상태를 아이콘으로 표시 (↑ 오름차순, ↓ 내림차순, ↕ 미선택)
- 기본 정렬: 입사일 빠른순(오름차순)
2026-02-26 19:46:16 +09:00
김보곤
ce942e8999 feat: [employee] 사원관리 정렬 기능 추가 (입사일/퇴직일)
- 정렬 드롭다운 추가: 입사일 빠른순/최신순, 퇴직일 최신순/빠른순, 상태순
- 기본 정렬을 입사일 빠른순으로 설정
- JSON 컬럼(json_extra.hire_date, resign_date) 기반 정렬
2026-02-26 19:46:16 +09:00
김보곤
40e3f93f5c Merge branch 'main' of http://114.203.209.83:3000/SamProject/sam-manage 2026-02-26 19:27:23 +09:00
김보곤
39061c244d refactor: [hr] 사번 필드 제거, 비밀번호 제거, 퇴직일 추가 2026-02-26 19:27:15 +09:00
김보곤
160716d333 feat: [hr] 사원 목록 테이블에 퇴직일 컬럼 추가 2026-02-26 19:09:55 +09:00
김보곤
85bb8b090a feat: [hr] 사원 등록/수정 - 비밀번호 제거 및 퇴직일 추가
- 비밀번호 필드 제거 (등록 폼, validation, 서비스)
- 퇴직일(resign_date) 필드 추가 (등록/수정/상세 화면)
- json_extra에 resign_date 저장/수정 지원
- Model에 resign_date accessor 추가
2026-02-26 19:04:55 +09:00
김보곤
d0b8679d13 refactor: [hr] 사번(employee_code) 필드 전체 제거
- Model: appends, accessor 제거
- Service: 검색 필터, json_extra 저장/수정 로직 제거
- Controller: validation 규칙 제거
- View: create, edit, show, table에서 사번 UI 제거
2026-02-26 18:53:54 +09:00
김보곤
72a5c096a2 fix: [hr] searchUsers에서 q 파라미터 null 처리
- ConvertEmptyStringsToNull 미들웨어로 인해 빈 q= 가 null로 변환되는 문제
2026-02-26 18:40:01 +09:00
김보곤
20fd449c39 feat: [hr] 사원 등록 - 기존 직원 불러오기 기능 추가
- 검색 API (GET /api/admin/hr/employees/search-users)
- 테넌트 소속 + 사원 미등록 사용자 검색
- 기존 사용자 선택 시 Employee만 생성 (User 생성 건너뜀)
- Alpine.js 검색 UI (포커스시 목록, debounce 검색, 선택/해제)
2026-02-26 18:40:01 +09:00
김보곤
2b3cb3bb92 fix: [hr] 사원 등록/수정 에러 메시지 화면 표시 개선
- API 컨트롤러 store/update/destroy에 try-catch 추가
- debug 모드에서 상세 에러 메시지 포함 응답
- create/edit 뷰에 showToast 기반 에러 표시 추가
- 422 validation 에러 필드별 메시지 표시
- 500 서버 에러 시 사용자 친화적 메시지 표시
2026-02-26 18:40:01 +09:00
김보곤
51cc12b229 fix: [hr] 사원 등록 시 users 테이블 NOT NULL 제약 오류 수정
- email 미입력 시 임시 이메일 생성 (NOT NULL 제약 대응)
- user_id 자동 생성 및 중복 방지 로직 추가
- role 필드 'ops' 기본값 설정
- Hash::make 사용으로 통일 (기존 패턴 준수)
2026-02-26 18:40:01 +09:00
김보곤
56e4ce937a feat: [hr] 직급/직책 인라인 추가 기능 구현
- Position 생성 API 엔드포인트 추가 (POST /admin/hr/positions)
- 직급/직책 select 옆 "+" 버튼으로 모달 열기
- 모달에서 이름 입력 → API 저장 → 드롭다운에 자동 추가 및 선택
- 중복 key 방지 (기존 값이면 그대로 반환)
- create/edit 뷰 모두 적용
2026-02-26 18:40:01 +09:00
김보곤
3ce980a5f7 fix: [hr] 사원 등록 시 user_tenants pivot 연동 추가
- User 생성 후 tenants()->attach() 호출 (멀티테넌트 필수)
- user_id, must_change_password, created_by 필드 추가
- 기존 UserService 패턴과 동일하게 맞춤
2026-02-26 18:40:01 +09:00
김보곤
29ca022321 feat: [hr] 인사관리 사원관리 Phase 1 구현
- Employee, Position 모델 생성 (tenant_user_profiles, positions 테이블)
- EmployeeService 생성 (CRUD, 통계, 필터/검색/페이지네이션)
- 뷰 컨트롤러(HR/EmployeeController) + API 컨트롤러 생성
- Blade 뷰: index(통계카드+HTMX테이블), create, edit, show, partials/table
- 라우트: web.php(/hr/employees/*), api.php(/admin/hr/employees/*)
2026-02-26 18:40:01 +09:00
김보곤
b3a2ced834 fix: [finance] 일일자금일보 입금 테이블 잔액 열 제거 2026-02-26 16:48:46 +09:00
70ff4ab40e fix:TCPDF 폰트를 PDF 인스턴스에 전체 경로로 등록하여 font definition 오류 해결
- addTTFfont()는 storage에 캐시만 생성하고 SetFont() 시 K_PATH_FONTS(vendor)에서 찾아 실패
- registerKoreanFont()로 분리: 캐시 생성 + $pdf->AddFont() 전체 경로 등록
- mergeSignatures(), generatePreview() 양쪽에 적용
2026-02-26 15:37:24 +09:00
김보곤
23e6b1d5d1 feat: [esign] PDF 서명 합성 폰트를 Pretendard로 통일
- NanumGothic → Pretendard-Regular.ttf 변경
- 전자계약 PDF 원본과 동일한 폰트로 필드 텍스트 렌더링
- storage/fonts/에 Pretendard-Regular.ttf 내장 (로컬/서버 공통)
2026-02-26 15:20:43 +09:00
70ef10e201 fix:TCPDF 폰트 캐시 경로를 storage로 변경 (vendor 쓰기 권한 문제 해결)
- getKoreanFont()에서 폰트 캐시를 vendor/tcpdf/fonts/ 대신 storage/app/private/fonts/에 저장
- www-data가 vendor 디렉토리에 쓸 수 없는 운영 환경 권한 문제 해결
- 배포 시마다 vendor가 새로 생성되어도 폰트 캐시가 shared/storage에 유지됨
2026-02-26 14:59:50 +09:00
f0192795e9 fix:배포 시 storage/logs를 shared 심링크로 변경
- 기존: mkdir로 릴리즈 디렉토리에 logs 생성 → 배포마다 로그 유실
- 변경: ln -sfn shared/storage/logs → 로그 영속 보존
- 원인: 전자계약 PDF 합성 오류 추적 중 발견

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 14:42:20 +09:00
김보곤
d7b8e866b2 fix: [holidays] 대량 등록 모달에 기존 등록 데이터 표시
- 해당 연도에 등록된 휴일이 있으면 기존 데이터를 텍스트 형식으로 표시
- 등록된 데이터가 없을 때만 기본 공휴일 예시 표시
2026-02-26 14:37:57 +09:00
김보곤
5793845def feat: [business-cards] 처리완료 삭제 기능 추가 및 기본 매수 500매로 변경
- 관리자 화면 처리완료 카드에 삭제 버튼 추가
- processed 상태만 삭제 가능 (서비스 검증)
- 파트너 명함신청 기본 매수 100매 → 500매 변경
2026-02-26 14:06:36 +09:00
김보곤
b01d7a0ed6 fix: [equipment] 설비 사진 원본 비율 유지 + 클릭 시 모달 확대 2026-02-26 13:28:40 +09:00
김보곤
3084b3d219 feat: [equipment] 수리이력 등록에 목업 데이터 자동 입력 버튼 추가
- 번개 아이콘 클릭 시 전체 필드에 랜덤 목업 데이터 채움
- 설비/수리자는 기존 옵션에서 랜덤 선택
- 외주업체는 보전구분이 외주일 때만 입력
2026-02-26 13:28:40 +09:00
김보곤
c187a0fca3 feat: [equipment] 목록 필터 상태를 sessionStorage에 저장/복원
- 검색/필터 후 수정 페이지 이동 → 목록 복귀 시 필터 유지
- 페이지네이션, select 변경 시에도 자동 저장
2026-02-26 13:28:40 +09:00
김보곤
e228348deb fix: [equipment] 사진 URL을 Signed URL로 변경 (비공개 GCS 버킷 대응)
- getPhotoUrls(): 공개 URL → GoogleCloudStorageService.getSignedUrl() 사용
- basic-info 탭: 동일하게 Signed URL로 변경
- URL 유효기간 120분
2026-02-26 13:28:40 +09:00
김보곤
52300969c3 fix: [equipment] 사진 업로드 시 stored_name 누락 오류 수정
- files 테이블 stored_name 컬럼이 NOT NULL인데 INSERT에서 누락
- uploadPhotos(), uploadPhotoFromPath() 모두 stored_name 추가
2026-02-26 13:28:40 +09:00
김보곤
dc40e3dc6b fix: [equipment] Ctrl+V 붙여넣기 클립보드 이미지 추출 수정
- DataTransferItemList 전통적 for 루프로 변경 (for...of 호환성 문제)
- kind === 'file' 조건 추가로 이미지 파일만 정확히 필터링
2026-02-26 13:28:40 +09:00
김보곤
eca26d557f feat: [equipment] 사진 업로드에 Ctrl+V 클립보드 붙여넣기 기능 추가
- create/edit 페이지에서 Ctrl+V로 클립보드 이미지 즉시 업로드
- 드롭존에 붙여넣기 안내 텍스트 추가
2026-02-26 13:28:40 +09:00
김보곤
5e164b1f26 feat: [equipment] 엑셀 Import 시 설비 사진 추출/업로드 기능 추가
- EquipmentPhotoService: uploadPhotoFromPath() 추가, 압축 메서드 public 전환
- EquipmentImportService: Drawing 추출/임시파일 저장/사진 업로드 통합
- EquipmentController: Import 응답 메시지에 사진 업로드 결과 포함
2026-02-26 13:28:40 +09:00
김보곤
3aa65f2b11 feat: [equipment] 설비 사진 업로드 시 이미지 압축 (1MB 이하)
- GD 라이브러리로 업로드 전 이미지 압축 처리
- 장축 2048px 초과 시 리사이즈 (비율 유지)
- JPEG 품질 85→40 점진적 감소로 1MB 이하 보장
- PNG(투명 없음)/GIF/BMP → JPEG 자동 변환
- PNG(투명 있음) → PNG 유지 (압축 레벨 9)
- 임시파일 자동 정리 (finally 블록)
2026-02-26 13:28:40 +09:00
김보곤
0c9d2fd441 feat: [equipment] 사진 멀티 업로드(GCS) + 엑셀 Import 기능 추가
- EquipmentPhotoService: GCS 기반 사진 업로드/삭제/조회 (최대 10장)
- EquipmentImportService: 엑셀 파싱 → 설비 일괄 등록 (한글 헤더 자동 매핑)
- API: 사진 업로드/목록/삭제, Import 미리보기/실행 엔드포인트
- 뷰: create/edit에 드래그앤드롭 사진 업로드, show에 갤러리 표시
- import.blade.php: 3단계 Import UI (파일선택 → 미리보기 → 결과)
- phpoffice/phpspreadsheet 패키지 추가
2026-02-26 13:28:40 +09:00
김보곤
d9c9739de1 fix: [equipment] API URL 경로 /api 접두사 누락 수정
- 모든 HTMX hx-get 및 fetch() URL에 /api 접두사 추가
- /admin/equipment → /api/admin/equipment 일괄 변경
- 대상: index, create, edit, show, inspections, repairs 뷰 7개 파일
2026-02-26 13:28:18 +09:00
김보곤
11a7f89216 feat: [equipment] 설비관리 모듈 구현
- 모델 6개 (Equipment, InspectionTemplate, Inspection, InspectionDetail, Repair, Process)
- 서비스 3개 (Equipment, Inspection, Repair)
- API 컨트롤러 3개 + FormRequest 4개
- Blade 컨트롤러 + 라우트 등록
- 뷰: 대시보드, 등록대장(CRUD), 일상점검표(캘린더 그리드), 수리이력
2026-02-26 13:28:18 +09:00
김보곤
f0178d8928 fix: [vat] 부가세 관리에서 매출(종이세금계산서) 항목 삭제
- 요약 테이블 행 삭제
- 필터 드롭다운 옵션 삭제
- 컨트롤러 계산 로직 및 stats 응답 제거
- React state 초기값에서 관련 필드 제거
2026-02-26 13:24:39 +09:00
김보곤
292e47a11e fix: [esign] 로컬 저장 방식 법인도장이 서명 페이지에서 미표시되는 버그 수정
- store(): GCS뿐 아니라 local_path 도장도 signer에 자동 적용
- getContract(): signer에 도장 없어도 tenant_settings에서 확인하여 has_stamp 반환
- submitSignature(): 기존 계약 creator도 tenant_settings에서 도장 가져와 적용
2026-02-26 12:40:49 +09:00
김보곤
405fbaf5da fix: [sms] 발신번호 02-6347-0005로 수정 2026-02-26 12:40:49 +09:00
김보곤
bcf64dc95c fix: [sms] API URL을 Blade route() 헬퍼로 변경 및 에러 상세 표시
- 하드코딩 URL → route() 기반으로 환경별 자동 대응
- 422 에러 시 validation 에러 메시지 상세 표시
2026-02-26 12:40:49 +09:00
김보곤
f12f0c34c9 feat: [sms] 번개 아이콘 클릭 시 테스트 데이터 자동 입력 2026-02-26 12:40:49 +09:00
김보곤
6d63c37371 fix: [sms] 발신번호를 고정 텍스트로 변경 (셀렉트박스 제거) 2026-02-26 12:40:49 +09:00
김보곤
964f0030dd fix: [sms] 발신번호 기본값 02-0005-0006 설정 2026-02-26 12:40:49 +09:00
김보곤
401ac649ae feat: [sms] SMS 발송 테스트 메뉴 추가
- SmsController (WEB): 카카오톡 패턴 동일한 HX-Redirect 처리
- BarobillSmsController (API): 발송, 발신번호 조회/확인, 전송상태 조회
- SMS 발송 테스트 블레이드 뷰: 발신번호 목록, 바이트 카운터, 발송 결과 표시
- web.php: barobill/sms/send 라우트 추가
- api.php: barobill/sms API 라우트 4개 추가
2026-02-26 12:40:49 +09:00
김보곤
25a7a87712 feat: [barobill] 독립 SMS API 연동 및 OTP 발송 전환
- BarobillService에 SMS WSDL 엔드포인트 추가
- sendSMSMessage, checkSMSFromNumber, getSMSFromNumbers 메서드 추가
- sendOtpViaSms를 알림톡 대체발송 → 독립 SMS API(SendSMSMessage)로 전환
2026-02-26 12:40:49 +09:00
김보곤
b25a9af824 fix: [esign] 본사(tenant_id=1) OTP는 항상 이메일 발송
- 본사는 알림톡 방식 선택 시에도 OTP를 이메일로 처리
- getContract 응답에서도 본사는 send_method를 email로 반환
2026-02-26 09:14:16 +09:00
김보곤
59f68e272c feat: [esign] OTP 인증코드 SMS 발송 기능 추가
- send_method가 alimtalk/both일 때 SMS로 OTP 발송
- 바로빌 sendATKakaotalkEx SMS 대체발송 기능 활용
- SMS 실패 시 이메일 폴백
- auth.blade.php UI 메시지 SMS/이메일 분기 표시
2026-02-26 09:14:16 +09:00
김보곤
daee3e3334 fix: [esign] 알림톡 버튼 URL 도메인 치환 제거 (카카오 템플릿 검증 불일치 방지) 2026-02-26 08:49:21 +09:00
김보곤
169d649ee6 fix: [esign] 알림톡 버튼 URL 도메인을 APP_URL로 치환 (개발/운영 환경 대응) 2026-02-26 08:35:30 +09:00
김보곤
0689c5418b fix: [esign] 알림톡 버튼 URL의 #{토큰} 변수를 실제 access_token으로 치환 2026-02-26 08:27:03 +09:00
김보곤
e9325ff74d feat: [esign] 알림톡 템플릿 선택 기능 추가
- 바로빌 승인된 알림톡 템플릿 목록 조회 API 추가
- 서명 요청 발송 시 템플릿 선택 드롭다운 UI 추가
- 템플릿 미리보기 (본문 + 버튼) 표시
- send()에 template_name 파라미터 전달 지원
- 미선택 시 기존 하드코딩 폴백 유지
2026-02-26 08:27:02 +09:00
김보곤
8c24b0ae24 feat: [equipment] 설비관리 도움말 페이지 추가
- /equipment/guide 라우트 및 컨트롤러 메서드 추가
- guide.blade.php 신규 생성 (히어로+TOC+5섹션+FAQ)
- academy-glossary에 equipment 도메인 용어 20개 추가
- 품질인정심사(ISO 9001) 대응 가이드, 보전 기초지식 포함
2026-02-25 22:15:15 +09:00
02e8b36a7a fix: [sync] config:cache 환경에서 동기화 API 401 오류 수정
menu_sync_api_key를 config/app.php에 등록하여 config:cache 후에도
env() 값이 정상 반환되도록 수정. 컨트롤러에서 env() 직접 호출 제거.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 17:58:39 +09:00
김보곤
36fdb75641 fix: [academy] 경정청구 페이지 이미지 hover 확대 효과 복원 2026-02-25 17:07:25 +09:00
김보곤
dc56468f6b feat: [academy] 경정청구 페이지 UI/UX 개선
- CSS 애니메이션 시스템 추가 (fadeUp, popIn, float, drawLine 등 @keyframes)
- 히어로 배너 SVG 일러스트 업그레이드 (세금문서→SAM→환급 플로우)
- 섹션별 SVG 인포그래픽 5종 추가 (플로우차트, Before/After, 타임라인, 효익 아이콘, SAM 아키텍처)
- IntersectionObserver 기반 스크롤 애니메이션 (AOS)
- KPI 카운트업 애니메이션 (requestAnimationFrame easeOut)
- TOC 활성 섹션 하이라이트
- 프로세스 토글 CSS 트랜지션 적용
- 미사용 데드코드 제거 (lightbox, hover-preview DOM/CSS/JS)
2026-02-25 17:07:25 +09:00
김보곤
62cd1c0938 feat: [academy] 경정청구 메뉴 추가
- 아카데미 하위에 경정청구 페이지 신규 생성
- sales 경정청구 자료를 MNG 아카데미 패턴으로 변환
- SAM 제안 형태: 청년 판정, 권역 판정, 데이터 통합 자동화
- Chart.js 차트 4종 포함 (소요시간, 비용절감, 오류유형, 이용자추이)
- 학습 가이드 (용어 해설 + 퀴즈 5문항)
2026-02-25 17:07:25 +09:00
2 changed files with 132 additions and 211 deletions

View File

@@ -7,18 +7,20 @@
body { font-family: 'Noto Sans KR', 'Malgun Gothic', 'Apple SD Gothic Neo', sans-serif; margin: 0; padding: 20px; background: #fff; }
.container { max-width: 720px; margin: 0 auto; background: #fff; padding: 40px 36px; }
h1 { text-align: center; font-size: 22px; font-weight: 800; letter-spacing: 2px; margin: 0 0 28px; border-bottom: 3px solid #333; padding-bottom: 16px; }
.info-table { width: 100%; border-collapse: collapse; margin-bottom: 20px; table-layout: fixed; }
.info-table td { padding: 6px 8px; font-size: 12px; border: 1px solid #999; overflow: hidden; }
.info-table .label { font-weight: bold; background: #f0f0f0; text-align: center; }
.info-table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
.info-table td { padding: 6px 10px; font-size: 13px; border: 1px solid #999; }
.info-table .label { font-weight: bold; background: #f0f0f0; width: 70px; white-space: nowrap; }
.info-table .value { min-width: 100px; }
.payslip-table { width: 100%; border-collapse: collapse; margin-bottom: 0; }
.payslip-table th, .payslip-table td { border: 1px solid #999; padding: 7px 12px; font-size: 13px; }
.payslip-table th { background: #e8e8e8; font-weight: 700; text-align: center; letter-spacing: 4px; }
.payslip-table .item-name { text-align: center; }
.payslip-table .item-amount { text-align: right; }
.payslip-table .item-amount { text-align: right; font-variant-numeric: tabular-nums; }
.payslip-table .total-row td { font-weight: 700; background: #f8f8f8; }
.payslip-table .net-row td { font-weight: 800; font-size: 14px; background: #f0f7ff; }
.footer-table { width: 100%; margin-top: 20px; padding-top: 12px; border: none; }
.footer-table td { font-size: 12px; color: #666; border: none; padding: 0; }
.footer { margin-top: 20px; padding-top: 12px; font-size: 12px; color: #666; overflow: hidden; }
.footer .left { float: left; }
.footer .right { float: right; }
</style>
</head>
<body>
@@ -27,29 +29,21 @@
{{-- 사원 정보 --}}
<table class="info-table">
<colgroup>
<col style="width: 13%;">
<col style="width: 20%;">
<col style="width: 13%;">
<col style="width: 20%;">
<col style="width: 13%;">
<col style="width: 21%;">
</colgroup>
<tr>
<td class="label">사원코드</td>
<td>{{ $payslipData['employee_code'] ?? '-' }}</td>
<td class="value">{{ $payslipData['employee_code'] ?? '-' }}</td>
<td class="label">사원명</td>
<td>{{ $payslipData['employee_name'] ?? '-' }}</td>
<td class="value">{{ $payslipData['employee_name'] ?? '-' }}</td>
<td class="label">입사일</td>
<td>{{ $payslipData['hire_date'] ?? '-' }}</td>
<td class="value">{{ $payslipData['hire_date'] ?? '-' }}</td>
</tr>
<tr>
<td class="label">부서</td>
<td>{{ $payslipData['department'] ?? '-' }}</td>
<td class="label">직급</td>
<td>{{ $payslipData['position'] ?? '-' }}</td>
<td class="label">호봉</td>
<td>{{ $payslipData['grade'] ?? '-' }}</td>
<td class="label"> </td>
<td class="value">{{ $payslipData['department'] ?? '-' }}</td>
<td class="label"> </td>
<td class="value">{{ $payslipData['position'] ?? '-' }}</td>
<td class="label"> </td>
<td class="value">{{ $payslipData['grade'] ?? '-' }}</td>
</tr>
</table>
@@ -106,12 +100,10 @@
</tbody>
</table>
<table class="footer-table">
<tr>
<td style="text-align: left;">귀하의 노고에 감사드립니다.</td>
<td style="text-align: right;">()코드브릿지엑스(CodebridgeX)</td>
</tr>
</table>
<div class="footer">
<span class="left">귀하의 노고에 감사드립니다.</span>
<span class="right">&#13134;코드브릿지엑스(CodebridgeX)</span>
</div>
</div>
</body>
</html>

View File

@@ -401,7 +401,7 @@
openHeight: 3000,
quantity: 1,
// Guide Rail
gr: { width:70, depth:120, thickness:1.55, lip:10, flange:26, sideWall:80, backWall:67, trimThick:1.2, sealThick:0.8, sealDepth:40, slatThick:0.8, anchorSpacing:500, viewMode:'cross', showDim:true, showSeal:true },
gr: { width:70, depth:120, thickness:1.55, lip:10, flange:30, sideWall:80, backWall:67, trimThick:1.2, sealThick:0.8, sealDepth:40, slatThick:0.8, anchorSpacing:500, viewMode:'cross', showDim:true, showSeal:true },
// Shutter Box
sb: { width:2280, height:380, depth:500, thickness:1.6, shaftDia:80, bracketW:10, motorSide:'right', viewMode:'front', showShaft:true, showSlatRoll:true, showMotor:true, showBrake:true, showSpring:true },
// 3D
@@ -420,7 +420,7 @@
sb:{height:550, depth:650, frontH:410, bottomOpen:75, shaftDia:120},
bk:{nmH:320, nmD:320, mtH:320, mtD:530, thick:18, sprocketR:215, motorSpR:40, motorOffset:160} },
screen: { marginW:140, marginH:350, weightFactor:2,
gr:{width:70, depth:120, thickness:1.55, lip:10, flange:26, sideWall:80, backWall:67, trimThick:1.2},
gr:{width:70, depth:120, thickness:1.55, lip:10, flange:30, sideWall:80, backWall:67, trimThick:1.2},
slatThick:0.8,
sb:{height:380, depth:500, frontH:240, bottomOpen:75, shaftDia:80},
bk:{nmH:180, nmD:180, mtH:180, mtD:380, thick:18, sprocketR:70, motorSpR:30, motorOffset:0} },
@@ -721,153 +721,79 @@ function renderGuideRail() {
function renderGrCross() {
const g = S.gr;
// ====== 스크린형: 실제 조립 구조 평면도 (5개 부재) ======
// 좌→우: 방화벽 → ③벽연형C → ④벽연형D → ②본체(C채널) → ⑤마감재(SUS커버) → 개구부
// 세로 = 채널 폭 70mm
// ====== 스크린형: 참조 도면 기준 평면도 ======
// 가로 = 깊이 방향 (120mm, 좌:벽/③④ → 우:개구부/LIP)
// 세로 = 개구부/(70mm)
if (S.productType === 'screen') {
const sc = 4; // px per mm
const t2 = g.thickness * sc; // 본체 EGI 1.55T
const t5 = (g.trimThick || 1.2) * sc; // 마감재 SUS 1.2T
const sc = 4;
const fw = g.width * sc; // 70mm → 280px (개구부/폭, 세로)
const sw = (g.sideWall || 80) * sc; // 80mm 사이드월
const t = g.thickness * sc; // 1.55mm
const bodyD = sw + t; // ~82mm 본체 깊이 (가로)
const fl = (g.flange || 30) * sc; // 30mm 플랜지 (슬롯=width-2*fl=10mm)
const lp = g.lip * sc; // 10mm 립
const sealT = g.sealThick * sc;
const sealD = g.sealDepth * sc;
const slatT = Math.max(g.slatThick * sc, 2);
// ── ② 본체 치수 (절곡: 10-26-80-67-80-26-10) ──
const bLip = g.lip * sc; // 10mm 립
const bFl = g.flange * sc; // 26mm 플랜지
const bSw = g.sideWall * sc; // 80mm 사이드월
const bBw = g.backWall * sc; // 67mm 백월
const bOuterW = bBw + 2 * t2; // 70mm 외폭 (세로)
const bSlot = bBw - 2 * bFl; // 15mm 슬롯 개구
const bkExt = 30 * sc; // ③ 브라켓 확장 (좌측)
const tmExt = 9 * sc; // ⑤ 트림 확장 (우측)
// ── ③ 벽연형-C 치수 (절곡: 30-45-30) ──
const c3Lip = 30 * sc; // 립 30mm
const c3Body = 45 * sc; // 45mm (백월에 밀착)
const pad = 80;
const wallW = 35;
const bx = pad + wallW + 10 + bkExt; // 좌측 (백월 외면)
const by = pad; // 본체 상단
const svgW = bx + bodyD + tmExt + pad + 50;
const svgH = fw + pad * 2 + 60;
// ── ④ 벽연형-D 치수 (절곡: 11-23-40-23-11) ──
const c4a = 11 * sc, c4b = 23 * sc, c4c = 40 * sc;
// ── ⑤ 마감재 치수 (절곡: 10-11-110-30-15-15-15) ──
const m5a = 10 * sc; // 벽측 립
const m5b = 11 * sc; // 벽측 절곡면
const m5c = 110 * sc; // 사이드월 커버 (긴 면)
const m5d = 30 * sc; // A각 절곡 후 면
const m5e = 15 * sc; // 끝단 1
const m5f = 15 * sc; // 끝단 2
const m5g = 15 * sc; // 끝단 3
// ── 레이아웃 (좌→우 배치) ──
const pad = 80, wallW = 35;
// ③ 벽연형-C의 가장 왼쪽: 벽면에서 립 30mm 돌출
const bkTotalD = c3Lip; // 벽→본체 백월 사이 깊이
const bx = pad + wallW + 10 + bkTotalD; // 본체 백월 외면 X
// 본체 사이드월 끝 (립 시작점)
const swEndX = bx + t2 + bSw; // 백월두께 + 사이드월
// 립 끝
const lipEndX = swEndX + bLip;
const by = pad; // 본체 상단 Y
const svgW = lipEndX + pad + 120;
const svgH = bOuterW + pad * 2 + 70;
// 색상 정의
const cBody = '#64748b'; // ② 본체 (EGI)
const cBk3 = '#78716c'; // ③ 벽연형-C
const cBk4 = '#92400e'; // ④ 벽연형-D
const cTrim = '#a1a1aa'; // ⑤ 마감재 (SUS)
const cClip = '#8b5cf6'; // ① 클립
const ms = '#94a3b8'; // 스트로크
const mw = 0.8;
// ── 채널 내부 배경 ──
const interiorSvg = `<rect x="${bx+t2}" y="${by+t2}" width="${bSw-t2}" height="${bOuterW-2*t2}" fill="#0f172a"/>`;
// ── ② 본체 C채널 (절곡: lip-flange-sideWall-backWall-sideWall-flange-lip) ──
// 본체 — 개별 부재로 분리 (슬롯 개구부가 열린 상태로 표현)
// 구조: 백월 + 사이드월×2 + 플랜지(안쪽절곡)×2 + 립(바깥절곡)×2
// 사이드월은 bodyD-lp 까지, 플랜지가 안쪽으로 꺾이고, 립이 개구부 방향으로 꺾임
const mc = '#64748b', ms = '#94a3b8', mw = 1;
const swLen = bodyD - lp; // 사이드월 길이 (플랜지 절곡점까지)
const bodySvg = [
// 백월 (수직, 좌측)
`<rect x="${bx}" y="${by}" width="${t2}" height="${bOuterW}" fill="${cBody}" stroke="${ms}" stroke-width="${mw}"/>`,
// 상단 사이드월 (백월→개구부 방향, 80mm)
`<rect x="${bx}" y="${by}" width="${t2+bSw}" height="${t2}" fill="${cBody}" stroke="${ms}" stroke-width="${mw}"/>`,
// 채널 내부 배경 (어두운 색)
`<rect x="${bx+t}" y="${by+t}" width="${swLen-2*t}" height="${fw-2*t}" fill="#0f172a"/>`,
// 백월 (좌측 수직)
`<rect x="${bx}" y="${by}" width="${t}" height="${fw}" fill="${mc}" stroke="${ms}" stroke-width="${mw}"/>`,
// 상단 사이드월 (백월→플랜지 절곡점)
`<rect x="${bx}" y="${by}" width="${swLen}" height="${t}" fill="${mc}" stroke="${ms}" stroke-width="${mw}"/>`,
// 하단 사이드월
`<rect x="${bx}" y="${by+bOuterW-t2}" width="${t2+bSw}" height="${t2}" fill="${cBody}" stroke="${ms}" stroke-width="${mw}"/>`,
// 상단 플랜지 (사이드월 끝에서 안쪽/중앙으로 26mm 절곡)
`<rect x="${swEndX-t2}" y="${by+t2}" width="${t2}" height="${bFl-t2}" fill="${cBody}" stroke="${ms}" stroke-width="${mw}"/>`,
// 하단 플랜지
`<rect x="${swEndX-t2}" y="${by+bOuterW-bFl}" width="${t2}" height="${bFl-t2}" fill="${cBody}" stroke="${ms}" stroke-width="${mw}"/>`,
// 상단 립 (플랜지 끝에서 개구부 방향으로 10mm)
`<rect x="${swEndX}" y="${by+bFl-t2}" width="${bLip}" height="${t2}" fill="${cBody}" stroke="${ms}" stroke-width="${mw}"/>`,
// 하단 립
`<rect x="${swEndX}" y="${by+bOuterW-bFl}" width="${bLip}" height="${t2}" fill="${cBody}" stroke="${ms}" stroke-width="${mw}"/>`,
`<rect x="${bx}" y="${by+fw-t}" width="${swLen}" height="${t}" fill="${mc}" stroke="${ms}" stroke-width="${mw}"/>`,
// 상단 플랜지 (사이드월 끝에서 안쪽/중앙으로 절곡)
`<rect x="${bx+swLen-t}" y="${by+t}" width="${t}" height="${fl-t}" fill="${mc}" stroke="${ms}" stroke-width="${mw}"/>`,
// 하단 플랜지 (사이드월 끝에서 안쪽/중앙으로 절곡)
`<rect x="${bx+swLen-t}" y="${by+fw-fl}" width="${t}" height="${fl-t}" fill="${mc}" stroke="${ms}" stroke-width="${mw}"/>`,
// 상단 립 (플랜지 끝에서 개구부 방향/바깥으로 절곡)
`<rect x="${bx+swLen}" y="${by+fl-t}" width="${lp}" height="${t}" fill="${mc}" stroke="${ms}" stroke-width="${mw}"/>`,
// 하단 립 (플랜지 끝에서 개구부 방향/바깥으로 절곡)
`<rect x="${bx+swLen}" y="${by+fw-fl}" width="${lp}" height="${t}" fill="${mc}" stroke="${ms}" stroke-width="${mw}"/>`,
].join('\n');
// ── ③ 벽연형-C (절곡: 30-45-30, 백월 뒤 C브라켓) ──
// C 개구부가 ② 본체쪽(우측)을 향함: 몸체(벽쪽) → 립(본체쪽)
const c3CenterY = by + bOuterW / 2;
const c3Y = c3CenterY - c3Body / 2;
const c3BodyX = bx - c3Lip; // 몸체 X (벽쪽, 좌측 끝)
const c3LipEnd = bx; // 립 끝 = ② 백월 외면
const bk3Svg = [
// 몸체 (세로 45mm, 벽쪽)
`<rect x="${c3BodyX}" y="${c3Y}" width="${t2}" height="${c3Body}" fill="${cBk3}" stroke="${ms}" stroke-width="${mw}"/>`,
// 상단 립 (몸체→본체 방향 30mm)
`<rect x="${c3BodyX}" y="${c3Y}" width="${c3Lip}" height="${t2}" fill="${cBk3}" stroke="${ms}" stroke-width="${mw}"/>`,
// 하단 립 (몸체→본체 방향 30mm)
`<rect x="${c3BodyX}" y="${c3Y+c3Body-t2}" width="${c3Lip}" height="${t2}" fill="${cBk3}" stroke="${ms}" stroke-width="${mw}"/>`,
].join('\n');
// ③ 브라켓 (본체 좌측)
const wcBody = 45 * sc;
const bracketSvg = `<rect x="${bx-bkExt}" y="${by+fw/2-wcBody/2}" width="${bkExt}" height="${wcBody}" fill="#4b5563" stroke="#64748b" stroke-width="1" opacity="0.6" rx="1"/>
${g.showDim ? `<text x="${bx-bkExt/2}" y="${by+fw/2+3}" fill="#94a3b8" font-size="8" font-weight="700" text-anchor="middle" font-family="Pretendard">③④</text>` : ''}`;
// ── ④ 벽연형-D (절곡: 11-23-40-23-11, ③ 내부에 중첩) ──
// ③ 내부에 배치, C 개구부가 ② 본체쪽(우측)을 향함
// 몸체(40) 벽쪽, 사이드(23) 본체 방향, 립(11) 안쪽 절곡
const c4CenterY = c3CenterY;
const c4Y = c4CenterY - c4c / 2;
const c4BodyX = c3BodyX + t2 + 2; // ③ 몸체 바로 안쪽
const c4SideEnd = c4BodyX + t2 + c4b; // 사이드 끝 (본체쪽)
const bk4Svg = [
// 몸체 (세로 40mm, ③ 안쪽 벽쪽)
`<rect x="${c4BodyX}" y="${c4Y}" width="${t2}" height="${c4c}" fill="${cBk4}" stroke="${ms}" stroke-width="${mw}" opacity="0.8"/>`,
// 상단 사이드 (23mm, 본체 방향)
`<rect x="${c4BodyX+t2}" y="${c4Y}" width="${c4b}" height="${t2}" fill="${cBk4}" stroke="${ms}" stroke-width="${mw}" opacity="0.8"/>`,
// 하단 사이드
`<rect x="${c4BodyX+t2}" y="${c4Y+c4c-t2}" width="${c4b}" height="${t2}" fill="${cBk4}" stroke="${ms}" stroke-width="${mw}" opacity="0.8"/>`,
// 상단 립 (11mm, 사이드 끝에서 안쪽/중앙으로 절곡)
`<rect x="${c4SideEnd-t2}" y="${c4Y+t2}" width="${t2}" height="${c4a}" fill="${cBk4}" stroke="${ms}" stroke-width="${mw}" opacity="0.8"/>`,
// 하단 립 (11mm, 사이드 끝에서 안쪽/중앙으로 절곡)
`<rect x="${c4SideEnd-t2}" y="${c4Y+c4c-t2-c4a}" width="${t2}" height="${c4a}" fill="${cBk4}" stroke="${ms}" stroke-width="${mw}" opacity="0.8"/>`,
].join('\n');
// ⑤ SUS 트림 (상하 외면)
const trimT = Math.max((g.trimThick || 1.2) * sc, 2);
const trimSvg = `
<rect x="${bx}" y="${by-trimT}" width="${bodyD+tmExt}" height="${trimT}" fill="#9ca3af" opacity="0.4" rx="1"/>
<rect x="${bx}" y="${by+fw}" width="${bodyD+tmExt}" height="${trimT}" fill="#9ca3af" opacity="0.4" rx="1"/>
${g.showDim ? `<text x="${bx+bodyD+tmExt+3}" y="${by-1}" fill="#9ca3af" font-size="7" font-weight="700" text-anchor="start" font-family="Pretendard"></text>` : ''}`;
// ── ⑤ 마감재 SUS 1.2T × 2 (절곡: 10-11-110-30-15-15-15) ──
// 평면도(위에서 봄): 접힌 후 외곽 프레임 형태로 보임
// 좌측: ③ 좌단과 정렬, 우측: 본체 립 끝 바깥으로 감싸는 형태
const trimL = bx - c3Lip; // 좌측 끝 (③ 좌단 정렬)
const trimR = lipEndX + t5; // 우측 끝 (립 바깥)
const trimX2 = trimR; // 치수선용
// 방화벽 (좌측 = 벽쪽)
const wallX = pad;
// 상단/하단 마감재: 좌측 리턴(10mm 안쪽절곡) + 수평(110mm) + 우측 리턴(30mm A각)
const trim5Svg = `
<polyline points="${trimL},${by-t5+m5a} ${trimL},${by-t5} ${trimR},${by-t5} ${trimR},${by+m5d}"
fill="none" stroke="${cTrim}" stroke-width="${t5}" stroke-linejoin="miter" opacity="0.7"/>
<polyline points="${trimL},${by+bOuterW+t5-m5a} ${trimL},${by+bOuterW+t5} ${trimR},${by+bOuterW+t5} ${trimR},${by+bOuterW-m5d}"
fill="none" stroke="${cTrim}" stroke-width="${t5}" stroke-linejoin="miter" opacity="0.7"/>`;
// ── ① 클립 (채널 내부, 개구부 근처 L형) ──
const clipArmLen = 10 * sc;
const clipLegLen = 15 * sc;
const clipT = Math.max(t2, 2);
const clipX1 = swEndX - t2 - 2; // 플랜지 내면 근처
const clipY1 = by + t2 + 2;
const clipY2 = by + bOuterW - t2 - 2;
const clipSvg = `
<path d="M${clipX1},${clipY1} L${clipX1},${clipY1+clipLegLen} L${clipX1-clipArmLen},${clipY1+clipLegLen} L${clipX1-clipArmLen},${clipY1+clipLegLen-clipT} L${clipX1-clipT},${clipY1+clipLegLen-clipT} L${clipX1-clipT},${clipY1} Z" fill="${cClip}" opacity="0.4"/>
<path d="M${clipX1},${clipY2} L${clipX1},${clipY2-clipLegLen} L${clipX1-clipArmLen},${clipY2-clipLegLen} L${clipX1-clipArmLen},${clipY2-clipLegLen+clipT} L${clipX1-clipT},${clipY2-clipLegLen+clipT} L${clipX1-clipT},${clipY2} Z" fill="${cClip}" opacity="0.4"/>`;
// ── 연기차단재 ──
// 연기차단재 — 슬롯에서 슬랫에 접촉하여 차연
// 참조 스케치: 립 사이 슬롯에서 슬랫 양면을 감싸는 형태
let sealSvg = '';
if (g.showSeal) {
const slatCenterY = by + bOuterW / 2;
const sealLen = bLip * 0.8;
const sealPosX = swEndX + 2;
const sealH = Math.max(sealT * 1.5, 6);
const slatCenterY = by + fw / 2; // 슬랫 중심 Y
const sealLen = lp * 0.8; // 차단재 길이 (립 깊이 방향)
const sealPosX = bx + swLen + 2; // 립 바깥쪽 (개구부 방향)
// 슬랫 위아래로 차단재 (슬랫을 감싸서 차연)
const sealH = Math.max(sealT * 1.5, 6); // 차단재 두께
sealSvg += `<rect x="${sealPosX}" y="${slatCenterY - slatT/2 - sealH}" width="${sealLen}" height="${sealH}" fill="#f97316" opacity="0.7" rx="1"/>`;
sealSvg += `<rect x="${sealPosX}" y="${slatCenterY + slatT/2}" width="${sealLen}" height="${sealH}" fill="#f97316" opacity="0.7" rx="1"/>`;
if (g.showDim) {
@@ -875,46 +801,53 @@ function renderGrCross() {
}
}
// ── 슬랫 ──
const slatY = by + bOuterW / 2 - slatT / 2;
const slatX1 = bx + t2 + 2;
const slatX2 = lipEndX - 2;
// 슬랫 — 슬롯 통과 수평선 (채널 내부 + 립 구간 관통)
const slatY = by + fw / 2 - slatT / 2;
const slatX1 = bx + t + 2;
const slatX2 = bx + swLen + lp - 2; // 슬랫은 립 끝까지 관통
// ── 방화벽 ──
const wallX = pad;
// ① 클립 (채널 내부, 사이드월 내면 — L형 브라켓)
// 참조 도면 기준: 개구부 근처 사이드월에 부착된 작은 브라켓
const clipArmLen = 10 * sc; // 10mm 돌출
const clipLegLen = 15 * sc; // 15mm 사이드월 따라
const clipT = Math.max(t, 2);
const clipX1 = bx + swLen - t - 2; // 플랜지 내면 근처
// 상단 클립 (사이드월 내면에서 아래로 L형)
const clipY1 = by + t + 2;
// 하단 클립 (사이드월 내면에서 위로 L형)
const clipY2 = by + fw - t - 2;
const clipSvg = `
<path d="M${clipX1},${clipY1} L${clipX1},${clipY1+clipLegLen} L${clipX1-clipArmLen},${clipY1+clipLegLen} L${clipX1-clipArmLen},${clipY1+clipLegLen-clipT} L${clipX1-clipT},${clipY1+clipLegLen-clipT} L${clipX1-clipT},${clipY1} Z" fill="#8b5cf6" opacity="0.4"/>
<path d="M${clipX1},${clipY2} L${clipX1},${clipY2-clipLegLen} L${clipX1-clipArmLen},${clipY2-clipLegLen} L${clipX1-clipArmLen},${clipY2-clipLegLen+clipT} L${clipX1-clipT},${clipY2-clipLegLen+clipT} L${clipX1-clipT},${clipY2} Z" fill="#8b5cf6" opacity="0.4"/>
${g.showDim ? `<text x="${clipX1-clipArmLen-2}" y="${clipY1+clipLegLen/2+3}" fill="#8b5cf6" font-size="7" font-weight="700" text-anchor="end" font-family="Pretendard"></text>` : ''}`;
// ── 치수선 ──
// 치수선
let dimLines = '';
if (g.showDim) {
const totalLeft = bx - c3Lip;
const totalRight = trimX2;
const totalLeft = bx - bkExt;
const totalRight = bx + bodyD + tmExt;
// 깊이 120mm (하단)
dimLines += `<line x1="${totalLeft}" y1="${by+bOuterW+35}" x2="${totalRight}" y2="${by+bOuterW+35}" stroke="#3b82f6" stroke-width="1"/>`;
dimLines += `<line x1="${totalLeft}" y1="${by+bOuterW+30}" x2="${totalLeft}" y2="${by+bOuterW+40}" stroke="#3b82f6" stroke-width="0.5"/>`;
dimLines += `<line x1="${totalRight}" y1="${by+bOuterW+30}" x2="${totalRight}" y2="${by+bOuterW+40}" stroke="#3b82f6" stroke-width="0.5"/>`;
dimLines += `<text x="${(totalLeft+totalRight)/2}" y="${by+bOuterW+52}" fill="#3b82f6" font-size="12" font-weight="900" text-anchor="middle" font-family="Pretendard">${g.depth} mm</text>`;
dimLines += `<line x1="${totalLeft}" y1="${by+fw+25}" x2="${totalRight}" y2="${by+fw+25}" stroke="#3b82f6" stroke-width="1"/>`;
dimLines += `<line x1="${totalLeft}" y1="${by+fw+20}" x2="${totalLeft}" y2="${by+fw+30}" stroke="#3b82f6" stroke-width="0.5"/>`;
dimLines += `<line x1="${totalRight}" y1="${by+fw+20}" x2="${totalRight}" y2="${by+fw+30}" stroke="#3b82f6" stroke-width="0.5"/>`;
dimLines += `<text x="${(totalLeft+totalRight)/2}" y="${by+fw+42}" fill="#3b82f6" font-size="12" font-weight="900" text-anchor="middle" font-family="Pretendard">${g.depth} mm</text>`;
// 폭 70mm (우측)
dimLines += `<line x1="${totalRight+12}" y1="${by}" x2="${totalRight+12}" y2="${by+bOuterW}" stroke="#3b82f6" stroke-width="1"/>`;
dimLines += `<line x1="${totalRight+12}" y1="${by}" x2="${totalRight+12}" y2="${by+fw}" stroke="#3b82f6" stroke-width="1"/>`;
dimLines += `<line x1="${totalRight+7}" y1="${by}" x2="${totalRight+17}" y2="${by}" stroke="#3b82f6" stroke-width="0.5"/>`;
dimLines += `<line x1="${totalRight+7}" y1="${by+bOuterW}" x2="${totalRight+17}" y2="${by+bOuterW}" stroke="#3b82f6" stroke-width="0.5"/>`;
dimLines += `<text x="${totalRight+22}" y="${by+bOuterW/2+4}" fill="#3b82f6" font-size="12" font-weight="900" text-anchor="start" font-family="Pretendard">${g.width} mm</text>`;
// 플랜지 26mm
dimLines += `<line x1="${lipEndX+3}" y1="${by}" x2="${lipEndX+3}" y2="${by+bFl}" stroke="#94a3b8" stroke-width="0.8"/>`;
dimLines += `<text x="${lipEndX+8}" y="${by+bFl/2+3}" fill="#94a3b8" font-size="9" font-weight="700" text-anchor="start" font-family="Pretendard">FL ${g.flange}</text>`;
// 슬롯 개구
dimLines += `<line x1="${lipEndX+1}" y1="${by+bFl+3}" x2="${lipEndX+1}" y2="${by+bOuterW-bFl-3}" stroke="#22c55e" stroke-width="0.8"/>`;
dimLines += `<text x="${lipEndX+6}" y="${by+bOuterW/2+3}" fill="#22c55e" font-size="8" font-weight="700" text-anchor="start" font-family="Pretendard">슬롯 ${bSlot/sc}</text>`;
// 립 깊이
dimLines += `<line x1="${swEndX}" y1="${by+bFl+3}" x2="${lipEndX}" y2="${by+bFl+3}" stroke="#94a3b8" stroke-width="0.8"/>`;
dimLines += `<text x="${(swEndX+lipEndX)/2}" y="${by+bFl+14}" fill="#94a3b8" font-size="9" font-weight="700" text-anchor="middle" font-family="Pretendard">립 ${g.lip}</text>`;
dimLines += `<line x1="${totalRight+7}" y1="${by+fw}" x2="${totalRight+17}" y2="${by+fw}" stroke="#3b82f6" stroke-width="0.5"/>`;
dimLines += `<text x="${totalRight+22}" y="${by+fw/2+4}" fill="#3b82f6" font-size="12" font-weight="900" text-anchor="start" font-family="Pretendard">${g.width} mm</text>`;
// 플랜지 (우측 상단 — 사이드월 끝에서 안쪽 절곡)
dimLines += `<line x1="${bx+swLen+lp+3}" y1="${by}" x2="${bx+swLen+lp+3}" y2="${by+fl}" stroke="#94a3b8" stroke-width="0.8"/>`;
dimLines += `<text x="${bx+swLen+lp+8}" y="${by+fl/2+3}" fill="#94a3b8" font-size="9" font-weight="700" text-anchor="start" font-family="Pretendard">FL ${g.flange}</text>`;
// 슬롯 개구부 (플랜지 사이, 립 끝에서)
const slotGap = g.width - 2 * g.flange;
dimLines += `<line x1="${bx+swLen+lp}" y1="${by+fl+3}" x2="${bx+swLen+lp}" y2="${by+fw-fl-3}" stroke="#22c55e" stroke-width="0.8"/>`;
dimLines += `<text x="${bx+swLen+lp+6}" y="${by+fw/2+3}" fill="#22c55e" font-size="8" font-weight="700" text-anchor="start" font-family="Pretendard">슬롯 ${slotGap}</text>`;
// 립 깊이 (플랜지 끝에서 개구부 방향으로)
dimLines += `<line x1="${bx+swLen}" y1="${by+fl+3}" x2="${bx+swLen+lp}" y2="${by+fl+3}" stroke="#94a3b8" stroke-width="0.8"/>`;
dimLines += `<text x="${bx+swLen+lp/2}" y="${by+fl+14}" fill="#94a3b8" font-size="9" font-weight="700" text-anchor="middle" font-family="Pretendard">립깊이 ${g.lip}</text>`;
// 두께
dimLines += `<text x="${bx+t2}" y="${by+bOuterW+65}" fill="#94a3b8" font-size="9" font-weight="700" font-family="Pretendard">t=${g.thickness} ⑤t=${g.trimThick||1.2}</text>`;
// 부재 번호 라벨
dimLines += `<text x="${bx+t2+bSw/2}" y="${by+bOuterW/2+4}" fill="#475569" font-size="11" font-weight="900" text-anchor="middle" font-family="Pretendard">②</text>`;
dimLines += `<text x="${c3BodyX+c3Lip/2}" y="${c3CenterY+4}" fill="${cBk3}" font-size="9" font-weight="900" text-anchor="middle" font-family="Pretendard">③</text>`;
dimLines += `<text x="${c4BodyX+c4b/2}" y="${c4CenterY+4}" fill="${cBk4}" font-size="9" font-weight="900" text-anchor="middle" font-family="Pretendard">④</text>`;
dimLines += `<text x="${(trimL+trimR)/2}" y="${by-t5-8}" fill="${cTrim}" font-size="9" font-weight="900" text-anchor="middle" font-family="Pretendard">⑤</text>`;
dimLines += `<text x="${clipX1-clipArmLen-2}" y="${clipY1+clipLegLen/2+3}" fill="${cClip}" font-size="8" font-weight="900" text-anchor="end" font-family="Pretendard">①</text>`;
dimLines += `<text x="${bx+t}" y="${by+fw+55}" fill="#94a3b8" font-size="9" font-weight="700" font-family="Pretendard">t=${g.thickness}</text>`;
}
const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${svgW} ${svgH}" style="max-width:100%;max-height:100%;">
@@ -924,30 +857,26 @@ function renderGrCross() {
</pattern>
</defs>
<text x="${svgW/2}" y="25" fill="#94a3b8" font-size="14" font-weight="900" text-anchor="middle" font-family="Pretendard">가이드레일 평면도 (Plan View) — 스크린형</text>
<!-- 방화벽 -->
<rect x="${wallX}" y="${by-20}" width="${wallW}" height="${bOuterW+40}" fill="url(#wallHatch)" stroke="#8b7355" stroke-width="1" rx="2"/>
<text x="${wallX+wallW/2}" y="${by+bOuterW+35}" fill="#a1887f" font-size="9" font-weight="700" text-anchor="middle" font-family="Pretendard">방화벽</text>
<!-- 채널 내부 -->
${interiorSvg}
<!-- ⑤ 마감재 SUS 커버 -->
${trim5Svg}
<!-- ③ 벽연형-C -->
${bk3Svg}
<!-- ④ 벽연형-D -->
${bk4Svg}
<!-- ② 본체 C채널 -->
<!-- 방화벽 (좌측 = 벽쪽) -->
<rect x="${wallX}" y="${by-10}" width="${wallW}" height="${fw+20}" fill="url(#wallHatch)" stroke="#8b7355" stroke-width="1" rx="2"/>
<text x="${wallX+wallW/2}" y="${by+fw+25}" fill="#a1887f" font-size="9" font-weight="700" text-anchor="middle" font-family="Pretendard">방화벽</text>
<!-- ⑤ SUS 트림 -->
${trimSvg}
<!-- ③④ 브라켓 -->
${bracketSvg}
<!-- 본체 (개별 부재 — 슬롯 열림) -->
${bodySvg}
<!-- ① 클립 -->
${clipSvg}
<!-- 연기차단재 -->
${sealSvg}
<!-- 슬랫 -->
<!-- 슬랫 (수평, 채널 중심) -->
<rect x="${slatX1}" y="${slatY}" width="${slatX2-slatX1}" height="${slatT}" fill="#c084fc" opacity="0.8" rx="1"/>
${g.showDim ? `<text x="${(slatX1+slatX2)/2}" y="${slatY-4}" fill="#c084fc" font-size="9" font-weight="700" text-anchor="middle" font-family="Pretendard">슬랫 t=${g.slatThick}</text>` : ''}
<!-- 개구부 방향 -->
<text x="${lipEndX+15}" y="${by+bOuterW/2+4}" fill="#22c55e" font-size="10" font-weight="700" text-anchor="start" font-family="Pretendard">→ 개구부</text>
<text x="${bx+swLen+lp+tmExt+5}" y="${by+fw/2+4}" fill="#22c55e" font-size="10" font-weight="700" text-anchor="start" font-family="Pretendard">→ 개구부</text>
${dimLines}
<text x="${(bx+lipEndX)/2}" y="${by+bOuterW+65}" fill="#94a3b8" font-size="11" font-weight="900" text-anchor="middle" font-family="Pretendard">GUIDE RAIL — 스크린형 (5부재 조립)</text>
<text x="${(bx+bx+bodyD)/2}" y="${by+fw+55}" fill="#94a3b8" font-size="11" font-weight="900" text-anchor="middle" font-family="Pretendard">GUIDE RAIL BODY — 스크린형</text>
</svg>`;
displaySvg(svg);
@@ -1724,7 +1653,7 @@ function createRailGroup() {
if (isScreen) {
// ====== 스크린형 가이드레일 (실제 조립 구조) ======
// 단면 좌표계: X=폭(0→70), Y=깊이(0=개구부/실내측, +=벽쪽)
const fl = g.flange; // 26mm 플랜지 (슬롯=backWall-2*fl=15mm)
const fl = g.flange; // 30mm (플랜지, 슬롯=width-2*fl=10mm)
const lp = g.lip; // 10mm (립)
const sw = g.sideWall; // 80mm (사이드월)
const bw = g.backWall; // 67mm (백월)