fix: finalize Flow v2 authoritative cutover semantics
This commit is contained in:
@@ -50,9 +50,30 @@ def test_due_and_future_customer_followup_semantics():
|
||||
assert (due.effective_action, due.queue) == ("FOLLOW_UP_CUSTOMER_REVIEW", "do_now")
|
||||
future = decide_authoritative_operation(projection(), obligations=[task("FOLLOW_UP_CUSTOMER_REVIEW", NOW + timedelta(days=1))], now=NOW)
|
||||
assert (future.effective_action, future.queue) == (None, "waiting")
|
||||
future_item = canonicalize_operations([{
|
||||
"source": "flow_v2", "id": "opp", "opportunity_id": "opp",
|
||||
"status": "projected", "action_code": "WAIT_CUSTOMER", "created_at": NOW,
|
||||
}], {"opp": future.to_dict()})["items"]
|
||||
assert len(future_item) == 1 and future_item[0]["operational_queue"] == "waiting"
|
||||
assert decide_authoritative_operation(projection(), now=NOW).queue == "waiting"
|
||||
|
||||
|
||||
def test_unanswered_send_info_remains_valid_on_awaiting_customer():
|
||||
inbound = NOW - timedelta(hours=2)
|
||||
obligation = task("SEND_INFO", latest_public_inbound=inbound, latest_public_outbound=None)
|
||||
got = decide_authoritative_operation(projection(), obligations=[obligation], now=NOW)
|
||||
assert (got.effective_action, got.queue, got.reason_code) == (
|
||||
"SEND_INFO", "do_now", "ACTIVE_RESPONSE_OBLIGATION")
|
||||
|
||||
|
||||
def test_send_info_satisfied_by_later_outbound_is_not_current():
|
||||
inbound = NOW - timedelta(hours=2)
|
||||
obligation = task("SEND_INFO", latest_public_inbound=inbound,
|
||||
latest_public_outbound=inbound + timedelta(minutes=10))
|
||||
got = decide_authoritative_operation(projection(), obligations=[obligation], now=NOW)
|
||||
assert (got.effective_action, got.queue) == (None, "waiting")
|
||||
|
||||
|
||||
def test_only_active_non_superseded_tasks_override_and_precedence():
|
||||
stale = task("SUPPORT", resolved_at=NOW)
|
||||
assert decide_authoritative_operation(projection("PROFORMA_REQUIRED", "CREATE_PROFORMA"), obligations=[stale], now=NOW).effective_action == "CREATE_PROFORMA"
|
||||
@@ -81,6 +102,18 @@ def test_duplicate_is_suppressed_even_with_pending_legacy_task():
|
||||
assert canonicalize_operations([source], {"opp": decision})["items"] == []
|
||||
|
||||
|
||||
def test_xmat_duplicate_suppresses_diagnostic_review_business_action():
|
||||
got = decide_authoritative_operation({
|
||||
**projection("REVIEW_REQUIRED", "REVIEW_REQUIRED"),
|
||||
"opportunity_id": "1816a06e-9a69-4a9b-9279-1263156892d3",
|
||||
"canonical_opportunity_id": "dc89a466-db24-401b-bfe9-d47644b2d0c8",
|
||||
"is_duplicate_representation": True,
|
||||
}, now=NOW).to_dict()
|
||||
assert got["business_next_action"] == "REVIEW_REQUIRED"
|
||||
assert got["effective_action"] is None and got["suppress_current_card"] is True
|
||||
assert got["canonical_opportunity_id"] == "dc89a466-db24-401b-bfe9-d47644b2d0c8"
|
||||
|
||||
|
||||
def test_authoritative_queue_and_action_survive_canonical_boundary():
|
||||
decision = decide_authoritative_operation(projection(), obligations=[task("FOLLOW_UP_CUSTOMER_REVIEW")], now=NOW).to_dict()
|
||||
source = {"source": "task", "id": "old", "status": "pending", "action_code": "SEND_INVOICE",
|
||||
|
||||
Reference in New Issue
Block a user