feat: 安全领取并分派采购任务 (#72)
This commit is contained in:
@@ -14,6 +14,7 @@ from src.admin_gateway import (
|
||||
ClientInfo,
|
||||
)
|
||||
from src.http_admin_gateway import HttpAdminGateway
|
||||
from src.task_models import TaskType
|
||||
|
||||
|
||||
class FakeResponse:
|
||||
@@ -88,7 +89,7 @@ class HttpAdminGatewayTest(unittest.TestCase):
|
||||
self.assertEqual(headers["authorization"], "Bearer secret-token")
|
||||
body = json.loads(opener.request.data.decode("utf-8"))
|
||||
self.assertEqual(body["client"]["name"], "办公室电脑")
|
||||
self.assertEqual(body["supported_types"], ["collect", "purchase"])
|
||||
self.assertEqual(body["supported_types"], ["collect"])
|
||||
self.assertEqual(body["device"]["platform"], "android")
|
||||
self.assertEqual(body["capabilities"]["purchase_mode"], "dry_run")
|
||||
self.assertEqual(opener.timeout, 2.5)
|
||||
@@ -218,7 +219,7 @@ class HttpAdminGatewayTest(unittest.TestCase):
|
||||
self.assertTrue(raised.exception.retryable)
|
||||
self.assertIn("可能已接收", str(raised.exception))
|
||||
|
||||
def test_claim_maps_real_admin_payload_and_only_reports_collect(self):
|
||||
def test_claim_maps_payload_and_serializes_confirmed_capabilities(self):
|
||||
opener = RecordingOpener(
|
||||
FakeResponse(
|
||||
200,
|
||||
@@ -267,6 +268,56 @@ class HttpAdminGatewayTest(unittest.TestCase):
|
||||
self.assertEqual(body["supported_types"], ["collect"])
|
||||
self.assertEqual(body["capabilities"]["purchase_mode"], "dry_run")
|
||||
|
||||
def test_claim_purchase_requires_all_safety_fields(self):
|
||||
valid_task = {
|
||||
"id": "PUR-001",
|
||||
"type": "purchase",
|
||||
"version": 1,
|
||||
"priority": 0,
|
||||
"payload": {
|
||||
"goods_url": "https://example.test/goods/PUR-001",
|
||||
"goods_id": "737116531267",
|
||||
"options": {"color": "黑色", "size": "L"},
|
||||
"quantity": 2,
|
||||
"max_price_cent": 4200,
|
||||
},
|
||||
"created_at": "2026-08-09T08:00:00Z",
|
||||
"updated_at": "2026-08-09T08:00:00Z",
|
||||
}
|
||||
gateway = HttpAdminGateway(
|
||||
opener=RecordingOpener(FakeResponse(200, {"task": valid_task}))
|
||||
)
|
||||
|
||||
task = gateway.claim_next(
|
||||
ClientInfo("CLIENT-001"),
|
||||
ClaimCapabilities(
|
||||
supported_types=(TaskType.COLLECT, TaskType.PURCHASE),
|
||||
purchase_mode="dry_run",
|
||||
),
|
||||
)
|
||||
|
||||
self.assertEqual(task.task_type, TaskType.PURCHASE)
|
||||
self.assertEqual(task.payload["max_price_cent"], 4200)
|
||||
|
||||
for missing in ("goods_id", "options", "quantity", "max_price_cent"):
|
||||
with self.subTest(missing=missing):
|
||||
invalid_task = dict(valid_task)
|
||||
invalid_payload = dict(valid_task["payload"])
|
||||
invalid_payload.pop(missing)
|
||||
invalid_task["payload"] = invalid_payload
|
||||
invalid_gateway = HttpAdminGateway(
|
||||
opener=RecordingOpener(
|
||||
FakeResponse(200, {"task": invalid_task})
|
||||
)
|
||||
)
|
||||
with self.assertRaises(AdminGatewayError) as raised:
|
||||
invalid_gateway.claim_next(
|
||||
ClientInfo("CLIENT-001"), self._capabilities()
|
||||
)
|
||||
self.assertEqual(
|
||||
raised.exception.code, "ADMIN_INVALID_RESPONSE"
|
||||
)
|
||||
|
||||
def test_claim_204_returns_none(self):
|
||||
gateway = HttpAdminGateway(opener=RecordingOpener(FakeResponse(204, {})))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user