mh_goadmin_server/app/admin/models/purchase_change.go
chenlin 2dbf95e50e 1、串码追踪接口优化,增加"采购换机"类型;
2、零售明细/销售明细中非串码商品按新增时添加数据进行展示,不单独拆分为每件商品一条数据;
3、零售明细中"采购单价"改成"采购价";
4、出库明细接口优化,返回门店名称和游戏名称;
5、采购换机列表接口返回数据添加采购换机商品信息。
2025-02-27 10:41:44 +08:00

625 lines
21 KiB
Go
Raw 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 models
import (
"errors"
"fmt"
"github.com/gin-gonic/gin"
orm "go-admin/common/global"
"go-admin/logger"
"go-admin/tools"
"gorm.io/gorm"
"math/rand"
"time"
)
// ErpPurchaseChangeOrder 采购换机订单表
type ErpPurchaseChangeOrder struct {
Model
SerialNumber string `json:"serial_number" gorm:"index"` // 单据编号
StoreId uint32 `json:"store_id" gorm:"index"` // 门店id
StoreName string `json:"store_name"` // 门店名称
ErpSupplierId uint32 `json:"erp_supplier_id" gorm:"index"` // 供应商id
ErpSupplierName string `json:"erp_supplier_name"` // 供应商名称
MakerTime *time.Time `json:"maker_time"` // 制单时间
MakerId uint32 `json:"maker_id" gorm:"index"` // 制单人id
MakerName string `json:"maker_name"` // 制单人名称
AuditTime *time.Time `json:"audit_time"` // 审核时间
AuditorId uint32 `json:"auditor_id" gorm:"index"` // 审核人id
AuditorName string `json:"auditor_name"` // 审核人名称
State uint32 `json:"state"` // 1-待审核 2-已完成
Remark string `json:"remark"` // 备注
Commodities []ErpPurchaseChangeCommodity `json:"commodities" gorm:"-"` // 采购换机商品信息
}
// ErpPurchaseChangeCommodity 采购换机订单商品表
type ErpPurchaseChangeCommodity struct {
Model
ChangeOrderId uint32 `json:"change_order_id" gorm:"index"` // 采购换机订单id
ErpCommodityId uint32 `json:"erp_commodity_id" gorm:"index"` // 商品id
ErpCommodityName string `json:"erp_commodity_name"` // 商品名称
CommoditySerialNumber string `json:"commodity_serial_number" gorm:"index"` // 商品编号
IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码
OriginIMEI string `json:"origin_imei"` // 原机身串码
NewIMEI string `json:"new_imei"` // 新机身串码
Count uint32 `json:"count"` // 数量
OriginColor string `json:"origin_color"` // 原机身颜色
NewColor string `json:"new_color"` // 新机身颜色
Remark string `json:"remark"` // 备注
}
// ErpPurchaseChangeCreateReq 新建采购换机订单入参
type ErpPurchaseChangeCreateReq struct {
StoreId uint32 `json:"store_id"` // 门店id:入库必传
ErpSupplierId uint32 `json:"erp_supplier_id"` // 供应商id:入库必传
Remark string `json:"remark"` // 备注
Commodities []ErpPurchaseChangeCommodity `json:"commodities" binding:"required"` // 采购换机商品信息
}
// ErpPurchaseChangeEditReq 编辑采购换机订单入参
type ErpPurchaseChangeEditReq struct {
ChangeOrderId uint32 `json:"change_order_id" gorm:"index"` // 采购换机订单id
StoreId uint32 `json:"store_id"` // 门店id:入库必传
ErpSupplierId uint32 `json:"erp_supplier_id"` // 供应商id:入库必传
Remark string `json:"remark"` // 备注
Commodities []ErpPurchaseChangeCommodity `json:"Commodities" binding:"required"` // 采购商品信息
}
// ErpPurchaseChangeOrderListReq 查询采购换机订单列表入参
type ErpPurchaseChangeOrderListReq struct {
SerialNumber string `json:"serial_number"` // 单据编号
StoreId uint32 `json:"store_id"` // 门店id
ErpSupplierId uint32 `json:"erp_supplier_id"` // 供应商id
MakerTimeStart string `json:"make_time_start"` // 制单开始时间
MakerTimeEnd string `json:"make_time_end"` // 制单结束时间
AuditTimeStart string `json:"audit_time_start"` // 审核开始时间
AuditTimeEnd string `json:"audit_time_end"` // 审核结束时间
State []uint32 `json:"state"` // 状态1-待审核 2-已完成
HandlerId uint32 `json:"handler_id"` // 经手人id
PageIndex int `json:"pageIndex"` // 页码
PageSize int `json:"pageSize"` // 页面条数
}
// ErpPurchaseChangeOrderListResp 查询采购换机订单列表出参
type ErpPurchaseChangeOrderListResp struct {
List []ErpPurchaseChangeOrder `json:"list"`
Total int `json:"total"` // 总条数
PageIndex int `json:"pageIndex"` // 页码
PageSize int `json:"pageSize"` // 页面条数
}
// ErpPurchaseChangeDeleteReq 删除采购换机订单入参
type ErpPurchaseChangeDeleteReq struct {
SerialNumber string `json:"serial_number" binding:"required"` // 单据编号
}
// ErpPurchaseChangeAuditReq 审核采购换机订单入参
type ErpPurchaseChangeAuditReq struct {
SerialNumber string `json:"serial_number" binding:"required"` // 单据编号
State int `json:"state" binding:"required"` // 审核操作: 1-审核 2-取消审核
}
// newErpPurchaseChangeSn 生成采购换机订单号
func newErpPurchaseChangeSn() string {
var prefix string
prefix = "cgh"
nowTime := time.Now()
rand.Seed(nowTime.UnixNano())
max := 1
for {
if max > 5 {
logger.Error("create sn err")
return ""
}
random := rand.Intn(9000) + 1000
sn := fmt.Sprintf("%s%d", nowTime.Format("060102"), random)
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_purchase_change_order WHERE "+
"serial_number='%s'", prefix+sn))
if err != nil {
logger.Error("exist sn err")
}
if !exist {
return prefix + sn
}
max++
}
}
// IdInit 添加商户和供应商信息
func (m *ErpPurchaseChangeOrder) IdInit() error {
if m.StoreId != 0 {
store, err := GetStore(m.StoreId)
if err != nil {
logger.Error("get store err:", logger.Field("err", err))
return err
}
m.StoreName = store.Name
}
if m.ErpSupplierId != 0 {
supplier, err := GetErpSupplier(m.ErpSupplierId)
if err != nil {
logger.Error("get supplier err:", logger.Field("err", err))
return err
}
m.ErpSupplierName = supplier.Name
}
return nil
}
// CheckCreateErpPurchaseChangeOrderParam 新增采购换机订单-检查参数
func CheckCreateErpPurchaseChangeOrderParam(req *ErpPurchaseChangeCreateReq) error {
if req.StoreId == 0 {
return errors.New("操作失败:门店id为空")
}
if req.ErpSupplierId == 0 {
return errors.New("操作失败:供应商id为空")
}
for _, item := range req.Commodities {
if item.Count <= 0 {
return errors.New("操作失败:采购换机数量需大于0")
}
// 判断是否是串码商品,非串码商品不支持
if item.IMEIType == 1 {
return errors.New("操作失败:采购换机不支持非串码商品")
}
var imeiStockCommodity ErpStockCommodity
err := orm.Eloquent.Table("erp_stock_commodity").Where("imei = ? and state = ?",
item.OriginIMEI, InStock).Find(&imeiStockCommodity).Error
if err != nil {
return err
}
if imeiStockCommodity.ID == 0 {
return errors.New("商品" + "[" + item.OriginIMEI + "]不在库")
}
if imeiStockCommodity.StoreId != req.StoreId {
return errors.New("商品" + "[" + item.OriginIMEI + "]非所选门店库存,请检查")
}
// 判断新商品串码是否已录入或者使用过
var newImeiStockCommodity ErpStockCommodity
err = orm.Eloquent.Table("erp_stock_commodity").Where("imei = ?",
item.NewIMEI).Find(&newImeiStockCommodity).Error
if err != nil {
return err
}
if newImeiStockCommodity.ID != 0 {
return errors.New("串码" + "[" + item.NewIMEI + "]重复")
}
}
return nil
}
// CheckEditErpPurchaseChangeOrderParam 编辑采购换机订单-检查参数
func CheckEditErpPurchaseChangeOrderParam(req *ErpPurchaseChangeEditReq) error {
if req.StoreId == 0 {
return errors.New("操作失败:门店id为空")
}
if req.ErpSupplierId == 0 {
return errors.New("操作失败:供应商id为空")
}
for _, item := range req.Commodities {
if item.Count <= 0 {
return errors.New("操作失败:采购换机数量需大于0")
}
// 判断是否是串码商品,非串码商品不支持
if item.IMEIType == 1 {
return errors.New("操作失败:采购换机不支持非串码商品")
}
var imeiStockCommodity ErpStockCommodity
err := orm.Eloquent.Table("erp_stock_commodity").Where("imei = ? and state = ?",
item.OriginIMEI, InStock).Find(&imeiStockCommodity).Error
if err != nil {
return err
}
if imeiStockCommodity.ID == 0 {
return errors.New("商品" + "[" + item.OriginIMEI + "]不在库")
}
if imeiStockCommodity.StoreId != req.StoreId {
return errors.New("商品" + "[" + item.OriginIMEI + "]非所选门店库存,请检查")
}
// 判断新商品串码是否已录入或者使用过
var newImeiStockCommodity ErpStockCommodity
err = orm.Eloquent.Table("erp_stock_commodity").Where("imei = ?",
item.NewIMEI).Find(&newImeiStockCommodity).Error
if err != nil {
return err
}
if newImeiStockCommodity.ID != 0 {
return errors.New("串码" + "[" + item.OriginIMEI + "]重复")
}
}
return nil
}
// CreateErpPurchaseChangeOrder 新增采购换机订单
func CreateErpPurchaseChangeOrder(req *ErpPurchaseChangeCreateReq, sysUser *SysUser) (*ErpPurchaseChangeOrder, error) {
var err error
nowTime := time.Now()
purchaseOrder := &ErpPurchaseChangeOrder{}
purchaseOrder = &ErpPurchaseChangeOrder{
SerialNumber: newErpPurchaseChangeSn(),
StoreId: req.StoreId,
ErpSupplierId: req.ErpSupplierId,
MakerTime: &nowTime,
MakerId: uint32(sysUser.UserId),
MakerName: sysUser.NickName,
State: ErpPurchaseChangeOrderUnAudit, // 1-待审核
Remark: req.Remark,
}
err = purchaseOrder.IdInit()
if err != nil {
logger.Error("info err:", logger.Field("err", err))
return nil, err
}
begin := orm.Eloquent.Begin()
err = begin.Create(purchaseOrder).Error
if err != nil {
begin.Rollback()
logger.Error("create purchase order err:", logger.Field("err", err))
return nil, err
}
for i, _ := range req.Commodities {
req.Commodities[i].ChangeOrderId = purchaseOrder.ID
err = begin.Create(&req.Commodities[i]).Error
if err != nil {
begin.Rollback()
logger.Error("create purchase commodity err:", logger.Field("err", err))
return nil, err
}
}
err = begin.Commit().Error
if err != nil {
begin.Rollback()
logger.Error("commit purchase commodity err:", logger.Field("err", err))
return nil, err
}
return purchaseOrder, nil
}
// EditErpPurchaseChangeOrder 编辑采购订单
func EditErpPurchaseChangeOrder(req *ErpPurchaseChangeEditReq, sysUser *SysUser) (*ErpPurchaseChangeOrder, error) {
// 查询订单信息
var purchaseChangeOrder ErpPurchaseChangeOrder
err := orm.Eloquent.Table("erp_purchase_change_order").Where("id=?", req.ChangeOrderId).Find(&purchaseChangeOrder).Error
if err != nil {
logger.Error("purchase change order err:", logger.Field("err", err))
return nil, err
}
if purchaseChangeOrder.State != ErpPurchaseChangeOrderUnAudit { // 只有待审核的订单才能编辑
return nil, errors.New("订单不是待审核状态")
}
if req.StoreId == 0 {
return nil, errors.New("操作失败:门店id为空")
}
begin := orm.Eloquent.Begin()
// 1-更新采购订单信息
purchaseChangeOrder.StoreId = req.StoreId
purchaseChangeOrder.ErpSupplierId = req.ErpSupplierId
purchaseChangeOrder.MakerId = uint32(sysUser.UserId)
purchaseChangeOrder.MakerName = sysUser.NickName
purchaseChangeOrder.Remark = req.Remark
err = purchaseChangeOrder.IdInit()
if err != nil {
logger.Error("purchase change IdInit err:", logger.Field("err", err))
return nil, err
}
err = begin.Model(&ErpPurchaseChangeOrder{}).Where("id = ?", req.ChangeOrderId).
Omit("created_at").Save(purchaseChangeOrder).Error
if err != nil {
begin.Rollback()
logger.Error("update erp_order err:", logger.Field("err", err))
return nil, err
}
// 2-更新采购订单商品表
err = updatePurchaseChangeCommodityData(begin, req.ChangeOrderId, req)
if err != nil {
begin.Rollback()
logger.Error("update erp_purchase_commodity err:", logger.Field("err", err))
return nil, err
}
err = begin.Commit().Error
if err != nil {
begin.Rollback()
logger.Error("commit err:", logger.Field("err", err))
return nil, err
}
return &purchaseChangeOrder, nil
}
// updatePurchaseChangeCommodityData 更新采购订单商品信息
func updatePurchaseChangeCommodityData(gdb *gorm.DB, orderId uint32, req *ErpPurchaseChangeEditReq) error {
// 查询现有的零售订单信息
var commodities []ErpPurchaseChangeCommodity
err := orm.Eloquent.Table("erp_purchase_change_commodity").Where("change_order_id = ?", orderId).Find(&commodities).Error
if err != nil {
logger.Error("query erp_purchase_change_commodity err:", logger.Field("err", err))
return err
}
// 1-删除所有的商品信息
if len(commodities) != 0 {
err = gdb.Delete(&commodities).Error
if err != nil {
logger.Error("更新商品订单信息-删除 error")
return errors.New("操作失败:" + err.Error())
}
}
for i, _ := range req.Commodities {
req.Commodities[i].ID = 0
if req.Commodities[i].ChangeOrderId == 0 { //发现前端有时会没传,后端打补丁
req.Commodities[i].ChangeOrderId = req.ChangeOrderId
}
}
// 2-更新商品订单信息-新增
if len(req.Commodities) != 0 {
err = gdb.Create(&req.Commodities).Error
if err != nil {
logger.Error("更新商品订单信息-新增 error")
return errors.New("操作失败:" + err.Error())
}
}
return nil
}
// List 查询采购订单列表
func (m *ErpPurchaseChangeOrderListReq) List(c *gin.Context) (*ErpPurchaseChangeOrderListResp, error) {
resp := &ErpPurchaseChangeOrderListResp{
PageIndex: m.PageIndex,
PageSize: m.PageSize,
}
page := m.PageIndex - 1
if page < 0 {
page = 0
}
if m.PageSize == 0 {
m.PageSize = 10
}
qs := orm.Eloquent.Table("erp_purchase_change_order")
if m.SerialNumber != "" {
qs = qs.Where("serial_number=?", m.SerialNumber)
} else {
if m.StoreId != 0 {
qs = qs.Where("store_id=?", m.StoreId)
}
// 非管理员才判断所属门店
if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
sysUser, err := GetSysUserByCtx(c)
if err != nil {
return nil, errors.New("操作失败:" + err.Error())
}
// 返回sysUser未过期的门店id列表
storeList := GetValidStoreIDs(sysUser.StoreData)
if len(storeList) > 0 {
if len(storeList) == 1 {
qs = qs.Where("store_id = ?", storeList[0])
} else {
qs = qs.Where("store_id IN (?)", storeList)
}
} else {
return nil, errors.New("用户未绑定门店")
}
}
if m.ErpSupplierId != 0 {
qs = qs.Where("erp_supplier_id=?", m.ErpSupplierId)
}
if len(m.State) > 0 {
qs = qs.Where("state IN (?)", m.State)
}
if m.MakerTimeStart != "" {
parse, err := time.Parse(QueryTimeFormat, m.MakerTimeStart)
if err != nil {
logger.Errorf("erpPurchaseChangeOrderList err:", err)
return nil, err
}
qs = qs.Where("make_time > ?", parse)
}
if m.MakerTimeEnd != "" {
parse, err := time.Parse(QueryTimeFormat, m.MakerTimeEnd)
if err != nil {
logger.Errorf("erpPurchaseChangeOrderList err:", err)
return nil, err
}
//parse = parse.AddDate(0, 0, 1)
qs = qs.Where("make_time < ?", parse)
}
if m.HandlerId != 0 {
qs = qs.Where("handler_id=?", m.HandlerId)
}
if m.AuditTimeStart != "" {
parse, err := time.Parse(QueryTimeFormat, m.AuditTimeStart)
if err != nil {
logger.Errorf("erpPurchaseChangeOrderList err:", err)
return nil, err
}
qs = qs.Where("audit_time > ?", parse)
}
if m.AuditTimeEnd != "" {
parse, err := time.Parse(QueryTimeFormat, m.AuditTimeEnd)
if err != nil {
logger.Errorf("erpPurchaseChangeOrderList err:", err)
return nil, err
}
//parse = parse.AddDate(0, 0, 1)
qs = qs.Where("audit_time < ?", parse)
}
if m.HandlerId != 0 {
qs = qs.Where("handler_id=?", m.HandlerId)
}
}
var count int64
err := qs.Count(&count).Error
if err != nil {
logger.Error("count err:", logger.Field("err", err))
return resp, err
}
resp.Total = int(count)
var orders []ErpPurchaseChangeOrder
err = qs.Order("id DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&orders).Error
if err != nil && err != RecordNotFound {
logger.Error("erp commodity list err:", logger.Field("err", err))
return resp, err
}
// 校验时间如果为01-01-01 08:05则赋值为空
for i, v := range orders {
if v.MakerTime != nil && v.MakerTime.IsZero() {
orders[i].MakerTime = nil
}
if v.AuditTime != nil && v.AuditTime.IsZero() {
orders[i].AuditTime = nil
}
}
changeOrderListSetCommodity(orders)
resp.List = orders
return resp, nil
}
// AuditChangeOrder 审核采购换机订单
func AuditChangeOrder(begin *gorm.DB, req ErpPurchaseChangeOrder, state int) error {
var commodities []ErpPurchaseChangeCommodity
err := orm.Eloquent.Table("erp_purchase_change_commodity").Where("change_order_id = ?", req.ID).Find(&commodities).Error
if err != nil {
logger.Error("check erp_purchase_change_order err:", logger.Field("err", err))
return err
}
if state == 1 { // 审核
for i, _ := range commodities {
if commodities[i].IMEIType == 2 || commodities[i].IMEIType == 3 { // 串码商品
if commodities[i].OriginIMEI == "" {
return errors.New("串码为空")
}
var imeiStockCommodity ErpStockCommodity
err = orm.Eloquent.Table("erp_stock_commodity").Where("imei = ? and state = ?",
commodities[i].OriginIMEI, InStock).Find(&imeiStockCommodity).Error
if err != nil {
return err
}
if imeiStockCommodity.ID == 0 {
return errors.New("商品" + "[" + commodities[i].ErpCommodityName + "]库存不足")
}
if imeiStockCommodity.StoreId != req.StoreId {
return errors.New("商品" + "[" + commodities[i].OriginIMEI + "]非所选门店库存,请检查")
}
err = begin.Table("erp_stock_commodity").Where("imei = ?", commodities[i].OriginIMEI).
Updates(map[string]interface{}{
"state": PurchaseChange,
"updated_at": time.Now(),
}).Error // 状态更新为"采购换机"
if err != nil {
begin.Rollback()
logger.Error("commodities err:", logger.Field("err", err))
return err
}
// 新串码商品入库
newStockCommodity := imeiStockCommodity
newStockCommodity.ID = 0
newStockCommodity.IMEI = commodities[i].NewIMEI
newStockCommodity.StockSn = req.SerialNumber
err = begin.Create(&newStockCommodity).Error
if err != nil {
begin.Rollback()
logger.Error("create purchase order err:", logger.Field("err", err))
return err
}
} else {
return errors.New("非串码商品不支持采购换货")
}
}
} else if state == 2 { // 取消审核
for i, _ := range commodities {
// 查询新串码的库存情况
var imeiStockCommodity ErpStockCommodity
err = orm.Eloquent.Table("erp_stock_commodity").Where("imei = ? and state = ?",
commodities[i].NewIMEI, InStock).Find(&imeiStockCommodity).Error
if err != nil {
return err
}
if imeiStockCommodity.ID == 0 {
return errors.New("商品" + "[" + commodities[i].NewIMEI + "]不在库")
}
err = begin.Delete(imeiStockCommodity).Error // 删除新串码库存
if err != nil {
begin.Rollback()
logger.Error("commodities err:", logger.Field("err", err))
return err
}
// 更新旧串码为在库状态
err = begin.Table("erp_stock_commodity").Where("imei = ?", commodities[i].OriginIMEI).
Updates(map[string]interface{}{
"state": InStock,
"updated_at": time.Now(),
}).Error // 状态更新为"在库"
if err != nil {
begin.Rollback()
logger.Error("commodities err:", logger.Field("err", err))
return err
}
}
}
return nil
}
// 添加采购换机订单的商品信息
func changeOrderListSetCommodity(list []ErpPurchaseChangeOrder) {
for i, _ := range list {
list[i].SetCommodity()
}
}
func (m *ErpPurchaseChangeOrder) SetCommodity() {
var orderCommodities []ErpPurchaseChangeCommodity
err := orm.Eloquent.Table("erp_purchase_change_commodity").Where("change_order_id = ?", m.ID).Find(&orderCommodities).Error
if err != nil {
logger.Error("SetCommodity query erp_purchase_change_commodity err:", logger.Field("err", err))
}
m.Commodities = orderCommodities
}