Files
SunYF 62e45b7379 feat: 完成附件存储重构与磁盘监控功能,同步物料档案与入库单规则更新
1.  新增跨平台磁盘空间监控能力,每日7点自动检测附件目录剩余空间,触发阈值告警
2.  重构附件存储方案为年/月/日/文件类型分层结构,统一MES与WMS的附件管理逻辑
3.  对齐物料档案与入库单的质量状态校验规则,仅合格品计入库存与出库
4.  实现入库单作废功能与区域库位的多级父子结构管理
5.  删除物料简称字段,补充规格型号与单位必填项,统一系统数据口径
6.  新增附件中心与磁盘状态查询接口,完善权限控制与操作日志
2026-09-19 10:54:15 +08:00

193 lines
5.1 KiB
Go
Raw Permalink 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 db
import (
"context"
"fmt"
"log/slog"
"time"
"bj_power_wms/ent"
"golang.org/x/crypto/bcrypt"
)
// SeedIfEmpty 首次启动时预置基础数据(区域/账号/演示物料与库存)
func SeedIfEmpty(client *ent.Client) error {
ctx := context.Background()
// 1. 区域(层级节点 level=1
zones, _ := client.Zone.Query().Count(ctx)
if zones == 0 {
for _, z := range []struct{ code, name string }{
{"Z01", "待检区"},
{"Z02", "标准存储区"},
{"Z03", "暂存区"},
{"Z04", "退货区"},
} {
client.Zone.Create().
SetLevel(1).
SetCode(z.code).
SetZoneName(z.name).
SetZoneCode(z.code).
SetParentCode("").
SetStatus("启用").
SaveX(ctx)
}
slog.Info("seed: zones created")
}
// 2. 账号(全部统一初始密码 123456)
users, _ := client.User.Query().Count(ctx)
if users == 0 {
adminHash, _ := bcrypt.GenerateFromPassword([]byte("123456"), bcrypt.DefaultCost)
opHash, _ := bcrypt.GenerateFromPassword([]byte("123456"), bcrypt.DefaultCost)
client.User.Create().
SetUsername("admin").
SetPassword(string(adminHash)).
SetRealName("系统管理员").
SetRole("admin").
SaveX(ctx)
client.User.Create().
SetUsername("store1").
SetPassword(string(opHash)).
SetRealName("一号库房保管员").
SetRole("operator").
SetDept("库房").
SaveX(ctx)
client.User.Create().
SetUsername("insp1").
SetPassword(string(opHash)).
SetRealName("质检员一号").
SetRole("inspector").
SetDept("质检").
SaveX(ctx)
slog.Info("seed: users created (admin/123456, store1/123456, insp1/123456)")
}
// 3. 演示物料与库存
materials, _ := client.Material.Query().Count(ctx)
if materials == 0 {
mats := []struct {
code, name, spec, unit string
mode int
isBatch, isSerial bool
}{
{"GJ-BAN-001", "10mm钢板(结构件)", "2000x1000x10", "张", 1, true, false},
{"GJ-GANGGUAN-002", "无缝钢管114x8", "114x8x6000", "根", 1, true, false},
{"LJ-LUOSI-M16", "M16高强度螺栓", "M16x80 10.9级", "件", 1, true, false},
{"JM-ZHOUCHENG-6020", "精密轴承6020", "6020-2RS", "套", 2, false, true},
{"JM-DIANJI-750W", "伺服电机750W", "ECMA-C21307", "台", 2, false, true},
{"BCP-JIEKOUTI", "接驳体半成品", "-", "件", 2, false, true},
}
for _, m := range mats {
client.Material.Create().
SetCode(m.code).
SetName(m.name).
SetNillableSpec(strPtrNil(m.spec)).
SetNillableUnit(strPtrNil(m.unit)).
SetManageMode(m.mode).
SetIsBatchManaged(m.isBatch).
SetIsSerialManaged(m.isSerial).
SaveX(ctx)
}
// 演示库存(统一 inventory 表,manage_mode 区分结构件/电气件)
today := time.Now().Format("2006-01-02")
// 结构件批次(已检合格)
client.Inventory.Create().
SetManageMode(1).
SetMaterialCode("GJ-BAN-001").
SetNillableMaterialName(strPtrNil("10mm钢板(结构件)")).
SetBatchNo("B2026060100001").
SetQuantity(120).SetLockedQty(0).
SetNillableProductionDate(strPtrNil("2026-06-01")).
SetNillableSupplier(strPtrNil("宝钢供应商")).
SetQualityStatus("合格").
SetNillableZoneCode(strPtrNil("Z02")).
SetStatus("在库").
SaveX(ctx)
client.Inventory.Create().
SetManageMode(1).
SetMaterialCode("GJ-GANGGUAN-002").
SetNillableMaterialName(strPtrNil("无缝钢管114x8")).
SetBatchNo("B2026060200034").
SetQuantity(50).SetLockedQty(0).
SetNillableProductionDate(strPtrNil(today)).
SetNillableSupplier(strPtrNil("天津钢管")).
SetQualityStatus("未检").
SetNillableZoneCode(strPtrNil("Z01")).
SetStatus("在库").
SaveX(ctx)
// 电气件 SN(在库,合格)
for i := 1; i <= 5; i++ {
client.Inventory.Create().
SetManageMode(2).
SetMaterialCode("JM-ZHOUCHENG-6020").
SetNillableMaterialName(strPtrNil("精密轴承6020")).
SetSnCode("SN20260601001" + itoaPad(i)).
SetQuantity(1).SetLockedQty(0).
SetQualityStatus("合格").
SetNillableZoneCode(strPtrNil("Z02")).
SetStatus("在库").
SaveX(ctx)
}
slog.Info("seed: demo materials & stock created")
}
// 4. 接驳台主数据 DOCK01~20(产线, DOCKn↔工位n) + DOCK21(库房)
docks, _ := client.Dock.Query().Count(ctx)
if docks == 0 {
for i := 1; i <= 20; i++ {
code := fmt.Sprintf("DOCK%02d", i)
client.Dock.Create().
SetDockCode(code).
SetName("产线接驳台 " + code + "(工位" + fmt.Sprintf("%d", i) + "").
SetDockType("line").
SetStationNo(i).
SetHasPallet(false).
SetStatus("ENABLED").
SaveX(ctx)
}
client.Dock.Create().
SetDockCode("DOCK21").
SetName("库房收货接驳台").
SetDockType("store").
SetStationNo(0).
SetHasPallet(false).
SetStatus("ENABLED").
SaveX(ctx)
slog.Info("seed: 21 docks created")
}
return nil
}
func strPtrNil(s string) *string {
if s == "" {
return nil
}
return &s
}
func itoaPad(n int) string {
base := "000"
return base[:len(base)-lenOfInt(n)] + intToStr(n)
}
func lenOfInt(n int) int {
c := 1
for n >= 10 {
n /= 10
c++
}
return c
}
func intToStr(n int) string {
if n < 10 {
return string(rune('0' + n))
}
return intToStr(n/10) + string(rune('0'+n%10))
}