mh_goadmin_server/app/admin/models/inventory_allot.go
chenlin 4bf39f8cdb 1.修复缺陷,优化代码:
(1)零售退货时增加"库存已有该串码商品"的判断;
(2)门店经营数据中销售数量类型改为int64,可能有负值;
(3)零售明细中字段类型int32调整为float64,包含:RetailPrice、SalePrice、WholesalePrice、StaffPrice;
(4)库存调拨商品信息表增加字段:CategoryId、CategoryName;
2024-05-15 11:08:46 +08:00

928 lines
32 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"
orm "go-admin/common/global"
"go-admin/logger"
"gorm.io/gorm"
"math/rand"
"time"
)
const (
ErpInventoryAllotOrderUnAudit = 1 // 库存调拨-待审核
ErpInventoryAllotOrderWaitSend = 2 // 库存调拨-待发货
ErpInventoryAllotOrderWaitReceive = 3 // 库存调拨-待收货
ErpInventoryAllotOrderFinished = 4 // 库存调拨-已完成
)
// ErpInventoryAllotOrder 库存调拨订单表
type ErpInventoryAllotOrder struct {
Model
SerialNumber string `json:"serial_number" gorm:"index"` // 单据编号
DeliverStoreId uint32 `json:"deliver_store_id" gorm:"index"` // 调出门店id
DeliverStoreName string `json:"deliver_store_name"` // 调出门店名称
ReceiveStoreId uint32 `json:"receive_store_id" gorm:"index"` // 调入门店id
ReceiveStoreName string `json:"receive_store_name"` // 调入门店名称
HandlerId uint32 `json:"handler_id" gorm:"index"` // 经手人id
HandlerName string `json:"handler_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"` // 审核人名称
DeliverTime *time.Time `json:"deliver_time"` // 发货时间
ReceiveTime *time.Time `json:"receive_time"` // 收货时间/调入时间
LogisticsNumber string `json:"logistics_number"` // 物流单号
State uint32 `json:"state"` // 1-待审核 2-待发货 3-待收货 4-已完成
TotalCount uint32 `json:"total_count"` // 商品总数量
Remark string `json:"remark"` // 备注
Commodities []ErpInventoryAllotCommodity `json:"commodities" gorm:"-"` // 库存调拨商品信息
}
// ErpInventoryAllotCommodity 库存调拨商品信息表
type ErpInventoryAllotCommodity struct {
Model
AllotOrderId uint32 `json:"allot_order_id" gorm:"index"` // 库存调拨订单表id
CommodityId uint32 `json:"commodity_id" gorm:"index"` // 商品id
CommodityName string `json:"commodity_name"` // 商品名称
CategoryId uint32 `json:"category_id" gorm:"index"` // 分类id
CategoryName string `json:"category_name"` // 分类名称
IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码
IMEI string `json:"imei"` // 商品串码
Count uint32 `json:"count"` // 数量
Amount float64 `json:"amount"` // 金额(采购价)
Remark string `json:"remark"` // 备注
}
// InventoryAllotAddReq 新增库存调拨入参
type InventoryAllotAddReq struct {
DeliverStoreId uint32 `json:"deliver_store_id" binding:"required"` // 调出门店id
DeliverStoreName string `json:"deliver_store_name" binding:"required"` // 调出门店名称
ReceiveStoreId uint32 `json:"receive_store_id" binding:"required"` // 调入门店id
ReceiveStoreName string `json:"receive_store_name" binding:"required"` // 调入门店名称
HandlerId uint32 `json:"handler_id" binding:"required"` // 经手人id
HandlerName string `json:"handler_name" binding:"required"` // 经手人名称
Commodities []ErpInventoryAllotCommodity `json:"commodities" binding:"required"` // 库存调拨商品信息
}
// InventoryAllotEditReq 编辑库存调拨入参
type InventoryAllotEditReq struct {
SerialNumber string `json:"serial_number" binding:"required"` // 单据编号
InventoryAllotAddReq
}
// InventoryAllotAuditReq 审核入参
type InventoryAllotAuditReq struct {
SerialNumber string `json:"serial_number" binding:"required"` // 单据编号
State int `json:"state" binding:"required"` // 审核操作: 1-审核 2-取消审核
}
// InventoryAllotDeleteReq 删除入参
type InventoryAllotDeleteReq struct {
SerialNumber string `json:"serial_number" binding:"required"` // 单据编号
}
// InventoryAllotListReq 查询库存调拨列表入参
type InventoryAllotListReq struct {
SerialNumber string `json:"serial_number"` // 单据编号
DeliverStoreId uint32 `json:"deliver_store_id"` // 调出门店id
ReceiveStoreId uint32 `json:"receive_store_id"` // 调入门店id
HandlerId uint32 `json:"handler_id"` // 经手人id
State int `json:"state"` // 1-待审核 2-待发货 3-待收货 4-已完成
AuditTimeStart string `json:"audit_time_start"` // 审核开始时间
AuditTimeEnd string `json:"audit_time_end"` // 审核结束时间
PageIndex int `json:"pageIndex"` // 页码
PageSize int `json:"pageSize"` // 页面条数
}
// InventoryAllotListResp 查询库存调拨列表出参
type InventoryAllotListResp struct {
List []ErpInventoryAllotOrder `json:"list"`
Total int `json:"total"` // 总条数
PageIndex int `json:"pageIndex"` // 页码
PageSize int `json:"pageSize"` // 页面条数
}
// InventoryAllotDetailReq 查询库存调拨详情入参
type InventoryAllotDetailReq struct {
SerialNumber string `json:"serial_number" binding:"required"` // 单据编号
}
// InventoryAllotDeliverReq 调拨发货入参
type InventoryAllotDeliverReq struct {
SerialNumber string `json:"serial_number" binding:"required"` // 单据编号
LogisticsNumber string `json:"logistics_number"` // 物流单号
Remark string `json:"remark"` // 备注
}
// InventoryAllotReceiveReq 调拨收货入参
type InventoryAllotReceiveReq struct {
SerialNumber string `json:"serial_number" binding:"required"` // 单据编号
}
// 检查新增库存调拨信息
func checkAllotInventoryParam(req *InventoryAllotAddReq, editFlag bool) error {
if len(req.Commodities) == 0 {
return errors.New("商品信息为空")
}
noIMEICommodityMap := make(map[uint32]bool, 0)
for _, item := range req.Commodities {
// 校验数量
if item.Count <= 0 {
return fmt.Errorf("商品[%s]数量[%d]错误需大于0", item.CommodityName, item.Count)
} else {
if item.Count != 1 && item.IMEIType != NoIMEICommodity { // 串码商品数量不为1则报错
return fmt.Errorf("串码商品[%s]数量[%d]错误需为1", item.CommodityName, item.Count)
}
}
// 校验编辑订单时是否有传商品ID
if editFlag {
if item.ID == 0 {
return fmt.Errorf("商品[%s]ID为空", item.CommodityName)
}
}
// 校验串码类型
switch item.IMEIType {
case 1, 2, 3:
// 串码商品校验串码是否为空
if item.IMEIType != NoIMEICommodity && item.IMEI == "" {
return fmt.Errorf("[%s]是串码商品,其串码不能为空", item.CommodityName)
}
default:
return fmt.Errorf("商品[%s]串码类型[%d]错误", item.CommodityName, item.IMEIType)
}
// 校验非串码商品是否重复
if item.IMEIType == NoIMEICommodity {
_, ok := noIMEICommodityMap[item.CommodityId]
if !ok {
noIMEICommodityMap[item.CommodityId] = true
} else {
return fmt.Errorf("商品[%s]重复相同的非串码商品只能有1条数据", item.CommodityName)
}
}
// 检查调出门店是否有对应商品,调拨数量是否 < 商品库存数量
var stockCount int64
var err error
if item.IMEIType == NoIMEICommodity { // 非串码商品
err = orm.Eloquent.Table("erp_stock_commodity").
Where("erp_commodity_id = ? AND store_id = ? AND state = 1", item.CommodityId, req.DeliverStoreId).
Count(&stockCount).Error
} else { // 串码商品
err = orm.Eloquent.Table("erp_stock_commodity").
Where("erp_commodity_id = ? AND store_id = ? AND state = 1 AND imei = ?", item.CommodityId,
req.DeliverStoreId, item.IMEI).Count(&stockCount).Error
}
if err != nil {
return errors.New("查询商品库存失败," + err.Error())
}
if stockCount == 0 {
return fmt.Errorf("商品[%s]库存数量为0", item.CommodityName)
}
if stockCount < int64(item.Count) {
return fmt.Errorf("商品[%s]库存数量[%d]少于调拨数量[%d]", item.CommodityName, stockCount, item.Count)
}
}
return nil
}
// newAllotInventorySn 生成库存调拨订单号
func newAllotInventorySn() string {
nowTime := time.Now()
rand.Seed(nowTime.UnixNano())
max := 1
for {
if max > 5 {
logger.Error("create NewProductInventorySn err")
return ""
}
random := rand.Intn(9000) + 1000
sn := fmt.Sprintf("%s%d", nowTime.Format("060102"), random)
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_inventory_allot_order "+
"WHERE serial_number='%s'", "db"+sn))
if err != nil {
logger.Error("exist sn err")
}
if !exist {
return "db" + sn
}
max++
}
}
// AddInventoryAllot 新增库存调拨
func AddInventoryAllot(req *InventoryAllotAddReq, sysUser *SysUser) (*ErpInventoryAllotOrder, error) {
// 检查库存调拨信息
if err := checkAllotInventoryParam(req, false); err != nil {
return nil, err
}
var err error
nowTime := time.Now()
// 计算库存调拨的总数量
var nTotalCount uint32
for i, _ := range req.Commodities {
nTotalCount += req.Commodities[i].Count // 数量
}
// 组合库存调拨订单数据
inventoryAllotOrder := &ErpInventoryAllotOrder{
SerialNumber: newAllotInventorySn(),
DeliverStoreId: req.DeliverStoreId,
DeliverStoreName: req.DeliverStoreName,
ReceiveStoreId: req.ReceiveStoreId,
ReceiveStoreName: req.ReceiveStoreName,
HandlerId: req.HandlerId,
HandlerName: req.HandlerName,
MakerTime: &nowTime,
MakerId: uint32(sysUser.UserId),
MakerName: sysUser.NickName,
State: ErpInventoryAllotOrderUnAudit,
TotalCount: nTotalCount,
}
// 创建库存调拨订单
begin := orm.Eloquent.Begin()
err = begin.Create(inventoryAllotOrder).Error
if err != nil {
begin.Rollback()
logger.Error("create allot order err:", logger.Field("err", err))
return nil, err
}
// 创建库存调拨商品信息添加库存调拨订单id
for i, _ := range req.Commodities {
req.Commodities[i].AllotOrderId = inventoryAllotOrder.ID
// 查询商品信息
commodityInfo, err := GetCommodity(req.Commodities[i].CommodityId)
if err != nil {
logger.Error("SetCategory err:", logger.Field("err", err))
return nil, err
}
req.Commodities[i].CategoryId = commodityInfo.ErpCategoryId
req.Commodities[i].CategoryName = commodityInfo.ErpCategoryName
err = begin.Create(&req.Commodities[i]).Error
if err != nil {
begin.Rollback()
logger.Error("create allot commodity err:", logger.Field("err", err))
return nil, err
}
}
err = begin.Commit().Error
if err != nil {
begin.Rollback()
logger.Error("commit allot commodity err:", logger.Field("err", err))
return nil, err
}
return inventoryAllotOrder, nil
}
// EditAllotInventory 编辑库存调拨
func EditAllotInventory(req *InventoryAllotEditReq) (*ErpInventoryAllotOrder, error) {
// 查询订单信息
var inventoryAllotOrder ErpInventoryAllotOrder
err := orm.Eloquent.Table("erp_inventory_allot_order").Where("serial_number = ?", req.SerialNumber).
Find(&inventoryAllotOrder).Error
if err != nil {
logger.Error("allot order err:", logger.Field("err", err))
return nil, err
}
// 未找到订单
if inventoryAllotOrder.ID == 0 {
return nil, fmt.Errorf("未找到该订单,请检查单据编号[%s]", req.SerialNumber)
}
if inventoryAllotOrder.State != ErpInventoryAllotOrderUnAudit { // 只有待审核的订单才能编辑
return nil, errors.New("订单不是待审核状态")
}
// 检查库存调拨信息
if err = checkAllotInventoryParam(&req.InventoryAllotAddReq, true); err != nil {
return nil, err
}
// 计算库存调拨的总数量
var nTotalCount uint32
for i, _ := range req.Commodities {
nTotalCount += req.Commodities[i].Count // 数量
}
begin := orm.Eloquent.Begin()
// 1-更新库存调拨信息
inventoryAllotOrder.DeliverStoreId = req.DeliverStoreId
inventoryAllotOrder.DeliverStoreName = req.DeliverStoreName
inventoryAllotOrder.ReceiveStoreId = req.ReceiveStoreId
inventoryAllotOrder.ReceiveStoreName = req.ReceiveStoreName
inventoryAllotOrder.HandlerId = req.HandlerId
inventoryAllotOrder.HandlerName = req.HandlerName
inventoryAllotOrder.TotalCount = nTotalCount
err = begin.Model(&ErpInventoryAllotOrder{}).Where("id = ?", inventoryAllotOrder.ID).
Updates(inventoryAllotOrder).Error
if err != nil {
begin.Rollback()
logger.Error("update allot order err:", logger.Field("err", err))
return nil, err
}
// 2-更新库存调拨商品表
err = updateAllotCommodityData(begin, inventoryAllotOrder.ID, req)
if err != nil {
begin.Rollback()
logger.Error("update erp_inventory_allot_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 &inventoryAllotOrder, nil
}
// updateAllotCommodityData 更新库存调拨商品信息
func updateAllotCommodityData(gdb *gorm.DB, orderId uint32, req *InventoryAllotEditReq) error {
// 查询现有的零售订单信息
var commodities []ErpInventoryAllotCommodity
err := orm.Eloquent.Table("erp_inventory_allot_commodity").Where("allot_order_id = ?", orderId).Find(&commodities).Error
if err != nil {
logger.Error("query erp_inventory_allot_commodity err:", logger.Field("err", err))
return err
}
var newCommodities []ErpInventoryAllotCommodity
var deletedCommodities []ErpInventoryAllotCommodity
var matchingCommodities []ErpInventoryAllotCommodity
// 找到新增的商品
for i, reqCommodity := range req.Commodities {
// 订单商品表信息添加零售订单id
req.Commodities[i].AllotOrderId = orderId
var found bool
for _, dbCommodity := range commodities {
if reqCommodity.CommodityId == dbCommodity.CommodityId && reqCommodity.ID == dbCommodity.ID {
found = true
break
}
}
if !found {
newCommodities = append(newCommodities, reqCommodity)
}
}
// 找到删除的商品
for _, dbCommodity := range commodities {
var found bool
for _, reqCommodity := range req.Commodities {
if reqCommodity.CommodityId == dbCommodity.CommodityId && reqCommodity.ID == dbCommodity.ID {
found = true
// 找到匹配的商品,加入匹配列表
matchingCommodities = append(matchingCommodities, reqCommodity)
break
}
}
if !found {
deletedCommodities = append(deletedCommodities, dbCommodity)
}
}
// 2-更新商品订单信息-更新
for _, commodity := range matchingCommodities {
if err := gdb.Model(&ErpInventoryAllotCommodity{}).Where("id = ?", commodity.ID).Updates(commodity).Error; err != nil {
logger.Error("更新商品订单信息-更新 error")
return errors.New("操作失败:" + err.Error())
}
}
// 2-更新商品订单信息-新增
if len(newCommodities) != 0 {
err = gdb.Create(&newCommodities).Error
if err != nil {
logger.Error("更新商品订单信息-新增 error")
return errors.New("操作失败:" + err.Error())
}
}
//2-更新商品订单信息-删除
if len(deletedCommodities) != 0 {
err = gdb.Delete(&deletedCommodities).Error
if err != nil {
logger.Error("更新商品订单信息-删除 error")
return errors.New("操作失败:" + err.Error())
}
}
return nil
}
// List 查询采购订单列表
func (m *InventoryAllotListReq) List() (*InventoryAllotListResp, error) {
resp := &InventoryAllotListResp{
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_inventory_allot_order")
if m.SerialNumber != "" {
qs = qs.Where("serial_number=?", m.SerialNumber)
} else {
if m.DeliverStoreId != 0 {
qs = qs.Where("deliver_store_id=?", m.DeliverStoreId)
}
if m.ReceiveStoreId != 0 {
qs = qs.Where("receive_store_id=?", m.ReceiveStoreId)
}
if m.HandlerId != 0 {
qs = qs.Where("handler_id=?", m.HandlerId)
}
if m.State != 0 {
qs = qs.Where("state=?", m.State)
}
if m.AuditTimeStart != "" {
parse, err := time.Parse(QueryTimeFormat, m.AuditTimeStart)
if err != nil {
logger.Errorf("AllotInventoryList 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("AllotInventoryList err:", err)
return nil, err
}
qs = qs.Where("audit_time < ?", parse)
}
}
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 []ErpInventoryAllotOrder
err = qs.Order("id DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&orders).Error
if err != nil && err != RecordNotFound {
logger.Error("allot 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
}
}
resp.List = orders
return resp, nil
}
// AuditAllotInventory 审核库存调拨入库 state1-审核2-取消审核
func AuditAllotInventory(req *InventoryAllotAuditReq, sysUser *SysUser) error {
// 查询订单信息
var inventoryAllotOrder ErpInventoryAllotOrder
err := orm.Eloquent.Table("erp_inventory_allot_order").Where("serial_number = ?", req.SerialNumber).
Find(&inventoryAllotOrder).Error
if err != nil {
logger.Error("order err:", logger.Field("err", err))
return err
}
if inventoryAllotOrder.ID == 0 {
return errors.New("未查询到订单信息")
}
begin := orm.Eloquent.Begin()
// 判断入参state1-审核2-取消审核
orderState := 0
switch req.State {
case 1: // 1-审核:待审核状态可以审核
if inventoryAllotOrder.State != ErpInventoryAllotOrderUnAudit { // 订单不是未审核状态
return errors.New("订单已审核,无需再次审核")
}
orderState = ErpInventoryAllotOrderWaitSend
// 更新商品的库存状态
err = allotAuditAndUpdateStock(begin, inventoryAllotOrder)
if err != nil {
begin.Rollback()
logger.Error("ProductAuditAndUpdateStock err:", logger.Field("err", err))
return fmt.Errorf("审核失败,%s", err.Error())
}
case 2: // 2-取消审核
orderState = ErpInventoryAllotOrderUnAudit
if inventoryAllotOrder.State == ErpInventoryAllotOrderUnAudit { // 订单未审核
return errors.New("订单是未审核状态,无需取消审核")
}
// 更新商品的库存状态
err = cancelAllotAuditAndUpdateStock(begin, inventoryAllotOrder)
if err != nil {
begin.Rollback()
return fmt.Errorf("取消审核失败,%s", err.Error())
}
default:
logger.Error("order err, req.State is:", logger.Field("req.State", req.State))
return errors.New("参数有误")
}
// 更新库存调拨订单表
err = begin.Table("erp_inventory_allot_order").Where("id = ?", inventoryAllotOrder.ID).
Updates(map[string]interface{}{
"state": orderState,
"auditor_id": sysUser.UserId,
"audit_time": time.Now(),
"auditor_name": sysUser.NickName,
}).Error
if err != nil {
begin.Rollback()
logger.Error("update erp_inventory_allot_order err:", logger.Field("err", err))
return err
}
err = begin.Commit().Error
if err != nil {
begin.Rollback()
logger.Errorf("commit err:", err)
return err
}
return nil
}
// allotAuditAndUpdateStock 库存调拨审核后更新库存信息
func allotAuditAndUpdateStock(gdb *gorm.DB, allotOrder ErpInventoryAllotOrder) error {
// 查询库存调拨商品信息
var commodities []ErpInventoryAllotCommodity
err := orm.Eloquent.Table("erp_inventory_allot_commodity").Where("allot_order_id = ?",
allotOrder.ID).Find(&commodities).Error
if err != nil {
logger.Error("query erp_inventory_allot_commodity err:", logger.Field("err", err))
return err
}
// 遍历库存调拨商品信息
for _, v := range commodities {
var stockCommodity []ErpStockCommodity
err = orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? AND store_id = ? "+
"AND state = ? AND imei = ?", v.CommodityId, allotOrder.DeliverStoreId, InStock, v.IMEI).
Order("first_stock_time ASC").Find(&stockCommodity).Error
if err != nil {
return fmt.Errorf("审核失败,查询商品库存失败:[%s]", err.Error())
}
if len(stockCommodity) == 0 {
return fmt.Errorf("审核失败,未找到商品库存信息")
}
if v.Count > uint32(len(stockCommodity)) {
return fmt.Errorf("审核失败,商品[%s]库存数量[%d]少于调拨数量[%d]", v.CommodityName,
len(stockCommodity), v.Count)
}
// 更新库存商品表商品状态为:调拨中
var nAmount float64
for i := 0; i < int(v.Count); i++ {
stockCommodity[i].StoreId = allotOrder.ReceiveStoreId
stockCommodity[i].StoreName = allotOrder.ReceiveStoreName
stockCommodity[i].State = InAllot
if err := gdb.Model(&ErpStockCommodity{}).Where("id = ?", stockCommodity[i].ID).
Updates(stockCommodity[i]).Error; err != nil {
return fmt.Errorf("审核失败,更新商品库存失败:%s", err.Error())
}
nAmount += stockCommodity[i].WholesalePrice
}
// 更新库存调拨商品信息表的调拨金额
err = gdb.Table("erp_inventory_allot_commodity").Where("id = ?", v.ID).
Updates(map[string]interface{}{
"amount": nAmount,
}).Error
if err != nil {
logger.Errorf("update erp_inventory_allot_commodity amount err:", err)
return err
}
// 更新库存商品数量
err = gdb.Exec(fmt.Sprintf(
"UPDATE erp_stock SET count=count-%d WHERE store_id=%d AND erp_commodity_id=%d",
v.Count, allotOrder.DeliverStoreId, v.CommodityId)).Error
if err != nil {
logger.Errorf("update stock err:", err)
return err
}
// 更新调入门店的库存调拨数量
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_stock WHERE store_id=%d AND erp_commodity_id=%d",
allotOrder.ReceiveStoreId, v.CommodityId))
if err != nil {
logger.Errorf("exist err:", err)
return err
}
if exist {
err = gdb.Exec(fmt.Sprintf(
"UPDATE erp_stock SET dispatch_count = dispatch_count+%d WHERE store_id=%d AND erp_commodity_id=%d",
v.Count, allotOrder.ReceiveStoreId, v.CommodityId)).Error
if err != nil {
logger.Errorf("update stock err:", err)
return err
}
} else {
stock := &ErpStock{
StoreId: allotOrder.ReceiveStoreId,
StoreName: allotOrder.ReceiveStoreName,
ErpCommodityId: v.CommodityId,
ErpCommodityName: v.CommodityName,
ErpCategoryId: stockCommodity[0].ErpCategoryId,
ErpCategoryName: stockCommodity[0].ErpCategoryName,
CommoditySerialNumber: stockCommodity[0].CommoditySerialNumber,
IMEIType: v.IMEIType,
RetailPrice: stockCommodity[0].RetailPrice,
MinRetailPrice: stockCommodity[0].MinRetailPrice,
Count: 0,
DispatchCount: v.Count,
}
err = gdb.Create(stock).Error
if err != nil {
logger.Errorf("create stock err:", err)
return err
}
}
}
return nil
}
// cancelAllotAuditAndUpdateStock 库存调拨反审核后更新库存信息
func cancelAllotAuditAndUpdateStock(gdb *gorm.DB, allotOrder ErpInventoryAllotOrder) error {
// 查询库存调拨商品信息
var commodities []ErpInventoryAllotCommodity
if err := orm.Eloquent.Table("erp_inventory_allot_commodity").Where("allot_order_id = ?",
allotOrder.ID).Find(&commodities).Error; err != nil {
logger.Error("query erp_inventory_allot_commodity err:", logger.Field("err", err))
return err
}
if len(commodities) == 0 {
return errors.New("取消审核失败,未查询到库存调拨商品信息")
}
switch allotOrder.State {
// 2 待发货:状态改为待审核,调拨中库存恢复为在库
// 3 待收货:状态改为待审核,调拨中库存恢复为在库
case ErpInventoryAllotOrderWaitSend, ErpInventoryAllotOrderWaitReceive:
// 遍历库存调拨商品信息
for _, v := range commodities {
var stockCommodity []ErpStockCommodity
err := orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? AND store_id = ? "+
"AND state = ? AND imei = ?", v.CommodityId, allotOrder.ReceiveStoreId, InAllot, v.IMEI).
Find(&stockCommodity).Error
if err != nil {
return fmt.Errorf("查询商品库存失败:[%s]", err.Error())
}
if len(stockCommodity) == 0 {
return fmt.Errorf("未找到商品库存信息")
}
// 更新库存商品表商品状态为:在库
for i := 0; i < int(v.Count); i++ {
stockCommodity[i].StoreId = allotOrder.DeliverStoreId
stockCommodity[i].StoreName = allotOrder.DeliverStoreName
stockCommodity[i].State = InStock
err = gdb.Model(&ErpStockCommodity{}).Where("id = ?", stockCommodity[i].ID).
Updates(stockCommodity[i]).Error
if err != nil {
return fmt.Errorf("更新商品库存失败:%s", err.Error())
}
}
// 更新库存商品数量
err = gdb.Exec(fmt.Sprintf(
"UPDATE erp_stock SET count=count+%d WHERE store_id=%d AND erp_commodity_id=%d",
v.Count, allotOrder.DeliverStoreId, v.CommodityId)).Error
if err != nil {
logger.Errorf("update stock err:", err)
return fmt.Errorf("更新库存商品数量失败:%s", err.Error())
}
// 更新库存商品调拨数量
err = gdb.Exec(fmt.Sprintf(
"UPDATE erp_stock SET dispatch_count = dispatch_count-%d WHERE store_id=%d AND erp_commodity_id=%d",
v.Count, allotOrder.ReceiveStoreId, v.CommodityId)).Error
if err != nil {
logger.Errorf("update stock err:", err)
return err
}
}
case ErpInventoryAllotOrderFinished: // 已完成:状态改为待审核,调入门店对应商品的库存更新到调出门店,如果库存不足则报错
// 遍历库存调拨商品信息
for _, v := range commodities {
var stockCommodity []ErpStockCommodity
err := orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? AND store_id = ? "+
"AND state = ? AND imei = ?", v.CommodityId, allotOrder.ReceiveStoreId, InStock, v.IMEI).
Find(&stockCommodity).Error
if err != nil {
return fmt.Errorf("查询商品库存失败:[%s]", err.Error())
}
if len(stockCommodity) == 0 {
return fmt.Errorf("未找到商品库存信息")
}
if v.Count > uint32(len(stockCommodity)) {
return fmt.Errorf("商品[%s]库存数量[%d]不足", v.CommodityName, len(stockCommodity))
}
// 更新库存商品表商品状态为:在库
for i := 0; i < int(v.Count); i++ {
stockCommodity[i].StoreId = allotOrder.DeliverStoreId
stockCommodity[i].StoreName = allotOrder.DeliverStoreName
stockCommodity[i].State = InStock
err = gdb.Model(&ErpStockCommodity{}).Where("id = ?", stockCommodity[i].ID).
Updates(stockCommodity[i]).Error
if err != nil {
return fmt.Errorf("更新商品库存失败:%s", err.Error())
}
}
// 更新库存商品数量
// 调入门店减去对应调入的数量
err = gdb.Exec(fmt.Sprintf(
"UPDATE erp_stock SET count=count-%d WHERE store_id=%d AND erp_commodity_id=%d",
v.Count, allotOrder.ReceiveStoreId, v.CommodityId)).Error
if err != nil {
logger.Errorf("update stock err:", err)
return err
}
// 调出门店加上对应调出的数量
err = gdb.Exec(fmt.Sprintf(
"UPDATE erp_stock SET count=count+%d WHERE store_id=%d AND erp_commodity_id=%d",
v.Count, allotOrder.DeliverStoreId, v.CommodityId)).Error
if err != nil {
logger.Errorf("update stock err:", err)
return err
}
}
default:
return fmt.Errorf("订单当前状态未知[%d]", allotOrder.State)
}
// 更新库存调拨订单信息
allotOrder.State = ErpInventoryAllotOrderUnAudit
err := gdb.Model(&ErpInventoryAllotOrder{}).Where("id = ?", allotOrder.ID).
Updates(allotOrder).Error
if err != nil {
return fmt.Errorf("更新库存调拨订单失败:%s", err.Error())
}
return nil
}
// DeliverAllotInventory 调拨发货
func DeliverAllotInventory(req *InventoryAllotDeliverReq) error {
// 查询订单信息
var inventoryAllotOrder ErpInventoryAllotOrder
err := orm.Eloquent.Table("erp_inventory_allot_order").Where("serial_number = ?", req.SerialNumber).
Find(&inventoryAllotOrder).Error
if err != nil {
logger.Error("order err:", logger.Field("err", err))
return err
}
if inventoryAllotOrder.ID == 0 {
return errors.New("未查询到订单信息")
}
if inventoryAllotOrder.State != ErpInventoryAllotOrderWaitSend {
return errors.New("订单不是待发货状态")
}
nowTime := time.Now()
inventoryAllotOrder.LogisticsNumber = req.LogisticsNumber
inventoryAllotOrder.Remark = req.Remark
inventoryAllotOrder.State = ErpInventoryAllotOrderWaitReceive
inventoryAllotOrder.DeliverTime = &nowTime
err = orm.Eloquent.Model(&ErpInventoryAllotOrder{}).Where("id = ?", inventoryAllotOrder.ID).
Updates(inventoryAllotOrder).Error
if err != nil {
return err
}
return nil
}
// ReceiveAllotInventory 调拨收货
func ReceiveAllotInventory(req *InventoryAllotReceiveReq) error {
// 查询订单信息
var inventoryAllotOrder ErpInventoryAllotOrder
if err := orm.Eloquent.Table("erp_inventory_allot_order").Where("serial_number = ?", req.SerialNumber).
Find(&inventoryAllotOrder).Error; err != nil {
logger.Error("order err:", logger.Field("err", err))
return err
}
if inventoryAllotOrder.ID == 0 {
return errors.New("未查询到订单信息")
}
if inventoryAllotOrder.State != ErpInventoryAllotOrderWaitReceive {
return errors.New("订单不是待收货状态")
}
// 查询库存调拨商品信息
var commodities []ErpInventoryAllotCommodity
if err := orm.Eloquent.Table("erp_inventory_allot_commodity").Where("allot_order_id = ?",
inventoryAllotOrder.ID).Find(&commodities).Error; err != nil {
logger.Error("query erp_inventory_allot_commodity err:", logger.Field("err", err))
return err
}
if len(commodities) == 0 {
return errors.New("未查询到库存调拨商品信息")
}
begin := orm.Eloquent.Begin()
// 遍历库存调拨商品信息
for _, v := range commodities {
var stockCommodity []ErpStockCommodity
err := orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? AND store_id = ? "+
"AND state = ? AND imei = ?", v.CommodityId, inventoryAllotOrder.ReceiveStoreId, InAllot, v.IMEI).
Find(&stockCommodity).Error
if err != nil {
return fmt.Errorf("查询商品库存失败:[%s]", err.Error())
}
if len(stockCommodity) == 0 {
return fmt.Errorf("未找到商品库存信息")
}
// 更新库存商品表商品状态为:在库
for i := 0; i < int(v.Count); i++ {
stockCommodity[i].State = InStock
stockCommodity[i].StockTime = time.Now()
err = begin.Model(&ErpStockCommodity{}).Where("id = ?", stockCommodity[i].ID).
Updates(stockCommodity[i]).Error
if err != nil {
return fmt.Errorf("更新商品库存失败:%s", err.Error())
}
}
// 更新库存商品数量,扣减库存调拨数量
err = begin.Exec(fmt.Sprintf(
"UPDATE erp_stock SET count=count+%d, dispatch_count = dispatch_count-%d WHERE store_id=%d AND erp_commodity_id=%d",
v.Count, v.Count, inventoryAllotOrder.ReceiveStoreId, v.CommodityId)).Error
if err != nil {
logger.Errorf("update stock err:", err)
return err
}
}
// 更新调拨订单的状态为:已完成
nowTime := time.Now()
inventoryAllotOrder.State = ErpInventoryAllotOrderFinished
inventoryAllotOrder.ReceiveTime = &nowTime
err := begin.Model(&ErpInventoryAllotOrder{}).Where("id = ?", inventoryAllotOrder.ID).
Updates(inventoryAllotOrder).Error
if err != nil {
return err
}
err = begin.Commit().Error
if err != nil {
begin.Rollback()
logger.Errorf("commit err:", err)
return err
}
return nil
}