Files
bj_power/bj_power_wms/schema/inventory.go
T
SunYF 1cc93795ce feat(mes): 添加定时同步可生产数量到WMS及BOM项相关标准字段
- 在main.go中添加定时任务每10分钟同步可生产数量到WMS系统
- 为BomItem实体添加relatedStandard字段及相关CRUD方法
- 为InspectionRecord实体添加reportNo、materialCode、materialName等字段
- 更新ent schema确保新字段的验证和默认值设置
- 添加必要的数据库迁移和字段映射逻辑
2026-09-17 12:49:07 +08:00

117 lines
6.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package schema
import (
"entgo.io/ent"
"entgo.io/ent/schema/field"
"entgo.io/ent/schema/index"
)
// Inventory 统一库存台账
//
// 业务背景:原系统把库存拆成「结构件批次(inventory_batch)」与「电气件序列号(serial_number)」
// 两张表,导致 锁库存 / 导出 / 汇总 都要分别写两套逻辑,运维成本高且容易不一致。
// 现合并为一张表,用 manage_mode 区分管理粒度,对外提供统一的 锁/查询/汇总/盘点 能力。
//
// 两种管理粒度的存储约定:
// - manage_mode = 1 结构件(批次管理):
// 一条记录 = 一个批次,quantity 表示该批次当前余量,locked_qty 表示已锁定件数。
// 可用量 = quantity - locked_qty。出库/盘点都按"数量"增减。
// - manage_mode = 2 电气件(SN 管理):
// 一条记录 = 一个单件(SN)quantity 恒为 1locked_qty 为 0 或 1(锁定时=1)。
// 生命周期用 status 字段跟踪:在库/锁定/出库/使用/报废。
// 可用量 = quantity - locked_qty(锁定时为 0)。
//
// 库位四级贯通(U18):zone_code(区域) + shelf_no(货架) + layer_no(层) + position_no(位置),均手填、不做编号规则校验,
// 贯穿入库/出库/库存明细/盘点/导出全链路;精确货位串由 locLabel 拼接(如 Z01/A架/3层/12位)。
// 统一收编(2026-09-07 定稿):半成品/成品也进本表(category 区分品类),废除独立 semi_finisheds 孤表;
// 成品由 MES 完工发码后经内部接口自动回流入库,成品 SN 与实物码解耦(系统必发号,实物可不贴码,允许手填覆盖)。
type Inventory struct {
ent.Schema
}
// 品类(category):1=原材料 2=半成品 3=成品。与 manage_mode 正交:
// manage_mode 管"怎么管"(批次数量 vs SN 单件),category 管"是什么"(原料/半成品/成品)。
const (
InvCategoryRaw = 1
InvCategorySemi = 2
InvCategoryFinished = 3
)
func (Inventory) Fields() []ent.Field {
return []ent.Field{
// 管理粒度:1=结构件(批次) 2=电气件(SN)。决定本行按"数量"还是按"单件"解释。
field.Int("manage_mode").Comment("管理粒度 1=结构件(批次) 2=电气件(SN)"),
// 品类:1=原材料 2=半成品 3=成品(统一库存主表收编 semi_finished 后新增)
field.Int("category").Default(InvCategoryRaw).Comment("品类 1=原材料 2=半成品 3=成品"),
// 物料编码,关联 materials 主数据。
field.String("material_code").Comment("物料编码(关联 materials 表)"),
// 物料名称冗余存储,查询时无需再 join 主数据。
field.String("material_name").Optional().Comment("物料名称(冗余,便于直接展示)"),
// 批次号:结构件必填(系统生成);电气件可填所属批次用于分组追溯。
field.String("batch_no").Optional().Comment("批次号(系统生成);电气件可关联所属批次"),
// 序列号:仅电气件填写,作为单件唯一追溯锚点。全局唯一(一物一码,P2-2):
// 代码层跨 manage_mode 查重 + DB 部分唯一索引 ux_inventories_sn_code(非空值)双重保证;空值表示非 SN 行。
field.String("sn_code").Optional().Comment("序列号(SN,仅电气件);全局唯一,空值表示非 SN 行"),
// 数量:结构件=批次余量;电气件恒为 1。
field.Int("quantity").Default(0).Comment("数量:结构件=批次余量;电气件=1"),
// 已锁定数量:结构件=锁定件数;电气件=0或1。可用量 = quantity - locked_qty。
field.Int("locked_qty").Default(0).Comment("已锁定数量(库存占用):结构件=件数;电气件=0/1"),
// 检验状态,由质量检验模块翻转。
field.String("quality_status").Default("未检").Comment("检验状态 未检/合格/不合格"),
// 所在区域(大分区)。
field.String("zone_code").Optional().Comment("所在区域(Z01~Z04 大分区)"),
// 库位四级贯通(客户诉求 问题记录 L32/L169 + D5):区域→货架号→第几层→位置号。
// 与 zones 表 shelf_no/layer_no/position_no 对齐,落位到具体货架/层/位置。
field.String("shelf_no").Optional().Comment("货架号(手填,如 A)"),
field.String("layer_no").Optional().Comment("第几层(手填,如 3)"),
field.String("position_no").Optional().Comment("位置号(手填,如 12)"),
// 生命周期状态:
// 结构件一律"在库"(锁定看 locked_qty,不靠本字段);
// 电气件随业务流转:在库/锁定/出库/使用/报废。
field.String("status").Default("在库").Comment("生命周期:在库/锁定/出库/使用/报废(电气件用;结构件恒在库)"),
// 生产日期(结构件批次用)。
field.String("production_date").Optional().Comment("生产日期"),
// 供应商(结构件批次用)。
field.String("supplier").Optional().Comment("供应商"),
// 关联入库单号,便于正向追溯。
field.String("inbound_no").Optional().Comment("关联入库单号"),
// 关联工单号(半成品流转/成品完工回流时由 MES 传入)。
field.String("order_no").Default("").MaxLen(64).Comment("关联工单号(半成品/成品回流)"),
// 已完成工序(半成品暂存回流用,如 135)。
field.String("completed_process").Default("").MaxLen(64).Comment("已完成工序(半成品用,如 135)"),
// 半成品/成品入库扩展字段(客户诉求 问题记录 L218/L222/L230:归属/产品状态/相关标准/试验记录单号/记录员/记录日期)
field.String("ownership_type").Optional().Comment("归属类型 workorder/project/other"),
field.String("ownership_no").Optional().Comment("归属编号(工单号/科技项目号/其他)"),
field.String("product_status").Optional().Comment("产品状态 已通过/部分通过/返修(成品用)"),
field.String("related_standard").Optional().Comment("相关标准(试验方案号)"),
field.String("test_record_no").Optional().Comment("试验记录单号"),
field.String("recorded_by").Optional().Comment("记录员"),
field.Int64("recorded_at").Optional().Comment("记录日期(unix 秒)"),
// 半成品/成品出库原因(客户诉求 L224:包装/继续生产/检验试验/其他)
field.String("outbound_reason").Optional().Comment("出库原因(半成品/成品出库用)"),
// 备注。
field.String("remark").Optional().Comment("备注"),
field.Int64("created_at").DefaultFunc(nowUnix),
field.Int64("updated_at").DefaultFunc(nowUnix),
}
}
func (Inventory) Indexes() []ent.Index {
return []ent.Index{
index.Fields("manage_mode"),
index.Fields("category"),
index.Fields("material_code"),
index.Fields("quality_status"),
index.Fields("zone_code"),
index.Fields("batch_no"),
index.Fields("sn_code"),
}
}