Files
sam-api/database/seeders/ApprovalTestDataSeeder.php

313 lines
13 KiB
PHP
Raw Normal View History

<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
class ApprovalTestDataSeeder extends Seeder
{
/**
* 결재 시스템 테스트 데이터 시더
* - 기안함: 15 (draft 5, pending 10)
* - 결재함: 15 (결재 대기 상태)
* - 참조함: 10 (열람 대기 상태)
*/
public function run(): void
{
$tenantId = 1;
$now = Carbon::now();
// 사용자 ID 가져오기
$users = DB::table('users')->pluck('id')->toArray();
if (count($users) < 3) {
$this->command->error('최소 3명의 사용자가 필요합니다.');
return;
}
$mainUser = $users[0]; // 기안자 겸 참조 대상
$approver1 = $users[1] ?? $users[0];
$approver2 = $users[2] ?? $users[0];
// 1. 결재 양식 생성
$this->command->info('결재 양식 생성 중...');
$forms = $this->createApprovalForms($tenantId, $mainUser, $now);
// 2. 결재 문서 생성
$this->command->info('결재 문서 생성 중...');
$this->createApprovals($tenantId, $forms, $mainUser, $approver1, $approver2, $now);
$this->command->info('✅ 결재 테스트 데이터 생성 완료!');
$this->command->info(' - 기안함: 15건');
$this->command->info(' - 결재함: 15건');
$this->command->info(' - 참조함: 10건');
}
private function createApprovalForms(int $tenantId, int $userId, Carbon $now): array
{
$forms = [
[
'tenant_id' => $tenantId,
'name' => '품의서',
'code' => 'proposal',
'category' => '일반',
'template' => json_encode([
'fields' => [
['name' => 'title', 'type' => 'text', 'label' => '제목', 'required' => true],
['name' => 'vendor', 'type' => 'text', 'label' => '거래처', 'required' => false],
['name' => 'description', 'type' => 'textarea', 'label' => '내용', 'required' => true],
['name' => 'reason', 'type' => 'textarea', 'label' => '사유', 'required' => true],
['name' => 'estimatedCost', 'type' => 'number', 'label' => '예상비용', 'required' => false],
]
]),
'is_active' => true,
'created_by' => $userId,
'created_at' => $now,
'updated_at' => $now,
],
[
'tenant_id' => $tenantId,
'name' => '지출결의서',
'code' => 'expenseReport',
'category' => '경비',
'template' => json_encode([
'fields' => [
['name' => 'requestDate', 'type' => 'date', 'label' => '신청일', 'required' => true],
['name' => 'paymentDate', 'type' => 'date', 'label' => '지급일', 'required' => true],
['name' => 'items', 'type' => 'array', 'label' => '지출항목', 'required' => true],
['name' => 'totalAmount', 'type' => 'number', 'label' => '총액', 'required' => true],
]
]),
'is_active' => true,
'created_by' => $userId,
'created_at' => $now,
'updated_at' => $now,
],
[
'tenant_id' => $tenantId,
'name' => '비용견적서',
'code' => 'expenseEstimate',
'category' => '경비',
'template' => json_encode([
'fields' => [
['name' => 'items', 'type' => 'array', 'label' => '비용항목', 'required' => true],
['name' => 'totalExpense', 'type' => 'number', 'label' => '총지출', 'required' => true],
['name' => 'accountBalance', 'type' => 'number', 'label' => '계좌잔액', 'required' => true],
]
]),
'is_active' => true,
'created_by' => $userId,
'created_at' => $now,
'updated_at' => $now,
],
];
$formIds = [];
foreach ($forms as $form) {
// 기존 양식 확인
$existing = DB::table('approval_forms')
->where('tenant_id', $tenantId)
->where('code', $form['code'])
->first();
if ($existing) {
$formIds[$form['code']] = $existing->id;
} else {
$formIds[$form['code']] = DB::table('approval_forms')->insertGetId($form);
}
}
return $formIds;
}
private function createApprovals(
int $tenantId,
array $forms,
int $mainUser,
int $approver1,
int $approver2,
Carbon $now
): void {
$proposalTitles = [
'신규 장비 구매 품의', '사무용품 구매 요청', '소프트웨어 라이선스 갱신',
'출장 경비 지원 요청', '교육 프로그램 신청', '복지시설 개선 제안',
'마케팅 예산 증액 품의', '시스템 업그레이드 제안', '인력 충원 요청',
'사무실 이전 품의', '연구개발 예산 신청', '고객 세미나 개최 품의',
'협력업체 계약 갱신', '보안 시스템 도입 품의', '업무 차량 구매 요청',
];
$expenseItems = [
'교통비', '식비', '숙박비', '소모품비', '통신비', '유류비', '접대비', '회의비'
];
$vendors = [
'삼성전자', 'LG전자', 'SK하이닉스', '현대자동차', '네이버', '카카오',
'쿠팡', '배달의민족', '토스', '당근마켓'
];
$docNumber = 1;
// 기안함용 문서 15건 (mainUser가 기안자)
for ($i = 0; $i < 15; $i++) {
$status = $i < 5 ? 'draft' : 'pending';
$formCode = ['proposal', 'expenseReport', 'expenseEstimate'][$i % 3];
$formId = $forms[$formCode];
$content = $this->generateContent($formCode, $proposalTitles[$i], $vendors, $expenseItems);
$approvalId = DB::table('approvals')->insertGetId([
'tenant_id' => $tenantId,
'document_number' => sprintf('DOC-%s-%04d', $now->format('Ymd'), $docNumber++),
'form_id' => $formId,
'title' => $proposalTitles[$i],
'content' => json_encode($content),
'status' => $status,
'drafter_id' => $mainUser,
'drafted_at' => $status === 'pending' ? $now->copy()->subDays(rand(1, 10)) : null,
'current_step' => $status === 'pending' ? 1 : 0,
'created_by' => $mainUser,
'created_at' => $now->copy()->subDays(rand(1, 15)),
'updated_at' => $now,
]);
// 결재선 추가 (pending 상태인 경우)
if ($status === 'pending') {
// 결재자 1 (approver1이 결재 대기)
DB::table('approval_steps')->insert([
'approval_id' => $approvalId,
'step_order' => 1,
'step_type' => 'approval',
'approver_id' => $approver1,
'status' => 'pending',
'created_at' => $now,
'updated_at' => $now,
]);
// 결재자 2
DB::table('approval_steps')->insert([
'approval_id' => $approvalId,
'step_order' => 2,
'step_type' => 'approval',
'approver_id' => $approver2,
'status' => 'pending',
'created_at' => $now,
'updated_at' => $now,
]);
// 참조 (mainUser에게 참조)
if ($i < 10) {
DB::table('approval_steps')->insert([
'approval_id' => $approvalId,
'step_order' => 3,
'step_type' => 'reference',
'approver_id' => $mainUser,
'status' => 'pending',
'is_read' => false,
'created_at' => $now,
'updated_at' => $now,
]);
}
}
}
// 결재함용 추가 문서 (approver1/approver2가 기안, mainUser가 결재자)
for ($i = 0; $i < 5; $i++) {
$formCode = ['proposal', 'expenseReport'][$i % 2];
$formId = $forms[$formCode];
$drafter = $i < 3 ? $approver1 : $approver2;
$title = '추가 결재 요청 문서 ' . ($i + 1);
$content = $this->generateContent($formCode, $title, $vendors, $expenseItems);
$approvalId = DB::table('approvals')->insertGetId([
'tenant_id' => $tenantId,
'document_number' => sprintf('DOC-%s-%04d', $now->format('Ymd'), $docNumber++),
'form_id' => $formId,
'title' => $title,
'content' => json_encode($content),
'status' => 'pending',
'drafter_id' => $drafter,
'drafted_at' => $now->copy()->subDays(rand(1, 5)),
'current_step' => 1,
'created_by' => $drafter,
'created_at' => $now->copy()->subDays(rand(1, 10)),
'updated_at' => $now,
]);
// mainUser가 결재자
DB::table('approval_steps')->insert([
'approval_id' => $approvalId,
'step_order' => 1,
'step_type' => 'approval',
'approver_id' => $mainUser,
'status' => 'pending',
'created_at' => $now,
'updated_at' => $now,
]);
}
}
private function generateContent(string $formCode, string $title, array $vendors, array $expenseItems): array
{
switch ($formCode) {
case 'proposal':
return [
'title' => $title,
'vendor' => $vendors[array_rand($vendors)],
'vendorPaymentDate' => Carbon::now()->addDays(rand(7, 30))->format('Y-m-d'),
'description' => $title . '에 대한 상세 설명입니다. 업무 효율성 향상과 비용 절감을 위해 필요합니다.',
'reason' => '업무 효율성 향상 및 경쟁력 강화를 위해 필수적으로 진행해야 합니다.',
'estimatedCost' => rand(100, 5000) * 10000,
];
case 'expenseReport':
$items = [];
$total = 0;
for ($j = 0; $j < rand(2, 5); $j++) {
$amount = rand(10, 200) * 1000;
$total += $amount;
$items[] = [
'id' => (string) ($j + 1),
'description' => $expenseItems[array_rand($expenseItems)],
'amount' => $amount,
'note' => '업무 관련 지출',
];
}
return [
'requestDate' => Carbon::now()->subDays(rand(1, 7))->format('Y-m-d'),
'paymentDate' => Carbon::now()->addDays(rand(1, 14))->format('Y-m-d'),
'items' => $items,
'cardId' => 'CARD-' . rand(1000, 9999),
'totalAmount' => $total,
];
case 'expenseEstimate':
$items = [];
$total = 0;
for ($j = 0; $j < rand(3, 8); $j++) {
$amount = rand(50, 500) * 10000;
$total += $amount;
$items[] = [
'id' => (string) ($j + 1),
'expectedPaymentDate' => Carbon::now()->addDays(rand(1, 60))->format('Y-m-d'),
'category' => $expenseItems[array_rand($expenseItems)],
'amount' => $amount,
'vendor' => $vendors[array_rand($vendors)],
'memo' => '예정 지출',
'checked' => false,
];
}
return [
'items' => $items,
'totalExpense' => $total,
'accountBalance' => rand(5000, 20000) * 10000,
'finalDifference' => rand(5000, 20000) * 10000 - $total,
];
default:
return [];
}
}
}