162 lines
5.2 KiB
Python
162 lines
5.2 KiB
Python
"""
|
||
成交跟进:工作日顺延、线路对负责人、未成交收下原因(不打外网)。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import unittest
|
||
from datetime import date, datetime
|
||
from zoneinfo import ZoneInfo
|
||
|
||
from agent.policy.deal_followup import (
|
||
SHANGHAI,
|
||
air_route_keys,
|
||
leader_matches,
|
||
next_followup_at,
|
||
shift_workdays,
|
||
workday_elapsed_hours,
|
||
)
|
||
|
||
|
||
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))
|
||
|
||
def test_skip_national_day(self) -> None:
|
||
# 2026-09-30 周三,国庆休 → 第四个工作日落到节后
|
||
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)
|
||
|
||
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))
|
||
|
||
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) # 周一
|
||
# 周五 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) # 周一
|
||
self.assertAlmostEqual(workday_elapsed_hours(start, now), 10.0, places=4)
|
||
|
||
def test_fractional_quarter_hour(self) -> None:
|
||
start = datetime(2026, 9, 18, 9, 0, tzinfo=SHANGHAI)
|
||
now = datetime(2026, 9, 18, 9, 15, tzinfo=SHANGHAI)
|
||
self.assertAlmostEqual(workday_elapsed_hours(start, now), 0.25, places=4)
|
||
|
||
|
||
class TestAirRouteKeys(unittest.TestCase):
|
||
def test_pair_and_dest(self) -> None:
|
||
keys = air_route_keys({"起运港": "SZX", "目的港": "KUL"})
|
||
self.assertIn("SZX-KUL", keys)
|
||
self.assertIn("KUL", keys)
|
||
|
||
def test_chinese_city_projects_iata(self) -> None:
|
||
keys = air_route_keys({"起运港": "深圳", "目的港": "吉隆坡"})
|
||
self.assertIn("SZX-KUL", keys)
|
||
self.assertIn("KUL", keys)
|
||
|
||
|
||
class TestLeaderMatch(unittest.TestCase):
|
||
def test_sea_all_line(self) -> None:
|
||
self.assertTrue(
|
||
leader_matches(
|
||
role_code="sea",
|
||
routes="海运全线",
|
||
is_leader=True,
|
||
business_line="SEA",
|
||
facts={},
|
||
)
|
||
)
|
||
self.assertFalse(
|
||
leader_matches(
|
||
role_code="sea",
|
||
routes="海运全线",
|
||
is_leader=False,
|
||
business_line="SEA",
|
||
facts={},
|
||
)
|
||
)
|
||
|
||
def test_land_route_category(self) -> None:
|
||
self.assertTrue(
|
||
leader_matches(
|
||
role_code="land",
|
||
routes="国内长途/零担,东南亚",
|
||
is_leader=True,
|
||
business_line="LAND",
|
||
facts={"线路类别": "国内长途/零担"},
|
||
)
|
||
)
|
||
self.assertFalse(
|
||
leader_matches(
|
||
role_code="land",
|
||
routes="东南亚",
|
||
is_leader=True,
|
||
business_line="LAND",
|
||
facts={"线路类别": "国内长途/零担"},
|
||
)
|
||
)
|
||
|
||
def test_air_pair_dest_and_all(self) -> None:
|
||
facts = {"起运港": "SZX", "目的港": "KUL"}
|
||
self.assertTrue(
|
||
leader_matches(
|
||
role_code="air",
|
||
routes="SZX-KUL",
|
||
is_leader=True,
|
||
business_line="AIR",
|
||
facts=facts,
|
||
)
|
||
)
|
||
self.assertTrue(
|
||
leader_matches(
|
||
role_code="air",
|
||
routes="KUL",
|
||
is_leader=True,
|
||
business_line="AIR",
|
||
facts=facts,
|
||
)
|
||
)
|
||
self.assertTrue(
|
||
leader_matches(
|
||
role_code="air",
|
||
routes="全线",
|
||
is_leader=True,
|
||
business_line="AIR",
|
||
facts=facts,
|
||
)
|
||
)
|
||
self.assertFalse(
|
||
leader_matches(
|
||
role_code="air",
|
||
routes="外采-空运",
|
||
is_leader=True,
|
||
business_line="AIR",
|
||
facts=facts,
|
||
)
|
||
)
|
||
self.assertTrue(
|
||
leader_matches(
|
||
role_code="air",
|
||
routes="外采-空运",
|
||
is_leader=True,
|
||
business_line="AIR",
|
||
facts={**facts, "外采": "1"},
|
||
)
|
||
)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
unittest.main()
|