1757 lines
48 KiB
Python
1757 lines
48 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import date, datetime
|
|
from decimal import Decimal
|
|
|
|
from pydantic import BaseModel, ConfigDict, Field
|
|
|
|
|
|
class ContactPayload(BaseModel):
|
|
contact_name: str | None = None
|
|
contact_phone: str | None = None
|
|
|
|
|
|
class SupplierRead(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
supplier_code: str
|
|
supplier_name: str
|
|
short_name: str | None = None
|
|
contact_name: str | None = None
|
|
contact_phone: str | None = None
|
|
contacts: list[ContactPayload] = Field(default_factory=list, max_length=3)
|
|
address: str | None = None
|
|
lead_time_days: int
|
|
default_tax_rate: float
|
|
status: str
|
|
remark: str | None = None
|
|
|
|
|
|
class SupplierCreate(BaseModel):
|
|
supplier_name: str
|
|
short_name: str | None = None
|
|
contact_name: str | None = None
|
|
contact_phone: str | None = None
|
|
contacts: list[ContactPayload] = Field(default_factory=list, max_length=3)
|
|
address: str | None = None
|
|
lead_time_days: int = 0
|
|
default_tax_rate: float = 0
|
|
status: str = "ACTIVE"
|
|
remark: str | None = None
|
|
|
|
|
|
class SupplierUpdate(SupplierCreate):
|
|
pass
|
|
|
|
|
|
class WorkCenterRead(BaseModel):
|
|
id: int
|
|
center_code: str
|
|
center_name: str
|
|
dept_id: int
|
|
dept_name: str | None = None
|
|
center_type: str
|
|
shift_pattern: str | None = None
|
|
capacity_hours_per_day: float
|
|
status: str
|
|
|
|
|
|
class WarehouseLocationRead(BaseModel):
|
|
id: int
|
|
warehouse_id: int
|
|
warehouse_code: str
|
|
warehouse_name: str
|
|
location_code: str
|
|
location_name: str
|
|
zone_name: str | None = None
|
|
is_default: bool
|
|
is_locked: bool
|
|
status: str
|
|
|
|
|
|
class PurchaseOrderItemCreate(BaseModel):
|
|
material_item_id: int
|
|
source_demand_id: int | None = None
|
|
order_qty: float = 0
|
|
order_weight_kg: float = 0
|
|
unit_price: float = 0
|
|
remark: str | None = None
|
|
|
|
|
|
class PurchaseOrderCreate(BaseModel):
|
|
supplier_id: int
|
|
order_date: date | None = None
|
|
expected_date: date | None = None
|
|
warning_lead_days: int = Field(default=0, ge=0)
|
|
purchaser_employee_id: int | None = None
|
|
target_warehouse_type: str = "RAW"
|
|
sales_order_ids: list[int] = Field(default_factory=list)
|
|
tax_rate: float = 0
|
|
remark: str | None = None
|
|
items: list[PurchaseOrderItemCreate]
|
|
|
|
|
|
class PurchaseOrderUpdate(PurchaseOrderCreate):
|
|
pass
|
|
|
|
|
|
class PurchaseOrderRead(BaseModel):
|
|
purchase_order_id: int
|
|
po_no: str
|
|
source_type: str = "STOCKING"
|
|
source_order_nos: str | None = None
|
|
sales_order_ids: list[int] = Field(default_factory=list)
|
|
supplier_id: int
|
|
supplier_code: str
|
|
supplier_name: str
|
|
order_date: date
|
|
expected_date: date | None = None
|
|
warning_lead_days: int = 0
|
|
warning_start_date: date | None = None
|
|
is_warning_active: bool = False
|
|
purchaser_employee_id: int | None = None
|
|
purchaser_name: str | None = None
|
|
target_warehouse_type: str = "RAW"
|
|
tax_rate: float
|
|
total_amount: float
|
|
status: str
|
|
display_status: str | None = None
|
|
remark: str | None = None
|
|
line_count: int
|
|
total_order_qty: float = 0
|
|
total_order_weight_kg: float
|
|
total_received_qty: float = 0
|
|
total_received_weight_kg: float
|
|
has_return: bool = False
|
|
total_return_weight_kg: float = 0
|
|
archive_status: str = "未生成"
|
|
archive_version: int | None = None
|
|
archive_created_at: datetime | None = None
|
|
archive_error_message: str | None = None
|
|
|
|
|
|
class PurchaseOrderItemRead(BaseModel):
|
|
purchase_order_item_id: int
|
|
purchase_order_id: int
|
|
po_no: str
|
|
line_no: int
|
|
material_item_id: int
|
|
material_code: str
|
|
material_name: str
|
|
specification: str | None = None
|
|
material_grade: str | None = None
|
|
performance_requirement: str | None = None
|
|
purchase_calc_mode: str | None = None
|
|
source_demand_id: int | None = None
|
|
order_qty: float
|
|
order_weight_kg: float
|
|
received_qty: float
|
|
received_weight_kg: float
|
|
returned_weight_kg: float = 0
|
|
net_received_weight_kg: float = 0
|
|
has_return: bool = False
|
|
unit_price: float
|
|
line_amount: float
|
|
status: str
|
|
display_status: str | None = None
|
|
remark: str | None = None
|
|
|
|
|
|
class PurchaseReceiptItemCreate(BaseModel):
|
|
purchase_order_item_id: int
|
|
material_item_id: int
|
|
location_id: int | None = None
|
|
lot_no: str | None = None
|
|
received_qty: float = 0
|
|
received_weight_kg: float = 0
|
|
unit_cost: float = 0
|
|
remark: str | None = None
|
|
|
|
|
|
class PurchaseReceiptCreate(BaseModel):
|
|
purchase_order_id: int
|
|
warehouse_id: int
|
|
receipt_date: datetime | None = None
|
|
receiver_employee_id: int | None = None
|
|
supplier_delivery_no: str | None = None
|
|
waybill_no: str | None = None
|
|
order_photo_url: str | None = None
|
|
freight_amount: float | None = None
|
|
remark: str | None = None
|
|
items: list[PurchaseReceiptItemCreate]
|
|
|
|
|
|
class PurchaseReceiptRead(BaseModel):
|
|
receipt_id: int
|
|
receipt_no: str
|
|
purchase_order_id: int
|
|
po_no: str
|
|
supplier_id: int
|
|
supplier_name: str
|
|
warehouse_id: int
|
|
warehouse_name: str
|
|
target_warehouse_type: str = "RAW"
|
|
receipt_date: datetime
|
|
receiver_employee_id: int | None = None
|
|
receiver_name: str | None = None
|
|
supplier_delivery_no: str | None = None
|
|
logistics_waybill_no: str | None = None
|
|
logistics_freight_amount: float | None = None
|
|
logistics_photo_url: str | None = None
|
|
material_names: str | None = None
|
|
status: str
|
|
remark: str | None = None
|
|
line_count: int
|
|
total_received_qty: float = 0
|
|
total_received_weight_kg: float
|
|
archive_status: str = "未生成"
|
|
archive_version: int | None = None
|
|
archive_created_at: datetime | None = None
|
|
archive_error_message: str | None = None
|
|
|
|
|
|
class PurchaseReceiptItemRead(BaseModel):
|
|
receipt_item_id: int
|
|
receipt_id: int
|
|
receipt_no: str
|
|
line_no: int
|
|
purchase_order_item_id: int
|
|
material_item_id: int
|
|
material_code: str
|
|
material_name: str
|
|
warehouse_id: int
|
|
warehouse_name: str
|
|
location_id: int | None = None
|
|
location_name: str | None = None
|
|
lot_no: str
|
|
received_qty: float
|
|
received_weight_kg: float
|
|
accepted_qty: float
|
|
accepted_weight_kg: float
|
|
unit_cost: float
|
|
status: str
|
|
quality_status: str | None = None
|
|
remark: str | None = None
|
|
|
|
|
|
class StockLotPurchaseLinkRead(BaseModel):
|
|
purchase_order_id: int
|
|
po_no: str
|
|
purchase_order_item_id: int
|
|
material_item_id: int
|
|
material_code: str
|
|
material_name: str
|
|
lot_id: int
|
|
lot_no: str
|
|
accepted_weight_kg: float
|
|
returned_weight_kg: float
|
|
returnable_weight_kg: float
|
|
unit_cost: float
|
|
|
|
|
|
class RawMaterialReturnOutboundItemCreate(BaseModel):
|
|
lot_id: int
|
|
purchase_order_item_id: int
|
|
return_weight_kg: float
|
|
reason: str | None = None
|
|
remark: str | None = None
|
|
|
|
|
|
class RawMaterialReturnOutboundCreate(BaseModel):
|
|
warehouse_id: int
|
|
return_date: datetime | None = None
|
|
waybill_no: str | None = None
|
|
order_photo_url: str | None = None
|
|
freight_amount: float | None = None
|
|
reason: str | None = None
|
|
remark: str | None = None
|
|
items: list[RawMaterialReturnOutboundItemCreate]
|
|
|
|
|
|
class PurchaseReturnItemRead(BaseModel):
|
|
purchase_return_item_id: int
|
|
purchase_return_id: int
|
|
line_no: int
|
|
purchase_order_item_id: int
|
|
material_item_id: int
|
|
material_code: str
|
|
material_name: str
|
|
lot_id: int
|
|
lot_no: str
|
|
return_weight_kg: float
|
|
unit_cost: float
|
|
amount: float
|
|
reason: str | None = None
|
|
status: str
|
|
remark: str | None = None
|
|
|
|
|
|
class PurchaseReturnRead(BaseModel):
|
|
purchase_return_id: int
|
|
return_no: str
|
|
purchase_order_id: int
|
|
po_no: str
|
|
warehouse_id: int
|
|
warehouse_name: str
|
|
return_date: datetime
|
|
logistics_waybill_no: str | None = None
|
|
logistics_freight_amount: float | None = None
|
|
logistics_photo_url: str | None = None
|
|
reason: str | None = None
|
|
status: str
|
|
remark: str | None = None
|
|
total_return_weight_kg: float
|
|
total_amount: float
|
|
items: list[PurchaseReturnItemRead] = Field(default_factory=list)
|
|
archive_status: str | None = None
|
|
archive_business_id: int | None = None
|
|
archive_document_type: str | None = None
|
|
archive_error_message: str | None = None
|
|
|
|
|
|
class StockLotRead(BaseModel):
|
|
lot_id: int
|
|
lot_no: str
|
|
parent_lot_id: int | None = None
|
|
lot_role: str | None = None
|
|
material_sub_batch_no: str | None = None
|
|
item_id: int
|
|
item_code: str
|
|
item_name: str
|
|
item_type: str
|
|
specification: str | None = None
|
|
item_remark: str | None = None
|
|
stock_unit_name: str | None = None
|
|
purchase_unit_name: str | None = None
|
|
sales_unit_name: str | None = None
|
|
warehouse_id: int
|
|
warehouse_name: str
|
|
warehouse_type: str | None = None
|
|
location_id: int | None = None
|
|
location_name: str | None = None
|
|
source_doc_type: str
|
|
source_doc_id: int
|
|
source_line_id: int | None = None
|
|
source_receipt_no: str | None = None
|
|
source_purchase_order_no: str | None = None
|
|
source_material_lot_id: int | None = None
|
|
source_material_lot_no: str | None = None
|
|
source_material_sub_batch_no: str | None = None
|
|
source_material_summary: str | None = None
|
|
logistics_waybill_no: str | None = None
|
|
logistics_freight_amount: float | None = None
|
|
logistics_photo_url: str | None = None
|
|
inbound_qty: float
|
|
inbound_weight_kg: float
|
|
remaining_qty: float
|
|
remaining_weight_kg: float
|
|
locked_qty: float
|
|
locked_weight_kg: float
|
|
unit_cost: float
|
|
quality_status: str
|
|
quality_user_name: str | None = None
|
|
status: str
|
|
created_at: datetime
|
|
archive_status: str | None = None
|
|
archive_business_id: int | None = None
|
|
archive_document_type: str | None = None
|
|
archive_error_message: str | None = None
|
|
|
|
|
|
class StockLotOptionRead(BaseModel):
|
|
lot_id: int
|
|
lot_no: str
|
|
item_id: int
|
|
item_code: str
|
|
item_name: str
|
|
warehouse_id: int
|
|
warehouse_name: str
|
|
remaining_weight_kg: float
|
|
unit_cost: float
|
|
quality_status: str
|
|
status: str
|
|
is_available_for_issue: bool
|
|
disabled_reason: str | None = None
|
|
|
|
|
|
class StockBalanceRead(BaseModel):
|
|
stock_balance_id: int
|
|
item_id: int
|
|
item_code: str
|
|
item_name: str
|
|
item_type: str
|
|
specification: str | None = None
|
|
item_remark: str | None = None
|
|
stock_unit_name: str | None = None
|
|
purchase_unit_name: str | None = None
|
|
sales_unit_name: str | None = None
|
|
warehouse_id: int
|
|
warehouse_name: str
|
|
warehouse_type: str | None = None
|
|
location_id: int | None = None
|
|
location_name: str | None = None
|
|
qty_on_hand: float
|
|
weight_on_hand_kg: float
|
|
qty_available: float
|
|
weight_available_kg: float
|
|
qty_allocated: float
|
|
weight_allocated_kg: float
|
|
avg_unit_cost: float
|
|
updated_at: datetime
|
|
|
|
|
|
class InventoryTxnRead(BaseModel):
|
|
inventory_txn_id: int
|
|
txn_no: str
|
|
txn_type: str
|
|
item_id: int
|
|
item_code: str
|
|
item_name: str
|
|
warehouse_id: int
|
|
warehouse_name: str
|
|
warehouse_type: str | None = None
|
|
location_id: int | None = None
|
|
location_name: str | None = None
|
|
lot_id: int | None = None
|
|
lot_no: str | None = None
|
|
qty_change: float
|
|
weight_change_kg: float
|
|
unit_cost: float
|
|
amount: float
|
|
source_doc_type: str
|
|
source_doc_id: int
|
|
source_line_id: int | None = None
|
|
source_material_lot_id: int | None = None
|
|
source_material_lot_no: str | None = None
|
|
source_material_sub_batch_no: str | None = None
|
|
source_material_summary: str | None = None
|
|
biz_time: datetime
|
|
logistics_waybill_no: str | None = None
|
|
logistics_freight_amount: float | None = None
|
|
logistics_photo_url: str | None = None
|
|
remark: str | None = None
|
|
archive_status: str = "未生成"
|
|
archive_business_id: int | None = None
|
|
archive_document_type: str | None = None
|
|
archive_error_message: str | None = None
|
|
|
|
|
|
class InventoryTxnLedgerRowRead(InventoryTxnRead):
|
|
direction: str
|
|
source_line_id: int | None = None
|
|
operator_user_id: int | None = None
|
|
operator_name: str | None = None
|
|
|
|
|
|
class InventoryTxnLedgerSummaryRead(BaseModel):
|
|
in_count: int = 0
|
|
out_count: int = 0
|
|
adjust_count: int = 0
|
|
in_qty: float = 0
|
|
out_qty: float = 0
|
|
in_weight_kg: float = 0
|
|
out_weight_kg: float = 0
|
|
latest_biz_time: datetime | None = None
|
|
|
|
|
|
class InventoryTxnLedgerResponse(BaseModel):
|
|
items: list[InventoryTxnLedgerRowRead]
|
|
total: int
|
|
summary: InventoryTxnLedgerSummaryRead
|
|
|
|
|
|
class SelectedStockLotIssueCreate(BaseModel):
|
|
source_lot_id: int
|
|
issued_weight_kg: float
|
|
material_item_id: int | None = None
|
|
|
|
|
|
class WorkOrderCreate(BaseModel):
|
|
source_sales_order_item_id: int | None = None
|
|
product_item_id: int
|
|
planned_qty: float = 0
|
|
issue_weight_kg: float = 0
|
|
selected_stock_lots: list[SelectedStockLotIssueCreate] = Field(default_factory=list)
|
|
planned_start_time: datetime | None = None
|
|
planned_end_time: datetime | None = None
|
|
priority_level: int = 3
|
|
auto_issue_materials: bool = False
|
|
remark: str | None = None
|
|
|
|
|
|
class WorkOrderRead(BaseModel):
|
|
work_order_id: int
|
|
work_order_no: str
|
|
work_order_type: str
|
|
source_sales_order_item_id: int | None = None
|
|
source_order_no: str | None = None
|
|
product_item_id: int
|
|
product_code: str
|
|
product_name: str
|
|
product_version_no: str | None = None
|
|
route_id: int
|
|
route_name: str
|
|
bom_id: int
|
|
planned_qty: float
|
|
released_qty: float
|
|
finished_qty: float
|
|
scrap_qty: float
|
|
planned_start_time: datetime | None = None
|
|
planned_end_time: datetime | None = None
|
|
actual_start_time: datetime | None = None
|
|
actual_end_time: datetime | None = None
|
|
priority_level: int
|
|
status: str
|
|
remark: str | None = None
|
|
operation_count: int
|
|
abnormal_operation_count: int
|
|
reported_good_qty: float = 0
|
|
received_qty: float = 0
|
|
max_receivable_qty: float = 0
|
|
all_operations_done: bool = False
|
|
archive_status: str | None = None
|
|
archive_business_id: int | None = None
|
|
archive_document_type: str | None = None
|
|
archive_error_message: str | None = None
|
|
|
|
|
|
class WorkOrderMaterialRead(BaseModel):
|
|
work_order_material_id: int
|
|
work_order_id: int
|
|
work_order_no: str
|
|
bom_item_id: int
|
|
material_item_id: int
|
|
material_code: str
|
|
material_name: str
|
|
required_qty: float
|
|
required_weight_kg: float
|
|
issued_qty: float
|
|
issued_weight_kg: float
|
|
returned_qty: float
|
|
returned_weight_kg: float
|
|
material_sub_batch_summary: str | None = None
|
|
issue_amount: float = 0
|
|
status: str
|
|
remark: str | None = None
|
|
|
|
|
|
class WorkOrderMaterialIssueRead(BaseModel):
|
|
material_issue_id: int
|
|
work_order_material_id: int
|
|
work_order_id: int
|
|
work_order_no: str
|
|
material_item_id: int
|
|
material_code: str
|
|
material_name: str
|
|
source_lot_id: int
|
|
source_lot_no: str
|
|
material_sub_batch_no: str
|
|
issued_qty: float
|
|
issued_weight_kg: float
|
|
unit_cost: float
|
|
amount: float
|
|
issue_time: datetime
|
|
remark: str | None = None
|
|
|
|
|
|
class ProductionBatchLedgerTxnRead(BaseModel):
|
|
production_ledger_txn_id: int
|
|
production_ledger_id: int
|
|
txn_type: str
|
|
qty_delta: float = 0
|
|
weight_delta_kg: float = 0
|
|
outside_weight_after_kg: float = 0
|
|
source_doc_type: str | None = None
|
|
source_doc_id: int | None = None
|
|
source_line_id: int | None = None
|
|
biz_time: datetime
|
|
operator_user_id: int | None = None
|
|
remark: str | None = None
|
|
archive_status: str | None = None
|
|
archive_business_id: int | None = None
|
|
archive_document_type: str | None = None
|
|
archive_error_message: str | None = None
|
|
|
|
|
|
class ProductionBatchLedgerRead(BaseModel):
|
|
production_ledger_id: int
|
|
material_lot_id: int
|
|
material_lot_no: str
|
|
material_item_id: int
|
|
material_code: str | None = None
|
|
material_name: str | None = None
|
|
product_item_id: int
|
|
product_code: str | None = None
|
|
product_name: str | None = None
|
|
status: str
|
|
miniapp_selectable: bool = True
|
|
total_issued_weight_kg: float = 0
|
|
outside_weight_kg: float = 0
|
|
finished_inbound_qty: float = 0
|
|
surplus_inbound_weight_kg: float = 0
|
|
scrap_inbound_weight_kg: float = 0
|
|
writeoff_weight_kg: float = 0
|
|
first_issue_time: datetime | None = None
|
|
last_issue_time: datetime | None = None
|
|
locked_at: datetime | None = None
|
|
reopened_at: datetime | None = None
|
|
lock_count: int = 0
|
|
remark: str | None = None
|
|
material_out_archive_status: str | None = None
|
|
material_out_archive_business_id: int | None = None
|
|
material_out_archive_document_type: str | None = None
|
|
material_out_archive_error_message: str | None = None
|
|
txns: list[ProductionBatchLedgerTxnRead] = Field(default_factory=list)
|
|
|
|
|
|
class ProductionBatchLedgerInboundPreviewRead(BaseModel):
|
|
production_ledger_id: int
|
|
material_lot_no: str
|
|
product_item_id: int
|
|
product_code: str | None = None
|
|
product_name: str | None = None
|
|
material_item_id: int
|
|
material_code: str | None = None
|
|
material_name: str | None = None
|
|
gross_weight_per_piece_kg: float = 0
|
|
net_weight_per_piece_kg: float = 0
|
|
total_issued_weight_kg: float = 0
|
|
outside_weight_kg: float = 0
|
|
finished_inbound_qty: float = 0
|
|
surplus_inbound_weight_kg: float = 0
|
|
scrap_inbound_weight_kg: float = 0
|
|
writeoff_weight_kg: float = 0
|
|
reference_finished_qty: float = 0
|
|
used_material_weight_kg: float = 0
|
|
theoretical_surplus_weight_kg: float = 0
|
|
theoretical_scrap_weight_kg: float = 0
|
|
|
|
|
|
class ProductionBatchLedgerInboundCreate(BaseModel):
|
|
production_ledger_id: int
|
|
finished_qty: float = 0
|
|
surplus_weight_kg: float = 0
|
|
scrap_weight_kg: float = 0
|
|
lock_material_batch: bool = False
|
|
lock_confirmed: bool = False
|
|
deviation_remark: str | None = None
|
|
remark: str | None = None
|
|
|
|
|
|
class ProductionBatchLedgerInboundRead(BaseModel):
|
|
production_ledger_id: int
|
|
material_lot_no: str
|
|
finished_qty: float = 0
|
|
surplus_weight_kg: float = 0
|
|
scrap_weight_kg: float = 0
|
|
finished_lot_id: int | None = None
|
|
surplus_lot_id: int | None = None
|
|
scrap_lot_id: int | None = None
|
|
finished_txn_id: int | None = None
|
|
surplus_txn_id: int | None = None
|
|
scrap_txn_id: int | None = None
|
|
locked: bool = False
|
|
status: str
|
|
remark: str | None = None
|
|
archive_status: str | None = None
|
|
archive_business_id: int | None = None
|
|
archive_document_type: str | None = None
|
|
archive_error_message: str | None = None
|
|
|
|
|
|
class WorkOrderOperationRead(BaseModel):
|
|
work_order_operation_id: int
|
|
work_order_id: int
|
|
work_order_no: str
|
|
route_operation_id: int
|
|
seq_no: int
|
|
operation_name: str
|
|
work_center_id: int
|
|
work_center_name: str
|
|
planned_qty: float
|
|
report_qty: float
|
|
good_qty: float
|
|
scrap_qty: float
|
|
rework_qty: float
|
|
std_labor_cost: float
|
|
std_machine_cost: float
|
|
std_outsource_cost: float
|
|
allowed_scrap_rate: float
|
|
is_abnormal: bool
|
|
status: str
|
|
remark: str | None = None
|
|
|
|
|
|
class WorkOrderLedgerMaterialRead(BaseModel):
|
|
material_item_id: int
|
|
material_code: str
|
|
material_name: str
|
|
source_lot_id: int
|
|
source_lot_no: str
|
|
issued_weight_kg: float
|
|
returned_weight_kg: float = 0
|
|
unit_cost: float = 0
|
|
amount: float = 0
|
|
|
|
|
|
class WorkOrderLedgerOperationRead(BaseModel):
|
|
work_order_operation_id: int
|
|
seq_no: int
|
|
operation_name: str
|
|
report_qty: float
|
|
good_qty: float
|
|
scrap_qty: float
|
|
status: str
|
|
|
|
|
|
class WorkOrderLedgerLimitRead(BaseModel):
|
|
gross_weight_per_piece_kg: float
|
|
net_weight_per_piece_kg: float
|
|
issued_weight_kg: float
|
|
used_material_weight_kg: float
|
|
returned_material_weight_kg: float
|
|
final_operation_good_qty: float
|
|
finished_received_qty: float
|
|
total_operation_scrap_qty: float
|
|
scrap_inbound_weight_kg: float
|
|
max_finished_inbound_qty: float
|
|
max_scrap_inbound_weight_kg: float
|
|
max_surplus_inbound_weight_kg: float
|
|
tolerance_finished_inbound_qty: float
|
|
tolerance_scrap_inbound_weight_kg: float
|
|
tolerance_surplus_inbound_weight_kg: float
|
|
|
|
|
|
class WorkOrderLedgerRead(BaseModel):
|
|
work_order_id: int
|
|
work_order_no: str
|
|
product_item_id: int
|
|
product_code: str
|
|
product_name: str
|
|
planned_qty: float
|
|
status: str
|
|
remark: str | None = None
|
|
material_summary: str
|
|
source_lot_summary: str
|
|
issued_weight_kg: float
|
|
used_material_weight_kg: float
|
|
returned_material_weight_kg: float
|
|
finished_received_qty: float
|
|
max_finished_inbound_qty: float
|
|
max_scrap_inbound_weight_kg: float
|
|
max_surplus_inbound_weight_kg: float
|
|
limits: WorkOrderLedgerLimitRead
|
|
materials: list[WorkOrderLedgerMaterialRead]
|
|
operations: list[WorkOrderLedgerOperationRead]
|
|
|
|
|
|
class ProductionWorkOrderInboundPreviewRead(BaseModel):
|
|
work_order_id: int
|
|
work_order_no: str
|
|
product_item_id: int
|
|
product_code: str
|
|
product_name: str
|
|
source_lot_id: int
|
|
source_lot_no: str
|
|
material_item_id: int
|
|
material_code: str
|
|
material_name: str
|
|
gross_weight_per_piece_kg: float
|
|
net_weight_per_piece_kg: float
|
|
issued_weight_kg: float
|
|
returned_weight_kg: float
|
|
final_operation_good_qty: float
|
|
finished_inbound_qty: float
|
|
reported_scrap_qty: float
|
|
scrap_inbound_weight_kg: float
|
|
reference_finished_qty: float
|
|
remaining_reference_finished_qty: float
|
|
finished_qty_upper_limit: float
|
|
finished_qty: float
|
|
theoretical_surplus_weight_kg: float
|
|
theoretical_scrap_weight_kg: float
|
|
|
|
|
|
class ProductionWorkOrderInboundCreate(BaseModel):
|
|
work_order_id: int
|
|
finished_qty: float = 0
|
|
surplus_weight_kg: float = 0
|
|
scrap_weight_kg: float = 0
|
|
settle_work_order: bool = False
|
|
settle_confirmed: bool = False
|
|
deviation_remark: str | None = None
|
|
remark: str | None = None
|
|
|
|
|
|
class ProductionWorkOrderInboundRead(BaseModel):
|
|
work_order_id: int
|
|
work_order_no: str
|
|
finished_qty: float = 0
|
|
surplus_weight_kg: float = 0
|
|
scrap_weight_kg: float = 0
|
|
finished_lot_id: int | None = None
|
|
surplus_lot_id: int | None = None
|
|
scrap_lot_id: int | None = None
|
|
finished_txn_id: int | None = None
|
|
surplus_txn_id: int | None = None
|
|
scrap_txn_id: int | None = None
|
|
settled: bool = False
|
|
status: str
|
|
remark: str | None = None
|
|
archive_status: str | None = None
|
|
archive_business_id: int | None = None
|
|
archive_document_type: str | None = None
|
|
archive_error_message: str | None = None
|
|
|
|
|
|
class OperationReportCreate(BaseModel):
|
|
work_order_id: int
|
|
work_order_operation_id: int
|
|
employee_id: int
|
|
equipment_id: int | None = None
|
|
report_source: str = "MANUAL"
|
|
shift_code: str | None = None
|
|
start_time: datetime
|
|
end_time: datetime
|
|
report_qty: float
|
|
good_qty: float
|
|
scrap_qty: float = 0
|
|
rework_qty: float = 0
|
|
scrap_reason: str | None = None
|
|
downtime_minutes: float = 0
|
|
extra_cost_amount: float = 0
|
|
remark: str | None = None
|
|
|
|
|
|
class OperationReportRead(BaseModel):
|
|
report_id: int
|
|
report_no: str
|
|
work_order_id: int
|
|
work_order_no: str
|
|
work_order_operation_id: int
|
|
seq_no: int
|
|
operation_name: str
|
|
employee_id: int
|
|
employee_name: str
|
|
equipment_id: int | None = None
|
|
equipment_name: str | None = None
|
|
report_source: str
|
|
shift_code: str | None = None
|
|
start_time: datetime
|
|
end_time: datetime
|
|
report_qty: float
|
|
good_qty: float
|
|
scrap_qty: float
|
|
rework_qty: float
|
|
downtime_minutes: float
|
|
extra_cost_amount: float
|
|
is_abnormal: bool
|
|
ref_cycle_seconds: float = 0
|
|
actual_cycle_seconds: float | None = None
|
|
abnormal_reason: str | None = None
|
|
scrap_reason: str | None = None
|
|
remark: str | None = None
|
|
|
|
|
|
class MiniAppOperationReportRead(BaseModel):
|
|
source_report_id: int
|
|
source_item_id: int
|
|
report_no: str
|
|
attendance_point_name: str = ""
|
|
employee_phone: str
|
|
employee_name: str
|
|
report_date: date
|
|
start_time: datetime
|
|
end_time: datetime
|
|
duration_minutes: float = 0
|
|
effective_minutes: float = 0
|
|
status: str
|
|
status_name: str
|
|
reviewer_phone: str | None = None
|
|
reviewed_at: datetime | None = None
|
|
reject_reason: str | None = None
|
|
device_no: str
|
|
project_no: str
|
|
product_name: str
|
|
material_code: str | None = None
|
|
material_name: str | None = None
|
|
raw_material_batch_no: str | None = None
|
|
process_name: str | None = None
|
|
standard_beat: float = 0
|
|
standard_workload: float = 0
|
|
good_qty: float = 0
|
|
defect_qty: float = 0
|
|
scrap_qty: float = 0
|
|
erp_scrap_qty: float = 0
|
|
allocated_minutes: float = 0
|
|
started_at: datetime | None = None
|
|
work_order_id: int | None = None
|
|
work_order_no: str | None = None
|
|
work_order_operation_id: int | None = None
|
|
operation_name: str | None = None
|
|
erp_report_id: int | None = None
|
|
erp_report_no: str | None = None
|
|
is_synced_to_erp: bool = False
|
|
abnormal_reason: str | None = None
|
|
|
|
|
|
class MiniAppOperationReportSyncRead(BaseModel):
|
|
sync_from: datetime | None = None
|
|
sync_to: datetime
|
|
last_synced_at: datetime
|
|
total: int = 0
|
|
synced: int = 0
|
|
skipped: int = 0
|
|
failed: int = 0
|
|
|
|
|
|
class MiniAppOperationReportSyncStateRead(BaseModel):
|
|
last_synced_at: datetime | None = None
|
|
|
|
|
|
class MiniAppScrapRecordCreate(BaseModel):
|
|
source_item_id: int
|
|
scrap_qty: float = 0
|
|
scrap_weight_kg: float = 0
|
|
scrap_reason: str | None = None
|
|
saleable_scrap_weight_kg: float = 0
|
|
scrap_cost_amount: float = 0
|
|
|
|
|
|
class ScrapRecordCreate(BaseModel):
|
|
report_id: int
|
|
work_order_id: int
|
|
work_order_operation_id: int
|
|
item_id: int
|
|
scrap_qty: float
|
|
scrap_weight_kg: float = 0
|
|
scrap_reason: str | None = None
|
|
disposal_type: str = "SCRAP"
|
|
saleable_scrap_weight_kg: float = 0
|
|
scrap_cost_amount: float = 0
|
|
|
|
|
|
class ScrapRecordRead(BaseModel):
|
|
scrap_record_id: int
|
|
scrap_no: str
|
|
report_id: int
|
|
report_no: str
|
|
work_order_id: int
|
|
work_order_no: str
|
|
work_order_operation_id: int
|
|
operation_name: str
|
|
item_id: int
|
|
item_code: str
|
|
item_name: str
|
|
scrap_qty: float
|
|
scrap_weight_kg: float
|
|
scrap_reason: str | None = None
|
|
disposal_type: str
|
|
saleable_scrap_weight_kg: float
|
|
scrap_cost_amount: float
|
|
status: str
|
|
created_at: datetime
|
|
|
|
|
|
class CompletionReceiptItemCreate(BaseModel):
|
|
product_item_id: int
|
|
location_id: int | None = None
|
|
receipt_qty: float
|
|
receipt_weight_kg: float = 0
|
|
remark: str | None = None
|
|
|
|
|
|
class CompletionReceiptCreate(BaseModel):
|
|
work_order_id: int
|
|
warehouse_id: int
|
|
receipt_time: datetime | None = None
|
|
receiver_employee_id: int | None = None
|
|
remark: str | None = None
|
|
settle_work_order: bool = False
|
|
settle_remark: str | None = None
|
|
items: list[CompletionReceiptItemCreate]
|
|
|
|
|
|
class CompletionReceiptRead(BaseModel):
|
|
completion_receipt_id: int
|
|
receipt_no: str
|
|
work_order_id: int
|
|
work_order_no: str
|
|
product_item_id: int
|
|
product_code: str
|
|
product_name: str
|
|
warehouse_id: int
|
|
warehouse_name: str
|
|
receipt_time: datetime
|
|
receiver_employee_id: int | None = None
|
|
receiver_name: str | None = None
|
|
status: str
|
|
line_count: int
|
|
total_receipt_qty: float
|
|
total_receipt_weight_kg: float
|
|
remark: str | None = None
|
|
|
|
|
|
class CompletionReceiptItemRead(BaseModel):
|
|
completion_receipt_item_id: int
|
|
completion_receipt_id: int
|
|
receipt_no: str
|
|
line_no: int
|
|
product_item_id: int
|
|
product_code: str
|
|
product_name: str
|
|
warehouse_id: int
|
|
warehouse_name: str
|
|
location_id: int | None = None
|
|
location_name: str | None = None
|
|
lot_no: str
|
|
source_material_lot_id: int | None = None
|
|
source_material_lot_no: str | None = None
|
|
source_material_sub_batch_no: str | None = None
|
|
source_material_summary: str | None = None
|
|
receipt_qty: float
|
|
receipt_weight_kg: float
|
|
unit_cost: float
|
|
status: str
|
|
remark: str | None = None
|
|
|
|
|
|
class DeliveryItemCreate(BaseModel):
|
|
sales_order_item_id: int | None = None
|
|
product_item_id: int
|
|
lot_id: int | None = None
|
|
delivery_qty: float
|
|
delivery_weight_kg: float = 0
|
|
unit_price: float = 0
|
|
remark: str | None = None
|
|
|
|
|
|
class DeliveryCreate(BaseModel):
|
|
sales_order_id: int | None = None
|
|
customer_id: int | None = None
|
|
warehouse_id: int
|
|
delivery_date: datetime | None = None
|
|
shipper_employee_id: int | None = None
|
|
consignee_name: str | None = None
|
|
consignee_phone: str | None = None
|
|
delivery_address: str | None = None
|
|
waybill_no: str | None = None
|
|
order_photo_url: str | None = None
|
|
freight_amount: float | None = None
|
|
remark: str | None = None
|
|
items: list[DeliveryItemCreate]
|
|
|
|
|
|
class DeliveryRead(BaseModel):
|
|
delivery_id: int
|
|
delivery_no: str
|
|
sales_order_id: int | None = None
|
|
customer_id: int | None = None
|
|
order_no: str | None = None
|
|
customer_name: str | None = None
|
|
warehouse_id: int
|
|
warehouse_name: str
|
|
delivery_date: datetime
|
|
shipper_employee_id: int | None = None
|
|
shipper_name: str | None = None
|
|
consignee_name: str | None = None
|
|
consignee_phone: str | None = None
|
|
delivery_address: str | None = None
|
|
logistics_waybill_no: str | None = None
|
|
logistics_freight_amount: float | None = None
|
|
logistics_photo_url: str | None = None
|
|
product_names: str | None = None
|
|
status: str
|
|
line_count: int
|
|
total_delivery_qty: float
|
|
total_line_amount: float
|
|
remark: str | None = None
|
|
archive_status: str | None = None
|
|
archive_business_id: int | None = None
|
|
archive_document_type: str | None = None
|
|
archive_error_message: str | None = None
|
|
|
|
|
|
class DeliveryItemRead(BaseModel):
|
|
delivery_item_id: int
|
|
delivery_id: int
|
|
delivery_no: str
|
|
line_no: int
|
|
sales_order_item_id: int | None = None
|
|
order_no: str | None = None
|
|
product_item_id: int
|
|
product_code: str
|
|
product_name: str
|
|
lot_id: int | None = None
|
|
lot_no: str | None = None
|
|
source_material_lot_id: int | None = None
|
|
source_material_lot_no: str | None = None
|
|
source_material_code: str | None = None
|
|
source_material_name: str | None = None
|
|
source_material_sub_batch_no: str | None = None
|
|
source_material_summary: str | None = None
|
|
delivery_qty: float
|
|
delivery_weight_kg: float
|
|
unit_price: float
|
|
line_amount: float
|
|
status: str
|
|
remark: str | None = None
|
|
|
|
|
|
class CustomerSuppliedInboundCreate(BaseModel):
|
|
material_item_id: int
|
|
warehouse_id: int
|
|
location_id: int | None = None
|
|
provider_name: str | None = None
|
|
inbound_weight_kg: float
|
|
lot_no: str | None = None
|
|
remark: str | None = None
|
|
|
|
|
|
class InventorySettlementRead(BaseModel):
|
|
settlement_type: str
|
|
source_doc_type: str
|
|
source_doc_id: int
|
|
doc_no: str
|
|
counterparty_name: str
|
|
biz_date: datetime
|
|
amount: float
|
|
settled_amount: float = 0
|
|
open_amount: float
|
|
status: str
|
|
remark: str | None = None
|
|
|
|
|
|
class EquipmentCreate(BaseModel):
|
|
equipment_name: str
|
|
category_name: str | None = None
|
|
work_center_id: int
|
|
manufacturer: str | None = None
|
|
model_no: str | None = None
|
|
install_date: date | None = None
|
|
rated_power_kw: float = 0
|
|
occupied_area_sqm: float = 0
|
|
maintenance_cycle_hours: float = 0
|
|
next_maintenance_at: datetime | None = None
|
|
status: str = "IDLE"
|
|
remark: str | None = None
|
|
|
|
|
|
class EquipmentRead(BaseModel):
|
|
equipment_id: int
|
|
equipment_code: str
|
|
equipment_name: str
|
|
category_name: str | None = None
|
|
work_center_id: int
|
|
work_center_name: str
|
|
manufacturer: str | None = None
|
|
model_no: str | None = None
|
|
install_date: date | None = None
|
|
rated_power_kw: float
|
|
occupied_area_sqm: float
|
|
maintenance_cycle_hours: float
|
|
last_maintenance_at: datetime | None = None
|
|
next_maintenance_at: datetime | None = None
|
|
status: str
|
|
remark: str | None = None
|
|
|
|
|
|
class MaintenanceOrderCreate(BaseModel):
|
|
equipment_id: int
|
|
maintenance_type: str
|
|
start_time: datetime | None = None
|
|
end_time: datetime | None = None
|
|
downtime_minutes: float = 0
|
|
owner_employee_id: int | None = None
|
|
result_summary: str | None = None
|
|
cost_amount: float = 0
|
|
status: str = "CREATED"
|
|
|
|
|
|
class MaintenanceOrderRead(BaseModel):
|
|
maintenance_order_id: int
|
|
order_no: str
|
|
equipment_id: int
|
|
equipment_code: str
|
|
equipment_name: str
|
|
maintenance_type: str
|
|
start_time: datetime | None = None
|
|
end_time: datetime | None = None
|
|
downtime_minutes: float
|
|
owner_employee_id: int | None = None
|
|
owner_name: str | None = None
|
|
result_summary: str | None = None
|
|
cost_amount: float
|
|
status: str
|
|
|
|
|
|
class QualityInspectionRead(BaseModel):
|
|
receipt_item_id: int
|
|
receipt_id: int
|
|
receipt_no: str
|
|
po_no: str
|
|
supplier_name: str
|
|
target_warehouse_type: str = "RAW"
|
|
material_item_id: int
|
|
material_code: str
|
|
material_name: str
|
|
warehouse_name: str
|
|
location_name: str | None = None
|
|
lot_no: str
|
|
received_qty: float
|
|
received_weight_kg: float
|
|
accepted_qty: float
|
|
accepted_weight_kg: float
|
|
status: str
|
|
quality_status: str
|
|
inspector_name: str | None = None
|
|
receipt_date: datetime
|
|
remark: str | None = None
|
|
archive_status: str = "未生成"
|
|
archive_version: int | None = None
|
|
archive_created_at: datetime | None = None
|
|
archive_error_message: str | None = None
|
|
|
|
|
|
class QualityInspectionAction(BaseModel):
|
|
result: str
|
|
remark: str | None = None
|
|
|
|
|
|
class AccountingPeriodCreate(BaseModel):
|
|
year_no: int
|
|
month_no: int
|
|
start_date: date
|
|
end_date: date
|
|
close_status: str = "OPEN"
|
|
|
|
|
|
class AccountingPeriodRead(BaseModel):
|
|
period_id: int
|
|
period_code: str
|
|
year_no: int
|
|
month_no: int
|
|
start_date: date
|
|
end_date: date
|
|
close_status: str
|
|
closed_at: datetime | None = None
|
|
|
|
|
|
class OverheadEntryCreate(BaseModel):
|
|
period_id: int
|
|
overhead_type: str
|
|
dept_id: int | None = None
|
|
amount: float
|
|
allocation_basis: str = "WORK_HOURS"
|
|
description: str | None = None
|
|
|
|
|
|
class OverheadEntryRead(BaseModel):
|
|
overhead_entry_id: int
|
|
period_id: int
|
|
period_code: str
|
|
year_no: int
|
|
month_no: int
|
|
overhead_type: str
|
|
dept_id: int | None = None
|
|
dept_name: str | None = None
|
|
amount: float
|
|
allocation_basis: str
|
|
description: str | None = None
|
|
created_at: datetime
|
|
|
|
|
|
class ProductMaterialCostExpenseRead(BaseModel):
|
|
key: str
|
|
label: str
|
|
amount: float
|
|
|
|
|
|
class ProductMaterialCostRowRead(BaseModel):
|
|
work_order_id: int
|
|
work_order_no: str
|
|
row_no: int
|
|
biz_date: date | None = None
|
|
product_code: str
|
|
customer_name: str | None = None
|
|
product_name: str
|
|
supply_mode: str
|
|
delivery_note_no: str | None = None
|
|
order_qty: float
|
|
actual_production_qty: float
|
|
shipped_qty: float
|
|
inventory_qty: float
|
|
inventory_value: float
|
|
untaxed_unit_price: float
|
|
untaxed_total_amount: float
|
|
purchase_material_weight_kg: float
|
|
used_material_weight_kg: float
|
|
material_inventory_weight_kg: float
|
|
material_inventory_producible_qty: float
|
|
material_inventory_value: float
|
|
material_grade: str | None = None
|
|
material_unit_price_kg: float
|
|
gross_weight_g: float
|
|
gross_material_cost_per_piece: float
|
|
gross_material_total_cost: float
|
|
net_weight_g: float
|
|
scrap_weight_g: float
|
|
scrap_unit_price_kg: float
|
|
scrap_revenue_per_piece: float
|
|
scrap_total_revenue: float
|
|
material_cost_per_piece: float
|
|
material_total_cost: float
|
|
loss_rate: float
|
|
loss_total_cost: float
|
|
labor_cost_per_piece: float
|
|
labor_total_cost: float
|
|
outsource_cost_per_piece: float
|
|
outsource_total_cost: float
|
|
product_cost_per_piece: float
|
|
product_cost_with_adjustment_per_piece: float
|
|
product_total_cost: float
|
|
rework_qty: float
|
|
rework_cost_per_piece: float
|
|
rework_total_cost: float
|
|
scrap_qty: float
|
|
scrap_residual_value_per_piece: float
|
|
scrap_total_cost: float
|
|
batch_adjustment_avg_cost: float
|
|
|
|
|
|
class ProductMaterialCostSummaryRead(BaseModel):
|
|
row_count: int
|
|
sales_total: float
|
|
gross_material_total: float
|
|
scrap_revenue_total: float
|
|
material_cost_total: float
|
|
material_loss_total: float
|
|
labor_total: float
|
|
outsource_total: float
|
|
rework_total: float
|
|
scrap_total: float
|
|
overhead_total: float
|
|
direct_cost_total: float
|
|
profit_amount: float
|
|
cost_ratio: float
|
|
|
|
|
|
class ProductMaterialCostBoardRead(BaseModel):
|
|
title: str
|
|
date_from: date
|
|
date_to: date
|
|
generated_at: datetime
|
|
rows: list[ProductMaterialCostRowRead]
|
|
expense_rows: list[ProductMaterialCostExpenseRead]
|
|
summary: ProductMaterialCostSummaryRead
|
|
|
|
|
|
class CostAllocationRead(BaseModel):
|
|
cost_allocation_id: int
|
|
period_id: int
|
|
period_code: str
|
|
work_order_id: int
|
|
work_order_no: str
|
|
product_item_id: int
|
|
product_code: str
|
|
product_name: str
|
|
allocation_basis_value: float
|
|
overhead_amount: float
|
|
material_amount: float
|
|
labor_amount: float
|
|
machine_amount: float
|
|
abnormal_loss_amount: float
|
|
total_cost_amount: float
|
|
unit_cost: float
|
|
|
|
|
|
class CostAllocationGenerateResult(BaseModel):
|
|
period_id: int
|
|
period_code: str
|
|
generated_count: int
|
|
rows: list[CostAllocationRead]
|
|
|
|
|
|
class StatementSnapshotCreate(BaseModel):
|
|
period_id: int
|
|
statement_type: str
|
|
report_date: date
|
|
|
|
|
|
class StatementSnapshotRead(BaseModel):
|
|
statement_snapshot_id: int
|
|
snapshot_no: str
|
|
period_id: int
|
|
period_code: str
|
|
statement_type: str
|
|
report_date: date
|
|
summary_json: dict
|
|
created_at: datetime
|
|
|
|
|
|
class ReturnItemCreate(BaseModel):
|
|
sales_order_item_id: int | None = None
|
|
delivery_item_id: int | None = None
|
|
product_item_id: int
|
|
source_lot_id: int | None = None
|
|
return_qty: float
|
|
return_weight_kg: float = 0
|
|
responsibility_type: str | None = None
|
|
remark: str | None = None
|
|
|
|
|
|
class ReturnOrderCreate(BaseModel):
|
|
customer_id: int
|
|
sales_order_id: int | None = None
|
|
delivery_id: int | None = None
|
|
return_date: datetime | None = None
|
|
return_reason: str | None = None
|
|
handler_employee_id: int | None = None
|
|
warehouse_id: int | None = None
|
|
remark: str | None = None
|
|
items: list[ReturnItemCreate]
|
|
|
|
|
|
class ReturnScrapInboundItemCreate(BaseModel):
|
|
delivery_item_id: int
|
|
product_item_id: int
|
|
source_lot_id: int | None = None
|
|
scrap_qty: float = 0
|
|
scrap_weight_kg: float
|
|
unit_cost: float | None = None
|
|
remark: str | None = None
|
|
|
|
|
|
class ReturnScrapInboundCreate(BaseModel):
|
|
customer_id: int
|
|
delivery_id: int
|
|
warehouse_id: int
|
|
inbound_date: datetime | None = None
|
|
return_reason: str | None = None
|
|
handler_employee_id: int | None = None
|
|
remark: str | None = None
|
|
items: list[ReturnScrapInboundItemCreate]
|
|
|
|
|
|
class ReturnOrderRead(BaseModel):
|
|
return_order_id: int
|
|
return_no: str
|
|
customer_id: int
|
|
customer_name: str
|
|
sales_order_id: int | None = None
|
|
order_no: str | None = None
|
|
delivery_id: int | None = None
|
|
delivery_no: str | None = None
|
|
return_date: datetime
|
|
return_reason: str | None = None
|
|
handler_employee_id: int | None = None
|
|
handler_name: str | None = None
|
|
product_names: str | None = None
|
|
status: str
|
|
line_count: int
|
|
total_return_qty: float
|
|
remark: str | None = None
|
|
archive_status: str | None = None
|
|
archive_business_id: int | None = None
|
|
archive_document_type: str | None = None
|
|
archive_error_message: str | None = None
|
|
|
|
|
|
class ReturnItemRead(BaseModel):
|
|
return_item_id: int
|
|
return_order_id: int
|
|
return_no: str
|
|
line_no: int
|
|
sales_order_item_id: int | None = None
|
|
delivery_item_id: int | None = None
|
|
delivery_no: str | None = None
|
|
product_item_id: int
|
|
product_code: str
|
|
product_name: str
|
|
source_lot_id: int | None = None
|
|
source_lot_no: str | None = None
|
|
source_material_lot_id: int | None = None
|
|
source_material_lot_no: str | None = None
|
|
source_material_code: str | None = None
|
|
source_material_name: str | None = None
|
|
source_material_sub_batch_no: str | None = None
|
|
source_material_summary: str | None = None
|
|
return_qty: float
|
|
return_weight_kg: float
|
|
disposition_status: str
|
|
responsibility_type: str | None = None
|
|
remark: str | None = None
|
|
|
|
|
|
class ReturnDispositionCreate(BaseModel):
|
|
return_item_id: int
|
|
disposition_type: str
|
|
scrap_weight_kg: float = 0
|
|
extra_cost_amount: float = 0
|
|
scrap_sale_amount: float = 0
|
|
remark: str | None = None
|
|
|
|
|
|
class ReturnDispositionRead(BaseModel):
|
|
return_disposition_id: int
|
|
disposition_no: str
|
|
return_item_id: int
|
|
return_no: str
|
|
product_item_id: int | None = None
|
|
product_code: str
|
|
product_name: str
|
|
return_qty: float = 0
|
|
return_weight_kg: float = 0
|
|
disposition_type: str
|
|
rework_work_order_id: int | None = None
|
|
rework_work_order_no: str | None = None
|
|
rework_report_good_qty: float = 0
|
|
rework_report_scrap_qty: float = 0
|
|
rework_finished_inbound_qty: float = 0
|
|
rework_scrap_inbound_qty: float = 0
|
|
remaining_rework_finished_inbound_qty: float = 0
|
|
remaining_rework_scrap_inbound_qty: float = 0
|
|
rework_close_ready: bool = False
|
|
rework_close_status: str | None = None
|
|
scrap_weight_kg: float
|
|
extra_cost_amount: float
|
|
scrap_sale_amount: float
|
|
closed_at: datetime | None = None
|
|
status: str
|
|
remark: str | None = None
|
|
archive_status: str | None = None
|
|
archive_business_id: int | None = None
|
|
archive_document_type: str | None = None
|
|
archive_error_message: str | None = None
|
|
|
|
|
|
# --- Warehouse unified inbound/outbound schemas ---
|
|
|
|
BIZ_TYPE_INBOUND = {
|
|
"OPENING", # 期初入库
|
|
"CUSTOMER_SUPPLIED", # 客料入库
|
|
"PRODUCTION_SURPLUS", # 生产余料入库
|
|
"OUTSOURCING_SURPLUS",# 委外余料入库
|
|
"PRODUCTION_SCRAP_IN",# 生产废料入库
|
|
"REWORK_SCRAP_IN", # 返工废料入库(废料库)
|
|
"OUTSOURCING_SCRAP_IN",# 委外废料入库
|
|
"RETURN_IN", # 退货入库(退货库)
|
|
"RETURN_SCRAP_IN", # 退货废料入库(废料库)
|
|
"WIP_IN", # 产中入库(半成品)
|
|
"OUTSOURCING_IN", # 委外入库(半成品/成品)
|
|
"PRODUCTION_FINISHED",# 生产入库(成品)
|
|
}
|
|
|
|
BIZ_TYPE_OUTBOUND = {
|
|
"PRODUCTION_OUT", # 生产出库(原材料/辅料)
|
|
"OUTSOURCING_OUT", # 委外出库(原材料/半成品)
|
|
"SCRAP_OUT", # 报废出库(原材料)
|
|
"SCRAP_SALE_OUT", # 废料销售出库(废料库)
|
|
"RETURN_OUT", # 返工出库(退货库)
|
|
"WIP_OUT", # 产中出库(半成品)
|
|
"SALES_OUT", # 销售出库(成品)
|
|
}
|
|
|
|
|
|
class WarehouseInboundCreate(BaseModel):
|
|
biz_type: str
|
|
item_id: int
|
|
warehouse_id: int
|
|
location_id: int | None = None
|
|
source_lot_id: int | None = None
|
|
inbound_weight_kg: float = 0
|
|
inbound_qty: float | None = 0
|
|
unit_cost: float | None = None
|
|
lot_no: str | None = None
|
|
source_doc_type: str | None = None
|
|
source_doc_id: int | None = None
|
|
source_line_id: int | None = None
|
|
source_lot_ids: list[int] = Field(default_factory=list)
|
|
source_material_sub_batch_no: str | None = None
|
|
source_material_summary: str | None = None
|
|
provider_name: str | None = None
|
|
waybill_no: str | None = None
|
|
order_photo_url: str | None = None
|
|
freight_amount: float | None = None
|
|
remark: str | None = None
|
|
settle_work_order: bool = False
|
|
settle_remark: str | None = None
|
|
|
|
|
|
class OpeningInventoryImportResult(BaseModel):
|
|
imported: int
|
|
warehouse_type: str
|
|
message: str
|
|
|
|
|
|
class WarehouseOutboundSourceLotCreate(BaseModel):
|
|
source_lot_id: int = Field(gt=0)
|
|
outbound_weight_kg: float = Field(gt=0)
|
|
|
|
|
|
class WarehouseOutboundCreate(BaseModel):
|
|
biz_type: str
|
|
item_id: int
|
|
warehouse_id: int
|
|
location_id: int | None = None
|
|
outbound_weight_kg: float = 0
|
|
outbound_qty: float | None = 0
|
|
target_doc_type: str | None = None
|
|
target_doc_id: int | None = None
|
|
target_doc_line_id: int | None = None
|
|
target_material_sub_batch_no: str | None = None
|
|
sale_unit_price: float | None = None
|
|
buyer_name: str | None = None
|
|
sale_remark: str | None = None
|
|
waybill_no: str | None = None
|
|
order_photo_url: str | None = None
|
|
freight_amount: float | None = None
|
|
outsourcing_party_name: str | None = None
|
|
remark: str | None = None
|
|
source_lots: list[WarehouseOutboundSourceLotCreate] = Field(default_factory=list)
|
|
|
|
|
|
class WarehouseTransferCreate(BaseModel):
|
|
item_id: int
|
|
source_warehouse_id: int
|
|
target_warehouse_id: int
|
|
transfer_weight_kg: float
|
|
lot_id: int | None = None
|
|
remark: str | None = None
|
|
|
|
|
|
# --- Stocktake schemas ---
|
|
|
|
|
|
class StocktakeStartCreate(BaseModel):
|
|
warehouse_ids: list[int] = Field(min_length=1, max_length=1)
|
|
remark: str | None = None
|
|
|
|
|
|
class StocktakeWarehouseRead(BaseModel):
|
|
id: int
|
|
warehouse_id: int
|
|
warehouse_name: str
|
|
warehouse_type: str
|
|
status: str
|
|
|
|
|
|
class StocktakeLineRead(BaseModel):
|
|
id: int
|
|
stocktake_id: int
|
|
line_no: int
|
|
warehouse_id: int
|
|
warehouse_name: str
|
|
warehouse_type: str
|
|
location_id: int | None = None
|
|
location_name: str | None = None
|
|
item_id: int
|
|
item_code: str
|
|
item_name: str
|
|
item_type: str
|
|
lot_id: int | None = None
|
|
lot_no: str | None = None
|
|
source_material_sub_batch_no: str | None = None
|
|
snapshot_qty: float
|
|
snapshot_weight_kg: float
|
|
snapshot_unit_cost: float
|
|
counted_qty: float | None = None
|
|
counted_weight_kg: float | None = None
|
|
diff_qty: float
|
|
diff_weight_kg: float
|
|
diff_amount: float
|
|
diff_type: str
|
|
row_status: str
|
|
error_message: str | None = None
|
|
remark: str | None = None
|
|
|
|
|
|
class StocktakeRead(BaseModel):
|
|
id: int
|
|
stocktake_no: str
|
|
status: str
|
|
started_by_user_id: int | None = None
|
|
imported_by_user_id: int | None = None
|
|
confirmed_by_user_id: int | None = None
|
|
canceled_by_user_id: int | None = None
|
|
started_at: datetime
|
|
exported_at: datetime | None = None
|
|
imported_at: datetime | None = None
|
|
confirmed_at: datetime | None = None
|
|
canceled_at: datetime | None = None
|
|
remark: str | None = None
|
|
warehouses: list[StocktakeWarehouseRead] = Field(default_factory=list)
|
|
summary: dict[str, float | int] = Field(default_factory=dict)
|
|
|
|
|
|
class StocktakeImportPreviewRead(BaseModel):
|
|
stocktake: StocktakeRead
|
|
lines: list[StocktakeLineRead]
|
|
summary: dict[str, float | int]
|
|
|
|
|
|
class StocktakeConfirmCreate(BaseModel):
|
|
confirm_text: str | None = None
|
|
remark: str | None = None
|
|
|
|
|
|
# --- Special warehouse adjustment schemas ---
|
|
|
|
|
|
class SpecialWarehouseAdjustmentLineCreate(BaseModel):
|
|
item_id: int
|
|
lot_id: int | None = None
|
|
location_id: int | None = None
|
|
adjust_qty: Decimal | None = None
|
|
adjust_weight_kg: Decimal | None = None
|
|
unit_cost: Decimal | None = None
|
|
line_reason: str | None = None
|
|
|
|
|
|
class SpecialWarehouseAdjustmentCreate(BaseModel):
|
|
warehouse_id: int
|
|
direction: str
|
|
reason: str | None = None
|
|
lines: list[SpecialWarehouseAdjustmentLineCreate] = Field(min_length=1)
|
|
|
|
|
|
class SpecialWarehouseAdjustmentLineRead(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
adjustment_id: int
|
|
line_no: int
|
|
item_id: int
|
|
warehouse_id: int
|
|
location_id: int | None = None
|
|
lot_id: int
|
|
inventory_txn_id: int | None = None
|
|
before_qty: float
|
|
change_qty: float
|
|
after_qty: float
|
|
before_weight_kg: float
|
|
change_weight_kg: float
|
|
after_weight_kg: float
|
|
unit_cost: float
|
|
line_reason: str | None = None
|
|
|
|
|
|
class SpecialWarehouseAdjustmentRead(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
adjustment_no: str
|
|
warehouse_id: int
|
|
warehouse_type: str
|
|
direction: str
|
|
reason: str
|
|
status: str
|
|
operator_user_id: int | None = None
|
|
adjusted_at: datetime
|
|
lines: list[SpecialWarehouseAdjustmentLineRead] = Field(default_factory=list)
|
|
archive_status: str | None = None
|
|
archive_business_id: int | None = None
|
|
archive_document_type: str | None = None
|
|
archive_error_message: str | None = None
|