"""Change C5 (Gitea issue 31): filing is blocked, not warned, while VISUAL still shows a work order open, on both routes. On a VISUAL packet the feed is the one writer of `vclosed`: it sets it when it sees every work order closed (the Clerical board then shows the packet under "Ready for data book") and clears it when one shows open again. The feed's observe step runs here on legs written by SQL. Nothing here reads VISUAL or M-Files.""" from __future__ import annotations from collections.abc import Iterator, Mapping from datetime import date from typing import Any import pytest from closehelpers import at_complete, file_packet, leg, q1, set_feed_legs from fakedir import FakeDirectory from pshelpers import app_conn, needs_pg from shophelpers import Shop, find_log, fresh, ok, open_shop, refused from packetstation.feed import apply from packetstation.feed.types import WoKey from packetstation.settings import Settings pytestmark = needs_pg W1 = WoKey("L670001", "001", "0", "0") W2 = WoKey("L670002", "001", "0", "0") OPEN_W2 = "VISUAL still shows work orders open on this packet: L670002/001. Filing waits until VISUAL closes them." @pytest.fixture def shop(pg_settings: Settings, fake_dir: FakeDirectory, dev_visual: None) -> Iterator[Shop]: yield from open_shop(pg_settings, fake_dir) def observe(settings: Settings, seen: Mapping[WoKey, str]) -> dict[str, Any]: """The feed's observe step for the given leg statuses. Returns the run's counts.""" with app_conn(settings) as conn: run = apply._Run(conn, None, None, None, date.today()) apply._observe(run, seen, None) return dict(run.counts) @pytest.mark.parametrize("route", ["databook", "shipping"]) def test_feed_closes_and_opens_a_visual_packet(shop: Shop, route: str) -> None: pkt = at_complete(shop, route=route) pid = pkt["id"] set_feed_legs(shop.settings, pid, [leg("L670001", st="R"), leg("L670002", st="R")]) c = shop("clerk.clara") # one leg closed: still open in VISUAL, nothing set counts = observe(shop.settings, {W1: "C", W2: "R"}) assert counts["closed_observed"] == 0 and counts["errors"] == 0, counts view = fresh(c, pid) assert view["vclosed"] is None and view["blocked"]["file"] == [OPEN_W2] # every leg closed: the feed sets vclosed (no person) and the file opens counts = observe(shop.settings, {W1: "C", W2: "C"}) assert counts["closed_observed"] == 1 and counts["errors"] == 0, counts view = fresh(c, pid) assert view["vclosed"]["at"] is not None and view["vclosed"]["by"] is None assert view["vclose_check"]["closed_at"] is not None and view["vclose_check"]["agrees"] is True assert "file" in view["can"] assert find_log(c, pid, "Closed in VISUAL (observed)") assert observe(shop.settings, {W1: "C", W2: "C"})["closed_observed"] == 0 # nothing changed: no write # a leg open again: the feed clears it and the file waits observe(shop.settings, {W1: "C", W2: "R"}) view = fresh(c, pid) assert view["vclosed"] is None and view["vclose_check"]["closed_at"] is None assert view["blocked"]["file"] == [OPEN_W2] assert find_log(c, pid, "Open again in VISUAL (observed)")["note"] == "L670002/001" refused(file_packet(shop, view), 403, "precondition", OPEN_W2) # closed and cancelled count as done assert observe(shop.settings, {W1: "C", W2: "X"})["closed_observed"] == 1 out = ok(file_packet(shop, fresh(c, pid))) assert out["status"] == "filed" and out["vclosed"]["by"] is None # the feed leaves a filed packet alone observe(shop.settings, {W1: "R", W2: "R"}) assert q1(shop.settings, "SELECT vclosed_at IS NOT NULL FROM packets WHERE id = %s", (pid,))[0] is True