diff --git a/app/Services/TodayIssueObserverService.php b/app/Services/TodayIssueObserverService.php index b3c6aa5..7ac892e 100644 --- a/app/Services/TodayIssueObserverService.php +++ b/app/Services/TodayIssueObserverService.php @@ -369,7 +369,12 @@ public function handleDepositDeleted(Deposit $deposit): void } /** - * 출금 등록 이슈 생성 + * 출금 등록 이슈 생성 (일일 누계 방식) + * + * - 첫 번째 출금: "거래처명 출금 금액원" + * - 두 번째 이후: "첫번째거래처명 외 N건 출금 합계 금액원" + * - source_id=null로 일일 1건만 유지 (upsert) + * - FCM 푸시 미발송 (알림 설정 미구현) */ public function handleWithdrawalCreated(Withdrawal $withdrawal): void { @@ -379,36 +384,88 @@ public function handleWithdrawalCreated(Withdrawal $withdrawal): void 'amount' => $withdrawal->amount, ]); - $clientName = $withdrawal->display_client_name ?: $withdrawal->merchant_name ?: __('message.today_issue.unknown_client'); - $amount = number_format($withdrawal->amount ?? 0); - - Log::info('TodayIssue: Creating withdrawal issue', [ - 'withdrawal_id' => $withdrawal->id, - 'client' => $clientName, - 'amount' => $amount, - ]); - - $this->createIssueWithFcm( - tenantId: $withdrawal->tenant_id, - sourceType: TodayIssue::SOURCE_WITHDRAWAL, - sourceId: $withdrawal->id, - badge: TodayIssue::BADGE_WITHDRAWAL, - content: __('message.today_issue.withdrawal_registered', [ - 'client' => $clientName, - 'amount' => $amount, - ]), - path: "/accounting/withdrawals/{$withdrawal->id}", - needsApproval: false, - expiresAt: Carbon::now()->addDays(7) - ); + $this->upsertWithdrawalDailyIssue($withdrawal->tenant_id); } /** - * 출금 삭제 시 이슈 삭제 + * 출금 삭제 시 일일 누계 이슈 갱신 */ public function handleWithdrawalDeleted(Withdrawal $withdrawal): void { - TodayIssue::removeBySource($withdrawal->tenant_id, TodayIssue::SOURCE_WITHDRAWAL, $withdrawal->id); + $this->upsertWithdrawalDailyIssue($withdrawal->tenant_id); + } + + /** + * 출금 일일 누계 이슈 upsert + * + * 오늘 날짜의 출금 건수/합계를 집계하여 이슈 1건으로 관리 + */ + private function upsertWithdrawalDailyIssue(int $tenantId): void + { + // 기존 개별 출금 이슈 정리 (source_id가 있는 레거시 데이터) + TodayIssue::where('tenant_id', $tenantId) + ->where('source_type', TodayIssue::SOURCE_WITHDRAWAL) + ->whereNotNull('source_id') + ->delete(); + + // 오늘 날짜 출금 조회 (출금일 기준, soft delete 제외) + $todayWithdrawals = Withdrawal::withoutGlobalScopes() + ->where('tenant_id', $tenantId) + ->whereDate('withdrawal_date', Carbon::today()) + ->whereNull('deleted_at') + ->orderBy('created_at', 'asc') + ->get(); + + $count = $todayWithdrawals->count(); + $totalAmount = $todayWithdrawals->sum('amount'); + + Log::info('TodayIssue: Withdrawal daily summary', [ + 'tenant_id' => $tenantId, + 'count' => $count, + 'total_amount' => $totalAmount, + ]); + + // 출금이 없으면 이슈 삭제 + if ($count === 0) { + TodayIssue::where('tenant_id', $tenantId) + ->where('source_type', TodayIssue::SOURCE_WITHDRAWAL) + ->whereNull('source_id') + ->delete(); + + return; + } + + // 첫 번째 출금의 거래처명 + $first = $todayWithdrawals->first(); + $firstClientName = $first->display_client_name + ?: $first->merchant_name + ?: __('message.today_issue.unknown_client'); + + // 1건이면 단건 메시지, 2건 이상이면 누계 메시지 + if ($count === 1) { + $content = __('message.today_issue.withdrawal_registered', [ + 'client' => $firstClientName, + 'amount' => number_format($totalAmount), + ]); + } else { + $content = __('message.today_issue.withdrawal_daily_summary', [ + 'client' => $firstClientName, + 'count' => $count - 1, + 'amount' => number_format($totalAmount), + ]); + } + + // source_id=null 로 일일 1건 upsert (FCM 미발송) + TodayIssue::createIssue( + tenantId: $tenantId, + sourceType: TodayIssue::SOURCE_WITHDRAWAL, + sourceId: null, + badge: TodayIssue::BADGE_WITHDRAWAL, + content: $content, + path: '/accounting/withdrawals', + needsApproval: false, + expiresAt: Carbon::now()->addDays(7) + ); } /** diff --git a/lang/ko/message.php b/lang/ko/message.php index 5a31536..2e03b3d 100644 --- a/lang/ko/message.php +++ b/lang/ko/message.php @@ -515,6 +515,7 @@ 'new_client' => ':name 등록', 'deposit_registered' => ':client 입금 :amount원', 'withdrawal_registered' => ':client 출금 :amount원', + 'withdrawal_daily_summary' => ':client 외 :count건 출금 합계 :amount원', // 기안 상태 변경 알림 'draft_approved' => ':title 결재가 승인되었습니다',