Commit Graph

75 Commits

Author SHA1 Message Date
김보곤
a352fa105b fix: [leave] 결재 승인 시 soft delete된 근태 레코드 중복 오류 수정
- SoftDeletes로 삭제된 Attendance 레코드가 있을 때 updateOrCreate가
  기존 레코드를 찾지 못해 INSERT 시도 → unique 제약 위반 발생
- withTrashed() 추가하여 soft delete된 레코드도 조회하고 복원하도록 수정
2026-03-16 15:28:21 +09:00
김보곤
da1acc9d1e fix: [payroll] 급여등록 사원선택에서 영업팀(외주) 제외 2026-03-12 09:56:46 +09:00
ee981d27d5 fix: [hr] 급여명세서 한글 폰트 — storage_path 기반으로 변경하여 배포 간 안정성 확보
- chroot에 storage_path('fonts') 추가 (symlink→shared 경로 허용)
- 폰트를 resources→storage로 복사 후 storage 경로로 등록 (릴리스 불변)
- 배포마다 .ufm 메트릭 재생성 방지

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 13:47:49 +09:00
8afd78c111 fix: [hr] DomPDF setOptions 제거 — chroot 덮어쓰기로 인한 폰트 등록 실패 수정
- setOptions()가 config의 chroot(base_path)를 new Options()로 전체 교체 → vendor 기본값으로 리셋
- resource_path 폰트 경로가 chroot 밖으로 판정되어 registerFont() false 반환
- setOptions 제거 → config/dompdf.php 설정(font_dir, font_cache, chroot) 그대로 사용
- storage 수동 복사도 제거 → DomPDF가 내부적으로 font_dir에 복사 + .ufm 생성

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 13:37:11 +09:00
5a6cd34a63 fix: [hr] DomPDF 인스턴스 불일치 해결 — 급여명세서 한글 폰트 깨짐 수정
- 기존: app()으로 별도 DomPDF 인스턴스에 폰트 등록 → Pdf::loadView()의 인스턴스에는 미적용
- 수정: $pdf->getDomPDF()로 동일 인스턴스에 폰트 등록 후 output() 호출
- Pretendard 폰트 사용, resources/fonts/에서 storage/fonts/로 복사 후 등록

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 13:19:05 +09:00
김보곤
d7428e1785 fix: [payroll] PDF 한글 폰트 NanumGothic → Pretendard 전환
- 운영서버 NanumGothic 메트릭 생성 실패 문제 해결
- Pretendard Regular/Bold TTF를 resources/fonts/에 번들링
- ensureKoreanFont()에서 Pretendard 등록으로 변경
- payslip.blade.php font-family를 Pretendard로 변경
- PDF 크기: 18KB (서브셋팅 적용)
2026-03-11 11:49:20 +09:00
김보곤
c0721d549a fix: [payslip] PDF 생성 시 font_dir 명시적 지정 (config 캐시 무관)
- setOptions()로 font_dir, font_cache, enable_font_subsetting 직접 전달
- ensureKoreanFont()에서도 DomPDF 옵션을 명시적으로 설정
- 캐시 유효성 검증 강화: TTF + .ufm 메트릭 파일 모두 확인
- config 캐시 상태와 무관하게 storage/fonts/ 사용 보장
2026-03-11 11:18:06 +09:00
김보곤
d919ad378b fix: [payslip] ensureKoreanFont 캐시 유효성 검증 추가
- installed-fonts.json에 키만 있고 실제 폰트 파일이 없으면 재등록
- 배포 후 수동 캐시 초기화 불필요
2026-03-11 11:09:55 +09:00
김보곤
e17314ad0f fix: [payslip] 폰트를 프로젝트에 포함하여 서버 의존성 제거
- resources/fonts/에 NanumGothic TTF 포함 (Git으로 배포)
- ensureKoreanFont()가 시스템 경로 대신 resource_path() 사용
- fonts-nanum 패키지 미설치 서버에서도 한글 PDF 정상 생성
2026-03-11 11:00:45 +09:00
김보곤
be1c984de0 fix: [hr] 급여명세서 PDF 한글 폰트 깨짐 수정
- NanumGothic 폰트 자동 등록 로직 추가 (ensureKoreanFont)
- storage/fonts/에 폰트 복사 후 DomPDF에 등록 (최초 1회)
- payslip.blade.php font-family를 NanumGothic으로 변경
- 서버 배포 시 수동 폰트 등록 불필요
2026-03-11 09:49:55 +09:00
김보곤
f90b317e63 fix: [hr] 급여명세서 PDF 구글 폰트 외부 로드 제거
- payslip.blade.php: @import 구글 폰트 URL 삭제, 시스템 기본 폰트 사용
- PayrollService.php: isRemoteEnabled 옵션 제거
- 운영서버 배포 시 폰트 캐시 권한 오류 근본 해결
2026-03-11 09:41:28 +09:00
김보곤
e65e2f3dc8 feat: [payroll] 슈퍼관리자 급여 수정/지급취소 권한 추가
- 지급완료/확정 상태에서도 슈퍼관리자는 급여 수정 가능
- 지급취소(unpay) 기능 추가: paid → draft 상태 되돌리기
- 테이블에 슈퍼관리자 전용 수정/지급취소 버튼 표시
2026-03-11 06:52:03 +09:00
김보곤
550fba5cb2 fix: [payroll] 급여명세서 이메일 발송 시 개인 이메일 우선 참조
- 개인 이메일이 있으면 개인 이메일로 발송
- 개인 이메일이 없으면 업무용 이메일로 폴백
- 목록의 이메일 모달에서도 동일 로직 적용
2026-03-10 10:57:46 +09:00
김보곤
50275b0500 feat: [employee] 사원관리 개인 이메일 필드 추가
- 사원 수정 폼에 개인 이메일 입력 필드 추가
- 레이아웃 2x2 배열로 변경 (업무용 이메일|개인 이메일 / 주민등록번호|연락처)
- Employee 모델에 personalEmail accessor 추가
- 컨트롤러 validation, 서비스 jsonExtraKeys에 personal_email 반영
2026-03-10 10:04:24 +09:00
김보곤
13ee95270e feat: [payroll] 급여명세서 이메일을 PDF 첨부파일로 변경
- 이메일 본문에 급여 내역 직접 노출 → PDF 첨부파일로 전환 (보안 강화)
- barryvdh/laravel-dompdf 패키지 추가
- 이메일 본문은 간단한 안내 메시지로 변경
- dompdf에서 한글 렌더링을 위해 Noto Sans KR 폰트 적용
2026-03-10 09:11:46 +09:00
김보곤
d948366c2a feat: [payroll] 이메일 발송 후 '발송' 라벨 표시 기능
- payrolls 테이블 options JSON에 email_sent_at/email_sent_to 저장
- 이메일 아이콘 아래 '발송' 텍스트 표시 (서버 렌더링 + JS 즉시 반영)
- Payroll 모델에 options 컬럼 추가
2026-03-10 01:20:25 +09:00
김보곤
ca0473d541 feat: [payroll] 급여명세서 이메일 발송 기능 추가
- PayslipMail Mailable 클래스 생성 (admin@codebridge-x.com 발송)
- 급여명세서 이메일 템플릿 (전통 한국식 양식)
- 이메일 발송 API 엔드포인트 추가 (POST /payrolls/{id}/send-payslip)
- 목록 테이블에 이메일 발송 아이콘 버튼 추가
- 급여명세서 미리보기 모달 + 인쇄 기능
2026-03-10 01:06:21 +09:00
김보곤
60669ffdd5 feat: [hr] 연차촉진 관리에 1차/2차 촉진기간 컬럼 추가
- 근로기준법 제61조 기준 입사일 기반 촉진기간 자동 계산
- 1차 촉진기간: 연차만료 6개월 전 ~ +10일
- 2차 촉진기간 마감: 연차만료 2개월 전
- 잔여일수 다음에 촉진기간 표시
2026-03-10 00:37:10 +09:00
김보곤
512f01bea6 feat: [hr] 휴가관리 참조자 선택 기능 추가
- 휴가 신청 모달에 참조자 검색/선택 UI 추가 (Alpine.js)
- 부서별 사용자 목록에서 참조자 검색 및 녹색 칩 표시
- LeaveController 참조 배열 유효성 검증 추가
- LeaveService에서 결재선 steps에 참조자 자동 병합
2026-03-10 00:09:09 +09:00
김보곤
2e97b824cd feat: [hr] 연차촉진 관리 페이지 추가
- LeavePromotionController: 대상자 목록 조회 + 일괄 통지 발송
- LeaveService: getPromotionCandidates(), sendPromotionNotices() 메서드 추가
- 통지 현황 추적 (미발송/1차 발송/완료)
- 일괄 선택 + 결재 문서 자동 생성 + 상신
2026-03-07 00:46:10 +09:00
김보곤
617c89a33f 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:36 +09:00
김보곤
30078e5e86 fix: [hr] 잔여연차 탭에서 영업팀+제외 사원 필터링 적용 2026-03-05 17:08:41 +09:00
김보곤
8100f889f5 feat: [hr] 근태관리 영업팀 및 제외 사원 필터링 적용
- 근태 목록/통계/요약/초과근무에서 영업팀+제외 사원 제외
- 근태관리 부서 드롭다운에서 영업팀 제외
- 활성 사원 목록(드롭다운)에서 영업팀+제외 사원 제외
2026-03-05 16:54:21 +09:00
김보곤
be35f7ba49 feat: [hr] 연차잔여 탭에 재직상태 필터 추가 (전체/재직자/퇴직자)
- 필터 기본값: 재직자 (active + leave)
- 퇴직자 선택 시 resigned만 표시
- 전체 선택 시 모든 상태 표시
2026-03-05 15:16:54 +09:00
김보곤
5f81e5f356 feat: [hr] 사원관리 영업팀 제외 및 강제 제외 기능 추가
- 영업팀 포함 부서 사원 기본 제외 (외부직원)
- json_extra.is_excluded 플래그로 강제 제외/복원 토글
- 필터에 '제외 사원 표시' 체크박스 추가
- 제외 사원 시각적 구분 (주황 배경, 제외 뱃지)
2026-03-05 15:16:15 +09:00
김보곤
6f03a8d12c feat: [hr] 슈퍼관리자 근태/신청 삭제 및 영구삭제 기능 추가
- AttendanceService: forceDeleteAttendance 메서드 추가
- LeaveService: deleteLeave(모든 상태), forceDeleteLeave 메서드 추가
- Controller: force 파라미터 + 슈퍼관리자 권한 분기
- 근태 테이블: 슈퍼관리자에게 삭제/영구삭제 버튼 표시
- 신청 테이블: 슈퍼관리자에게 삭제/영구삭제 버튼 표시
2026-03-04 00:15:41 +09:00
김보곤
6cdcc293cf feat: [hr] 근태등록 + 휴가관리 통합 시스템 구현
- Leave 모델 확장: 6개 유형 추가 (출장/재택/외근/조퇴/지각사유서/결근사유서)
- LeaveService: 유형별 결재양식 자동 선택, 유형별 Attendance 반영 분기
- ApprovalService: 콜백 3개 결재양식코드로 확장
- AttendanceIntegratedController: 통합 화면 컨트롤러
- 통합 UI: 근태현황/신청결재/연차잔여 3탭 + 신규 신청 드롭다운
- AttendanceRequest 모델/서비스/컨트롤러/뷰 삭제 (Leave로 일원화)
- AttendanceService: deductLeaveBalance 제거 (Leave 시스템으로 일원화)
2026-03-03 23:50:27 +09:00
김보곤
d55e34357d feat: [leave] 휴가 신청 시 결재선 선택 기능 추가
- 휴가 신청 모달에 결재선 드롭다운 + 미리보기 UI 추가
- 선택된 결재선으로 결재 생성 (미선택 시 기본결재선 fallback)
- 휴가 목록에 결재진행 컬럼 추가 (원형 아이콘: ✓승인/✗반려/숫자대기/파랑현재)
- approval.steps.approver eager load 추가
2026-03-03 22:36:05 +09:00
김보곤
4513e51e50 feat: [hr] 사원관리 퇴직자 영구삭제 기능 추가
- 슈퍼관리자만 퇴직 상태 사원을 영구삭제 가능
- 관련 첨부파일도 함께 삭제
- DELETE /admin/hr/employees/{id}/force 엔드포인트 추가
2026-03-03 21:46:37 +09:00
김보곤
bd42adad55 feat: [hr] 사업소득자 임금대장 동적 행 입력 리디자인
- earner 고정 행 → 동적 행 추가/삭제 구조로 변경
- 상호/성명 datalist 콤보박스 (드롭다운 선택 + 직접 입력)
- display_name/business_reg_number 컬럼 직접 저장
- bulkSave: payment_id 기반 upsert + 미제출 draft 자동 삭제
- confirmed/paid 행 수정/삭제 불가 유지
- 엑셀 내보내기 display_name 직접 사용으로 단순화
2026-03-03 14:20:44 +09:00
김보곤
ec6e33699e fix: [payroll] 급여목록 정렬 기준을 입사일 오름차순으로 변경 2026-03-03 11:35:08 +09:00
김보곤
f372791ba9 feat: [hr] 사업소득자 임금대장 CSV→XLSX 내보내기 변환
- PhpSpreadsheet로 스타일링된 XLSX 생성 (제목, 남색 헤더, 테두리)
- 금액 열 천 단위 구분(#,##0), 지급일자 빨간색
- earner 프로필 일괄 로드로 사업자등록번호/주민번호 표시
2026-02-28 17:13:01 +09:00
김보곤
272a4842e8 fix: [leaves] 최종결재자 조회 시 reorder() 적용
- steps() 관계의 기본 orderBy(ASC)와 충돌 방지
- reorder('step_order', 'desc')로 마지막 승인자 정확히 조회
2026-02-28 16:03:32 +09:00
김보곤
4d375d2725 fix: [leaves] 결재 승인 시 최종결재자 ID 조회 수정
- $approval->steps (캐시된 컬렉션) → $approval->steps() (fresh 쿼리)로 변경
- 트랜잭션 내에서 업데이트된 step이 정확히 반영되도록 수정
2026-02-28 16:01:36 +09:00
김보곤
50c0c9ce50 feat: [leaves] 휴가신청 → 전자결재 자동 연동
- LeaveService: 휴가 신청 시 결재 자동 생성+상신
- LeaveService: approveByApproval/rejectByApproval 메서드 추가
- LeaveService: deletePendingLeave 시 연결된 결재 자동 취소
- ApprovalService: 승인/반려/회수/전결 시 휴가 상태 자동 동기화
- Leave 모델: approval_id, approval() 관계 추가
- UI: pending 휴가에 결재 상세 링크 추가, 승인/반려 버튼 제거
2026-02-28 15:54:41 +09:00
김보곤
8c574088f4 feat: [payroll] 급여 확정 취소 기능 추가
- 확정 상태에서 작성중으로 되돌리는 기능 추가
- Model: isUnconfirmable() 상태 헬퍼 추가
- Service: unconfirmPayroll() 메서드 추가
- Controller: unconfirm() 엔드포인트 추가
- Route: POST /{id}/unconfirm 라우트 추가
- View: 확정 취소 버튼 및 JS 함수 추가
2026-02-27 22:17:15 +09:00
김보곤
f922646b7b feat: [hr] 사업소득자 임금대장 입력 기능 구현
- BusinessIncomePayment 모델 (소득세3%/지방소득세0.3% 자동계산)
- BusinessIncomePaymentService (일괄저장/통계/CSV내보내기)
- 웹/API 컨트롤러 (ALLOWED_PAYROLL_USERS 접근 제한)
- 스프레드시트 UI (인라인 편집, 실시간 세금 계산)
- HTMX 연월 변경 갱신, CSV 내보내기
2026-02-27 20:22:07 +09:00
김보곤
958a9302b0 fix: [payroll] 전월 복사/일괄 생성 시 SoftDeletes 유니크 제약 충돌 수정
- exists() 대신 withTrashed()->first()로 soft-deleted 레코드 포함 체크
- soft-deleted 레코드 존재 시 forceDelete() 후 재생성
- copyFromPreviousMonth(), bulkGenerate() 양쪽 동일 수정
2026-02-27 18:01:38 +09:00
김보곤
d55d1c3405 feat: [payroll] 전월 급여 복사 등록 기능 추가
- PayrollService에 copyFromPreviousMonth() 메서드 추가
- PayrollController에 copyFromPrevious() 액션 추가
- 전월 지급/공제 금액을 그대로 복사 (요율 재계산 없음)
- 이미 존재하는 사원/연월은 스킵 처리
2026-02-27 17:30:06 +09:00
김보곤
1b38071fd1 fix: [payroll] 급여 수정 시 요율 재계산 제거
- updatePayroll()에서 calculateAmounts() 호출 제거
- 저장된 공제 금액을 그대로 유지 (요율 변경 영향 없음)
- 수동 수정(deduction_overrides)만 반영
- 총지급액/총공제액/실수령액은 재합산
2026-02-27 16:44:04 +09:00
김보곤
0faf4e4d4e fix: [payroll] 중복 급여 등록 시 자동으로 수정 모드 전환
- store 시 동일 사원/기간 레코드가 존재하면 updatePayroll로 전환
- 기존 INSERT 실패(500) 대신 정상 수정 처리
2026-02-27 15:51:24 +09:00
김보곤
cc3aed004c fix: [payroll] 급여 등록 중복 체크 Race Condition 수정
- 중복 체크를 트랜잭션 내부로 이동 + lockForUpdate()
- UniqueConstraintViolationException 방어 처리 (500→422)
2026-02-27 15:48:29 +09:00
김보곤
dfc207668a fix: [payroll] 공제 항목 전체 원단위 절삭(10원 단위) 적용
- 건강보험, 장기요양보험, 국민연금, 고용보험: round() → floor(x/10)*10
- 고소득 구간 근로소득세 공식 계산도 10원 단위 절삭 적용
- 지방소득세는 이전 커밋에서 이미 적용됨
2026-02-27 14:10:25 +09:00
김보곤
743ab6da34 feat: [payroll] 근로소득세 간이세액표 기반 자동 계산 기능
- IncomeTaxBracket 모델 생성 (DB 조회 방식)
- PayrollService: calculateIncomeTax DB 기반으로 리팩토링
- 10,000천원 초과 구간 공식 계산 (calculateHighIncomeTax)
- 지방소득세 10원 단위 절삭 적용
- 공제대상가족수(1~11명) 반영 (본인 + 피부양자)
- calculate API에 user_id 파라미터 추가
- 사원 select에 data-dependents 속성 추가
- 모달에 공제대상가족수 표시
2026-02-27 13:58:59 +09:00
김보곤
f02e96d4fd 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:46:50 +09:00
김보곤
41693d1888 feat: [leave] 잔여연차 퇴사자 포함 및 퇴사일 기준 연차 계산
- getBalanceSummary에 resigned 상태 포함
- 퇴사자 연차는 퇴사일까지만 산출
- 퇴사자 1년 미만 재계산 대상 제외
- 상태 컬럼 추가 (재직/휴직/퇴사 배지)
- 퇴사자 행 회색 배경 시각적 구분
- 근속 계산: 퇴사자는 입사일~퇴사일 기준
2026-02-27 13:16:08 +09:00
김보곤
d99fdcc2ec feat: [leave] 잔여연차 테이블 헤더 클릭 정렬 기능 추가
- 사원, 부서, 입사일, 부여, 사용, 잔여, 소진율 컬럼 정렬 지원
- 기본 정렬: 입사일 오름차순 (빠른 순)
- 활성 정렬 컬럼 파란색 강조 + 방향 화살표 표시
2026-02-27 13:06:42 +09:00
김보곤
c1b097b7fe fix: [leave] 1년 미만 직원 연차 부여를 월별 발생 방식으로 수정
- 입사일~오늘 완료 월수 기준으로 연차 산출 (기존: 연말까지 선부여)
- 잔여연차 조회 시 1년 미만 직원 total_days 자동 재계산
- 도움말 가이드 연차 산출 방식 설명 갱신
2026-02-27 12:42:10 +09:00
김보곤
df1e83af1b fix: [employee] 부양가족 체크박스(장애인/피부양자) 값 저장·표시 오류 수정
- Alpine x-model + hidden input 패턴 개선 (동적 :value 바인딩)
- JSON 로드 시 boolean 정규화로 체크 상태 정확히 복원
- 서비스 레이어에서 filter_var BOOLEAN 캐스팅 추가
- show 페이지 표시 로직 filter_var로 강화
2026-02-27 11:25:11 +09:00
김보곤
efc133bd78 fix: [payroll] 식대 비과세 처리 + 국민연금 상한/하한 적용 개선
- 식대(bonus)를 과세표준에서 제외하여 4대보험/세금 산출 시 비과세 처리
- 라벨 '식대' → '식대(비과세)'로 변경 (등록/수정/상세/엑셀)
- 합계 영역에 과세표준(식대 제외) 표시 추가
- 국민연금은 기존대로 settings의 상한액/하한액 적용 (과세표준 기준으로 변경)
2026-02-27 11:17:17 +09:00