'일일', self::WEEKLY => '주간', self::MONTHLY => '월간', self::BIMONTHLY => '2개월', self::QUARTERLY => '분기', self::SEMIANNUAL => '반년', ]; } /** * 주기별 라벨 반환 */ public static function label(string $cycle): string { return self::all()[$cycle] ?? $cycle; } /** * 주기별 기간 필터 타입 반환 */ public static function periodType(string $cycle): string { return $cycle === self::DAILY ? 'month' : 'year'; } /** * 주기별 그리드 열 라벨 반환 * * @return array [colIndex => label] */ public static function columnLabels(string $cycle, ?string $period = null): array { return match ($cycle) { self::DAILY => self::dailyLabels($period), self::WEEKLY => self::weeklyLabels(), self::MONTHLY => self::monthlyLabels(), self::BIMONTHLY => self::bimonthlyLabels(), self::QUARTERLY => self::quarterlyLabels(), self::SEMIANNUAL => self::semiannualLabels(), default => self::dailyLabels($period), }; } /** * 열 인덱스 → check_date 변환 */ public static function resolveCheckDate(string $cycle, string $period, int $colIndex): string { return match ($cycle) { self::DAILY => self::dailyCheckDate($period, $colIndex), self::WEEKLY => self::weeklyCheckDate($period, $colIndex), self::MONTHLY => self::monthlyCheckDate($period, $colIndex), self::BIMONTHLY => self::bimonthlyCheckDate($period, $colIndex), self::QUARTERLY => self::quarterlyCheckDate($period, $colIndex), self::SEMIANNUAL => self::semiannualCheckDate($period, $colIndex), default => self::dailyCheckDate($period, $colIndex), }; } /** * check_date → year_month(period) 역산 */ public static function resolvePeriod(string $cycle, string $checkDate): string { $date = Carbon::parse($checkDate); return match ($cycle) { self::DAILY => $date->format('Y-m'), self::WEEKLY => (string) $date->isoWeekYear, default => $date->format('Y'), }; } /** * 주기별 그리드 열 수 */ public static function columnCount(string $cycle, ?string $period = null): int { return count(self::columnLabels($cycle, $period)); } /** * 주말 여부 (daily 전용) */ public static function isWeekend(string $period, int $colIndex): bool { $date = Carbon::createFromFormat('Y-m', $period)->startOfMonth()->addDays($colIndex - 1); return in_array($date->dayOfWeek, [0, 6]); } /** * 해당 기간의 휴일 날짜 목록 반환 (date string Set) */ public static function getHolidayDates(string $cycle, string $period): array { $tenantId = session('selected_tenant_id', 1); if ($cycle === self::DAILY) { $start = Carbon::createFromFormat('Y-m', $period)->startOfMonth(); $end = $start->copy()->endOfMonth(); } else { $start = Carbon::create((int) $period, 1, 1); $end = Carbon::create((int) $period, 12, 31); } $holidays = \App\Models\System\Holiday::where('tenant_id', $tenantId) ->where('start_date', '<=', $end->toDateString()) ->where('end_date', '>=', $start->toDateString()) ->get(); $dates = []; foreach ($holidays as $holiday) { $hStart = $holiday->start_date->copy()->max($start); $hEnd = $holiday->end_date->copy()->min($end); $current = $hStart->copy(); while ($current->lte($hEnd)) { $dates[$current->format('Y-m-d')] = true; $current->addDay(); } } return $dates; } /** * 비근무일 여부 (주말 또는 휴일) */ public static function isNonWorkingDay(string $checkDate, array $holidayDates = []): bool { $date = Carbon::parse($checkDate); return $date->isWeekend() || isset($holidayDates[$checkDate]); } // --- Daily --- private static function dailyLabels(?string $period): array { $date = Carbon::createFromFormat('Y-m', $period ?? now()->format('Y-m')); $days = $date->daysInMonth; $labels = []; for ($d = 1; $d <= $days; $d++) { $labels[$d] = (string) $d; } return $labels; } private static function dailyCheckDate(string $period, int $colIndex): string { return Carbon::createFromFormat('Y-m', $period)->startOfMonth()->addDays($colIndex - 1)->format('Y-m-d'); } // --- Weekly --- private static function weeklyLabels(): array { $labels = []; for ($w = 1; $w <= 52; $w++) { $labels[$w] = $w.'주'; } return $labels; } private static function weeklyCheckDate(string $year, int $colIndex): string { // ISO 주차의 월요일 return Carbon::create((int) $year)->setISODate((int) $year, $colIndex, 1)->format('Y-m-d'); } // --- Monthly --- private static function monthlyLabels(): array { $labels = []; for ($m = 1; $m <= 12; $m++) { $labels[$m] = $m.'월'; } return $labels; } private static function monthlyCheckDate(string $year, int $colIndex): string { return Carbon::create((int) $year, $colIndex, 1)->format('Y-m-d'); } // --- Bimonthly --- private static function bimonthlyLabels(): array { return [ 1 => '1~2월', 2 => '3~4월', 3 => '5~6월', 4 => '7~8월', 5 => '9~10월', 6 => '11~12월', ]; } private static function bimonthlyCheckDate(string $year, int $colIndex): string { $month = ($colIndex - 1) * 2 + 1; return Carbon::create((int) $year, $month, 1)->format('Y-m-d'); } // --- Quarterly --- private static function quarterlyLabels(): array { return [ 1 => '1분기', 2 => '2분기', 3 => '3분기', 4 => '4분기', ]; } private static function quarterlyCheckDate(string $year, int $colIndex): string { $month = ($colIndex - 1) * 3 + 1; return Carbon::create((int) $year, $month, 1)->format('Y-m-d'); } // --- Semiannual --- private static function semiannualLabels(): array { return [ 1 => '상반기', 2 => '하반기', ]; } private static function semiannualCheckDate(string $year, int $colIndex): string { $month = $colIndex === 1 ? 1 : 7; return Carbon::create((int) $year, $month, 1)->format('Y-m-d'); } }