Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/api/v1/orchestrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,8 @@ async def assess_and_record(
result = await _orchestrate_or_http(db, llm_client, base)

live = (await db.execute(_QUERY_LIVE_STATE, {"call_sign": request.call_sign})).mappings().first()
stage = stage_from_nav_status(live["nav_status_code"] if live else None)
stage = stage_from_nav_status(live["nav_status_code"] if live else None,
target_source=result.target_source)
port_call_key = request.port_call_key or (
await db.execute(_QUERY_CURRENT_CALL_KEY, {"call_sign": request.call_sign})
).scalar()
Expand Down
13 changes: 10 additions & 3 deletions app/services/assessment.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,18 @@
# AIS 항해상태 하나만 본다. PORT-MIS 를 쓰지 않는 이유는 모델 주석 참고
# (수집창 [어제, 오늘+3일] 밖이면 동결 — 2026-09-21 실측 79척 중 32척).

def stage_from_nav_status(nav_status_code: str | None) -> AssessmentStage | None:
"""UPA 항해상태 → 시점. 상태를 모르면 None(= 판정불가로 기록)."""
def stage_from_nav_status(
nav_status_code: str | None, *, target_source: str | None = None,
) -> AssessmentStage | None:
"""UPA 항해상태 → 시점. 상태를 모르면 None(= 판정불가로 기록).

[2026-09-29] 상태가 없어도 판정 대상이 PORT-MIS 배정 선석이면 입항 전이다 — 아직 AIS 에
잡히지 않은 배다. 예전엔 None 이 되어 '입항전'으로 기록되면서도 조치안·받는 곳이 비었다
(운영 308 HYODONG CHEMI, [판정 요청] 경로).
"""
nav = (nav_status_code or "").strip()
if not nav:
return None
return AssessmentStage.BEFORE_ARRIVAL if target_source == "PORT-MIS" else None
if nav.startswith("정박(계류)"):
return AssessmentStage.DURING_CARGO
if nav.startswith("정박(앵커링)"):
Expand Down
30 changes: 30 additions & 0 deletions tests/test_stage_before_arrival_20260929.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""AIS 항해상태가 없는 입항 전 배의 시점 (2026-09-29).

입항 목록에서 [판정 요청]한 배는 아직 AIS 에 잡히지 않아 항해상태가 없다. 예전엔 시점이
None 이 되어 '입항전'으로 기록되면서도 조치안·받는 곳이 비었다(운영 308 HYODONG CHEMI).
판정 대상이 PORT-MIS 배정 선석이면 아직 붙지 않은 배이므로 입항 전으로 본다.
"""
from app.models.assessment_history import AssessmentLevel, AssessmentStage
from app.services.assessment import _action_for, _RECIPIENT_BY_STAGE, stage_from_nav_status


def test_no_ais_with_portmis_target_is_before_arrival():
assert stage_from_nav_status(None, target_source="PORT-MIS") is AssessmentStage.BEFORE_ARRIVAL
assert stage_from_nav_status(" ", target_source="PORT-MIS") is AssessmentStage.BEFORE_ARRIVAL


def test_no_ais_without_portmis_target_stays_unknown():
# AIS 로 접안한 배인데 상태가 없거나, 대상 출처를 모르면 여전히 모른다.
assert stage_from_nav_status(None) is None
assert stage_from_nav_status(None, target_source="AIS") is None


def test_nav_status_wins_over_target_source():
assert stage_from_nav_status("정박(계류)", target_source="PORT-MIS") is AssessmentStage.DURING_CARGO


def test_unfit_before_arrival_gets_action_and_berth_operator():
stage = stage_from_nav_status(None, target_source="PORT-MIS")
action = _action_for(AssessmentLevel.UNFIT, stage)
assert action is not None and action.value == "대체선석"
assert _RECIPIENT_BY_STAGE[stage].value == "선석운영주체"
Loading