154 lines
5.5 KiB
Python
154 lines
5.5 KiB
Python
from __future__ import annotations
|
|
|
|
import unittest
|
|
from decimal import Decimal
|
|
|
|
from sqlalchemy import BigInteger, create_engine, select
|
|
from sqlalchemy.ext.compiler import compiles
|
|
from sqlalchemy.orm import Session, sessionmaker
|
|
|
|
|
|
@compiles(BigInteger, "sqlite")
|
|
def _compile_bigint_for_sqlite(type_, compiler, **kw) -> str:
|
|
_ = type_, compiler, kw
|
|
return "INTEGER"
|
|
|
|
|
|
import app.models.master_data # noqa: E402,F401
|
|
import app.models.operations # noqa: E402,F401
|
|
from app.api.routes.inventory import create_customer_supplied_inbound, create_warehouse_inbound # noqa: E402
|
|
from app.models.base import Base # noqa: E402
|
|
from app.models.master_data import Item, StockBalance, Warehouse # noqa: E402
|
|
from app.models.operations import StockLot # noqa: E402
|
|
from app.schemas.operations import CustomerSuppliedInboundCreate, WarehouseInboundCreate # noqa: E402
|
|
|
|
|
|
class User:
|
|
id = 1
|
|
|
|
|
|
class Context:
|
|
user = User()
|
|
|
|
|
|
class CustomerSuppliedInboundLotNoTest(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
engine = create_engine("sqlite+pysqlite:///:memory:", future=True)
|
|
Base.metadata.create_all(engine)
|
|
self.SessionLocal = sessionmaker(bind=engine, autoflush=False, autocommit=False, future=True)
|
|
self.db: Session = self.SessionLocal()
|
|
self.material = Item(
|
|
id=1,
|
|
item_code="110501000185",
|
|
item_name="左右后纵梁后段毛坯",
|
|
item_type="RAW_MATERIAL",
|
|
unit_weight_kg=Decimal("1"),
|
|
status="ACTIVE",
|
|
)
|
|
self.warehouse = Warehouse(
|
|
id=1,
|
|
warehouse_code="WH-RAW",
|
|
warehouse_name="原材料库",
|
|
warehouse_type="RAW",
|
|
status="ACTIVE",
|
|
)
|
|
self.db.add_all([self.material, self.warehouse])
|
|
self.db.commit()
|
|
|
|
def tearDown(self) -> None:
|
|
self.db.close()
|
|
|
|
def _seed_existing_lot(self, lot_no: str) -> None:
|
|
self.db.add(
|
|
StockLot(
|
|
lot_no=lot_no,
|
|
lot_role="CUSTOMER_SUPPLIED_RAW",
|
|
item_id=self.material.id,
|
|
warehouse_id=self.warehouse.id,
|
|
source_doc_type="CUSTOMER_SUPPLIED_IN",
|
|
source_doc_id=1,
|
|
inbound_qty=Decimal("0"),
|
|
inbound_weight_kg=Decimal("100"),
|
|
remaining_qty=Decimal("0"),
|
|
remaining_weight_kg=Decimal("100"),
|
|
locked_qty=Decimal("0"),
|
|
locked_weight_kg=Decimal("0"),
|
|
unit_cost=Decimal("0"),
|
|
quality_status="PASS",
|
|
status="AVAILABLE",
|
|
)
|
|
)
|
|
self.db.commit()
|
|
|
|
def test_generic_customer_supplied_inbound_ignores_manual_lot_no_and_uses_global_raw_sequence(self) -> None:
|
|
self._seed_existing_lot("JH_左右后纵梁后段毛坯00185_0001")
|
|
|
|
first_row = create_warehouse_inbound(
|
|
WarehouseInboundCreate(
|
|
biz_type="CUSTOMER_SUPPLIED",
|
|
item_id=self.material.id,
|
|
warehouse_id=self.warehouse.id,
|
|
inbound_weight_kg=50,
|
|
unit_cost=0,
|
|
lot_no="用户手填批次号",
|
|
source_material_sub_batch_no="用户手填来源批次",
|
|
provider_name="客户A",
|
|
waybill_no="YD-KL-001",
|
|
freight_amount=0,
|
|
),
|
|
context=Context(),
|
|
db=self.db,
|
|
)
|
|
second_row = create_warehouse_inbound(
|
|
WarehouseInboundCreate(
|
|
biz_type="CUSTOMER_SUPPLIED",
|
|
item_id=self.material.id,
|
|
warehouse_id=self.warehouse.id,
|
|
inbound_weight_kg=25,
|
|
unit_cost=0,
|
|
lot_no="第二个用户手填批次号",
|
|
source_material_sub_batch_no="第二个用户手填来源批次",
|
|
provider_name="客户A",
|
|
waybill_no="YD-KL-002",
|
|
freight_amount=0,
|
|
),
|
|
context=Context(),
|
|
db=self.db,
|
|
)
|
|
|
|
lot = self.db.scalar(select(StockLot).where(StockLot.id == first_row.lot_id))
|
|
second_lot = self.db.scalar(select(StockLot).where(StockLot.id == second_row.lot_id))
|
|
balance = self.db.scalar(
|
|
select(StockBalance).where(
|
|
StockBalance.item_id == self.material.id,
|
|
StockBalance.warehouse_id == self.warehouse.id,
|
|
)
|
|
)
|
|
self.assertEqual(lot.lot_no, "YL0001")
|
|
self.assertEqual(second_lot.lot_no, "YL0002")
|
|
self.assertIsNone(lot.source_material_sub_batch_no)
|
|
self.assertEqual(lot.source_material_summary, "客户A")
|
|
self.assertIsNotNone(balance)
|
|
self.assertEqual(balance.weight_on_hand_kg, Decimal("75.000000"))
|
|
|
|
def test_dedicated_customer_supplied_inbound_ignores_manual_lot_no_and_starts_from_one(self) -> None:
|
|
row = create_customer_supplied_inbound(
|
|
CustomerSuppliedInboundCreate(
|
|
material_item_id=self.material.id,
|
|
warehouse_id=self.warehouse.id,
|
|
provider_name="客户B",
|
|
inbound_weight_kg=80,
|
|
lot_no="旧接口手填批次号",
|
|
),
|
|
context=Context(),
|
|
db=self.db,
|
|
)
|
|
|
|
lot = self.db.scalar(select(StockLot).where(StockLot.id == row.lot_id))
|
|
self.assertEqual(lot.lot_no, "YL0001")
|
|
self.assertEqual(lot.source_material_summary, "客户B")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|