Files
bj_power/bj_power_wms/internal/handler/excel.go
T
SunYF ebf901ad16 chore: 完成多系统功能迭代与优化
1. 通用优化:
   - 统一系统标题为"库房客户端"/"MES产线控制",移除北自所前缀
   - 调整内置账号密码为统一123456,优化密码校验逻辑
   - 新增数据库自动创建逻辑,简化部署流程
   - 修复日志时间格式配置,优化日志输出
   - 新增纯数字密码安全提示

2. MES系统优化:
   - 新增日排产管理功能,支持增删改查与自动算料生成备料单
   - 重构BOM模块,改为按产品编码维护而非工单维度
   - 新增工艺参数模板配置与手动报工页面
   - 新增产品类型自动编码功能
   - 优化菜单结构,调整工单管理、扫码报工等页面名称与路由
   - 新增删除日排产接口与权限保护
   - 修复物料清单查询逻辑,适配新BOM结构
   - 新增refreshToken支持,优化登录会话管理

3. WMS系统优化:
   - 新增基础数据维护页面,支持区域与物料档案管理
   - 新增工单列表下拉接口,对接MES获取未完成工单优先展示
   - 优化入库管理提示文案,替换英文提示为中文
   - 修复精密件入库校验逻辑,优化错误提示
   - 优化Excel导入功能,新增备注字段支持
   - 优化登录页面与菜单文案,统一备料台账名称
   - 新增自动打开浏览器功能,优化客户端启动体验
   - 修复备料出库页面查询提示文案
   - 新增WMS与MES对接配置,完善内部API调用逻辑

4. 其他优化:
   - 删除冗余的旧版静态资源文件,更新资源引用路径
   - 新增帮助文档,完善基础数据模块说明
   - 修复多处文案不统一、英文残留问题
2026-08-29 15:30:25 +08:00

133 lines
3.6 KiB
Go

package handler
import (
"fmt"
"net/http"
"strings"
"bj_power_wms/ent/inventorybatch"
"bj_power_wms/ent/material"
"bj_power_wms/internal/svc"
"github.com/xuri/excelize/v2"
)
// excelInboundHandler Excel 批量导入入库(结构件)
// 列头(第一行忽略):物料编码 | 批次号(可空,自动生成) | 数量 | 生产日期 | 供应商 | 区域 | 备注
func excelInboundHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if err := r.ParseMultipartForm(20 << 20); err != nil {
fail(w, http.StatusBadRequest, "文件上传失败: "+err.Error())
return
}
f, _, err := r.FormFile("file")
if err != nil {
fail(w, http.StatusBadRequest, "缺少 file 字段")
return
}
defer f.Close()
xl, err := excelize.OpenReader(f)
if err != nil {
fail(w, http.StatusBadRequest, "无法解析 Excel: "+err.Error())
return
}
defer xl.Close()
sheet := xl.GetSheetList()[0]
rows, err := xl.GetRows(sheet)
if err != nil {
fail(w, http.StatusBadRequest, "读取工作表失败: "+err.Error())
return
}
type resultRow struct {
Row int `json:"row"`
Code string `json:"materialCode"`
BatchNo string `json:"batchNo"`
Qty int `json:"quantity"`
Error string `json:"error,omitempty"`
}
results := []resultRow{}
success := 0
for i, row := range rows {
if i == 0 {
continue // 表头
}
cell := func(idx int) string {
if idx < len(row) {
return strings.TrimSpace(row[idx])
}
return ""
}
code := cell(0)
batchNo := cell(1)
qtyStr := cell(2)
qty := atoi(qtyStr, 0)
prodDate := cell(3)
supplier := cell(4)
zone := cell(5)
remark := cell(6)
res := resultRow{Row: i + 1, Code: code, BatchNo: batchNo, Qty: qty}
switch {
case code == "":
res.Error = "物料编码为空"
case qty <= 0:
res.Error = "数量必须大于 0"
default:
m, err := ctx.EntClient.Material.Query().
Where(material.CodeEQ(code)).Only(ctx0())
if err != nil {
res.Error = "物料不存在"
} else if m.ManageMode == 2 {
res.Error = "精密件请使用 SN 扫码入库,不支持 Excel 导入"
} else {
if batchNo == "" {
batchNo = genBatchNo(code)
}
// 同批次追加或新建
existing, err := ctx.EntClient.InventoryBatch.Query().
Where(inventorybatch.BatchNoEQ(batchNo)).Only(ctx0())
if err == nil {
ctx.EntClient.InventoryBatch.UpdateOneID(existing.ID).
SetQuantity(existing.Quantity + qty).
SetNillableSupplier(strPtr(supplier)).
ExecX(ctx0())
} else {
ctx.EntClient.InventoryBatch.Create().
SetBatchNo(batchNo).
SetMaterialCode(code).
SetNillableMaterialName(strPtr(m.Name)).
SetQuantity(qty).
SetLockedQty(0).
SetNillableProductionDate(strPtr(prodDate)).
SetNillableSupplier(strPtr(supplier)).
SetQualityStatus("未检").
SetNillableZoneCode(strPtr(zone)).
SaveX(ctx0())
}
inboundNo := "IB" + nowStr() + fmt.Sprintf("%03d", i)
ctx.EntClient.InboundOrder.Create().
SetInboundNo(inboundNo).
SetNillableInboundType(strPtr("purchase")).
SetMaterialCode(code).
SetNillableMaterialName(strPtr(m.Name)).
SetManageMode(1).
SetNillableZoneCode(strPtr(zone)).
SetQuantity(qty).
SetNillableRemark(strPtr(remark)).
SetOperator("excel-import").
SaveX(ctx0())
res.BatchNo = batchNo
success++
}
}
results = append(results, res)
}
ok(w, map[string]any{"total": len(results), "success": success, "rows": results})
}
}