feat: [leaves] 휴가신청 → 전자결재 자동 연동

- LeaveService: 휴가 신청 시 결재 자동 생성+상신
- LeaveService: approveByApproval/rejectByApproval 메서드 추가
- LeaveService: deletePendingLeave 시 연결된 결재 자동 취소
- ApprovalService: 승인/반려/회수/전결 시 휴가 상태 자동 동기화
- Leave 모델: approval_id, approval() 관계 추가
- UI: pending 휴가에 결재 상세 링크 추가, 승인/반려 버튼 제거
This commit is contained in:
김보곤
2026-02-28 15:54:41 +09:00
parent 4aea02b085
commit 34b8a75b08
5 changed files with 331 additions and 26 deletions

View File

@@ -276,6 +276,9 @@ public function approve(int $id, ?string $comment = null): Approval
'completed_at' => now(),
'updated_by' => auth()->id(),
]);
// 연동 후처리 (휴가 등)
$this->handleApprovalCompleted($approval);
}
return $approval->fresh(['form', 'drafter', 'steps.approver']);
@@ -315,6 +318,9 @@ public function reject(int $id, string $comment): Approval
'updated_by' => auth()->id(),
]);
// 연동 후처리 (휴가 등)
$this->handleApprovalRejected($approval, $comment);
return $approval->fresh(['form', 'drafter', 'steps.approver']);
});
}
@@ -358,6 +364,9 @@ public function cancel(int $id, ?string $recallReason = null): Approval
'updated_by' => auth()->id(),
]);
// 연동 후처리 (휴가 회수)
$this->handleApprovalCancelled($approval);
return $approval->fresh(['form', 'drafter', 'steps.approver']);
});
}
@@ -472,6 +481,9 @@ public function preDecide(int $id, ?string $comment = null): Approval
'updated_by' => auth()->id(),
]);
// 연동 후처리 (휴가 등)
$this->handleApprovalCompleted($approval);
return $approval->fresh(['form', 'drafter', 'steps.approver']);
});
}
@@ -692,6 +704,58 @@ public function getBadgeCounts(int $userId): array
// Private 헬퍼
// =========================================================================
/**
* 결재 최종 승인 시 연동 처리 (휴가 등)
*/
private function handleApprovalCompleted(Approval $approval): void
{
if (! $approval->form || $approval->form->code !== 'leave') {
return;
}
$leave = \App\Models\HR\Leave::where('approval_id', $approval->id)->first();
if ($leave && $leave->status === 'pending') {
app(\App\Services\HR\LeaveService::class)->approveByApproval($leave, $approval);
}
}
/**
* 결재 반려 시 연동 처리 (휴가 등)
*/
private function handleApprovalRejected(Approval $approval, string $comment): void
{
if (! $approval->form || $approval->form->code !== 'leave') {
return;
}
$leave = \App\Models\HR\Leave::where('approval_id', $approval->id)->first();
if ($leave && $leave->status === 'pending') {
app(\App\Services\HR\LeaveService::class)->rejectByApproval(
$leave,
$comment,
auth()->id()
);
}
}
/**
* 결재 회수 시 연동 처리 (휴가 등)
*/
private function handleApprovalCancelled(Approval $approval): void
{
if (! $approval->form || $approval->form->code !== 'leave') {
return;
}
$leave = \App\Models\HR\Leave::where('approval_id', $approval->id)->first();
if ($leave && $leave->status === 'pending') {
$leave->update([
'status' => 'cancelled',
'updated_by' => auth()->id(),
]);
}
}
/**
* 결재선 steps에 user_name, department, position 스냅샷 보강
*/