feat: 完成WMS系统权限体系与业务功能迭代

本提交完成了WMS系统的多维度优化升级:
1. 新增RBAC权限系统,支持角色/菜单/按钮三级权限管控
2. 重构库存盘点、物料管理、区域维护等模块的查询筛选与展示逻辑
3. 优化入库/出库/质检等业务流程,完善数据冗余与业务闭环
4. 移除旧装箱表,将装箱逻辑合并到出库主表
5. 新增前端权限判断工具、导出工具与端到端测试用例
6. 补充完善各类注释与数据库字段说明
This commit is contained in:
SunYF
2026-09-03 14:20:37 +08:00
parent 665ff257dc
commit 572fa975bc
101 changed files with 14531 additions and 4692 deletions
+6
View File
@@ -22,6 +22,12 @@ func (InspectionRecord) Fields() []ent.Field {
field.String("inspection_type").Default("incoming").Comment("来料检/过程检/成品检"),
field.String("status").Default("未检").Comment("未检/合格/不合格"),
field.String("result_value").Optional().Comment("实测值(部分检验项)"),
// 检验数量 / 合格数量(量化闭环:来料/过程/成品检的批次抽检量)
field.Int("inspect_qty").Default(0).Comment("检验数量(抽检件数)"),
field.Int("pass_qty").Default(0).Comment("合格数量(≤检验数量)"),
// 检测说明 / 不合格原因
field.String("check_desc").Optional().Comment("检测说明(检验项目/方法)"),
field.String("fail_reason").Optional().Comment("不合格原因(不合格时必填)"),
field.String("inspector").Optional().Comment("检验人"),
field.String("remark").Optional().Comment("备注"),
field.Int64("created_at").DefaultFunc(nowUnix),
+10 -3
View File
@@ -6,8 +6,10 @@ import (
"entgo.io/ent/schema/index"
)
// OutboundOrder 出库
// 出库强约束:累计出库 ≤ 工单 BOM 需求量(由 MES 校验),WMS 侧校验 order_no 对应台账
// OutboundOrder 出库统一主表
// 所有出库(备料出库 workorder / 通用出库 general / 装箱)都落在这一张表,
// 用 outbound_type 区分;装箱属性(箱号/SN清单/合同号)直接存本表,不再单独建装箱表。
// 备料出库强约束:累计出库 ≤ 工单 BOM 需求量(由 MES 校验),WMS 侧校验 order_no 对应台账。
type OutboundOrder struct {
ent.Schema
}
@@ -15,7 +17,7 @@ type OutboundOrder struct {
func (OutboundOrder) Fields() []ent.Field {
return []ent.Field{
field.String("outbound_no").Unique().Comment("出库单号"),
// 类型:workorder(工单领料) semi(半成品) finished(成品) scrap(报废)
// 类型:workorder(工单领料/MES) general(通用出库,不依赖工单)
field.String("outbound_type").Default("workorder").Comment("出库类型"),
field.String("order_no").Optional().Comment("关联工单号(工单为唯一挂靠载体)"),
field.String("material_code").Comment("物料编码"),
@@ -28,6 +30,10 @@ func (OutboundOrder) Fields() []ent.Field {
field.String("reviewer").Optional().Comment("复核人"),
field.String("target_dock").Optional().Comment("目标接驳台(AGV配送)"),
field.String("remark").Optional().Comment("备注"),
// 装箱属性:出库时一并记录箱号/SN清单/合同号,统一落在出库主表,不再单独建装箱表
field.String("box_no").Optional().Comment("箱号(装箱出库时填写,用于整箱发货追溯)"),
field.String("box_sn_list").Optional().Comment("装箱 SN 清单(JSON 数组字符串)"),
field.String("contract_no").Optional().Comment("合同号(装箱选填)"),
field.Int64("created_at").DefaultFunc(nowUnix).Comment("创建时间"),
}
}
@@ -37,5 +43,6 @@ func (OutboundOrder) Indexes() []ent.Index {
index.Fields("order_no"),
index.Fields("material_code"),
index.Fields("outbound_type"),
index.Fields("box_no"),
}
}
-38
View File
@@ -1,38 +0,0 @@
package schema
import (
"entgo.io/ent"
"entgo.io/ent/schema/field"
"entgo.io/ent/schema/index"
)
// PackageBox 包装箱 ↔ SN 关联(装箱管理)
// 将一个或多个精密件 SN 绑定到一个箱号,便于整箱出入库与追溯。
// sn_list 以字符串存多个 SN(逗号分隔 / JSON),不强制外键关联 inventory,
// 因为装箱是业务封装动作,箱内 SN 仍各自在 inventory 表中独立流转。
type PackageBox struct {
ent.Schema
}
func (PackageBox) Fields() []ent.Field {
return []ent.Field{
field.String("box_no").Unique().Comment("箱号"),
// 关联 SN 列表(逗号分隔)或 JSON
field.String("sn_list").Optional().Comment("箱内 SN 列表"),
field.String("material_code").Optional().Comment("物料编码"),
field.Int("quantity").Default(0).Comment("箱内数量"),
field.String("operator").Optional().Comment("包装人"),
field.String("contract_no").Optional().Comment("合同号(选填)"),
field.String("remark").Optional().Comment("备注"),
field.Int64("created_at").DefaultFunc(nowUnix),
field.Int64("updated_at").DefaultFunc(nowUnix).Optional().Comment("更新时间"),
}
}
func (PackageBox) Indexes() []ent.Index {
return []ent.Index{
index.Fields("material_code"),
index.Fields("contract_no"),
index.Fields("operator"),
}
}
+40
View File
@@ -0,0 +1,40 @@
package schema
import (
"entgo.io/ent"
"entgo.io/ent/dialect/entsql"
"entgo.io/ent/schema"
"entgo.io/ent/schema/field"
"entgo.io/ent/schema/index"
)
// Permission 权限/菜单
// 模型移植自 MESschema/permission.go),按 WMS 约定调整字段命名与时间类型。
// type 区分两类:
// - MENU 菜单权限:对应侧栏菜单项,path 为前端路由
// - BUTTON 按钮权限:对应页面内的操作按钮,无 path
type Permission struct {
ent.Schema
}
func (Permission) Annotations() []schema.Annotation {
return []schema.Annotation{entsql.Annotation{Table: "permissions"}}
}
func (Permission) Fields() []ent.Field {
return []ent.Field{
field.String("code").Unique().MaxLen(64).Comment("权限编码,如 inbound:view"),
field.String("name").MaxLen(64).Comment("名称"),
field.String("type").Default("MENU").MaxLen(20).Comment("类型 MENU菜单/BUTTON按钮"),
field.String("path").Default("").MaxLen(128).Optional().Comment("前端路由(菜单类)"),
field.String("icon").Default("").MaxLen(64).Optional().Comment("图标(菜单类)"),
field.Int("sort").Default(0).Optional().Comment("排序"),
field.String("remark").Default("").MaxLen(255).Optional().Comment("备注"),
field.Int64("created_at").DefaultFunc(nowUnix).Comment("创建时间"),
field.Int64("updated_at").DefaultFunc(nowUnix).Comment("更新时间"),
}
}
func (Permission) Indexes() []ent.Index {
return []ent.Index{index.Fields("code").Unique()}
}
+41
View File
@@ -0,0 +1,41 @@
package schema
import (
"entgo.io/ent"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/entsql"
"entgo.io/ent/schema"
"entgo.io/ent/schema/field"
"entgo.io/ent/schema/index"
)
// Role 角色:承载菜单/按钮权限
// 模型移植自 MESschema/role.go),但按 WMS 约定调整:
// - 字段名 snake_case(由 tools/generate.go 统一转 camelCase 输出 JSON
// - 时间字段用 Int64 unix 秒,与 WMS 其余表保持一致
// - 与 MES 的差异:MES 的角色/权限为"系统预置只读",WMS 要求可维护,故支持增删改
type Role struct {
ent.Schema
}
func (Role) Annotations() []schema.Annotation {
return []schema.Annotation{entsql.Annotation{Table: "roles"}}
}
func (Role) Fields() []ent.Field {
return []ent.Field{
field.String("name").MaxLen(64).Comment("角色名称"),
field.String("code").Unique().MaxLen(64).Comment("角色编码,如 admin/operator/inspector"),
field.String("remark").Default("").MaxLen(255).Optional().Comment("备注"),
// 权限编码列表,如 inbound:view / inbound:create
field.JSON("permission_codes", []string{}).Optional().SchemaType(map[string]string{
dialect.Postgres: "jsonb",
}).Comment("权限编码列表"),
field.Int64("created_at").DefaultFunc(nowUnix).Comment("创建时间"),
field.Int64("updated_at").DefaultFunc(nowUnix).Comment("更新时间"),
}
}
func (Role) Indexes() []ent.Index {
return []ent.Index{index.Fields("code").Unique()}
}
+2 -1
View File
@@ -18,7 +18,8 @@ func (User) Fields() []ent.Field {
field.String("username").Unique().Comment("登录名"),
field.String("password").Comment("密码(哈希)"),
field.String("real_name").Optional().Comment("姓名"),
field.String("role").Default("operator").Comment("角色 admin/operator/inspector"),
field.String("role").Default("operator").Comment("角色 admin/operator/inspector(旧字段,权限数据化后由 role_id 决定,此字段仅作兼容/展示)"),
field.Int("role_id").Optional().Comment("角色ID,关联 roles 表;为空时回退按 role 字符串取权限"),
field.String("dept").Optional().Comment("部门"),
field.String("phone").Optional().Comment("电话"),
field.Bool("is_active").Default(true).Comment("是否启用"),