- 급여 관리 API 추가 (SalaryController, SalaryService, Salary 모델) - 급여 목록/상세/등록/수정/삭제 - 상태 변경 (scheduled/completed) - 일괄 상태 변경 - 통계 조회 - 더미 시더 확장 - 근태, 휴가, 부서, 사용자 시더 추가 - 기존 시더 tenant_id/created_by/updated_by 필드 추가 - 부서 서비스 개선 (tree 조회 기능 추가) - 카드 서비스 수정 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
135 lines
4.3 KiB
PHP
135 lines
4.3 KiB
PHP
<?php
|
|
|
|
namespace Database\Seeders\Dummy;
|
|
|
|
use App\Models\Tenants\Leave;
|
|
use Database\Seeders\DummyDataSeeder;
|
|
use Illuminate\Database\Seeder;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class DummyLeaveSeeder extends Seeder
|
|
{
|
|
public function run(): void
|
|
{
|
|
$tenantId = DummyDataSeeder::TENANT_ID;
|
|
$userId = DummyDataSeeder::USER_ID;
|
|
|
|
// 테넌트 소속 사용자 조회
|
|
$userIds = DB::table('user_tenants')
|
|
->where('tenant_id', $tenantId)
|
|
->pluck('user_id')
|
|
->toArray();
|
|
|
|
if (empty($userIds)) {
|
|
$this->command->warn(' ⚠ leaves: 사용자가 없습니다');
|
|
return;
|
|
}
|
|
|
|
// 휴가 유형 (가중치)
|
|
$leaveTypes = [
|
|
'annual' => 50, // 연차 50%
|
|
'half_am' => 15, // 오전 반차 15%
|
|
'half_pm' => 15, // 오후 반차 15%
|
|
'sick' => 10, // 병가 10%
|
|
'family' => 5, // 경조사 5%
|
|
'other' => 5, // 기타 5%
|
|
];
|
|
|
|
// 상태 (가중치)
|
|
$statuses = [
|
|
'approved' => 60, // 승인 60%
|
|
'pending' => 25, // 대기 25%
|
|
'rejected' => 10, // 반려 10%
|
|
'cancelled' => 5, // 취소 5%
|
|
];
|
|
|
|
$count = 0;
|
|
$year = 2025;
|
|
|
|
// 사용자별로 1~4건의 휴가 생성
|
|
foreach ($userIds as $uId) {
|
|
$leaveCount = rand(1, 4);
|
|
|
|
for ($i = 0; $i < $leaveCount; $i++) {
|
|
$month = rand(1, 12);
|
|
$day = rand(1, 28);
|
|
$startDate = sprintf('%04d-%02d-%02d', $year, $month, $day);
|
|
|
|
$leaveType = $this->getRandomWeighted($leaveTypes);
|
|
$status = $this->getRandomWeighted($statuses);
|
|
|
|
// 휴가 일수 결정
|
|
if (in_array($leaveType, ['half_am', 'half_pm'])) {
|
|
$days = 0.5;
|
|
$endDate = $startDate;
|
|
} else {
|
|
$days = rand(1, 3);
|
|
$endDate = date('Y-m-d', strtotime($startDate . ' + ' . ($days - 1) . ' days'));
|
|
}
|
|
|
|
// 승인자 정보
|
|
$approvedBy = null;
|
|
$approvedAt = null;
|
|
$rejectReason = null;
|
|
|
|
if ($status === 'approved') {
|
|
$approvedBy = $userId;
|
|
$approvedAt = date('Y-m-d H:i:s', strtotime($startDate . ' - 2 days'));
|
|
} elseif ($status === 'rejected') {
|
|
$approvedBy = $userId;
|
|
$approvedAt = date('Y-m-d H:i:s', strtotime($startDate . ' - 2 days'));
|
|
$rejectReason = '업무 일정 상 불가';
|
|
}
|
|
|
|
Leave::create([
|
|
'tenant_id' => $tenantId,
|
|
'user_id' => $uId,
|
|
'leave_type' => $leaveType,
|
|
'start_date' => $startDate,
|
|
'end_date' => $endDate,
|
|
'days' => $days,
|
|
'reason' => $this->getLeaveReason($leaveType),
|
|
'status' => $status,
|
|
'approved_by' => $approvedBy,
|
|
'approved_at' => $approvedAt,
|
|
'reject_reason' => $rejectReason,
|
|
'created_by' => $uId,
|
|
]);
|
|
|
|
$count++;
|
|
}
|
|
}
|
|
|
|
$this->command->info(' ✓ leaves: ' . $count . '건 생성');
|
|
}
|
|
|
|
private function getRandomWeighted(array $weights): string
|
|
{
|
|
$total = array_sum($weights);
|
|
$rand = rand(1, $total);
|
|
$cumulative = 0;
|
|
|
|
foreach ($weights as $key => $weight) {
|
|
$cumulative += $weight;
|
|
if ($rand <= $cumulative) {
|
|
return $key;
|
|
}
|
|
}
|
|
|
|
return array_key_first($weights);
|
|
}
|
|
|
|
private function getLeaveReason(string $type): string
|
|
{
|
|
return match ($type) {
|
|
'annual' => '개인 휴가',
|
|
'half_am' => '오전 병원 방문',
|
|
'half_pm' => '오후 개인 일정',
|
|
'sick' => '건강 사유',
|
|
'family' => '가족 행사',
|
|
'maternity' => '출산 휴가',
|
|
'parental' => '육아 휴직',
|
|
default => '개인 사유',
|
|
};
|
|
}
|
|
} |