450 lines
24 KiB
Go
450 lines
24 KiB
Go
|
package model
|
|||
|
|
|||
|
import (
|
|||
|
"fmt"
|
|||
|
"github.com/codinl/go-logger"
|
|||
|
"github.com/jinzhu/gorm"
|
|||
|
"math/rand"
|
|||
|
"time"
|
|||
|
)
|
|||
|
|
|||
|
const (
|
|||
|
ErpOrderStateAudited = "audited" // 已审核
|
|||
|
HavePaid = 2 // 已支付
|
|||
|
NoPrint = 1 // 未打印
|
|||
|
RetailTypeSale = "sale" // 零售销售订单
|
|||
|
SysUserIdByAdmin = 1 // 系统管理员id
|
|||
|
SysUserNameByAdmin = "系统管理员" // 系统管理员名称
|
|||
|
SoldOut = 2 // 已售
|
|||
|
)
|
|||
|
|
|||
|
// ErpStock 库存列表
|
|||
|
type ErpStock struct {
|
|||
|
Model
|
|||
|
|
|||
|
StoreId uint32 `json:"store_id" gorm:"index"` // 门店编号
|
|||
|
StoreName string `json:"store_name"` // 门店名称
|
|||
|
ErpCommodityId uint32 `json:"erp_commodity_id" gorm:"index"` // 商品id
|
|||
|
ErpCommodityName string `json:"erp_commodity_name"` // 商品名称
|
|||
|
ErpCategoryId uint32 `json:"erp_category_id" gorm:"index"` // 分类id
|
|||
|
ErpCategoryName string `json:"erp_category_name"` // 分类名称
|
|||
|
CommoditySerialNumber string `json:"commodity_serial_number" gorm:"index"` // 商品编码/串码
|
|||
|
IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码(系统生成) 3-串码(手动添加)
|
|||
|
RetailPrice float64 `json:"retail_price"` // 指导零售价
|
|||
|
MinRetailPrice float64 `json:"min_retail_price"` // 最低零售价
|
|||
|
Count uint32 `json:"count"` // 数量
|
|||
|
DispatchCount uint32 `json:"dispatch_count"` // 调拨中数量(调拨中调入)
|
|||
|
DecisionStoreId []uint32 `json:"decision_store_id" gorm:"-"` // 门店编号列表(查询进销存的时候使用)
|
|||
|
Commodities []ErpStockCommodity `json:"commodities" gorm:"-"` //
|
|||
|
}
|
|||
|
|
|||
|
// ErpStockCommodity 库存详情
|
|||
|
type ErpStockCommodity struct {
|
|||
|
Model
|
|||
|
|
|||
|
ErpStockId uint32 `json:"erp_stock_id" gorm:"index"` // 库存id
|
|||
|
StoreId uint32 `json:"store_id" gorm:"index"` // 门店id
|
|||
|
StoreName string `json:"store_name"` // 门店名称
|
|||
|
ErpCommodityId uint32 `json:"erp_commodity_id" gorm:"index"` // 商品id
|
|||
|
ErpCommodityName string `json:"erp_commodity_name"` // 商品名称
|
|||
|
CommoditySerialNumber string `json:"commodity_serial_number" gorm:"index"` // 商品编号
|
|||
|
ErpCategoryId uint32 `json:"erp_category_id" gorm:"index"` // 分类id
|
|||
|
ErpCategoryName string `json:"erp_category_name"` // 分类名称
|
|||
|
ErpBarcode string `json:"erp_barcode"` // 商品条码
|
|||
|
IMEIType uint32 `json:"imei_type"` // 是否串码:1-无串码 2-串码(系统生成) 3-串码(手动添加)
|
|||
|
IMEI string `json:"imei"` // 商品串码
|
|||
|
ErpSupplierId uint32 `json:"erp_supplier_id" gorm:"index"` // 供应商id
|
|||
|
ErpSupplierName string `json:"erp_supplier_name"` // 供应商名称
|
|||
|
StockTime time.Time `json:"stock_time"` // 最近入库时间
|
|||
|
RetailPrice float64 `json:"retail_price"` // 指导零售价
|
|||
|
MinRetailPrice float64 `json:"min_retail_price"` // 最低零售价
|
|||
|
StaffCostPrice float64 `json:"staff_cost_price"` // 员工成本价加价(如:加价50,不是加价后的价格)
|
|||
|
WholesalePrice float64 `json:"wholesale_price"` // 指导采购价
|
|||
|
MemberDiscount float64 `json:"member_discount"` // 会员优惠
|
|||
|
State uint32 `json:"state"` // 状态:1-在库 2-已售 3-采购退货 4-调拨中 5-销售锁定中 6-产品出库 7-盘点出库
|
|||
|
Count uint32 `json:"count"` // 数量
|
|||
|
StorageType uint32 `json:"storage_type"` // 入库方式:1-系统入库 2-采购入库 3-产品入库 4-盘点入库
|
|||
|
FirstStockTime time.Time `json:"first_stock_time"` // 首次入库时间
|
|||
|
StockSn string `json:"stock_sn"` // 库存订单编号(跟采购入库的入库编号关联)
|
|||
|
OriginalSn string `json:"original_sn" gorm:"index"` // 首次入库订单编号(单据编号)
|
|||
|
StockStartTime time.Time `json:"stock_start_time" gorm:"-"` // 最近入库开始时间
|
|||
|
StockEndTime time.Time `json:"stock_end_time" gorm:"-"` // 最近入库结束时间
|
|||
|
Age uint32 `json:"age" gorm:"-"` // 最近库龄
|
|||
|
AllAge uint32 `json:"all_age" gorm:"-"` // 总库龄
|
|||
|
Remark string `json:"remark"` // 备注
|
|||
|
CategoryNumber string `json:"category_number" gorm:"-"` // 商品分类编号
|
|||
|
}
|
|||
|
|
|||
|
// ErpCommodity 商品表
|
|||
|
type ErpCommodity struct {
|
|||
|
Model
|
|||
|
|
|||
|
SerialNumber string `json:"serial_number"` // 商品编号
|
|||
|
Number uint32 `json:"number"` // 商品数量
|
|||
|
Name string `json:"name"` // 商品名称
|
|||
|
ErpCategoryId uint32 `json:"erp_category_id" gorm:"index"` // 商品分类id
|
|||
|
ErpCategoryName string `json:"erp_category_name"` // 商品分类名称
|
|||
|
ErpBarcode string `json:"erp_barcode"` // 商品条码
|
|||
|
IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码(系统生成) 3-串码(手动添加)
|
|||
|
IMEI string `json:"imei"` // 串码
|
|||
|
ErpSupplierId uint32 `json:"erp_supplier_id" gorm:"index"` // 主供应商id
|
|||
|
ErpSupplierName string `json:"erp_supplier_name"` // 主供应商名称
|
|||
|
RetailPrice uint32 `json:"retail_price"` // 指导零售价
|
|||
|
MinRetailPrice uint32 `json:"min_retail_price"` // 最低零售价
|
|||
|
StaffCostPrice uint32 `json:"staff_cost_price"` // 员工成本价加价(如:加价50,不是加价后的价格)
|
|||
|
WholesalePrice uint32 `json:"wholesale_price"` // 指导采购价
|
|||
|
Brokerage1 float64 `json:"brokerage_1"` // 销售毛利提成
|
|||
|
Brokerage2 float64 `json:"brokerage_2"` // 员工毛利提成
|
|||
|
MemberDiscount float64 `json:"member_discount"` // 会员优惠
|
|||
|
Origin string `json:"origin"` // 产地
|
|||
|
Remark string `json:"remark" gorm:"type:varchar(512)"` // 备注
|
|||
|
Img string `json:"img"` // 图片
|
|||
|
StopPurchase uint32 `json:"stop_purchase"` // 0-未勾选,正常采购;1-勾选,停止采购
|
|||
|
ManufacturerCode string `json:"manufacturer_code"` // 厂家编码
|
|||
|
IsSyncedToMall uint32 `json:"is_synced_to_mall"` // 是否同步到小程序商城:0-否;1-是
|
|||
|
GoodsId uint32 `json:"goods_id"` // 小程序商城-商品ID
|
|||
|
SaleStatus uint32 `json:"sale_status"` // 小程序商城-在售状态 1-在售 2-下架
|
|||
|
|
|||
|
ErpCategory *ErpCategory `json:"erp_category" gorm:"-"`
|
|||
|
}
|
|||
|
|
|||
|
// ErpCategory 商品分类
|
|||
|
type ErpCategory struct {
|
|||
|
Model
|
|||
|
|
|||
|
Name string `json:"name"` // 名称
|
|||
|
Priority string `json:"priority"` // 分类
|
|||
|
Number uint32 `json:"number"` //
|
|||
|
FullNum uint32 `json:"full_num"` //
|
|||
|
State uint32 `json:"state"` // 1-未使用 2-使用 3-隐藏
|
|||
|
Level uint32 `json:"level"` // 分类层级
|
|||
|
Pid uint32 `json:"pid" gorm:"index"` //
|
|||
|
Sort uint32 `json:"sort"` //
|
|||
|
SubCats []ErpCategory `json:"sub_cats" gorm:"-"` // 子列表
|
|||
|
}
|
|||
|
|
|||
|
// ErpOrder 零售订单表
|
|||
|
type ErpOrder struct {
|
|||
|
Model
|
|||
|
|
|||
|
BillSn string `json:"bill_sn" gorm:"index"` // 单据编号
|
|||
|
RetailType string `json:"retail_type"` // 销售类型:sale 零售销售; rejected 零售退货
|
|||
|
GoodsOrderId uint32 `json:"goods_order_id" gorm:"index"` // 小程序商城订单id
|
|||
|
Uid int `json:"uid"` // 用户id
|
|||
|
UserType int `json:"user_type"` // 会员类别:1-普通会员 2-黄金会员 4-白金会员 5-黑金会员 6-尊享会员 7-黄金&尊享 8-白金&尊享 9-黑金&尊享
|
|||
|
Tel string `json:"tel" gorm:"index"` // 客户手机号
|
|||
|
StoreId uint32 `json:"store_id" gorm:"index"` // 门店id
|
|||
|
StoreName string `json:"store_name"` // 门店名称
|
|||
|
MakerId uint32 `json:"maker_id" gorm:"index"` // 制单人id
|
|||
|
MakerName string `json:"maker_name"` // 制单人名称
|
|||
|
MakerTime time.Time `json:"maker_time"` // 制单时间
|
|||
|
AuditorId uint32 `json:"auditor_id" gorm:"index"` // 审核人id
|
|||
|
AuditorName string `json:"auditor_name"` // 审核人姓名
|
|||
|
AuditTime *time.Time `json:"audit_time"` // 审核时间
|
|||
|
CashierList string `json:"cashier_list" gorm:"type:text"` // 付款方式,存储json数据
|
|||
|
SalesmanList string `json:"salesman_list" gorm:"type:text"` // 销售员信息,存储json数据
|
|||
|
MemberType string `json:"member_type"` // 会员类型:general 普通; member 会员
|
|||
|
State string `json:"state" gorm:"index"` // 订单状态:un_audit 待审核; audited 已审核
|
|||
|
TotalRetailPrice float64 `json:"total_retail_price"` // 订单总指导零售价
|
|||
|
TotalAmount float64 `json:"total_amount"` // 订单实收金额
|
|||
|
TotalCount int32 `json:"total_count"` // 订单商品数量
|
|||
|
TotalSalesProfit float64 `json:"total_sales_profit"` // 订单总销售毛利
|
|||
|
TotalStaffProfit float64 `json:"total_staff_profit"` // 订单总员工毛利
|
|||
|
VmCount uint32 `json:"vm_count"` // 使用会员积分
|
|||
|
SaleOrderId uint32 `json:"sale_order_id"` // 销售订单id
|
|||
|
PayStatus uint32 `json:"pay_status"` // 支付状态 0-未创建 ;1-待支付; 2-已支付
|
|||
|
IsPrint uint32 `json:"is_print"` // 是否打印小票 1-未打印 2-已打印
|
|||
|
PrintCount uint32 `json:"print_count"` // 小票打印次数
|
|||
|
InvoiceCode string `json:"invoice_code"` // 发票代码
|
|||
|
InvoiceNumber string `json:"invoice_number"` // 发票编码
|
|||
|
RejectedTotalAmount float64 `json:"rejected_total_amount" gorm:"-"` // 订单总退货金额
|
|||
|
RejectedTotalCount uint32 `json:"rejected_total_count" gorm:"-"` // 订单总退货数量
|
|||
|
StorePer float64 `json:"store_per"` // 门店提成:订单总员工毛利X该门店设置好的提成比例,保留到小数后两位多余舍去
|
|||
|
TotalDiscount float64 `json:"total_discount"` // 订单总优惠:订单所有商品零售优惠+会员优惠+会员积分抵扣之和
|
|||
|
BankTrxNo string `json:"bank_trx_no" gorm:"-"` // 银行流水号
|
|||
|
Commodities []ErpOrderCommodity `json:"commodities" gorm:"-"` // 零售订单商品信息
|
|||
|
Cashiers []ErpOrderCashier `json:"cashiers" gorm:"-"` // 收付款方式
|
|||
|
Salesman []ErpOrderSales `json:"salesman" gorm:"-"` // 销售员信息
|
|||
|
}
|
|||
|
|
|||
|
// ErpOrderSales 销售员信息
|
|||
|
type ErpOrderSales struct {
|
|||
|
Model
|
|||
|
|
|||
|
ErpOrderId uint32 `json:"erp_order_id" gorm:"index"` // 零售订单id(后端生成)
|
|||
|
Uid uint32 `json:"userId" binding:"required"` // 销售员用户ID(20240322:更换为系统用户表主键id)
|
|||
|
Name string `json:"name"` // 销售员用户姓名
|
|||
|
SalesProfitPer float64 `json:"sales_profit_per"` // 销售毛利提成:每个商品销售毛利X其对应的提成比例后求和;如果是两个销售员参与则分别除以2 ,保留到小数后两位多余舍去
|
|||
|
StaffProfitPer float64 `json:"staff_profit_per"` // 员工毛利提成:每个商品员工毛利X其对应的提成比例后求和;如果是两个销售员参与则分别除以2 ,保留到小数后两位多余舍去
|
|||
|
SalesmanPer float64 `json:"salesman_per"` // 销售员提成:订单总员工毛利X该销售员设置好的提成比例;如果是两个销售员参与,那么两个人算出的提成均除以2,保留到小数后两位多余舍去
|
|||
|
}
|
|||
|
|
|||
|
// ErpOrderCashier 订单收款方式
|
|||
|
type ErpOrderCashier struct {
|
|||
|
CashierId uint32 `json:"cashier_id"` // 收付款方式id
|
|||
|
Name string `json:"name"` // 收付款方式名称
|
|||
|
Amount float64 `json:"amount"` // 金额
|
|||
|
}
|
|||
|
|
|||
|
// ErpOrderCommodity 零售订单商品表
|
|||
|
type ErpOrderCommodity struct {
|
|||
|
Model
|
|||
|
|
|||
|
ErpOrderId uint32 `json:"erp_order_id" gorm:"index"` // 零售订单id(后端生成)
|
|||
|
ErpCategoryId uint32 `json:"erp_category_id" gorm:"index"` // 分类id
|
|||
|
ErpCategoryName string `json:"erp_category_name"` // 分类名称
|
|||
|
ErpCommodityId uint32 `json:"erp_commodity_id" gorm:"index"` // 商品id
|
|||
|
ErpCommodityName string `json:"erp_commodity_name"` // 商品名称
|
|||
|
ErpSupplierId uint32 `json:"erp_supplier_id" gorm:"index"` // 主供应商id
|
|||
|
ErpSupplierName string `json:"erp_supplier_name"` // 主供应商名称
|
|||
|
IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码
|
|||
|
IMEI string `json:"imei" gorm:"index"` // 串码
|
|||
|
PresentType uint32 `json:"present_type"` // 赠送类型:1-非赠送 2-赠送
|
|||
|
RetailPrice float64 `json:"retail_price"` // 指导零售价
|
|||
|
SalePrice float64 `json:"sale_price"` // 零售价
|
|||
|
Count int32 `json:"count"` // 销售数量
|
|||
|
SaleDiscount float64 `json:"sale_discount"` // 零售优惠
|
|||
|
MemberDiscount float64 `json:"member_discount"` // 会员优惠
|
|||
|
VmDiscount float64 `json:"vm_discount"` // 会员积分抵扣
|
|||
|
CouponID uint32 `json:"coupon_id"` // 优惠券ID
|
|||
|
CouponDiscount float64 `json:"coupon_discount"` // 优惠券抵扣
|
|||
|
CouponCode string `json:"coupon_code"` // 优惠券券码
|
|||
|
CouponName string `json:"coupon_name"` // 优惠券名称
|
|||
|
Amount float64 `json:"amount"` // 实际零售价
|
|||
|
ReceivedAmount float64 `json:"received_amount"` // 商品实收金额
|
|||
|
Remark string `json:"remark"` // 销售备注
|
|||
|
RejectedRemark string `json:"rejected_remark"` // 退货备注
|
|||
|
RejectedPrice float64 `json:"rejected_price"` // 退货单价
|
|||
|
RejectedCount uint32 `json:"rejected_count"` // 退货数量
|
|||
|
RejectedAmount float64 `json:"rejected_amount"` // 退货金额
|
|||
|
RejectedOrderCommodityId uint32 `json:"rejected_order_commodity_id"` // 退货订单商品id
|
|||
|
StaffCostPrice float64 `json:"staff_cost_price"` // 员工成本价加价(如:加价50,不是加价后的价格)
|
|||
|
WholesalePrice float64 `json:"wholesale_price"` // 指导采购价
|
|||
|
SalesProfit float64 `json:"sales_profit"` // 销售毛利:实际零售价-采购单价;如果为退货订单,则为实际退货价-采购单价
|
|||
|
StaffProfit float64 `json:"staff_profit"` // 员工毛利:实际零售价-员工成本价;如果为退货订单,则为实际退货价-员工成本价
|
|||
|
ErpStockCommodityID string `json:"erp_stock_commodity_id"` // 库存商品表主键id
|
|||
|
StaffPrice float64 `json:"staff_price" gorm:"-"` // 员工成本价
|
|||
|
CommoditySerialNumber string `json:"commodity_serial_number" gorm:"-"` // 商品编号
|
|||
|
CategoryNumber string `json:"category_number" gorm:"-"` // 商品分类编号
|
|||
|
}
|
|||
|
|
|||
|
// NewErpBillSn 生成零售订单号
|
|||
|
func NewErpBillSn() string {
|
|||
|
nowTime := time.Now()
|
|||
|
rand.Seed(nowTime.UnixNano())
|
|||
|
max := 1
|
|||
|
for {
|
|||
|
if max > 5 {
|
|||
|
logger.Error("create sn err")
|
|||
|
return ""
|
|||
|
}
|
|||
|
random := rand.Int31n(9999) + 1000
|
|||
|
sn := fmt.Sprintf("%s%d", nowTime.Format("060102"), random)
|
|||
|
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_order WHERE bill_sn='%s'", sn))
|
|||
|
if err != nil {
|
|||
|
logger.Error("exist sn err")
|
|||
|
}
|
|||
|
if !exist {
|
|||
|
return sn
|
|||
|
}
|
|||
|
|
|||
|
max++
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// SelectDeliveryStock 选择发货库存
|
|||
|
// commodityId: 商品ID
|
|||
|
// storeId: 指定门店ID(0 表示不指定)
|
|||
|
// return: 选中的库存记录
|
|||
|
func SelectDeliveryStock(commodityId, storeId uint32) (*ErpStockCommodity, error) {
|
|||
|
var stock ErpStockCommodity
|
|||
|
|
|||
|
// 1️⃣ 优先指定门店
|
|||
|
if storeId > 0 {
|
|||
|
err := DB.Table("erp_stock_commodity").
|
|||
|
Where("erp_commodity_id = ? AND store_id = ? AND state = 1 AND count > 0", commodityId, storeId).
|
|||
|
Order("first_stock_time ASC").
|
|||
|
First(&stock).Error
|
|||
|
if err == nil {
|
|||
|
return &stock, nil
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 2️⃣ 其他门店,优先库龄最久
|
|||
|
var otherStocks []ErpStockCommodity
|
|||
|
err := DB.Table("erp_stock_commodity").
|
|||
|
Where("erp_commodity_id = ? AND state = 1 AND count > 0", commodityId).
|
|||
|
Order("first_stock_time ASC").
|
|||
|
Find(&otherStocks).Error
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
if len(otherStocks) == 0 {
|
|||
|
return nil, fmt.Errorf("无可用库存")
|
|||
|
}
|
|||
|
|
|||
|
// 3️⃣ 多个相同库龄,随机一个
|
|||
|
oldestTime := otherStocks[0].FirstStockTime
|
|||
|
var oldestStocks []ErpStockCommodity
|
|||
|
for _, s := range otherStocks {
|
|||
|
if s.FirstStockTime.Equal(oldestTime) {
|
|||
|
oldestStocks = append(oldestStocks, s)
|
|||
|
} else {
|
|||
|
break
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
rand.Seed(time.Now().UnixNano())
|
|||
|
chosen := oldestStocks[rand.Intn(len(oldestStocks))]
|
|||
|
return &chosen, nil
|
|||
|
}
|
|||
|
|
|||
|
// CreateErpOrder 根据小程序订单生成ERP零售订单
|
|||
|
func CreateErpOrder(goodsOrder *GoodsOrder, goods *Goods) error {
|
|||
|
logger.Infof("enter CreateErpOrder")
|
|||
|
logger.Infof("goods: %+v", goods)
|
|||
|
logger.Infof("goodsOrder: %+v", goodsOrder)
|
|||
|
tx := DB.Begin()
|
|||
|
if tx.Error != nil {
|
|||
|
return tx.Error
|
|||
|
}
|
|||
|
|
|||
|
defer func() {
|
|||
|
if r := recover(); r != nil {
|
|||
|
logger.Errorf("事务 panic 回滚: %v", r)
|
|||
|
tx.Rollback()
|
|||
|
}
|
|||
|
}()
|
|||
|
|
|||
|
// 1. 查找用户信息
|
|||
|
var user User
|
|||
|
if err := tx.Where("uid = ?", goodsOrder.Uid).First(&user).Error; err != nil {
|
|||
|
logger.Infof("用户 %d 不存在", goodsOrder.Uid)
|
|||
|
return fmt.Errorf("用户不存在: %w", err)
|
|||
|
}
|
|||
|
|
|||
|
var orderCommodities []ErpOrderCommodity
|
|||
|
var totalAmount, totalRetailPrice, totalSalesProfit, totalStaffProfit float64
|
|||
|
var totalCount int32
|
|||
|
|
|||
|
// 遍历小程序订单的商品明细
|
|||
|
// 选择库存:优先指定门店 → 其他门店库龄最久
|
|||
|
stock, err := SelectDeliveryStock(goods.ErpCommodityId, goodsOrder.NearestStoreId)
|
|||
|
if err != nil {
|
|||
|
tx.Rollback()
|
|||
|
logger.Infof("商品 %d 无库存: %v", goods.ErpCommodityId, err)
|
|||
|
return fmt.Errorf("商品 %d 无库存: %v", goods.ErpCommodityId, err)
|
|||
|
}
|
|||
|
logger.Infof("stock: %+v", stock)
|
|||
|
|
|||
|
// 扣减库存
|
|||
|
err = tx.Table("erp_stock_commodity").Where("id = ?", stock.ID).
|
|||
|
Updates(map[string]interface{}{
|
|||
|
"state": SoldOut,
|
|||
|
"updated_at": time.Now(),
|
|||
|
}).Error // 状态更新为已销售
|
|||
|
if err != nil {
|
|||
|
logger.Error("update erp_stock_commodity err:", err)
|
|||
|
tx.Rollback()
|
|||
|
return fmt.Errorf("库存扣减失败: %v", err)
|
|||
|
}
|
|||
|
|
|||
|
err = tx.Table("erp_stock").Where("store_id = ? and erp_commodity_id = ? AND count > 0",
|
|||
|
stock.StoreId, stock.ErpCommodityId).
|
|||
|
Updates(map[string]interface{}{
|
|||
|
"count": gorm.Expr("count - ?", 1),
|
|||
|
"updated_at": time.Now(),
|
|||
|
}).Error // 库存数量-1
|
|||
|
if err != nil {
|
|||
|
logger.Error("update erp_stock err:", err)
|
|||
|
tx.Rollback()
|
|||
|
return fmt.Errorf("库存不足")
|
|||
|
}
|
|||
|
|
|||
|
// 金额计算
|
|||
|
receivedAmount := float64(goodsOrder.Quantity) * float64(goods.PriceRm/100)
|
|||
|
salesProfit := receivedAmount - stock.WholesalePrice*float64(goodsOrder.Quantity)
|
|||
|
staffProfit := receivedAmount - (stock.WholesalePrice+stock.StaffCostPrice)*float64(goodsOrder.Quantity)
|
|||
|
|
|||
|
orderCommodities = append(orderCommodities, ErpOrderCommodity{
|
|||
|
ErpCategoryId: stock.ErpCategoryId,
|
|||
|
ErpCategoryName: stock.ErpCategoryName,
|
|||
|
ErpCommodityId: stock.ErpCommodityId,
|
|||
|
ErpCommodityName: stock.ErpCommodityName,
|
|||
|
ErpSupplierId: stock.ErpSupplierId,
|
|||
|
ErpSupplierName: stock.ErpSupplierName,
|
|||
|
IMEIType: stock.IMEIType,
|
|||
|
IMEI: "",
|
|||
|
PresentType: 1,
|
|||
|
RetailPrice: stock.RetailPrice,
|
|||
|
SalePrice: float64(goods.PriceRm / 100),
|
|||
|
Count: int32(goodsOrder.Quantity),
|
|||
|
Amount: receivedAmount,
|
|||
|
ReceivedAmount: receivedAmount,
|
|||
|
StaffCostPrice: stock.StaffCostPrice,
|
|||
|
WholesalePrice: stock.WholesalePrice,
|
|||
|
SalesProfit: salesProfit,
|
|||
|
StaffProfit: staffProfit,
|
|||
|
ErpStockCommodityID: fmt.Sprintf("%d", stock.ID),
|
|||
|
})
|
|||
|
logger.Infof("orderCommodities 长度: %d", len(orderCommodities))
|
|||
|
|
|||
|
totalAmount += receivedAmount
|
|||
|
totalRetailPrice += stock.RetailPrice * float64(goodsOrder.Quantity)
|
|||
|
totalSalesProfit += salesProfit
|
|||
|
totalStaffProfit += staffProfit
|
|||
|
totalCount += int32(goodsOrder.Quantity)
|
|||
|
|
|||
|
nowTime := time.Now()
|
|||
|
// ERP订单
|
|||
|
order := ErpOrder{
|
|||
|
BillSn: NewErpBillSn(),
|
|||
|
GoodsOrderId: goodsOrder.OrderId,
|
|||
|
RetailType: RetailTypeSale,
|
|||
|
Uid: int(goodsOrder.Uid),
|
|||
|
UserType: int(user.MemberLevel),
|
|||
|
Tel: user.Tel,
|
|||
|
StoreId: stock.StoreId,
|
|||
|
StoreName: stock.StoreName,
|
|||
|
MakerId: SysUserIdByAdmin,
|
|||
|
MakerName: SysUserNameByAdmin,
|
|||
|
MakerTime: nowTime,
|
|||
|
AuditorId: SysUserIdByAdmin,
|
|||
|
AuditorName: SysUserNameByAdmin,
|
|||
|
AuditTime: &nowTime,
|
|||
|
State: ErpOrderStateAudited,
|
|||
|
TotalRetailPrice: totalRetailPrice,
|
|||
|
TotalAmount: totalAmount,
|
|||
|
TotalCount: totalCount,
|
|||
|
TotalSalesProfit: totalSalesProfit,
|
|||
|
TotalStaffProfit: totalStaffProfit,
|
|||
|
PayStatus: HavePaid, // 已支付
|
|||
|
IsPrint: NoPrint, // 未打印
|
|||
|
PrintCount: 0,
|
|||
|
}
|
|||
|
|
|||
|
if err = tx.Create(&order).Error; err != nil {
|
|||
|
logger.Infof("新建erp零售订单失败: %v", err)
|
|||
|
tx.Rollback()
|
|||
|
return fmt.Errorf("新建erp零售订单失败: %v", err)
|
|||
|
}
|
|||
|
|
|||
|
// 绑定订单ID
|
|||
|
for i := range orderCommodities {
|
|||
|
orderCommodities[i].ErpOrderId = order.ID
|
|||
|
if err = tx.Create(&orderCommodities[i]).Error; err != nil {
|
|||
|
logger.Errorf("新建erp零售订单商品信息失败: %v", err)
|
|||
|
tx.Rollback()
|
|||
|
return fmt.Errorf("新建erp零售订单商品信息失败: %v", err)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if err = tx.Commit().Error; err != nil {
|
|||
|
logger.Infof("提交事务失败: %v", err)
|
|||
|
return fmt.Errorf("提交事务失败: %v", err)
|
|||
|
}
|
|||
|
|
|||
|
logger.Infof("leave CreateErpOrder")
|
|||
|
return nil
|
|||
|
}
|