feat(API): 입금/출금 알림 Observer 추가 및 LoanController 수정

- DepositIssueObserver, WithdrawalIssueObserver 신규 추가
- TodayIssueObserverService에 입금/출금 핸들러 및 디버그 로그 추가
- TodayIssue 모델에 입금/출금 상수 추가
- AppServiceProvider에 Observer 등록
- ApprovalService에 기존 결재선 사용 시 수동 알림 트리거 추가
- LoanController ApiResponse::handle() → ApiResponse::success() 수정

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-01-23 10:05:50 +09:00
parent fabf302e1f
commit d75f6f5bd1
9 changed files with 232 additions and 22 deletions

View File

@@ -14,6 +14,10 @@
class ApprovalService extends Service
{
public function __construct(
protected TodayIssueObserverService $todayIssueService
) {}
// =========================================================================
// 결재 양식 관리
// =========================================================================
@@ -730,13 +734,8 @@ public function submit(int $id, array $data): Approval
throw new BadRequestHttpException(__('error.approval.not_submittable'));
}
// steps가 있으면 새로 생성, 없으면 기존 결재선 사용
if (! empty($data['steps'])) {
// 기존 결재선 삭제 후 새로 생성
$approval->steps()->delete();
$this->createApprovalSteps($approval, $data['steps']);
} else {
// 기존 결재선이 없으면 에러
// 기존 결재선 확인 (steps 없이 상신하는 경우)
if (empty($data['steps'])) {
$existingSteps = $approval->steps()
->whereIn('step_type', [ApprovalLine::STEP_TYPE_APPROVAL, ApprovalLine::STEP_TYPE_AGREEMENT])
->count();
@@ -746,12 +745,31 @@ public function submit(int $id, array $data): Approval
}
}
// 먼저 approval을 pending으로 변경 (Observer가 올바른 상태로 트리거되도록)
$approval->status = Approval::STATUS_PENDING;
$approval->drafted_at = now();
$approval->current_step = 1;
$approval->updated_by = $userId;
$approval->save();
// steps가 있으면 새로 생성 (approval이 pending 상태일 때 생성해야 알림 발송)
if (! empty($data['steps'])) {
// 기존 결재선 삭제 후 새로 생성
$approval->steps()->delete();
$this->createApprovalSteps($approval, $data['steps']);
} else {
// 기존 결재선 사용 시, Observer가 트리거되지 않으므로 수동으로 알림 발송
$firstPendingStep = $approval->steps()
->where('status', ApprovalStep::STATUS_PENDING)
->whereIn('step_type', [ApprovalLine::STEP_TYPE_APPROVAL, ApprovalLine::STEP_TYPE_AGREEMENT])
->orderBy('step_order')
->first();
if ($firstPendingStep) {
$this->todayIssueService->handleApprovalStepChange($firstPendingStep);
}
}
return $approval->fresh([
'form:id,name,code,category',
'drafter:id,name',