@@ -11,6 +11,7 @@ from zoneinfo import ZoneInfo
from agent . policy . deal_followup import (
SHANGHAI ,
air_route_keys ,
is_workday ,
leader_matches ,
next_followup_at ,
shift_workdays ,
@@ -20,33 +21,42 @@ from agent.policy.deal_followup import (
class TestWorkdays ( unittest . TestCase ) :
def test_skip_weekend ( self ) - > None :
# 2026-09 -18 周五,顺延 3 个工作日 → 21、22、23,第四个工作日 24
self . assertEqual ( shift_workdays ( date ( 2026 , 9 , 18 ) , 3 ) , date ( 2026 , 9 , 23 ) )
self . assertEqual ( shift_workdays ( date ( 2026 , 9 , 18 ) , 4 ) , date ( 2026 , 9 , 24 ) )
# 普通周末仍跳过。 2026-11 -13 周五 → 16、17、18 三个工作日,第四个是 19 日。
self . assertEqual ( shift_workdays ( date ( 2026 , 11 , 13 ) , 3 ) , date ( 2026 , 11 , 18 ) )
self . assertEqual ( shift_workdays ( date ( 2026 , 11 , 13 ) , 4 ) , date ( 2026 , 11 , 19 ) )
def test_sept20_makeup_pulls_followup_forward ( self ) - > None :
# 2026-09-18 周五。9 月 20 日周日调休上班,第四个工作日是 23 日,不是 24 日。
self . assertEqual ( shift_workdays ( date ( 2026 , 9 , 18 ) , 4 ) , date ( 2026 , 9 , 23 ) )
def test_skip_national_day ( self ) - > None :
# 2026-09-30 周三,国庆休 → 第四个工作日落到节后
# 2026-09-30 周三。10 月 1–7 日放假,8 日上班,10 日周六调休。
# 节后第 1 个工作日 8 日,第 4 个是 12 日周一。
fourth = shift_workdays ( date ( 2026 , 9 , 30 ) , 4 )
self . assertGreaterEqual ( fourth , date ( 2026 , 10 , 9 ) )
self . assertNotEqual ( fourth . weekday ( ) , 5 )
self . assertNotEqual ( fourth . weekday ( ) , 6 )
self . assertEqual ( fourth , date ( 2026 , 10 , 12 ) )
def test_oct8_works_and_sept20_is_makeup ( self ) - > None :
# 国办发明电〔2025〕7号:10 月 8 日正常上班,9 月 20 日周日调休上班。
self . assertTrue ( is_workday ( date ( 2026 , 10 , 8 ) ) )
self . assertTrue ( is_workday ( date ( 2026 , 9 , 20 ) ) )
self . assertFalse ( is_workday ( date ( 2026 , 10 , 7 ) ) )
def test_next_followup_is_9am ( self ) - > None :
when = next_followup_at ( datetime ( 2026 , 9 , 18 , 15 , 30 , tzinfo = SHANGHAI ) )
self . assertEqual ( when . hour , 9 )
self . assertEqual ( when . minute , 0 )
self . assertEqual ( when . tzinfo , SHANGHAI )
self . assertEqual ( when . date ( ) , date ( 2026 , 9 , 24 ) )
self . assertEqual ( when . date ( ) , date ( 2026 , 9 , 23 ) )
def test_skip_weekend_keep_weekday_night ( self ) - > None :
start = datetime ( 2026 , 9 , 18 , 17 , 0 , tzinfo = SHANGHAI ) # 周五
now = datetime ( 2026 , 9 , 21 , 17 , 0 , tzinfo = SHANGHAI ) # 周一
start = datetime ( 2026 , 11 , 13 , 17 , 0 , tzinfo = SHANGHAI ) # 周五
now = datetime ( 2026 , 11 , 16 , 17 , 0 , tzinfo = SHANGHAI ) # 周一
# 周五 17–24 = 7h,周末不算,周一 0– 17 = 17h
self . assertAlmostEqual ( workday_elapsed_hours ( start , now ) , 24.0 , places = 4 )
def test_rest_day_start_counts_from_next_workday ( self ) - > None :
start = datetime ( 2026 , 9 , 19 , 10 , 0 , tzinfo = SHANGHAI ) # 周六
now = datetime ( 2026 , 9 , 21 , 10 , 0 , tzinfo = SHANGHAI ) # 周一
start = datetime ( 2026 , 11 , 14 , 10 , 0 , tzinfo = SHANGHAI ) # 周六
now = datetime ( 2026 , 11 , 16 , 10 , 0 , tzinfo = SHANGHAI ) # 周一
self . assertAlmostEqual ( workday_elapsed_hours ( start , now ) , 10.0 , places = 4 )
def test_fractional_quarter_hour ( self ) - > None :