From 47296dd35bb52478a1d4a7a63340c607423bbc75 Mon Sep 17 00:00:00 2001 From: KINDNICK Date: Fri, 1 May 2026 13:13:01 +0900 Subject: [PATCH] v2.9.0: \ud734\uc77c hot-path \uc218\uc815 + \uc5f0\ucc28 \ubbf8\ub9ac\ub4f1\ub85d + \ubc18\ubcf5 \ud328\ud134 + \uadfc\ub85c\uc790\uc758\ub0a0 \ucd94\uac00 \uc0ac\uc6a9\uc790 \ubcf4\uace0: \ud734\uc77c\uc5d0 \ucd9c\uadfc\ud574\ub3c4 \uc815\uc0c1 \ucd9c\uadfc\uc73c\ub85c \ucc98\ub9ac\ub418\uc5b4 \ucd94\uac00\uadfc\ubb34 \uc801\ub9bd \uc548\ub428. - update_display() 1Hz \ub8e8\ud504\uc5d0 is_non_working_day \ubd84\uae30 \ub204\ub77d\uc774 \uc6d0\uc778 (d41e5cb) - \uc5f0\ucc28 \ubbf8\ub9ac\ub4f1\ub85d \uc2dc\uc2a4\ud15c\uacfc \ud568\uaed8 v2.9.0\uc73c\ub85c \ud1b5\ud569 \ub9b4\ub9ac\uc2a4 (c98ca36) - holidays.KR\uc774 \uc54a \uc7a1\ub294 \uadfc\ub85c\uc790\uc758 \ub0a0(5/1) \uba85\uc2dc\uc801 \uc790\ub3d9 \ucd94\uac00 \ub9b4\ub9ac\uc2a4 \uadf8\ub8f9: 122\u2192175 pytest, 48\u219253 \ud1b5\ud569 \uc2dc\ub098\ub9ac\uc624 (\uc0c1\uc138 CHANGELOG \ucc38\uc870) --- CHANGELOG.md | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ core/database.py | 9 +++++++++ core/version.py | 2 +- 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 616fa2e..381bfd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,54 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). +## [2.9.0] — 2026-05-01 + +### Fixed — 휴일 hot-path 버그 (사용자 보고) +- **휴일에 출근해도 정상 출근으로 처리되어 추가근무 적립이 안 되던 문제** + - `update_display()` 1Hz 루프에 `is_non_working_day` 분기 누락으로 휴일에도 + "남은 시간 8h"부터 카운트다운 → 실제 출근 즉시 적립이 시작되지 않음 + - 수정: 출근 직후부터 음수 remaining 표시, "공휴일 근무 (전체 적립)" 그룹 타이틀 + - 진행바: 휴일은 100% 고정 (의미 없음) + - 예상 퇴근: "휴일 근무 (정해진 퇴근시각 없음)" +- **휴일 "퇴근 30분 전" 알림 게이팅** — 휴일엔 정해진 퇴근시각이 없으니 무의미한 알림 스킵 +- **자동복구 퇴근 3곳의 `// 30) * 30` 하드코딩** → 사용자 `overtime_unit` (15/30/60) 설정 적용 +- 4곳에 중복되던 휴일 연장 계산 로직을 `TimeCalculator.calculate_holiday_overtime()` 헬퍼로 통합 + +### Added — 연차 미리등록 + 통합 스케줄 + 반복 연차 (Phase 1+2) + +#### Phase 1 — 연차 미리등록 + 자동 적용 +- **DB:** `get_leave_minutes_for(date)` / `has_full_day_leave(date)` / + `get_leave_records_by_date(date)` / `get_leave_records_by_range(start, end)` +- **TimeCalculator:** `effective_work_minutes(date_obj, db)` — 부분 연차만큼 정규 근무 차감 +- **종일 연차일 자동 처리:** + - 자동 출근감지 스킵 (event_monitor 호출 안 함) + - "🌴 오늘은 휴가" 카드 표시, 카운트다운 제거 + - 메인/미니 위젯/트레이 모두 일관된 휴가 상태 표시 +- **종일 연차 + 출근 override:** 휴일처럼 전체 시간 적립 (사용자 확인 후) +- **부분 연차 (반차/반반차/시간):** 기존 leave_used 경로로 카운트다운 단축 +- **AddLeaveDialog 검증 강화:** 미래 1년 setMaximumDate / 주말·공휴일 차단 / 같은 날 1일 초과 차단 +- **leave_calendar_view:** 예정(파랑) / 사용완료(녹·노·보) 색상 분리 + +#### Phase 2 — 통합 스케줄 + 반복 연차 +- **`recurring_leaves` 테이블** (pattern/leave_type/days/start_date/end_date/memo) +- **`core/recurring_leaves.py`:** weekly / biweekly / monthly 패턴 파서 + expand_for_range/date +- **자동 합산:** `get_leave_minutes_for()` / `has_full_day_leave()`가 반복 패턴 인스턴스도 함께 검사 +- **`ui/recurring_leave_dialog.py`:** 매주/격주 요일 또는 매월 N일 입력 +- **`ui/schedule_view.py`:** 월간 통합 캘린더 (휴일·연차·반복 색상 구분 + 우클릭 삭제) +- **진입점:** MainWindow.show_schedule(), 트레이 "🗓️ 스케줄", LeaveView "🗓️ 스케줄" + +### Changed +- **근로자의 날(5/1) 자동 추가** — `holidays.KR` 패키지가 누락하는 노동자 휴일을 + `add_korean_holidays_auto()`에서 명시적 보강 (매년 반복) + +### Tests +- pytest: 122 → **175** (+53) + - `tests/test_recurring_leaves.py` 32개 (패턴 파싱/매칭/expand/describe) + - `tests/test_database.py` +12 (TestLeaveQueriesByDate + TestRecurringLeavesDB) + - `tests/test_time_calculator.py` +9 (TestHolidayOvertime) +- 통합 시나리오: 48 → **53** (+5) + - S52A 휴일 hot-path / S52B 종일 연차 / S52C 반복 패턴 / S52D 반차 effective / S52E 종일 effective + ## [2.8.0] — 2026-05-01 ### Added — 도전과제 시스템 + 디자인 리뉴얼 diff --git a/core/database.py b/core/database.py index 1afa3ef..6aacc89 100644 --- a/core/database.py +++ b/core/database.py @@ -1758,6 +1758,15 @@ class Database: if not self.is_holiday(date_str): self.add_holiday(date_str, name, is_recurring=False) added += 1 + + # holidays.KR이 누락하는 한국 노동자 휴일 보강. + # 근로자의 날(5/1)은 공식 '공휴일'은 아니지만 대부분 회사가 휴무. + # 패키지 버전마다 포함 여부가 달라서 명시적 추가. + extra = [(f"{y}-05-01", "근로자의 날")] + for date_str, name in extra: + if not self.is_holiday(date_str): + self.add_holiday(date_str, name, is_recurring=True) + added += 1 return added def copy_recurring_holidays(self, from_year: int, to_year: int): diff --git a/core/version.py b/core/version.py index 16f5c67..7cbc8fd 100644 --- a/core/version.py +++ b/core/version.py @@ -4,4 +4,4 @@ 릴리스 시 이 값을 올린 후 git tag → push. CHANGELOG.md의 최상단 항목과 일치시킬 것. """ -__version__ = '2.8.0' +__version__ = '2.9.0'