235 lines
6.5 KiB
Go
235 lines
6.5 KiB
Go
package controllers
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"server/models"
|
|
|
|
"github.com/beego/beego/v2/client/orm"
|
|
)
|
|
|
|
// BackendErpWarehouseController 仓库档案
|
|
type BackendErpWarehouseController struct {
|
|
BackendErpBaseController
|
|
}
|
|
|
|
type erpWarehousePayload struct {
|
|
WarehouseCode string `json:"warehouse_code"`
|
|
WarehouseName string `json:"warehouse_name"`
|
|
Address string `json:"address"`
|
|
Manager string `json:"manager"`
|
|
Phone string `json:"phone"`
|
|
IsDefault int8 `json:"is_default"`
|
|
Status *int8 `json:"status"`
|
|
Remark string `json:"remark"`
|
|
}
|
|
|
|
// List GET /backend/erp/warehouse/list
|
|
func (c *BackendErpWarehouseController) List() {
|
|
cl, err := c.claims()
|
|
if c.denied(err) {
|
|
return
|
|
}
|
|
rows, code, msg := erpWarehouseListCore(
|
|
erpNewActor(cl),
|
|
c.GetString("keyword"),
|
|
c.GetString("status"),
|
|
strings.TrimSpace(c.GetString("only_enabled")) == "1",
|
|
)
|
|
if msg != "" {
|
|
c.fail(code, code, msg)
|
|
return
|
|
}
|
|
c.ok(map[string]interface{}{"list": rows})
|
|
}
|
|
|
|
// Detail GET /backend/erp/warehouse/:id
|
|
func (c *BackendErpWarehouseController) Detail() {
|
|
cl, err := c.claims()
|
|
if c.denied(err) {
|
|
return
|
|
}
|
|
id := c.pathID()
|
|
var row models.ErpWarehouse
|
|
if err := models.Orm.QueryTable(new(models.ErpWarehouse)).
|
|
Filter("id", id).Filter("tenant_id", c.tid(cl)).
|
|
Filter("delete_time__isnull", true).One(&row); err != nil {
|
|
c.fail(404, 404, "仓库未找到")
|
|
return
|
|
}
|
|
c.ok(row)
|
|
}
|
|
|
|
// Create POST /backend/erp/warehouse
|
|
func (c *BackendErpWarehouseController) Create() {
|
|
cl, err := c.claims()
|
|
if c.denied(err) {
|
|
return
|
|
}
|
|
var p erpWarehousePayload
|
|
if !c.bindJSON(&p) {
|
|
return
|
|
}
|
|
if strings.TrimSpace(p.WarehouseName) == "" {
|
|
c.fail(400, 400, "仓库名称不能为空")
|
|
return
|
|
}
|
|
tid := c.tid(cl)
|
|
name := strings.TrimSpace(p.WarehouseName)
|
|
code := strings.TrimSpace(p.WarehouseCode)
|
|
if erpWarehouseFieldTaken(tid, "warehouse_name", name, 0) {
|
|
c.fail(400, 400, "仓库名称「"+name+"」已存在")
|
|
return
|
|
}
|
|
if code != "" && erpWarehouseFieldTaken(tid, "warehouse_code", code, 0) {
|
|
c.fail(400, 400, "仓库编号「"+code+"」已存在")
|
|
return
|
|
}
|
|
now := time.Now()
|
|
row := models.ErpWarehouse{
|
|
TenantID: tid, WarehouseCode: strings.TrimSpace(p.WarehouseCode),
|
|
WarehouseName: strings.TrimSpace(p.WarehouseName), Address: p.Address,
|
|
Manager: p.Manager, Phone: p.Phone, IsDefault: p.IsDefault,
|
|
Status: erpStatusOr(p.Status, 1), Remark: p.Remark,
|
|
CreateTime: now, UpdateTime: now,
|
|
}
|
|
if row.WarehouseCode == "" {
|
|
row.WarehouseCode = fmt.Sprintf("CK%s", now.Format("01021504"))
|
|
}
|
|
id, err := models.Orm.Insert(&row)
|
|
if err != nil {
|
|
c.fail(500, 500, "创建失败: "+err.Error())
|
|
return
|
|
}
|
|
if row.IsDefault == 1 {
|
|
erpClearDefaultWarehouse(tid, uint64(id))
|
|
}
|
|
c.ok(map[string]interface{}{"id": id})
|
|
}
|
|
|
|
// Update PUT /backend/erp/warehouse/:id
|
|
func (c *BackendErpWarehouseController) Update() {
|
|
cl, err := c.claims()
|
|
if c.denied(err) {
|
|
return
|
|
}
|
|
id := c.pathID()
|
|
if id == 0 {
|
|
c.fail(400, 400, "无效的ID")
|
|
return
|
|
}
|
|
var p erpWarehousePayload
|
|
if !c.bindJSON(&p) {
|
|
return
|
|
}
|
|
if strings.TrimSpace(p.WarehouseName) == "" {
|
|
c.fail(400, 400, "仓库名称不能为空")
|
|
return
|
|
}
|
|
tid := c.tid(cl)
|
|
var row models.ErpWarehouse
|
|
if err := models.Orm.QueryTable(new(models.ErpWarehouse)).
|
|
Filter("id", id).Filter("tenant_id", tid).
|
|
Filter("delete_time__isnull", true).One(&row); err != nil {
|
|
c.fail(404, 404, "仓库未找到")
|
|
return
|
|
}
|
|
name := strings.TrimSpace(p.WarehouseName)
|
|
code := strings.TrimSpace(p.WarehouseCode)
|
|
if erpWarehouseFieldTaken(tid, "warehouse_name", name, id) {
|
|
c.fail(400, 400, "仓库名称「"+name+"」已存在")
|
|
return
|
|
}
|
|
if code != "" && erpWarehouseFieldTaken(tid, "warehouse_code", code, id) {
|
|
c.fail(400, 400, "仓库编号「"+code+"」已存在")
|
|
return
|
|
}
|
|
if _, err := models.Orm.QueryTable(new(models.ErpWarehouse)).Filter("id", id).
|
|
Update(orm.Params{
|
|
"warehouse_code": strings.TrimSpace(p.WarehouseCode),
|
|
"warehouse_name": strings.TrimSpace(p.WarehouseName),
|
|
"address": p.Address, "manager": p.Manager, "phone": p.Phone,
|
|
"is_default": p.IsDefault, "status": erpStatusOr(p.Status, row.Status), "remark": p.Remark,
|
|
"update_time": time.Now(),
|
|
}); err != nil {
|
|
c.fail(500, 500, "更新失败: "+err.Error())
|
|
return
|
|
}
|
|
if p.IsDefault == 1 {
|
|
erpClearDefaultWarehouse(tid, id)
|
|
}
|
|
c.ok(nil)
|
|
}
|
|
|
|
// Delete DELETE /backend/erp/warehouse/:id
|
|
func (c *BackendErpWarehouseController) Delete() {
|
|
cl, err := c.claims()
|
|
if c.denied(err) {
|
|
return
|
|
}
|
|
id := c.pathID()
|
|
if id == 0 {
|
|
c.fail(400, 400, "无效的ID")
|
|
return
|
|
}
|
|
tid := c.tid(cl)
|
|
var row models.ErpWarehouse
|
|
if err := models.Orm.QueryTable(new(models.ErpWarehouse)).
|
|
Filter("id", id).Filter("tenant_id", tid).
|
|
Filter("delete_time__isnull", true).One(&row); err != nil {
|
|
c.fail(404, 404, "仓库未找到")
|
|
return
|
|
}
|
|
var qty float64
|
|
var stocks []models.ErpStock
|
|
_, _ = models.Orm.QueryTable(new(models.ErpStock)).
|
|
Filter("tenant_id", tid).Filter("warehouse_id", id).All(&stocks, "quantity")
|
|
for _, s := range stocks {
|
|
qty += s.Quantity
|
|
}
|
|
if qty > 0.000001 {
|
|
c.fail(400, 400, "该仓库仍有库存,不能删除,请先调拨出库或停用")
|
|
return
|
|
}
|
|
now := time.Now()
|
|
if _, err := models.Orm.QueryTable(new(models.ErpWarehouse)).Filter("id", id).
|
|
Update(orm.Params{"delete_time": now, "update_time": now}); err != nil {
|
|
c.fail(500, 500, "删除失败: "+err.Error())
|
|
return
|
|
}
|
|
c.ok(nil)
|
|
}
|
|
|
|
// erpStatusOr status 用指针区分「未传」与「显式传 0(停用)」,未传时回落到调用方给的默认值。
|
|
func erpStatusOr(v *int8, def int8) int8 {
|
|
if v == nil {
|
|
return def
|
|
}
|
|
return *v
|
|
}
|
|
|
|
// erpWarehouseFieldTaken 仓库名称/编号在租户内是否已被占用(excludeID>0 时排除自身)。
|
|
// 名称唯一是硬约束:ERP 基础设置里的默认仓库按名称存储,重名会让设置指向错误的仓。
|
|
func erpWarehouseFieldTaken(tid, field, value string, excludeID uint64) bool {
|
|
if strings.TrimSpace(value) == "" {
|
|
return false
|
|
}
|
|
qs := models.Orm.QueryTable(new(models.ErpWarehouse)).
|
|
Filter("tenant_id", tid).Filter("delete_time__isnull", true).
|
|
Filter(field, value)
|
|
if excludeID > 0 {
|
|
qs = qs.Exclude("id", excludeID)
|
|
}
|
|
n, _ := qs.Count()
|
|
return n > 0
|
|
}
|
|
|
|
// erpClearDefaultWarehouse 默认仓库全租户唯一
|
|
func erpClearDefaultWarehouse(tid string, keepID uint64) {
|
|
_, _ = models.Orm.QueryTable(new(models.ErpWarehouse)).
|
|
Filter("tenant_id", tid).Filter("is_default", 1).Exclude("id", keepID).
|
|
Update(orm.Params{"is_default": 0, "update_time": time.Now()})
|
|
}
|