from marshmallow import Schema, fields, validate, validates_schema, ValidationError class StockBuySchema(Schema): # 只用于输出的字段 id = fields.Int(dump_only=True) # --- 输入字段 --- # 1. 核心识别字段 material_id = fields.Int(missing=None) # 如果是老物料,可能传ID sku_code = fields.Str(required=True, error_messages={"required": "SKU编码是必填项"}) # 必填 # 2. 新物料自动建档字段 (如果是新SKU,这些需要校验) material_name = fields.Str(missing=None) spec_model = fields.Str(missing=None) unit = fields.Str(missing=None) category = fields.Str(missing=None) # 3. 入库业务字段 qty_inbound = fields.Float(required=True, validate=validate.Range(min=0.0001, error="入库数量必须大于0")) price_unit = fields.Float(missing=0) inbound_date = fields.DateTime(format='%Y-%m-%d %H:%M:%S') batch_no = fields.Str(missing='') warehouse_loc = fields.Str(missing='') supplier_name = fields.Str(missing='') @validates_schema def validate_material_logic(self, data, **kwargs): """ 自定义校验逻辑: 如果用户没传 material_id,说明可能想新建物料。 虽然最终是否新建由 Service 层判断数据库决定, 但这里可以做一个弱校验:尽量让用户填上名字。 """ pass # 这里暂时不强制抛出错误,交给 Service 层处理 "SKU不存在且无名字" 的情况 class StockServiceSchema(Schema): # 只用于输出的字段 id = fields.Int(dump_only=True) sku = fields.Str(dump_only=True) created_at = fields.DateTime(format='%Y-%m-%d %H:%M:%S', dump_only=True) updated_at = fields.DateTime(format='%Y-%m-%d %H:%M:%S', dump_only=True) material_name = fields.Str(dump_only=True) spec_model = fields.Str(dump_only=True) unit = fields.Str(dump_only=True) # 输入字段 base_id = fields.Int(required=True, error_messages={"required": "必须选择基础物料"}) sale_price = fields.Float(required=True, validate=validate.Range(min=0, error="售价不能为负数")) provider_name = fields.Str(required=True, error_messages={"required": "服务商名称不能为空"}) description = fields.Str(missing='') @validates_schema def validate_base_id(self, data, **kwargs): # 可以在这里添加对 base_id 是否存在的检查,但更建议在 Service 层进行 pass # 实例化 Schema stock_buy_schema = StockBuySchema() stock_service_schema = StockServiceSchema()