Initial commit
This commit is contained in:
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import date, datetime
|
||||
from typing import Any
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class OverviewMetric(BaseModel):
|
||||
code: str
|
||||
label: str
|
||||
value: str
|
||||
unit: str | None = None
|
||||
highlight: str = "normal"
|
||||
note: str | None = None
|
||||
|
||||
|
||||
class AlertItem(BaseModel):
|
||||
level: str
|
||||
title: str
|
||||
description: str
|
||||
owner: str
|
||||
action: str
|
||||
|
||||
|
||||
class FlowStep(BaseModel):
|
||||
step_code: str
|
||||
title: str
|
||||
status: str
|
||||
summary: str
|
||||
quantity: str
|
||||
|
||||
|
||||
class BoardSection(BaseModel):
|
||||
title: str
|
||||
items: list[FlowStep]
|
||||
|
||||
|
||||
class DashboardPayload(BaseModel):
|
||||
company: str
|
||||
overview: list[OverviewMetric]
|
||||
alerts: list[AlertItem]
|
||||
flow_board: list[BoardSection]
|
||||
|
||||
|
||||
class DashboardSalesOrderRead(BaseModel):
|
||||
order_id: int
|
||||
order_no: str
|
||||
customer_code: str | None = None
|
||||
customer_name: str
|
||||
order_date: date
|
||||
promised_date: date | None = None
|
||||
delivery_address: str | None = None
|
||||
total_amount: float
|
||||
status: str
|
||||
line_count: int
|
||||
total_order_qty: float
|
||||
total_delivered_qty: float
|
||||
mrp_count: int
|
||||
purchase_order_count: int
|
||||
work_order_count: int
|
||||
completion_receipt_count: int
|
||||
delivery_count: int
|
||||
return_count: int
|
||||
updated_at: datetime | None = None
|
||||
|
||||
|
||||
class DashboardMaterialLotRead(BaseModel):
|
||||
lot_id: int
|
||||
lot_no: str
|
||||
material_item_id: int
|
||||
material_code: str
|
||||
material_name: str
|
||||
specification: str | None = None
|
||||
warehouse_name: str
|
||||
inbound_weight_kg: float
|
||||
remaining_weight_kg: float
|
||||
unit_cost: float
|
||||
inbound_amount: float
|
||||
issued_batch_count: int
|
||||
issued_weight_kg: float
|
||||
finished_batch_count: int
|
||||
finished_qty: float
|
||||
delivery_count: int
|
||||
status: str
|
||||
quality_status: str
|
||||
created_at: datetime | None = None
|
||||
|
||||
|
||||
class LifecycleDetailItem(BaseModel):
|
||||
label: str
|
||||
value: str
|
||||
|
||||
|
||||
class LifecycleNode(BaseModel):
|
||||
id: str
|
||||
type: str
|
||||
title: str
|
||||
subtitle: str | None = None
|
||||
status: str | None = None
|
||||
stage: str
|
||||
level: int
|
||||
tone: str = "normal"
|
||||
summary: str | None = None
|
||||
metrics: list[LifecycleDetailItem] = Field(default_factory=list)
|
||||
details: list[LifecycleDetailItem] = Field(default_factory=list)
|
||||
raw: dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
|
||||
class LifecycleEdge(BaseModel):
|
||||
id: str
|
||||
source: str
|
||||
target: str
|
||||
label: str | None = None
|
||||
|
||||
|
||||
class SalesOrderLifecycleRead(BaseModel):
|
||||
order: DashboardSalesOrderRead
|
||||
nodes: list[LifecycleNode]
|
||||
edges: list[LifecycleEdge]
|
||||
|
||||
|
||||
class MaterialLotLifecycleRead(BaseModel):
|
||||
lot: DashboardMaterialLotRead
|
||||
nodes: list[LifecycleNode]
|
||||
edges: list[LifecycleEdge]
|
||||
@@ -0,0 +1,644 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import date, datetime
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
|
||||
class DataCountItem(BaseModel):
|
||||
code: str
|
||||
label: str
|
||||
count: int
|
||||
|
||||
|
||||
class BroadcastMessageCreate(BaseModel):
|
||||
title: str = Field(min_length=1, max_length=100)
|
||||
content: str = Field(min_length=1, max_length=500)
|
||||
attendance_point_names: list[str] = Field(default_factory=list)
|
||||
tone: str = "INFO"
|
||||
status: str = "ACTIVE"
|
||||
starts_at: datetime | None = None
|
||||
ends_at: datetime | None = None
|
||||
sort_no: int = 0
|
||||
|
||||
|
||||
class BroadcastMessageRead(BroadcastMessageCreate):
|
||||
broadcast_id: int
|
||||
created_by: int | str | None = None
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
|
||||
class AiAssistantConfigUpdate(BaseModel):
|
||||
assistant_name: str = Field(default="嘉恒工艺助手", min_length=1, max_length=100)
|
||||
provider_name: str | None = None
|
||||
api_base_url: str | None = None
|
||||
api_key: str | None = None
|
||||
model_name: str | None = None
|
||||
temperature: float = Field(default=0.3, ge=0, le=2)
|
||||
system_prompt: str | None = None
|
||||
enabled: bool = False
|
||||
|
||||
|
||||
class AiAssistantConfigRead(AiAssistantConfigUpdate):
|
||||
config_id: int | None = None
|
||||
api_key_configured: bool = False
|
||||
updated_at: datetime | None = None
|
||||
|
||||
|
||||
class SystemConfigUpdate(BaseModel):
|
||||
config_value: str = Field(min_length=1, max_length=500)
|
||||
remark: str | None = Field(default=None, max_length=500)
|
||||
|
||||
|
||||
class SystemConfigRead(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
config_code: str
|
||||
config_name: str
|
||||
config_value: str
|
||||
remark: str | None = None
|
||||
updated_at: datetime | None = None
|
||||
|
||||
|
||||
class SmartOperationReportConfigUpdate(BaseModel):
|
||||
enabled: bool
|
||||
remark: str | None = Field(default=None, max_length=500)
|
||||
|
||||
|
||||
class SmartOperationReportConfigRead(BaseModel):
|
||||
config_code: str = "SMART_OPERATION_REPORT_ENABLED"
|
||||
config_name: str = "对接智能报工小程序"
|
||||
enabled: bool = True
|
||||
config_value: str = "开启"
|
||||
remark: str | None = None
|
||||
updated_at: datetime | None = None
|
||||
|
||||
|
||||
class LoginUser(BaseModel):
|
||||
user_id: int
|
||||
username: str
|
||||
employee_id: int
|
||||
mobile: str | None = None
|
||||
display_name: str
|
||||
title: str
|
||||
dept_name: str | None = None
|
||||
role_codes: list[str]
|
||||
role_names: list[str]
|
||||
permission_codes: list[str]
|
||||
|
||||
|
||||
class AuthLoginRequest(BaseModel):
|
||||
username: str
|
||||
password: str
|
||||
|
||||
|
||||
class AuthChangePasswordRequest(BaseModel):
|
||||
old_password: str = Field(min_length=1)
|
||||
new_password: str = Field(min_length=6, max_length=128)
|
||||
|
||||
|
||||
class AuthResetPasswordRequest(BaseModel):
|
||||
username: str = Field(min_length=1, max_length=50)
|
||||
new_password: str = Field(min_length=6, max_length=128)
|
||||
|
||||
|
||||
class AuthSession(LoginUser):
|
||||
access_token: str
|
||||
token_type: str
|
||||
expires_at: datetime
|
||||
|
||||
|
||||
class DepartmentRead(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
dept_code: str
|
||||
dept_name: str
|
||||
dept_type: str
|
||||
manager_name: str | None = None
|
||||
status: str
|
||||
|
||||
|
||||
class EmployeeRead(BaseModel):
|
||||
id: int
|
||||
employee_code: str
|
||||
employee_name: str
|
||||
dept_id: int
|
||||
dept_name: str | None = None
|
||||
mobile: str | None = None
|
||||
gender: str | None = None
|
||||
hire_date: date | None = None
|
||||
job_title: str | None = None
|
||||
shift_code: str | None = None
|
||||
is_operator: bool
|
||||
is_workshop_staff: bool
|
||||
status: str
|
||||
remark: str | None = None
|
||||
username: str | None = None
|
||||
role_names: list[str] = Field(default_factory=list)
|
||||
|
||||
|
||||
class EmployeeCreate(BaseModel):
|
||||
employee_name: str
|
||||
dept_id: int = Field(gt=0)
|
||||
mobile: str | None = None
|
||||
gender: str | None = None
|
||||
hire_date: date | None = None
|
||||
job_title: str | None = None
|
||||
shift_code: str | None = None
|
||||
manager_employee_id: int | None = None
|
||||
is_operator: bool = False
|
||||
is_workshop_staff: bool = False
|
||||
status: str = "ACTIVE"
|
||||
remark: str | None = None
|
||||
|
||||
|
||||
class EmployeeUpdate(BaseModel):
|
||||
employee_name: str
|
||||
dept_id: int = Field(gt=0)
|
||||
mobile: str | None = None
|
||||
gender: str | None = None
|
||||
hire_date: date | None = None
|
||||
job_title: str | None = None
|
||||
shift_code: str | None = None
|
||||
manager_employee_id: int | None = None
|
||||
is_operator: bool = False
|
||||
is_workshop_staff: bool = False
|
||||
status: str = "ACTIVE"
|
||||
remark: str | None = None
|
||||
|
||||
|
||||
class MiniAppPersonnelRead(BaseModel):
|
||||
phone: str
|
||||
name: str
|
||||
role: str | None = None
|
||||
role_name: str | None = None
|
||||
roles: list[str] = Field(default_factory=list)
|
||||
role_names: list[str] = Field(default_factory=list)
|
||||
attendance_point_names: list[str] = Field(default_factory=list)
|
||||
is_temporary: bool = False
|
||||
temporary_expires_at: datetime | None = None
|
||||
temporary_expired: bool = False
|
||||
created_at: datetime | None = None
|
||||
updated_at: datetime | None = None
|
||||
|
||||
|
||||
class MiniAppPersonnelUpsert(BaseModel):
|
||||
phone: str = Field(min_length=1, max_length=20)
|
||||
name: str = Field(min_length=1, max_length=64)
|
||||
roles: list[str] = Field(default_factory=lambda: ["worker"])
|
||||
attendance_point_names: list[str] = Field(default_factory=list)
|
||||
is_temporary: bool = False
|
||||
temporary_expires_at: datetime | None = None
|
||||
|
||||
|
||||
class MiniAppAttendancePointRead(BaseModel):
|
||||
name: str
|
||||
latitude: float | None = None
|
||||
longitude: float | None = None
|
||||
radius_meters: int = 500
|
||||
remark: str | None = None
|
||||
is_active: bool = True
|
||||
created_at: datetime | None = None
|
||||
updated_at: datetime | None = None
|
||||
|
||||
|
||||
class MiniAppProductRead(BaseModel):
|
||||
attendance_point_name: str
|
||||
project_no: str
|
||||
product_name: str
|
||||
profile_no: str | None = None
|
||||
material_code: str | None = None
|
||||
material_name: str | None = None
|
||||
supplier: str | None = None
|
||||
product_net_weight_kg: float | None = None
|
||||
product_gross_weight_kg: float | None = None
|
||||
allowed_scrap_rate: float | None = None
|
||||
scrap_loss_rate: float | None = None
|
||||
waste_price_yuan_per_kg: float | None = None
|
||||
device_no: str
|
||||
process_name: str | None = None
|
||||
stamping_method: str | None = None
|
||||
operator_count: float = 1
|
||||
standard_beat: float = 0
|
||||
standard_workload: float = 0
|
||||
display_name: str
|
||||
created_at: datetime | None = None
|
||||
updated_at: datetime | None = None
|
||||
|
||||
|
||||
class MiniAppProductUpsert(BaseModel):
|
||||
attendance_point_name: str = Field(min_length=1, max_length=128)
|
||||
project_no: str = Field(min_length=1, max_length=64)
|
||||
product_name: str = Field(min_length=1, max_length=255)
|
||||
profile_no: str | None = None
|
||||
material_code: str | None = None
|
||||
material_name: str | None = None
|
||||
supplier: str | None = None
|
||||
product_net_weight_kg: float | None = Field(default=None, ge=0)
|
||||
product_gross_weight_kg: float | None = Field(default=None, ge=0)
|
||||
allowed_scrap_rate: float | None = Field(default=None, ge=0)
|
||||
scrap_loss_rate: float | None = Field(default=None, ge=0)
|
||||
waste_price_yuan_per_kg: float | None = Field(default=None, ge=0)
|
||||
device_no: str = Field(default="", max_length=64)
|
||||
process_name: str = Field(default="", max_length=128)
|
||||
stamping_method: str | None = None
|
||||
operator_count: float = Field(default=1, ge=0)
|
||||
standard_beat: float = Field(default=0, ge=0)
|
||||
standard_workload: float = Field(default=0, ge=0)
|
||||
original_attendance_point_name: str | None = None
|
||||
original_project_no: str | None = None
|
||||
original_product_name: str | None = None
|
||||
original_device_no: str | None = None
|
||||
original_process_name: str | None = None
|
||||
|
||||
|
||||
class MiniAppProductImportResult(BaseModel):
|
||||
imported: int = 0
|
||||
updated: int = 0
|
||||
skipped: int = 0
|
||||
errors: list[str] = Field(default_factory=list)
|
||||
material_sync: dict[str, object] = Field(default_factory=dict)
|
||||
product_specs: dict[str, int] = Field(default_factory=dict)
|
||||
message: str
|
||||
|
||||
|
||||
class MiniAppMaterialWastePriceSync(BaseModel):
|
||||
material_code: str | None = None
|
||||
material_name: str | None = None
|
||||
waste_price_yuan_per_kg: float = Field(default=0, ge=0)
|
||||
|
||||
|
||||
class WarehouseRead(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
warehouse_code: str
|
||||
warehouse_name: str
|
||||
warehouse_type: str
|
||||
status: str
|
||||
|
||||
|
||||
class ItemRead(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
item_code: str
|
||||
item_name: str
|
||||
item_type: str
|
||||
specification: str | None = None
|
||||
material_grade: str | None = None
|
||||
unit_weight_kg: float
|
||||
safety_stock_weight_kg: float
|
||||
status: str
|
||||
|
||||
|
||||
class MaterialRead(BaseModel):
|
||||
item_id: int
|
||||
item_code: str
|
||||
item_name: str
|
||||
specification: str | None = None
|
||||
material_grade: str | None = None
|
||||
unit_weight_kg: float = 0
|
||||
safety_stock_weight_kg: float = 0
|
||||
scrap_sale_price: float = 0
|
||||
default_supplier_id: int | None = None
|
||||
supplier_name: str | None = None
|
||||
purchase_calc_mode: str
|
||||
min_purchase_qty: float
|
||||
purchase_multiple_qty: float
|
||||
purchase_multiple_weight_kg: float
|
||||
lead_time_days: int
|
||||
quality_rule: str | None = None
|
||||
remark: str | None = None
|
||||
status: str = "ACTIVE"
|
||||
|
||||
|
||||
class ProductRead(BaseModel):
|
||||
item_id: int
|
||||
item_code: str
|
||||
item_name: str
|
||||
specification: str | None = None
|
||||
drawing_no: str | None = None
|
||||
product_family: str | None = None
|
||||
version_no: str
|
||||
unit_weight_kg: float
|
||||
allowed_scrap_rate: float
|
||||
standard_output_qty: float = 0
|
||||
quality_standard: str | None = None
|
||||
safety_stock_weight_kg: float = 0
|
||||
status: str
|
||||
|
||||
|
||||
class ProductCreate(BaseModel):
|
||||
item_code: str | None = None
|
||||
item_name: str
|
||||
specification: str | None = None
|
||||
drawing_no: str | None = None
|
||||
product_family: str | None = None
|
||||
version_no: str = "V1.0"
|
||||
unit_weight_kg: float = Field(gt=0)
|
||||
allowed_scrap_rate: float = Field(default=0, ge=0)
|
||||
standard_output_qty: float = Field(default=0, ge=0)
|
||||
quality_standard: str | None = None
|
||||
safety_stock_weight_kg: float = Field(default=0, ge=0)
|
||||
status: str = "ACTIVE"
|
||||
|
||||
|
||||
class ProductUpdate(BaseModel):
|
||||
item_code: str | None = None
|
||||
item_name: str
|
||||
specification: str | None = None
|
||||
drawing_no: str | None = None
|
||||
product_family: str | None = None
|
||||
version_no: str
|
||||
unit_weight_kg: float = Field(gt=0)
|
||||
allowed_scrap_rate: float = Field(default=0, ge=0)
|
||||
standard_output_qty: float = Field(default=0, ge=0)
|
||||
quality_standard: str | None = None
|
||||
safety_stock_weight_kg: float = Field(default=0, ge=0)
|
||||
status: str = "ACTIVE"
|
||||
|
||||
|
||||
class MaterialCreate(BaseModel):
|
||||
item_code: str | None = None
|
||||
item_name: str
|
||||
specification: str
|
||||
material_grade: str
|
||||
unit_weight_kg: float = Field(gt=0)
|
||||
safety_stock_weight_kg: float = Field(default=0, ge=0)
|
||||
scrap_sale_price: float = Field(default=0, ge=0)
|
||||
default_supplier_id: int | None = None
|
||||
purchase_calc_mode: str = "BY_WEIGHT"
|
||||
min_purchase_qty: float = Field(default=0, ge=0)
|
||||
purchase_multiple_qty: float = Field(default=0, ge=0)
|
||||
purchase_multiple_weight_kg: float = Field(default=0, ge=0)
|
||||
lead_time_days: int = Field(default=0, ge=0)
|
||||
quality_rule: str | None = None
|
||||
remark: str | None = None
|
||||
status: str = "ACTIVE"
|
||||
|
||||
|
||||
class MaterialUpdate(MaterialCreate):
|
||||
pass
|
||||
|
||||
|
||||
class BomItemPayload(BaseModel):
|
||||
seq_no: int = Field(gt=0)
|
||||
material_item_id: int = Field(gt=0)
|
||||
usage_type: str = "WEIGHT"
|
||||
qty_per_piece: float = Field(default=1, gt=0)
|
||||
net_weight_per_piece_kg: float = Field(default=0, ge=0)
|
||||
gross_weight_per_piece_kg: float = Field(default=0, ge=0)
|
||||
loss_rate: float = Field(default=0, ge=0)
|
||||
issue_over_tolerance_rate: float = Field(default=0, ge=0)
|
||||
remark: str | None = None
|
||||
|
||||
|
||||
class BomItemRead(BomItemPayload):
|
||||
bom_item_id: int
|
||||
material_code: str
|
||||
material_name: str
|
||||
seq_no: int
|
||||
material_item_id: int
|
||||
usage_type: str
|
||||
qty_per_piece: float
|
||||
net_weight_per_piece_kg: float
|
||||
gross_weight_per_piece_kg: float
|
||||
loss_rate: float
|
||||
issue_over_tolerance_rate: float
|
||||
remark: str | None = None
|
||||
|
||||
|
||||
class BomRead(BaseModel):
|
||||
bom_id: int
|
||||
bom_code: str
|
||||
product_item_id: int
|
||||
product_code: str
|
||||
product_name: str
|
||||
version_no: str
|
||||
is_default: bool
|
||||
status: str
|
||||
effective_date: date | None = None
|
||||
expire_date: date | None = None
|
||||
remark: str | None = None
|
||||
item_count: int = 0
|
||||
items: list[BomItemRead] = Field(default_factory=list)
|
||||
|
||||
|
||||
class BomUpsert(BaseModel):
|
||||
bom_code: str | None = None
|
||||
product_item_id: int
|
||||
version_no: str = "V1.0"
|
||||
is_default: bool = True
|
||||
status: str = "ACTIVE"
|
||||
effective_date: date | None = None
|
||||
expire_date: date | None = None
|
||||
remark: str | None = None
|
||||
items: list[BomItemPayload]
|
||||
|
||||
|
||||
class ProcessRead(BaseModel):
|
||||
process_id: int
|
||||
process_code: str
|
||||
process_name: str
|
||||
process_type: str
|
||||
is_report_required: bool
|
||||
is_quality_gate: bool
|
||||
status: str
|
||||
|
||||
|
||||
class RouteOperationPayload(BaseModel):
|
||||
seq_no: int = Field(gt=0)
|
||||
process_id: int = Field(gt=0)
|
||||
work_center_id: int = Field(gt=0)
|
||||
operation_name: str
|
||||
std_setup_minutes: float = Field(default=0, ge=0)
|
||||
std_cycle_seconds: float = Field(default=0, ge=0)
|
||||
std_labor_cost: float = Field(default=0, ge=0)
|
||||
std_machine_cost: float = Field(default=0, ge=0)
|
||||
std_outsource_cost: float = Field(default=0, ge=0)
|
||||
allowed_scrap_rate: float = Field(default=0, ge=0)
|
||||
report_required: bool = True
|
||||
is_key_operation: bool = False
|
||||
status: str = "ACTIVE"
|
||||
remark: str | None = None
|
||||
|
||||
|
||||
class RouteOperationRead(RouteOperationPayload):
|
||||
route_operation_id: int
|
||||
process_code: str
|
||||
process_name: str
|
||||
stamping_method: str | None = None
|
||||
work_center_code: str
|
||||
work_center_name: str
|
||||
seq_no: int
|
||||
process_id: int
|
||||
work_center_id: int
|
||||
operation_name: str
|
||||
std_setup_minutes: float
|
||||
std_cycle_seconds: float
|
||||
std_labor_cost: float
|
||||
std_machine_cost: float
|
||||
std_outsource_cost: float
|
||||
allowed_scrap_rate: float
|
||||
report_required: bool
|
||||
is_key_operation: bool
|
||||
status: str
|
||||
remark: str | None = None
|
||||
|
||||
|
||||
class ProcessRouteRead(BaseModel):
|
||||
route_id: int
|
||||
route_code: str
|
||||
route_name: str
|
||||
product_item_id: int
|
||||
product_code: str
|
||||
product_name: str
|
||||
version_no: str
|
||||
is_default: bool
|
||||
status: str
|
||||
effective_date: date | None = None
|
||||
expire_date: date | None = None
|
||||
remark: str | None = None
|
||||
operation_count: int = 0
|
||||
operations: list[RouteOperationRead] = Field(default_factory=list)
|
||||
|
||||
|
||||
class ProcessRouteUpsert(BaseModel):
|
||||
route_code: str | None = None
|
||||
route_name: str
|
||||
product_item_id: int
|
||||
version_no: str = "V1.0"
|
||||
is_default: bool = True
|
||||
status: str = "ACTIVE"
|
||||
effective_date: date | None = None
|
||||
expire_date: date | None = None
|
||||
remark: str | None = None
|
||||
operations: list[RouteOperationPayload]
|
||||
|
||||
|
||||
class SalesOrderRead(BaseModel):
|
||||
order_id: int
|
||||
order_no: str
|
||||
customer_id: int
|
||||
customer_code: str
|
||||
customer_name: str
|
||||
sales_employee_id: int | None = None
|
||||
sales_employee_name: str | None = None
|
||||
order_date: date
|
||||
promised_date: date | None = None
|
||||
delivery_address: str | None = None
|
||||
total_amount: float
|
||||
status: str
|
||||
line_count: int
|
||||
mrp_count: int = 0
|
||||
purchase_order_count: int = 0
|
||||
delivery_count: int = 0
|
||||
delivery_item_count: int = 0
|
||||
work_order_count: int = 0
|
||||
can_delete: bool = False
|
||||
archive_status: str = "未生成"
|
||||
archive_version: int | None = None
|
||||
archive_created_at: datetime | None = None
|
||||
archive_error_message: str | None = None
|
||||
|
||||
|
||||
class CustomerRead(BaseModel):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
id: int
|
||||
customer_code: str
|
||||
customer_name: str
|
||||
short_name: str | None = None
|
||||
contact_name: str | None = None
|
||||
contact_phone: str | None = None
|
||||
contacts: list[dict[str, str]] = Field(default_factory=list, max_length=3)
|
||||
address: str | None = None
|
||||
credit_days: int = 0
|
||||
status: str
|
||||
|
||||
|
||||
class CustomerCreate(BaseModel):
|
||||
customer_name: str
|
||||
short_name: str | None = None
|
||||
contact_name: str | None = None
|
||||
contact_phone: str | None = None
|
||||
contacts: list[dict[str, str]] = Field(default_factory=list, max_length=3)
|
||||
address: str | None = None
|
||||
tax_no: str | None = None
|
||||
credit_days: int = 30
|
||||
|
||||
|
||||
class SalesOrderItemCreate(BaseModel):
|
||||
product_item_id: int
|
||||
order_qty: float
|
||||
unit_price: float
|
||||
promised_date: date | None = None
|
||||
customer_part_no: str | None = None
|
||||
|
||||
|
||||
class SalesOrderCreate(BaseModel):
|
||||
customer_id: int
|
||||
sales_employee_id: int | None = None
|
||||
promised_date: date | None = None
|
||||
delivery_address: str | None = None
|
||||
tax_rate: float = 0
|
||||
remark: str | None = None
|
||||
items: list[SalesOrderItemCreate]
|
||||
|
||||
|
||||
class SalesOrderItemRead(BaseModel):
|
||||
sales_order_item_id: int
|
||||
sales_order_id: int
|
||||
order_no: str
|
||||
line_no: int
|
||||
product_item_id: int
|
||||
product_code: str
|
||||
product_name: str
|
||||
customer_part_no: str | None = None
|
||||
order_qty: float
|
||||
delivered_qty: float
|
||||
unit_price: float
|
||||
line_amount: float
|
||||
promised_date: date | None = None
|
||||
status: str
|
||||
|
||||
|
||||
class SalesOrderCreateResult(BaseModel):
|
||||
order_id: int
|
||||
order_no: str
|
||||
total_amount: float
|
||||
item_count: int
|
||||
status: str
|
||||
archive_status: str = "未生成"
|
||||
archive_version: int | None = None
|
||||
archive_error_message: str | None = None
|
||||
|
||||
|
||||
class MaterialDemandRead(BaseModel):
|
||||
demand_id: int
|
||||
demand_no: str
|
||||
order_no: str
|
||||
material_item_id: int
|
||||
product_code: str
|
||||
product_name: str
|
||||
material_code: str
|
||||
material_name: str
|
||||
purchase_calc_mode: str
|
||||
order_qty: float
|
||||
theoretical_weight_kg: float
|
||||
planned_weight_kg: float
|
||||
shortage_weight_kg: float
|
||||
suggested_purchase_qty: float
|
||||
suggested_purchase_weight_kg: float
|
||||
status: str
|
||||
generated_at: datetime | None = None
|
||||
|
||||
|
||||
class MrpGenerationResult(BaseModel):
|
||||
sales_order_id: int
|
||||
order_no: str
|
||||
generated_count: int
|
||||
demand_rows: list[MaterialDemandRead]
|
||||
@@ -0,0 +1,35 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
|
||||
|
||||
class DocumentArchiveRead(BaseModel):
|
||||
archive_id: int
|
||||
document_type: str
|
||||
business_id: int
|
||||
document_no: str
|
||||
archive_version: int
|
||||
template_version: str
|
||||
file_format: str
|
||||
file_name: str
|
||||
status: str
|
||||
error_message: str | None = None
|
||||
created_at: datetime
|
||||
|
||||
|
||||
class DocumentArchiveGenerateResult(BaseModel):
|
||||
business_id: int
|
||||
document_type: str
|
||||
document_no: str
|
||||
archive_status: str
|
||||
archive_version: int | None = None
|
||||
archive_error_message: str | None = None
|
||||
|
||||
|
||||
class DocumentArchiveBatchDownloadRequest(BaseModel):
|
||||
model_config = ConfigDict(validate_default=True)
|
||||
|
||||
document_type: str
|
||||
business_ids: list[int] = Field(default_factory=list, min_length=1)
|
||||
@@ -0,0 +1,52 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class ProductSummary(BaseModel):
|
||||
product_code: str
|
||||
product_name: str
|
||||
material_name: str
|
||||
order_qty: int
|
||||
unit_weight_kg: float
|
||||
gross_material_kg_per_piece: float
|
||||
planned_material_weight_kg: float
|
||||
suggested_purchase_weight_kg: float
|
||||
purchase_multiple_weight_kg: float
|
||||
|
||||
|
||||
class OperationCostLine(BaseModel):
|
||||
seq_no: int
|
||||
operation_name: str
|
||||
work_center: str
|
||||
std_labor_cost: float
|
||||
std_machine_cost: float
|
||||
allowed_scrap_rate: float
|
||||
reported_good_qty: int
|
||||
reported_scrap_qty: int
|
||||
abnormal: bool
|
||||
|
||||
|
||||
class InventoryLotSummary(BaseModel):
|
||||
lot_no: str
|
||||
item_name: str
|
||||
warehouse: str
|
||||
location: str
|
||||
inbound_weight_kg: float
|
||||
remaining_weight_kg: float
|
||||
status: str
|
||||
|
||||
|
||||
class MiniAppField(BaseModel):
|
||||
field_name: str
|
||||
label: str
|
||||
required: bool
|
||||
description: str
|
||||
|
||||
|
||||
class CostInsight(BaseModel):
|
||||
category: str
|
||||
amount: float
|
||||
ratio: float
|
||||
note: str
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,160 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class PermissionRead(BaseModel):
|
||||
permission_id: int
|
||||
permission_code: str
|
||||
permission_name: str
|
||||
module_code: str
|
||||
action_code: str
|
||||
status: str
|
||||
|
||||
|
||||
class MenuPermissionNode(BaseModel):
|
||||
permission_code: str
|
||||
permission_name: str
|
||||
children: list["MenuPermissionNode"] = Field(default_factory=list)
|
||||
|
||||
|
||||
class OrgEmployeeNode(BaseModel):
|
||||
employee_id: int
|
||||
employee_name: str
|
||||
mobile: str | None = None
|
||||
job_title: str | None = None
|
||||
username: str | None = None
|
||||
role_names: list[str] = Field(default_factory=list)
|
||||
status: str
|
||||
|
||||
|
||||
class OrgNodeRead(BaseModel):
|
||||
node_id: int
|
||||
node_type: str
|
||||
node_label: str
|
||||
parent_id: int | None = None
|
||||
dept_code: str
|
||||
dept_type: str
|
||||
manager_employee_id: int | None = None
|
||||
manager_name: str | None = None
|
||||
manager_employee_ids: list[int] = Field(default_factory=list)
|
||||
manager_names: list[str] = Field(default_factory=list)
|
||||
status: str
|
||||
sort_no: int = 0
|
||||
remark: str | None = None
|
||||
employees: list[OrgEmployeeNode] = Field(default_factory=list)
|
||||
children: list["OrgNodeRead"] = Field(default_factory=list)
|
||||
|
||||
|
||||
class OrgNodeCreate(BaseModel):
|
||||
parent_id: int | None = None
|
||||
node_type: str = Field(pattern="^(COMPANY|BRANCH|DEPARTMENT|GROUP)$")
|
||||
node_label: str = Field(min_length=1, max_length=100)
|
||||
dept_code: str | None = Field(default=None, max_length=50)
|
||||
dept_type: str = Field(default="ADMIN", max_length=32)
|
||||
manager_employee_id: int | None = None
|
||||
manager_employee_ids: list[int] = Field(default_factory=list)
|
||||
sort_no: int = 0
|
||||
remark: str | None = Field(default=None, max_length=255)
|
||||
status: str = Field(default="ACTIVE", pattern="^(ACTIVE|INACTIVE)$")
|
||||
|
||||
|
||||
class OrgNodeUpdate(BaseModel):
|
||||
node_label: str = Field(min_length=1, max_length=100)
|
||||
dept_type: str = Field(default="ADMIN", max_length=32)
|
||||
manager_employee_id: int | None = None
|
||||
manager_employee_ids: list[int] = Field(default_factory=list)
|
||||
sort_no: int = 0
|
||||
remark: str | None = Field(default=None, max_length=255)
|
||||
status: str = Field(default="ACTIVE", pattern="^(ACTIVE|INACTIVE)$")
|
||||
|
||||
|
||||
class OrgEmployeeBind(BaseModel):
|
||||
employee_id: int = Field(gt=0)
|
||||
sort_no: int = 0
|
||||
|
||||
|
||||
class RoleRead(BaseModel):
|
||||
role_id: int
|
||||
role_code: str
|
||||
role_name: str
|
||||
role_scope: str
|
||||
status: str
|
||||
remark: str | None = None
|
||||
permission_codes: list[str] = Field(default_factory=list)
|
||||
user_count: int = 0
|
||||
created_at: datetime | None = None
|
||||
updated_at: datetime | None = None
|
||||
|
||||
|
||||
class RoleCreate(BaseModel):
|
||||
role_code: str = Field(min_length=2, max_length=50, pattern="^[A-Z][A-Z0-9_]*$")
|
||||
role_name: str = Field(min_length=1, max_length=100)
|
||||
role_scope: str = Field(default="SYSTEM", max_length=32)
|
||||
status: str = Field(default="ACTIVE", pattern="^(ACTIVE|INACTIVE)$")
|
||||
remark: str | None = Field(default=None, max_length=500)
|
||||
permission_codes: list[str] = Field(default_factory=list)
|
||||
|
||||
|
||||
class RoleUpdate(BaseModel):
|
||||
role_name: str = Field(min_length=1, max_length=100)
|
||||
role_scope: str = Field(default="SYSTEM", max_length=32)
|
||||
status: str = Field(default="ACTIVE", pattern="^(ACTIVE|INACTIVE)$")
|
||||
remark: str | None = Field(default=None, max_length=500)
|
||||
permission_codes: list[str] = Field(default_factory=list)
|
||||
|
||||
|
||||
class RolePermissionUpdate(BaseModel):
|
||||
permission_codes: list[str] = Field(default_factory=list)
|
||||
|
||||
|
||||
class SystemUserRead(BaseModel):
|
||||
user_id: int
|
||||
username: str
|
||||
employee_id: int
|
||||
employee_name: str
|
||||
dept_id: int
|
||||
dept_name: str | None = None
|
||||
mobile: str | None = None
|
||||
nickname: str | None = None
|
||||
is_super_admin: bool = False
|
||||
status: str
|
||||
role_ids: list[int] = Field(default_factory=list)
|
||||
role_names: list[str] = Field(default_factory=list)
|
||||
last_login_at: datetime | None = None
|
||||
created_at: datetime | None = None
|
||||
updated_at: datetime | None = None
|
||||
|
||||
|
||||
class SystemUserCreate(BaseModel):
|
||||
employee_id: int = Field(gt=0)
|
||||
role_ids: list[int] = Field(min_length=1)
|
||||
password: str = Field(min_length=6, max_length=128)
|
||||
status: str = Field(default="ACTIVE", pattern="^(ACTIVE|INACTIVE)$")
|
||||
|
||||
|
||||
class SystemUserRoleUpdate(BaseModel):
|
||||
role_ids: list[int] = Field(min_length=1)
|
||||
|
||||
|
||||
class SystemUserStatusUpdate(BaseModel):
|
||||
status: str = Field(pattern="^(ACTIVE|INACTIVE)$")
|
||||
|
||||
|
||||
class SystemUserPasswordReset(BaseModel):
|
||||
password: str = Field(min_length=6, max_length=128)
|
||||
|
||||
|
||||
class EmployeeOption(BaseModel):
|
||||
employee_id: int
|
||||
employee_name: str
|
||||
dept_id: int
|
||||
dept_name: str | None = None
|
||||
mobile: str | None = None
|
||||
job_title: str | None = None
|
||||
username: str | None = None
|
||||
role_names: list[str] = Field(default_factory=list)
|
||||
permission_codes: list[str] = Field(default_factory=list)
|
||||
has_system_user: bool = False
|
||||
Reference in New Issue
Block a user