command->info('종합분석 테스트 데이터 생성 시작...'); DB::transaction(function () { $this->seedApprovalForms(); $this->seedApprovals(); $this->seedExpectedExpenses(); $this->seedDeposits(); $this->seedBadDebts(); $this->updateClientBalances(); }); $this->command->info('종합분석 테스트 데이터 생성 완료!'); } /** * 결재 양식 생성 */ private function seedApprovalForms(): void { $forms = [ ['code' => 'proposal', 'name' => '품의서', 'category' => 'request'], ['code' => 'expenseReport', 'name' => '지출결의서', 'category' => 'expense'], ['code' => 'expenseEstimate', 'name' => '지출 예상 내역서', 'category' => 'expense_estimate'], ]; foreach ($forms as $form) { ApprovalForm::firstOrCreate( ['tenant_id' => $this->tenantId, 'code' => $form['code']], [ 'name' => $form['name'], 'category' => $form['category'], 'template' => ['fields' => []], 'is_active' => true, 'created_by' => $this->userId, ] ); } $this->command->info(' - 결재 양식 3건 생성'); } /** * 결재 대기 문서 생성 */ private function seedApprovals(): void { $form = ApprovalForm::where('tenant_id', $this->tenantId)->first(); if (! $form) { $this->command->warn(' - 결재 양식이 없어 결재 문서 생성 건너뜀'); return; } $approvals = [ ['title' => '12월 사무용품 구매 품의', 'time' => '09:15'], ['title' => '연말 회식비 지출결의', 'time' => '10:30'], ['title' => '출장비 정산 요청', 'time' => '11:45'], ['title' => '서버 호스팅 비용 결재', 'time' => '14:20'], ['title' => '신규 장비 구매 품의', 'time' => '15:00'], ]; $today = Carbon::today(); foreach ($approvals as $i => $approval) { $approvalRecord = Approval::firstOrCreate( [ 'tenant_id' => $this->tenantId, 'document_number' => 'DOC-'.date('Ymd').'-'.str_pad($i + 1, 3, '0', STR_PAD_LEFT), ], [ 'form_id' => $form->id, 'title' => $approval['title'], 'content' => ['description' => $approval['title'].' 내용입니다.'], 'status' => Approval::STATUS_PENDING, 'drafter_id' => $this->userId, 'drafted_at' => $today->copy()->setTimeFromTimeString($approval['time']), 'current_step' => 1, 'created_by' => $this->userId, ] ); // 결재 단계 생성 (현재 로그인 사용자가 승인/반려할 수 있도록) ApprovalStep::firstOrCreate( [ 'approval_id' => $approvalRecord->id, 'step_order' => 1, ], [ 'step_type' => 'approval', // ApprovalLine::STEP_TYPE_APPROVAL 'approver_id' => $this->userId, 'status' => ApprovalStep::STATUS_PENDING, ] ); } $this->command->info(' - 결재 대기 문서 5건 + 결재 단계 생성'); } /** * 예상 지출 데이터 생성 */ private function seedExpectedExpenses(): void { $today = Carbon::today(); $thisMonth = $today->copy()->startOfMonth(); $lastMonth = $today->copy()->subMonth()->startOfMonth(); $expenses = [ // 이번 달 지출 ['type' => 'purchase', 'amount' => 5000000, 'status' => 'paid', 'date' => $thisMonth->copy()->addDays(5)], ['type' => 'purchase', 'amount' => 3000000, 'status' => 'pending', 'date' => $thisMonth->copy()->addDays(15)], ['type' => 'salary', 'amount' => 25000000, 'status' => 'paid', 'date' => $thisMonth->copy()->addDays(25)], ['type' => 'insurance', 'amount' => 2500000, 'status' => 'pending', 'date' => $thisMonth->copy()->addDays(28)], ['type' => 'rent', 'amount' => 3000000, 'status' => 'paid', 'date' => $thisMonth->copy()->addDays(1)], ['type' => 'utilities', 'amount' => 500000, 'status' => 'pending', 'date' => $thisMonth->copy()->addDays(20)], ['type' => 'tax', 'amount' => 1500000, 'status' => 'pending', 'date' => $thisMonth->copy()->addDays(25)], ['type' => 'other', 'amount' => 2000000, 'status' => 'paid', 'date' => $thisMonth->copy()->addDays(10)], // 가지급금/선급금 ['type' => 'suspense', 'amount' => 5000000, 'status' => 'pending', 'date' => $thisMonth->copy()->addDays(3)], ['type' => 'suspense', 'amount' => 3000000, 'status' => 'pending', 'date' => $thisMonth->copy()->addDays(12)], ['type' => 'advance', 'amount' => 2000000, 'status' => 'pending', 'date' => $thisMonth->copy()->addDays(8)], // 연체 (지난 달) ['type' => 'purchase', 'amount' => 1500000, 'status' => 'pending', 'date' => $lastMonth->copy()->addDays(20)], ]; foreach ($expenses as $expense) { ExpectedExpense::create([ 'tenant_id' => $this->tenantId, 'expected_payment_date' => $expense['date'], 'transaction_type' => $expense['type'], 'amount' => $expense['amount'], 'payment_status' => $expense['status'], 'approval_status' => 'approved', 'description' => ExpectedExpense::TRANSACTION_TYPES[$expense['type']].' 지출', 'created_by' => $this->userId, ]); } $this->command->info(' - 예상 지출 12건 생성'); } /** * 입금 데이터 생성 */ private function seedDeposits(): void { $today = Carbon::today(); $thisMonth = $today->copy()->startOfMonth(); $deposits = [ // 오늘 입금 ['amount' => 5000000, 'method' => 'transfer', 'date' => $today, 'client' => '(주)테스트고객A'], ['amount' => 3000000, 'method' => 'transfer', 'date' => $today, 'client' => '(주)테스트고객B'], // 이번 달 입금 ['amount' => 10000000, 'method' => 'transfer', 'date' => $thisMonth->copy()->addDays(5), 'client' => '(주)테스트고객C'], ['amount' => 7500000, 'method' => 'card', 'date' => $thisMonth->copy()->addDays(10), 'client' => '(주)테스트고객D'], ['amount' => 15000000, 'method' => 'transfer', 'date' => $thisMonth->copy()->addDays(15), 'client' => '(주)테스트고객E'], ['amount' => 8000000, 'method' => 'check', 'date' => $thisMonth->copy()->addDays(20), 'client' => '(주)테스트고객F'], ]; foreach ($deposits as $deposit) { Deposit::create([ 'tenant_id' => $this->tenantId, 'deposit_date' => $deposit['date'], 'amount' => $deposit['amount'], 'payment_method' => $deposit['method'], 'client_name' => $deposit['client'], 'description' => $deposit['client'].' 입금', 'created_by' => $this->userId, ]); } $this->command->info(' - 입금 6건 생성'); } /** * 채권추심 데이터 생성 */ private function seedBadDebts(): void { // 먼저 테스트 거래처 생성 $clients = $this->ensureTestClients(); $badDebts = [ // 추심중 ['client_idx' => 0, 'amount' => 5000000, 'status' => BadDebt::STATUS_COLLECTING, 'days' => 45], ['client_idx' => 1, 'amount' => 3000000, 'status' => BadDebt::STATUS_COLLECTING, 'days' => 60], // 법적조치 ['client_idx' => 2, 'amount' => 8000000, 'status' => BadDebt::STATUS_LEGAL_ACTION, 'days' => 120], // 회수완료 (올해) ['client_idx' => 3, 'amount' => 2000000, 'status' => BadDebt::STATUS_RECOVERED, 'days' => 30, 'closed' => true], ['client_idx' => 4, 'amount' => 1500000, 'status' => BadDebt::STATUS_RECOVERED, 'days' => 45, 'closed' => true], // 대손처리 ['client_idx' => 5, 'amount' => 10000000, 'status' => BadDebt::STATUS_BAD_DEBT, 'days' => 365, 'closed' => true], ]; foreach ($badDebts as $debt) { $occurredAt = Carbon::today()->subDays($debt['days']); BadDebt::create([ 'tenant_id' => $this->tenantId, 'client_id' => $clients[$debt['client_idx']]->id ?? null, 'debt_amount' => $debt['amount'], 'status' => $debt['status'], 'overdue_days' => $debt['days'], 'assigned_user_id' => $this->userId, 'occurred_at' => $occurredAt, 'closed_at' => isset($debt['closed']) ? Carbon::today() : null, 'is_active' => ! isset($debt['closed']), 'created_by' => $this->userId, ]); } $this->command->info(' - 채권추심 6건 생성'); } /** * 테스트 거래처 생성 */ private function ensureTestClients(): array { $clientNames = [ '(주)문제거래처A', '(주)문제거래처B', '(주)문제거래처C', '(주)정상거래처D', '(주)정상거래처E', '(주)대손거래처F', ]; $clients = []; foreach ($clientNames as $i => $name) { $clients[] = Client::firstOrCreate( ['tenant_id' => $this->tenantId, 'client_code' => 'T'.$this->tenantId.'-'.str_pad($i + 1, 3, '0', STR_PAD_LEFT)], [ 'name' => $name, 'is_active' => true, 'client_type' => 'company', ] ); } return $clients; } /** * 거래처 미수금/여신한도 업데이트 */ private function updateClientBalances(): void { // 기존 거래처 중 일부에 미수금/여신한도 설정 $clients = Client::where('tenant_id', $this->tenantId) ->where('is_active', true) ->limit(5) ->get(); $balances = [ ['outstanding' => 15000000, 'limit' => 10000000], // 한도 초과 ['outstanding' => 8000000, 'limit' => 10000000], // 정상 ['outstanding' => 12000000, 'limit' => 10000000], // 한도 초과 ['outstanding' => 5000000, 'limit' => 20000000], // 정상 ['outstanding' => 25000000, 'limit' => 20000000], // 한도 초과 ]; foreach ($clients as $i => $client) { if (isset($balances[$i])) { $client->update([ 'outstanding_balance' => $balances[$i]['outstanding'], 'credit_limit' => $balances[$i]['limit'], ]); } } $this->command->info(' - 거래처 미수금/여신한도 업데이트 '.min(count($clients), 5).'건'); } }