更新
This commit is contained in:
1 parent
5718a00e31
commit
1850ac640e
226 files changed
+37772
-12071
No files matched your search
@@ -0,0 +1,234 @@
|
||||
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()})
|
||||
}
|
||||
Reference in new issue
Block a user