138 lines
4.1 KiB
Python
138 lines
4.1 KiB
Python
from __future__ import annotations
|
|
|
|
import importlib
|
|
import json
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from gyxx_flow.adapters import WORKFLOW_ACCEPTANCE_RECIPIENT_OPEN_ID
|
|
|
|
|
|
@pytest.fixture
|
|
def acceptance_environment(
|
|
tmp_path: Path,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> Path:
|
|
evidence = tmp_path / "evidence.jsonl"
|
|
monkeypatch.setenv("GYXX_WORKFLOW_ACCEPTANCE", "1")
|
|
monkeypatch.setenv("GYXX_FEISHU_TABLE_WRITE_DISABLED", "1")
|
|
monkeypatch.setenv("GYXX_COOKIE_INVALID_SKIP", "1")
|
|
monkeypatch.setenv(
|
|
"GYXX_NOTIFICATION_RECIPIENT_OPEN_ID",
|
|
WORKFLOW_ACCEPTANCE_RECIPIENT_OPEN_ID,
|
|
)
|
|
monkeypatch.setenv("GYXX_ACCEPTANCE_EVIDENCE_FILE", str(evidence))
|
|
return evidence
|
|
|
|
|
|
def test_replenishment_bitable_run_is_physically_skipped(
|
|
tmp_path: Path,
|
|
acceptance_environment: Path,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
module = importlib.import_module(
|
|
"gyxx_flow.modules.supply_chain.orchestrator.scripts."
|
|
"insert_replenishment_bitable"
|
|
)
|
|
pending = tmp_path / "pending_insert.json"
|
|
pending.write_text(
|
|
json.dumps(
|
|
{
|
|
"pending_count": 2,
|
|
"records": [
|
|
{"商品编号": "SKU1"},
|
|
{"商品编号": "SKU2"},
|
|
],
|
|
},
|
|
ensure_ascii=False,
|
|
),
|
|
encoding="utf-8",
|
|
)
|
|
monkeypatch.setattr(
|
|
module,
|
|
"_search_record_id_by_sku",
|
|
lambda *_args, **_kwargs: pytest.fail("must not access Feishu"),
|
|
)
|
|
|
|
result = module.run(pending)
|
|
|
|
assert result == {
|
|
"inserted": 0,
|
|
"updated": 0,
|
|
"skipped": 2,
|
|
"record_ids": [],
|
|
"errors": [],
|
|
"skipped_by_policy": True,
|
|
}
|
|
assert "feishu_write_skipped" in acceptance_environment.read_text(
|
|
encoding="utf-8"
|
|
)
|
|
|
|
|
|
def test_supply_card_sender_forces_only_wang_yunlong(
|
|
acceptance_environment: Path,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
module = importlib.import_module(
|
|
"gyxx_flow.modules.supply_chain.orchestrator.scripts."
|
|
"send_card_notification"
|
|
)
|
|
sent: list[str] = []
|
|
monkeypatch.setattr(module, "_get_tenant_token", lambda: "test-token")
|
|
monkeypatch.setattr(
|
|
module,
|
|
"_send_card",
|
|
lambda _token, open_id, _card: sent.append(open_id) or "mid-1",
|
|
)
|
|
|
|
result = module.run(["ou_other", "oc_group"], {"elements": []})
|
|
|
|
assert sent == [WORKFLOW_ACCEPTANCE_RECIPIENT_OPEN_ID]
|
|
assert result == {"message_ids": ["mid-1"], "errors": []}
|
|
|
|
|
|
def test_supply_config_uses_the_two_local_hermes_api_servers(
|
|
acceptance_environment: Path,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
monkeypatch.setenv(
|
|
"COLLECTOR_API_SERVER_URL",
|
|
"http://127.0.0.1:8643/v1/chat/completions",
|
|
)
|
|
monkeypatch.setenv(
|
|
"ANALYZER_API_SERVER_URL",
|
|
"http://127.0.0.1:8642/v1/chat/completions",
|
|
)
|
|
module = importlib.import_module(
|
|
"gyxx_flow.modules.supply_chain.orchestrator.config"
|
|
)
|
|
module = importlib.reload(module)
|
|
|
|
assert module.HERMES_GATEWAYS["collector"]["url"] == "http://127.0.0.1:8643/v1"
|
|
assert module.HERMES_GATEWAYS["collector"]["model"] == "data-collector"
|
|
assert module.HERMES_GATEWAYS["analyzer"]["url"] == "http://127.0.0.1:8642/v1"
|
|
assert module.HERMES_GATEWAYS["analyzer"]["model"] == "data-analyzer"
|
|
for targets in module.FEISHU_CONFIG["notification_targets"].values():
|
|
assert targets == [WORKFLOW_ACCEPTANCE_RECIPIENT_OPEN_ID]
|
|
|
|
|
|
def test_purchase_order_update_is_blocked_before_erp_mutation(
|
|
acceptance_environment: Path,
|
|
) -> None:
|
|
module = importlib.import_module(
|
|
"gyxx_flow.modules.supply_chain.orchestrator.mcp_workflow"
|
|
)
|
|
module = importlib.reload(module)
|
|
|
|
result = module.run_mcp_workflow(
|
|
"purchase-order-update",
|
|
"acceptance-purchase-order-update",
|
|
)
|
|
|
|
assert result["status"] == "blocked_business_mutation"
|
|
assert "approved test task/SKU fixture" in result["error"]
|
|
assert "business_mutation_blocked" in acceptance_environment.read_text(
|
|
encoding="utf-8"
|
|
)
|