From 88ef6a8490a2b62382607da6a837af40e93eff87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Tue, 3 Mar 2026 23:50:04 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20[hr]=20Leave=20=EB=AA=A8=EB=8D=B8=20?= =?UTF-8?q?=ED=99=95=EC=9E=A5=20+=20=EA=B2=B0=EC=9E=AC=EC=96=91=EC=8B=9D?= =?UTF-8?q?=20=EB=A7=88=EC=9D=B4=EA=B7=B8=EB=A0=88=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Leave 타입 6개 추가: business_trip, remote, field_work, early_leave, late_reason, absent_reason - 그룹 상수 추가: VACATION_TYPES, ATTENDANCE_REQUEST_TYPES, REASON_REPORT_TYPES - FORM_CODE_MAP: 유형 → 결재양식코드 매핑 상수 - ATTENDANCE_STATUS_MAP: 유형 → 근태상태 매핑 상수 - 결재양식 2개 추가: attendance_request(근태신청), reason_report(사유서) --- app/Models/Tenants/Leave.php | 57 ++++++++++++++++++ ...00100_insert_attendance_approval_forms.php | 59 +++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 database/migrations/2026_03_03_100100_insert_attendance_approval_forms.php diff --git a/app/Models/Tenants/Leave.php b/app/Models/Tenants/Leave.php index eee6d93..604306b 100644 --- a/app/Models/Tenants/Leave.php +++ b/app/Models/Tenants/Leave.php @@ -82,6 +82,18 @@ class Leave extends Model public const TYPE_PARENTAL = 'parental'; // 육아 + public const TYPE_BUSINESS_TRIP = 'business_trip'; // 출장 + + public const TYPE_REMOTE = 'remote'; // 재택근무 + + public const TYPE_FIELD_WORK = 'field_work'; // 외근 + + public const TYPE_EARLY_LEAVE = 'early_leave'; // 조퇴 + + public const TYPE_LATE_REASON = 'late_reason'; // 지각사유서 + + public const TYPE_ABSENT_REASON = 'absent_reason'; // 결근사유서 + public const STATUS_PENDING = 'pending'; public const STATUS_APPROVED = 'approved'; @@ -98,6 +110,45 @@ class Leave extends Model self::TYPE_FAMILY, self::TYPE_MATERNITY, self::TYPE_PARENTAL, + self::TYPE_BUSINESS_TRIP, + self::TYPE_REMOTE, + self::TYPE_FIELD_WORK, + self::TYPE_EARLY_LEAVE, + self::TYPE_LATE_REASON, + self::TYPE_ABSENT_REASON, + ]; + + // 그룹 상수 + public const VACATION_TYPES = [ + self::TYPE_ANNUAL, self::TYPE_HALF_AM, self::TYPE_HALF_PM, + self::TYPE_SICK, self::TYPE_FAMILY, self::TYPE_MATERNITY, self::TYPE_PARENTAL, + ]; + + public const ATTENDANCE_REQUEST_TYPES = [ + self::TYPE_BUSINESS_TRIP, self::TYPE_REMOTE, self::TYPE_FIELD_WORK, self::TYPE_EARLY_LEAVE, + ]; + + public const REASON_REPORT_TYPES = [ + self::TYPE_LATE_REASON, self::TYPE_ABSENT_REASON, + ]; + + // 유형 → 결재양식코드 매핑 + public const FORM_CODE_MAP = [ + 'annual' => 'leave', 'half_am' => 'leave', 'half_pm' => 'leave', + 'sick' => 'leave', 'family' => 'leave', 'maternity' => 'leave', 'parental' => 'leave', + 'business_trip' => 'attendance_request', 'remote' => 'attendance_request', + 'field_work' => 'attendance_request', 'early_leave' => 'attendance_request', + 'late_reason' => 'reason_report', 'absent_reason' => 'reason_report', + ]; + + // 유형 → 근태상태 매핑 (승인 시 Attendance에 반영할 상태) + public const ATTENDANCE_STATUS_MAP = [ + 'annual' => 'vacation', 'half_am' => 'vacation', 'half_pm' => 'vacation', + 'sick' => 'vacation', 'family' => 'vacation', 'maternity' => 'vacation', 'parental' => 'vacation', + 'business_trip' => 'businessTrip', 'remote' => 'remote', 'field_work' => 'fieldWork', + 'early_leave' => null, + 'late_reason' => null, + 'absent_reason' => null, ]; public const STATUSES = [ @@ -253,6 +304,12 @@ public function getLeaveTypeLabelAttribute(): string self::TYPE_FAMILY => '경조사', self::TYPE_MATERNITY => '출산휴가', self::TYPE_PARENTAL => '육아휴직', + self::TYPE_BUSINESS_TRIP => '출장', + self::TYPE_REMOTE => '재택근무', + self::TYPE_FIELD_WORK => '외근', + self::TYPE_EARLY_LEAVE => '조퇴', + self::TYPE_LATE_REASON => '지각사유서', + self::TYPE_ABSENT_REASON => '결근사유서', default => $this->leave_type, }; } diff --git a/database/migrations/2026_03_03_100100_insert_attendance_approval_forms.php b/database/migrations/2026_03_03_100100_insert_attendance_approval_forms.php new file mode 100644 index 0000000..db3cc7f --- /dev/null +++ b/database/migrations/2026_03_03_100100_insert_attendance_approval_forms.php @@ -0,0 +1,59 @@ +insertOrIgnore([ + 'tenant_id' => 1, + 'name' => '근태신청', + 'code' => 'attendance_request', + 'category' => 'request', + 'template' => json_encode([ + 'fields' => [ + ['name' => 'user_name', 'type' => 'text', 'label' => '신청자'], + ['name' => 'request_type', 'type' => 'text', 'label' => '신청유형'], + ['name' => 'period', 'type' => 'text', 'label' => '기간'], + ['name' => 'days', 'type' => 'number', 'label' => '일수'], + ['name' => 'reason', 'type' => 'text', 'label' => '사유'], + ], + ], JSON_UNESCAPED_UNICODE), + 'is_active' => true, + 'created_by' => 1, + 'created_at' => now(), + 'updated_at' => now(), + ]); + + // 사유서 결재 양식 (지각사유서/결근사유서) + DB::table('approval_forms')->insertOrIgnore([ + 'tenant_id' => 1, + 'name' => '사유서', + 'code' => 'reason_report', + 'category' => 'request', + 'template' => json_encode([ + 'fields' => [ + ['name' => 'user_name', 'type' => 'text', 'label' => '신청자'], + ['name' => 'report_type', 'type' => 'text', 'label' => '사유서유형'], + ['name' => 'target_date', 'type' => 'date', 'label' => '대상일'], + ['name' => 'reason', 'type' => 'text', 'label' => '사유'], + ], + ], JSON_UNESCAPED_UNICODE), + 'is_active' => true, + 'created_by' => 1, + 'created_at' => now(), + 'updated_at' => now(), + ]); + } + + public function down(): void + { + DB::table('approval_forms') + ->where('tenant_id', 1) + ->whereIn('code', ['attendance_request', 'reason_report']) + ->delete(); + } +};