更新登录页及优化相关功能
This commit is contained in:
@@ -2,7 +2,7 @@ import hashlib
|
||||
import inspect
|
||||
import json
|
||||
import unittest
|
||||
from datetime import datetime
|
||||
from datetime import date, datetime
|
||||
from types import SimpleNamespace
|
||||
from typing import Any, get_type_hints
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
@@ -60,7 +60,7 @@ def make_page(
|
||||
strain_id: int = 11,
|
||||
batch_no: str = 'B-20260726',
|
||||
package_spec: str = '20kg',
|
||||
initial_packages: int = 18,
|
||||
initial_packages: int = 100,
|
||||
idempotency_key: str = 'fill-key',
|
||||
) -> FillingCreateModel:
|
||||
return FillingCreateModel(
|
||||
@@ -68,6 +68,8 @@ def make_page(
|
||||
warehouseId=warehouse_id,
|
||||
strainId=strain_id,
|
||||
batchNo=batch_no,
|
||||
productionDate='2026-07-20',
|
||||
expiryDate='2027-01-20',
|
||||
packageSpec=package_spec,
|
||||
initialPackages=initial_packages,
|
||||
idempotencyKey=idempotency_key,
|
||||
@@ -78,7 +80,7 @@ def make_pallet(
|
||||
pallet_id: int = 2,
|
||||
*,
|
||||
qr_token: str = 'qr-2',
|
||||
capacity_packages: int = 20,
|
||||
capacity_packages: int = 100,
|
||||
asset_status: str = '0',
|
||||
test_batch_id: int | None = None,
|
||||
) -> BizPallet:
|
||||
@@ -200,7 +202,9 @@ class TestFillingPublicContract(unittest.TestCase):
|
||||
expected_payload = json.dumps(
|
||||
{
|
||||
'batch_no': 'B-20260726',
|
||||
'initial_packages': 18,
|
||||
'production_date': '2026-07-20',
|
||||
'expiry_date': '2027-01-20',
|
||||
'initial_packages': 100,
|
||||
'package_spec': '20kg',
|
||||
'qr_token': 'qr-2',
|
||||
'strain_id': 11,
|
||||
@@ -364,7 +368,7 @@ class TestFillingReadServices(unittest.IsolatedAsyncioTestCase):
|
||||
self.db.commit.assert_not_awaited()
|
||||
self.assertEqual(PalletFlowState.EMPTY_IN_WAREHOUSE, result.flow_state)
|
||||
self.assertEqual(['filling'], result.allowed_actions)
|
||||
self.assertEqual(20, result.capacity_packages)
|
||||
self.assertEqual(100, result.capacity_packages)
|
||||
self.assertEqual(0, result.remaining_packages)
|
||||
|
||||
async def test_scan_checks_access_before_exposing_invalid_state(self) -> None:
|
||||
@@ -534,8 +538,10 @@ class TestFillPalletService(unittest.IsolatedAsyncioTestCase):
|
||||
self.assertEqual('S-011', filling.strain_code_snapshot)
|
||||
self.assertEqual('香菇 11', filling.strain_name_snapshot)
|
||||
self.assertEqual('B-20260726', filling.batch_no)
|
||||
self.assertEqual(date(2026, 7, 20), filling.production_date)
|
||||
self.assertEqual(date(2027, 1, 20), filling.expiry_date)
|
||||
self.assertEqual('20kg', filling.package_spec)
|
||||
self.assertEqual(18, filling.initial_packages)
|
||||
self.assertEqual(100, filling.initial_packages)
|
||||
self.assertEqual('ACTIVE', filling.active_slot)
|
||||
self.assertEqual('fill-key', filling.idempotency_key)
|
||||
self.assertEqual(FillingService._build_request_hash(self.page), filling.request_hash)
|
||||
@@ -547,7 +553,7 @@ class TestFillPalletService(unittest.IsolatedAsyncioTestCase):
|
||||
self.assertEqual(self.fixed_time, filling.update_time)
|
||||
|
||||
self.assertEqual(31, self.inventory.active_filling_id)
|
||||
self.assertEqual(18, self.inventory.remaining_packages)
|
||||
self.assertEqual(100, self.inventory.remaining_packages)
|
||||
self.assertEqual(PalletFlowState.FILLED_IN_WAREHOUSE.value, self.inventory.flow_state)
|
||||
self.assertEqual(4, self.inventory.version)
|
||||
self.assertEqual(self.fixed_time, self.inventory.updated_at)
|
||||
@@ -566,7 +572,7 @@ class TestFillPalletService(unittest.IsolatedAsyncioTestCase):
|
||||
self.assertIsNone(event.before_line_id)
|
||||
self.assertIsNone(event.after_line_id)
|
||||
self.assertEqual(0, event.before_remaining_packages)
|
||||
self.assertEqual(18, event.after_remaining_packages)
|
||||
self.assertEqual(100, event.after_remaining_packages)
|
||||
self.assertEqual(7, event.operator_id)
|
||||
self.assertEqual(self.fixed_time, event.occurred_at)
|
||||
self.assertEqual('fill-key', event.idempotency_key)
|
||||
@@ -632,8 +638,8 @@ class TestFillPalletService(unittest.IsolatedAsyncioTestCase):
|
||||
self.db.commit.assert_not_awaited()
|
||||
self.db.rollback.assert_awaited_once()
|
||||
|
||||
async def test_fill_rejects_packages_over_persisted_pallet_capacity(self) -> None:
|
||||
await self._assert_fill_rejected(page=make_page(initial_packages=21))
|
||||
async def test_fill_rejects_historical_nonstandard_pallet_capacity(self) -> None:
|
||||
await self._assert_fill_rejected(pallet=make_pallet(capacity_packages=20))
|
||||
|
||||
async def test_fill_rejects_stopped_warehouse_only_after_core_locks(self) -> None:
|
||||
actions: list[str] = []
|
||||
@@ -1152,7 +1158,7 @@ class TestFillingController(unittest.TestCase):
|
||||
@staticmethod
|
||||
def _routes() -> dict[tuple[str, str], APIRoute]:
|
||||
return {
|
||||
(route.path, next(iter(route.methods))): route
|
||||
(route.path_format, next(iter(route.methods))): route
|
||||
for route in filling_controller_module.filling_controller.routes
|
||||
if isinstance(route, APIRoute)
|
||||
}
|
||||
@@ -1189,7 +1195,7 @@ class TestFillingController(unittest.TestCase):
|
||||
self.assertEqual(ResponseBaseModel, routes[('/business/filling', 'POST')].response_model)
|
||||
|
||||
def test_static_routes_are_declared_before_dynamic_detail(self) -> None:
|
||||
paths = [route.path for route in filling_controller_module.filling_controller.routes]
|
||||
paths = [route.path_format for route in filling_controller_module.filling_controller.routes]
|
||||
detail_index = paths.index('/business/filling/{filling_id}')
|
||||
self.assertLess(paths.index('/business/filling/strain-options'), detail_index)
|
||||
self.assertLess(paths.index('/business/filling/scan/{qr_token}'), detail_index)
|
||||
@@ -1218,7 +1224,7 @@ class TestFillingController(unittest.TestCase):
|
||||
set(actual.values()),
|
||||
)
|
||||
|
||||
def test_all_routes_inject_current_user_and_only_post_has_log(self) -> None:
|
||||
def test_all_routes_inject_current_user_and_expected_routes_have_log(self) -> None:
|
||||
for key, route in self._routes().items():
|
||||
self.assertTrue(
|
||||
any(
|
||||
@@ -1227,7 +1233,11 @@ class TestFillingController(unittest.TestCase):
|
||||
),
|
||||
key,
|
||||
)
|
||||
self.assertEqual(key == ('/business/filling', 'POST'), hasattr(route.endpoint, '__wrapped__'))
|
||||
expected_logged = {
|
||||
('/business/filling/scan/{qr_token}', 'GET'),
|
||||
('/business/filling', 'POST'),
|
||||
}
|
||||
self.assertEqual(key in expected_logged, hasattr(route.endpoint, '__wrapped__'))
|
||||
|
||||
def test_controller_does_not_add_scan_export_or_draft_permissions(self) -> None:
|
||||
source = inspect.getsource(filling_controller_module)
|
||||
|
||||
Reference in New Issue
Block a user