Files
sam-api/database/seeders/ApprovalTestDataSeeder.php
kent be90c351fa chore(API): Seeder 파일 정리
- Dummy Seeder 파일들 정리 및 개선
- ApprovalTestDataSeeder 수정
- PositionSeeder, StockReceivingSeeder 수정

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-13 19:49:28 +09:00

322 lines
13 KiB
PHP

<?php
namespace Database\Seeders;
use Carbon\Carbon;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class ApprovalTestDataSeeder extends Seeder
{
/**
* 결재 시스템 테스트 데이터 시더
* - 기안함: 15건 (draft 5건, pending 10건)
* - 결재함: 15건 (결재 대기 상태)
* - 참조함: 10건 (열람 대기 상태)
*/
public function run(): void
{
$tenantId = DummyDataSeeder::TENANT_ID;
$now = Carbon::now();
$this->command->info('');
$this->command->info('📋 결재 데이터 생성...');
// 해당 테넌트의 사용자 ID 가져오기
$users = DB::table('user_tenants')
->where('tenant_id', $tenantId)
->pluck('user_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 [];
}
}
}