837 lines
33 KiB
Go
837 lines
33 KiB
Go
package models
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
orm "go-admin/common/global"
|
||
"go-admin/logger"
|
||
"gorm.io/gorm"
|
||
"math/rand"
|
||
"time"
|
||
)
|
||
|
||
const (
|
||
ErpPurchaseOrderUnAudit = 1 // 待审核
|
||
ErpPurchaseOrderWaitInventory = 2 // 待入库
|
||
ErpPurchaseOrderWaitReject = 3 // 待退货
|
||
ErpPurchaseOrderFinished = 4 // 已完成
|
||
ErpPurchaseOrderEnd = 5 // 已终止
|
||
ErpPurchaseOrderInInventory = 6 // 入库中,部分入库
|
||
ErpPurchaseOrderInReject = 7 // 退货中,部分退货
|
||
|
||
ErpProcureOrder = "procure" // 采购入库订单
|
||
ErpRejectOrder = "reject" // 采购退货订单
|
||
)
|
||
|
||
// ErpPurchaseOrder 采购订单表
|
||
type ErpPurchaseOrder struct {
|
||
Model
|
||
SerialNumber string `json:"serial_number" gorm:"index"` // 单据编号
|
||
PurchaseType string `json:"purchase_type"` // 类型:procure-采购 reject-退货
|
||
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-待入库 3-待退货 4-已完成 5-已终止
|
||
RejectedPurchaseOrderId uint32 `json:"rejected_purchase_order_id"` // 退货采购订单id
|
||
ErpCashierId uint32 `json:"erp_cashier_id"` // 付款方式/收款方式id
|
||
ErpCashierName string `json:"erp_cashier_name"` // 付款方式/收款方式名称
|
||
AccountHolder string `json:"account_holder"` // 收款人
|
||
OpeningBank string `json:"opening_bank"` // 开户行
|
||
BankAccount string `json:"bank_account"` // 银行卡号
|
||
DeliveryTime string `json:"delivery_time"` // 交货日期
|
||
Commodities []ErpPurchaseCommodity `json:"commodities" gorm:"-"`
|
||
}
|
||
|
||
// ErpPurchaseCommodity 采购订单商品表
|
||
type ErpPurchaseCommodity struct {
|
||
Model
|
||
ErpPurchaseOrderId uint32 `json:"erp_purchase_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-串码
|
||
IMEI string `json:"imei"` // 商品串码
|
||
Count uint32 `json:"count"` // 计划采购数量
|
||
Price uint32 `json:"price"` // 计划采购单价
|
||
Amount uint32 `json:"amount"` // 计划采购金额
|
||
Remark string `json:"remark"` // 备注
|
||
RejectedPrice uint32 `json:"rejected_price"` // 计划退货单价
|
||
RejectedCount uint32 `json:"rejected_count"` // 计划退货数量
|
||
RejectedAmount uint32 `json:"rejected_amount"` // 计划退货金额
|
||
InventoryCount int32 `json:"inventory_count"` // 入库数量(=执行数量)
|
||
ExecutionCount uint32 `json:"execute_count" gorm:"-"` // 执行数量
|
||
ExecutionPrice uint32 `json:"execute_price" gorm:"-"` // 平均采购单价
|
||
ExecutionEmployeePrice uint32 `json:"execute_employee_price" gorm:"-"` // 平均员工成本价
|
||
ExecutionAmount uint32 `json:"execute_amount" gorm:"-"` // 执行金额
|
||
}
|
||
|
||
// ErpPurchaseInventory 采购入库执行表
|
||
type ErpPurchaseInventory struct {
|
||
Model
|
||
SerialNumber string `json:"serial_number" gorm:"index"` // 入库编号
|
||
InventoryType string `json:"inventory_type"` // 采购类型:procure-采购 reject-退货
|
||
ErpPurchaseOrderId uint32 `json:"erp_purchase_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-串码
|
||
IMEI string `json:"imei"` // 商品串码
|
||
Count uint32 `json:"count"` // 数量
|
||
Price uint32 `json:"price"` // 采购单价
|
||
ImplementationPrice uint32 `json:"implementation_price"` // 执行单价
|
||
EmployeePrice uint32 `json:"employee_price"` // 员工成本价
|
||
InventoryCount int32 `json:"inventory_count"` // 入库数量
|
||
Amount uint32 `json:"amount"` // 入库金额
|
||
Remark string `json:"remark"` // 备注
|
||
|
||
//ErpPurchaseCommodity *ErpPurchaseCommodity `json:"erp_purchase_commodity" gorm:"-"`
|
||
}
|
||
|
||
// ErpInventoryCommodity 采购入库执行商品表
|
||
type ErpInventoryCommodity struct {
|
||
Model
|
||
SerialNumber string `json:"serial_number" gorm:"index"` // 入库编号
|
||
InventoryType string `json:"inventory_type"` //
|
||
ErpPurchaseInventoryId uint32 `json:"erp_purchase_inventory_id"` // 商品采购入库id
|
||
ErpPurchaseOrderId uint32 `json:"erp_purchase_order_id"` // 商品采购订单id
|
||
ErpCommodityId uint32 `json:"erp_commodity_id"` // 商品id
|
||
ErpCommodityName string `json:"erp_commodity_name"` // 商品名称
|
||
CommoditySerialNumber string `json:"commodity_serial_number"` // 商品编码
|
||
IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码
|
||
IMEI string `json:"imei"` // 串码
|
||
Count uint32 `json:"count"` //
|
||
Price uint32 `json:"price"` //
|
||
EmployeePrice uint32 `json:"employee_price"` // 员工成本
|
||
ImplementationPrice uint32 `json:"implementation_price"` //
|
||
Amount uint32 `json:"amount"` //
|
||
Remark string `json:"remark"` // 备注
|
||
}
|
||
|
||
type ErpPurchaseCreateReq struct {
|
||
PurchaseType string `json:"purchase_type" binding:"required"` // 采购类型:procure-采购 reject-退货
|
||
PurchaseOrderSn string `json:"purchase_order_sn"` // 采购退货订单号
|
||
StoreId uint32 `json:"store_id" binding:"required"` // 门店id
|
||
DeliveryAddress string `json:"delivery_address" binding:"required"` // 交货地址
|
||
MakerId uint32 `json:"maker_id" binding:"required"` // 经手人
|
||
ErpSupplierId uint32 `json:"erp_supplier_id" binding:"required"` // 供应商id
|
||
ErpCashierId uint32 `json:"erp_cashier_id" binding:"required"` // 付款方式
|
||
AccountHolder string `json:"account_holder"` // 收款人
|
||
OpeningBank string `json:"opening_bank" validate:"required"` // 开户行
|
||
BankAccount string `json:"bank_account" validate:"required"` // 银行卡号
|
||
DeliveryTime string `json:"delivery_time" binding:"required"` // 交货日期
|
||
Remark string `json:"remark"` // 备注
|
||
ErpPurchaseCommodities []ErpPurchaseCommodity `json:"erp_purchase_commodities" binding:"required"` // 采购商品信息
|
||
}
|
||
|
||
type ErpPurchaseEditReq struct {
|
||
ErpPurchaseOrderId uint32 `json:"erp_purchase_order_id" binding:"required"` // 采购订单id
|
||
PurchaseType string `json:"purchase_type" binding:"required"` // 采购类型:procure-采购 reject-退货
|
||
PurchaseOrderSn string `json:"purchase_order_sn"` // 采购退货订单号
|
||
StoreId uint32 `json:"store_id" binding:"required"` // 门店id
|
||
DeliveryAddress string `json:"delivery_address" binding:"required"` // 交货地址
|
||
MakerId uint32 `json:"maker_id" binding:"required"` // 经手人
|
||
ErpSupplierId uint32 `json:"erp_supplier_id" binding:"required"` // 供应商id
|
||
ErpCashierId uint32 `json:"erp_cashier_id" binding:"required"` // 付款方式
|
||
AccountHolder string `json:"account_holder"` // 收款人
|
||
OpeningBank string `json:"opening_bank" validate:"required"` // 开户行
|
||
BankAccount string `json:"bank_account" validate:"required"` // 银行卡号
|
||
DeliveryTime string `json:"delivery_time" binding:"required"` // 交货日期
|
||
Remark string `json:"remark"` // 备注
|
||
ErpPurchaseCommodities []ErpPurchaseCommodity `json:"erp_purchase_commodities" binding:"required"` // 采购商品信息
|
||
}
|
||
|
||
type ErpPurchaseOrderListReq struct {
|
||
SerialNumber string `json:"serial_number"` // 单据编号
|
||
PurchaseType string `json:"purchase_type"` // 采购类型:procure-采购 reject-退货
|
||
StoreId uint32 `json:"store_id"` // 门店id
|
||
ErpSupplierId uint32 `json:"erp_supplier_id"` // 供应商id
|
||
AuditTimeStart string `json:"audit_time_start"` // 审核开始时间
|
||
AuditTimeEnd string `json:"audit_time_end"` // 审核结束时间
|
||
State uint32 `json:"state"` // 状态:1-待审核 2-待入库 3-待退货 4-已完成
|
||
PageIndex int `json:"pageIndex"` // 页码
|
||
PageSize int `json:"pageSize"` // 页面条数
|
||
}
|
||
|
||
type ErpPurchaseOrderListResp struct {
|
||
List []ErpPurchaseOrder `json:"list"`
|
||
Total int `json:"total"` // 总条数
|
||
PageIndex int `json:"pageIndex"` // 页码
|
||
PageSize int `json:"pageSize"` // 页面条数
|
||
}
|
||
|
||
type ErpPurchaseDetailReq struct {
|
||
ErpPurchaseOrderId uint32 `json:"erp_purchase_order_id" binding:"required"` // 采购订单id
|
||
}
|
||
|
||
// ErpPurchaseInventoryReq 入库(退货)入参;执行(入库/退货)入参
|
||
type ErpPurchaseInventoryReq struct {
|
||
ErpPurchaseOrderId uint32 `json:"erp_purchase_order_id" binding:"required"` // 采购订单id
|
||
InventoryType string `json:"inventory_type" binding:"required"` // 采购类型:procure-采购 reject-退货
|
||
Inventories []ErpPurchaseInventory `json:"inventories" binding:"required"` // 采购入库执行信息
|
||
//Commodities []ErpInventoryCommodity `json:"commodities" binding:"required"`
|
||
}
|
||
|
||
// ErpPurchaseAuditReq 审核采购订单入参
|
||
type ErpPurchaseAuditReq struct {
|
||
SerialNumber string `json:"serial_number" binding:"required"` // 单据编号
|
||
State int `json:"state" binding:"required"` // 审核操作: 1-审核 2-取消审核
|
||
}
|
||
|
||
// ErpPurchaseTerminateReq 终止采购入参
|
||
type ErpPurchaseTerminateReq struct {
|
||
SerialNumber string `json:"serial_number" binding:"required"` // 单据编号
|
||
}
|
||
|
||
// ErpPurchaseExecuteResp 执行(入库/退货)出参
|
||
type ErpPurchaseExecuteResp struct {
|
||
List []ExecuteData `json:"list"`
|
||
Total int `json:"total"` // 总条数
|
||
PageIndex int `json:"pageIndex"` // 页码
|
||
PageSize int `json:"pageSize"` // 页面条数
|
||
}
|
||
|
||
type ExecuteData struct {
|
||
ErpPurchaseOrderId uint32 `json:"erp_purchase_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-串码
|
||
IMEI string `json:"imei"` // 商品串码
|
||
Count uint32 `json:"count"` // 数量
|
||
ImplementationPrice uint32 `json:"implementation_price"` // 执行单价
|
||
EmployeePrice uint32 `json:"employee_price"` // 员工成本价
|
||
}
|
||
|
||
func (m *ErpPurchaseOrderListReq) List() (*ErpPurchaseOrderListResp, error) {
|
||
resp := &ErpPurchaseOrderListResp{
|
||
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_order")
|
||
if m.SerialNumber != "" {
|
||
qs = qs.Where("serial_number=?", m.SerialNumber)
|
||
} else {
|
||
if m.PurchaseType != "" {
|
||
qs = qs.Where("purchase_type=?", m.PurchaseType)
|
||
}
|
||
if m.StoreId != 0 {
|
||
qs = qs.Where("store_id=?", m.StoreId)
|
||
}
|
||
if m.ErpSupplierId != 0 {
|
||
qs = qs.Where("erp_supplier_id=?", m.ErpSupplierId)
|
||
}
|
||
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("erpPurchaseOrderList 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("erpPurchaseOrderList err:", err)
|
||
return nil, err
|
||
}
|
||
parse = parse.AddDate(0, 0, 1)
|
||
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 []ErpPurchaseOrder
|
||
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
|
||
}
|
||
|
||
resp.List = orders
|
||
return resp, nil
|
||
}
|
||
|
||
// NewErpPurchaseSn 生成采购订单号
|
||
func NewErpPurchaseSn() 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_purchase_order WHERE serial_number='%s'", sn))
|
||
if err != nil {
|
||
logger.Error("exist sn err")
|
||
}
|
||
if !exist {
|
||
return sn
|
||
}
|
||
|
||
max++
|
||
}
|
||
}
|
||
|
||
func ErpPurchaseCommodityListPerfectInfo(purchaseCommodities []ErpPurchaseCommodity) error {
|
||
commodityIds := make([]uint32, 0, len(purchaseCommodities))
|
||
for i, _ := range purchaseCommodities {
|
||
commodityIds = append(commodityIds, purchaseCommodities[i].ID)
|
||
}
|
||
commodityMap, err := GetErpCommodityMap(commodityIds)
|
||
if err != nil {
|
||
logger.Error("purchase commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
for i, _ := range purchaseCommodities {
|
||
v, ok := commodityMap[purchaseCommodities[i].ErpCommodityId]
|
||
if ok {
|
||
purchaseCommodities[i].CommoditySerialNumber = v.SerialNumber
|
||
purchaseCommodities[i].IMEIType = v.IMEIType
|
||
//purchaseCommodities[i].IMEI = v.IMEI
|
||
purchaseCommodities[i].ErpCommodityName = v.Name
|
||
if purchaseCommodities[i].Count != 0 {
|
||
purchaseCommodities[i].Amount = purchaseCommodities[i].Count * purchaseCommodities[i].Price
|
||
}
|
||
if purchaseCommodities[i].RejectedCount != 0 {
|
||
purchaseCommodities[i].RejectedAmount = purchaseCommodities[i].RejectedCount * purchaseCommodities[i].RejectedPrice
|
||
}
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// IdInit 添加商户和供应商信息
|
||
func (m *ErpPurchaseOrder) 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
|
||
}
|
||
|
||
if m.ErpCashierId != 0 {
|
||
cashier, err := GetAccountDetail(int(m.ErpCashierId))
|
||
if err != nil {
|
||
logger.Error("get cashier err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
m.ErpCashierName = cashier.Name
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// GetPurchaseInventorySn 生成入库编号
|
||
func GetPurchaseInventorySn() string {
|
||
count := 0
|
||
for {
|
||
if count > 5 {
|
||
return ""
|
||
}
|
||
nowTime := time.Now()
|
||
sn := nowTime.Format("060102")
|
||
sn += fmt.Sprintf("%d", nowTime.Unix()%100)
|
||
rand.Seed(nowTime.UnixNano())
|
||
sn += fmt.Sprintf("%d", rand.Int31n(100))
|
||
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_purchase_inventory WHERE serial_number='%s'", sn))
|
||
if err != nil {
|
||
logger.Error("sn err:", logger.Field("err", err))
|
||
count++
|
||
continue
|
||
}
|
||
if err == nil && !exist {
|
||
return sn
|
||
}
|
||
return ""
|
||
}
|
||
}
|
||
|
||
func GetErpPurchaseOrderPurchaseCommodityMap(orderId uint32) (map[uint32]ErpPurchaseCommodity, error) {
|
||
commodityMap := make(map[uint32]ErpPurchaseCommodity, 0)
|
||
if orderId == 0 {
|
||
return commodityMap, nil
|
||
}
|
||
|
||
var commodities []ErpPurchaseCommodity
|
||
err := orm.Eloquent.Table("erp_purchase_commodity").Where("erp_purchase_order_id=?", orderId).Find(&commodities).Error
|
||
if err != nil {
|
||
logger.Error("commodities err:", logger.Field("err", err))
|
||
return commodityMap, err
|
||
}
|
||
|
||
for i, _ := range commodities {
|
||
commodityMap[commodities[i].ErpCommodityId] = commodities[i]
|
||
}
|
||
|
||
return commodityMap, nil
|
||
}
|
||
|
||
func ErpPurchaseInventoryListIdInit(inventories []ErpPurchaseInventory /*commodities []ErpInventoryCommodity,*/, orderId uint32, inventoryType string) error {
|
||
//inventorySn := GetPurchaseInventorySn()
|
||
ids := make([]uint32, 0, len(inventories))
|
||
for i, _ := range inventories {
|
||
ids = append(ids, inventories[i].ErpCommodityId)
|
||
}
|
||
commodityMap, err := GetErpCommodityMap(ids)
|
||
if err != nil {
|
||
logger.Error("commodity map err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
purchaseCommodityMap, err := GetErpPurchaseOrderPurchaseCommodityMap(orderId)
|
||
if err != nil {
|
||
logger.Error("purchase commodity map err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
commodityCountMap := make(map[uint32]uint32, 0)
|
||
//for i, _ := range commodities {
|
||
// purchaseCommodity, _ := purchaseCommodityMap[inventories[i].ErpCommodityId]
|
||
// v, ok := commodityMap[commodities[i].ErpCommodityId]
|
||
// if ok {
|
||
// commodities[i].SerialNumber = inventorySn
|
||
// commodities[i].InventoryType = inventoryType
|
||
// commodities[i].ErpPurchaseOrderId = orderId
|
||
// commodities[i].ErpCommodityName = v.Name
|
||
// commodities[i].CommoditySerialNumber = v.SerialNumber
|
||
// commodities[i].IMEIType = v.IMEIType
|
||
// commodities[i].Price = purchaseCommodity.Price
|
||
// commodities[i].Amount = commodities[i].Count * commodities[i].ImplementationPrice
|
||
// if v.IMEIType == 1 {
|
||
// commodityCountMap[v.ID] += commodities[i].Count
|
||
// } else {
|
||
// commodityCountMap[v.ID] += 1
|
||
// }
|
||
//
|
||
// //commodities[i].InventoryCount = int32(inventories[i].Count)
|
||
// }
|
||
//}
|
||
|
||
for i, _ := range inventories {
|
||
purchaseCommodity, _ := purchaseCommodityMap[inventories[i].ErpCommodityId]
|
||
commodityCount, _ := commodityCountMap[inventories[i].ErpCommodityId]
|
||
v, ok := commodityMap[inventories[i].ErpCommodityId]
|
||
if ok {
|
||
inventories[i].ErpPurchaseOrderId = orderId
|
||
inventories[i].InventoryType = inventoryType
|
||
inventories[i].ErpCommodityName = v.Name
|
||
inventories[i].CommoditySerialNumber = v.SerialNumber
|
||
inventories[i].IMEIType = v.IMEIType
|
||
inventories[i].Price = purchaseCommodity.Price
|
||
inventories[i].Count = commodityCount
|
||
inventories[i].Amount = inventories[i].Count * inventories[i].ImplementationPrice
|
||
inventories[i].InventoryCount = purchaseCommodity.InventoryCount + int32(inventories[i].Count)
|
||
if int32(purchaseCommodity.Count) < inventories[i].InventoryCount {
|
||
return errors.New(fmt.Sprintf("order id:%d purchase commodity id:%d inventory count err", orderId, purchaseCommodity.ID))
|
||
}
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// CreateErpPurchaseOrder 新增采购订单
|
||
func CreateErpPurchaseOrder(req *ErpPurchaseCreateReq, sysUser *SysUser) (*ErpPurchaseOrder, error) {
|
||
var err error
|
||
nowTime := time.Now()
|
||
|
||
purchaseOrder := &ErpPurchaseOrder{}
|
||
if req.PurchaseType == ErpProcureOrder { // 采购入库订单
|
||
purchaseOrder = &ErpPurchaseOrder{
|
||
SerialNumber: "cgr" + NewErpPurchaseSn(),
|
||
PurchaseType: req.PurchaseType,
|
||
StoreId: req.StoreId,
|
||
ErpSupplierId: req.ErpSupplierId,
|
||
MakerTime: nowTime,
|
||
MakerId: uint32(sysUser.UserId),
|
||
MakerName: sysUser.NickName,
|
||
State: ErpPurchaseOrderUnAudit, // 1-待审核
|
||
ErpCashierId: req.ErpCashierId,
|
||
AccountHolder: req.AccountHolder,
|
||
OpeningBank: req.OpeningBank,
|
||
BankAccount: req.BankAccount,
|
||
DeliveryTime: req.DeliveryTime,
|
||
}
|
||
err = purchaseOrder.IdInit()
|
||
} else if req.PurchaseType == ErpRejectOrder { // 采购退货订单
|
||
var erpPurchaseOrder ErpPurchaseOrder
|
||
err = orm.Eloquent.Table("erp_purchase_order").Where("serial_number=?", req.PurchaseOrderSn).Find(&erpPurchaseOrder).Error
|
||
if err != nil {
|
||
logger.Error("purchase order err:", logger.Field("err", err))
|
||
return nil, err
|
||
}
|
||
|
||
purchaseOrder = &ErpPurchaseOrder{
|
||
SerialNumber: "cgt" + NewErpPurchaseSn(),
|
||
PurchaseType: req.PurchaseType,
|
||
StoreId: erpPurchaseOrder.StoreId,
|
||
ErpSupplierId: erpPurchaseOrder.ErpSupplierId,
|
||
MakerTime: nowTime,
|
||
MakerId: uint32(req.MakerId),
|
||
//MakerName: sysUser.NickName,
|
||
State: ErpPurchaseOrderUnAudit, // 1-待审核
|
||
ErpCashierId: req.ErpCashierId,
|
||
}
|
||
err = purchaseOrder.IdInit()
|
||
} else {
|
||
logger.Errorf("purchase_type err:", req.PurchaseType)
|
||
return nil, errors.New("操作失败:采购类型有误")
|
||
}
|
||
|
||
if err != nil {
|
||
logger.Error("info err:", logger.Field("err", err))
|
||
return nil, err
|
||
}
|
||
err = ErpPurchaseCommodityListPerfectInfo(req.ErpPurchaseCommodities)
|
||
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.ErpPurchaseCommodities {
|
||
req.ErpPurchaseCommodities[i].ErpPurchaseOrderId = purchaseOrder.ID
|
||
req.ErpPurchaseCommodities[i].InventoryCount = 0 // todo 数量待核实
|
||
err = begin.Create(&req.ErpPurchaseCommodities[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
|
||
}
|
||
|
||
// EditErpPurchaseOrder 编辑采购订单
|
||
func EditErpPurchaseOrder(req *ErpPurchaseEditReq, sysUser *SysUser) (*ErpPurchaseOrder, error) {
|
||
// 查询订单信息
|
||
var purchaseOrder ErpPurchaseOrder
|
||
err := orm.Eloquent.Table("erp_purchase_order").Where("id=?", req.ErpPurchaseOrderId).Find(&purchaseOrder).Error
|
||
if err != nil {
|
||
logger.Error("purchase order err:", logger.Field("err", err))
|
||
return nil, err
|
||
}
|
||
|
||
if purchaseOrder.State != ErpPurchaseOrderUnAudit { // 只有待审核的订单才能编辑
|
||
return nil, errors.New("订单不是待审核状态")
|
||
}
|
||
begin := orm.Eloquent.Begin()
|
||
// 1-更新采购订单信息
|
||
purchaseOrder.StoreId = req.StoreId
|
||
purchaseOrder.ErpSupplierId = req.ErpSupplierId
|
||
purchaseOrder.MakerId = req.MakerId
|
||
purchaseOrder.ErpCashierId = req.ErpCashierId
|
||
purchaseOrder.AccountHolder = req.AccountHolder
|
||
purchaseOrder.OpeningBank = req.OpeningBank
|
||
purchaseOrder.BankAccount = req.BankAccount
|
||
purchaseOrder.DeliveryTime = req.DeliveryTime
|
||
err = purchaseOrder.IdInit()
|
||
if err != nil {
|
||
logger.Error("purchase IdInit err:", logger.Field("err", err))
|
||
return nil, err
|
||
}
|
||
|
||
err = begin.Model(&ErpPurchaseOrder{}).Where("id = ?", req.ErpPurchaseOrderId).Updates(purchaseOrder).Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("update erp_order err:", logger.Field("err", err))
|
||
return nil, err
|
||
}
|
||
|
||
// 2-更新采购订单商品表
|
||
err = updatePurchaseCommodityData(begin, req.ErpPurchaseOrderId, 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 &purchaseOrder, nil
|
||
}
|
||
|
||
// updatePurchaseCommodityData 更新采购订单商品信息
|
||
func updatePurchaseCommodityData(gdb *gorm.DB, orderId uint32, req *ErpPurchaseEditReq) error {
|
||
// 查询现有的零售订单信息
|
||
var commodities []ErpPurchaseCommodity
|
||
err := orm.Eloquent.Table("erp_purchase_commodity").Where("erp_purchase_order_id = ?", orderId).Find(&commodities).Error
|
||
if err != nil {
|
||
logger.Error("query erp_purchase_commodity err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
var newCommodities []ErpPurchaseCommodity
|
||
var deletedCommodities []ErpPurchaseCommodity
|
||
var matchingCommodities []ErpPurchaseCommodity
|
||
// 找到新增的商品
|
||
for i, reqCommodity := range req.ErpPurchaseCommodities {
|
||
// 订单商品表信息添加零售订单id
|
||
req.ErpPurchaseCommodities[i].ErpPurchaseOrderId = orderId
|
||
|
||
var found bool
|
||
for _, dbCommodity := range commodities {
|
||
if reqCommodity.ErpCommodityId == dbCommodity.ErpCommodityId {
|
||
found = true
|
||
break
|
||
}
|
||
}
|
||
if !found {
|
||
newCommodities = append(newCommodities, reqCommodity)
|
||
}
|
||
}
|
||
|
||
// 找到删除的商品
|
||
for _, dbCommodity := range commodities {
|
||
var found bool
|
||
for _, reqCommodity := range req.ErpPurchaseCommodities {
|
||
if 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(&ErpPurchaseCommodity{}).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
|
||
}
|
||
|
||
// InventoryErpPurchase 采购订单入库
|
||
func InventoryErpPurchase(req *ErpPurchaseInventoryReq) error {
|
||
err := checkPurchaseInventory(req)
|
||
if err != nil {
|
||
logger.Error("checkPurchaseInventoryReq err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
begin := orm.Eloquent.Begin()
|
||
for _, v := range req.Inventories {
|
||
// 更新采购商品表的执行数量
|
||
err = begin.Model(&ErpPurchaseCommodity{}).
|
||
Where("erp_purchase_order_id = ? AND erp_commodity_id = ?", v.ErpPurchaseOrderId, v.ErpCommodityId).
|
||
UpdateColumn("inventory_count", gorm.Expr("inventory_count + ?", v.InventoryCount)).Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("update inventory count err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
// 新建采购入库记录
|
||
err = begin.Create(&v).Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("create erp inventory commodity err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
// todo 更新库存信息表
|
||
}
|
||
|
||
err = begin.Commit().Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("commit err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// 校验入参数据,执行数量是否超过总数;串码商品的串码是否重复
|
||
func checkPurchaseInventory(req *ErpPurchaseInventoryReq) error {
|
||
// 查询现有的零售订单信息
|
||
var commodities []ErpPurchaseCommodity
|
||
err := orm.Eloquent.Table("erp_purchase_commodity").Where("erp_purchase_order_id = ?", req.ErpPurchaseOrderId).Find(&commodities).Error
|
||
if err != nil {
|
||
logger.Error("query erp_purchase_commodity err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
countMap := make(map[uint32]int32)
|
||
for _, inventory := range req.Inventories {
|
||
countMap[inventory.ErpCommodityId] += inventory.InventoryCount
|
||
|
||
// 如果该商品是串码商品,判断其串码是否会重复
|
||
if inventory.IMEI != "" {
|
||
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_stock_commodity WHERE FIND_IN_SET(%s, imei) > 0", inventory.IMEI))
|
||
if err != nil {
|
||
logger.Error("exist sn err")
|
||
}
|
||
if exist {
|
||
return fmt.Errorf("串码重复[%s]", inventory.IMEI)
|
||
}
|
||
}
|
||
}
|
||
|
||
// 入库的商品信息有误,不在之前的商品列表中
|
||
for commodityID := range countMap {
|
||
found := false
|
||
for _, commodity := range commodities {
|
||
if commodity.ErpCommodityId == commodityID {
|
||
found = true
|
||
break
|
||
}
|
||
}
|
||
if !found {
|
||
return fmt.Errorf("商品编号[%d]不属于该采购订单", commodityID)
|
||
}
|
||
}
|
||
|
||
// 本次入库的数量超出该商品未入库数量
|
||
for _, commodity := range commodities {
|
||
if inventoryCount, ok := countMap[commodity.ErpCommodityId]; ok {
|
||
if int32(commodity.Count)-commodity.InventoryCount < inventoryCount {
|
||
return fmt.Errorf("本次入库商品[%s]数量[%d]超出该商品未入库数量[%d]", commodity.ErpCommodityName,
|
||
inventoryCount, int32(commodity.Count)-commodity.InventoryCount)
|
||
}
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// ExecuteErpPurchase 执行(入库/退货)
|
||
func ExecuteErpPurchase(req *ErpPurchaseInventoryReq) (*ErpPurchaseExecuteResp, error) {
|
||
err := checkPurchaseInventory(req)
|
||
if err != nil {
|
||
logger.Error("checkPurchaseInventoryReq err:", logger.Field("err", err))
|
||
return nil, err
|
||
}
|
||
|
||
resp := &ErpPurchaseExecuteResp{
|
||
List: make([]ExecuteData, 0),
|
||
}
|
||
|
||
for _, inventory := range req.Inventories {
|
||
if inventory.IMEIType == 2 {
|
||
// 如果是串码商品,根据 InventoryCount 拆分成对应数量的数据
|
||
for i := 0; i < int(inventory.InventoryCount); i++ {
|
||
// 调用函数B生成商品串码
|
||
imei, err := generateIMEI(inventory.ErpCommodityId)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 将拆分后的商品信息添加到执行响应中
|
||
resp.List = append(resp.List, ExecuteData{
|
||
ErpPurchaseOrderId: inventory.ErpPurchaseOrderId,
|
||
ErpCommodityId: inventory.ErpCommodityId,
|
||
ErpCommodityName: inventory.ErpCommodityName,
|
||
CommoditySerialNumber: inventory.CommoditySerialNumber,
|
||
IMEIType: inventory.IMEIType,
|
||
IMEI: imei,
|
||
Count: 1,
|
||
ImplementationPrice: inventory.ImplementationPrice,
|
||
EmployeePrice: inventory.EmployeePrice,
|
||
})
|
||
}
|
||
} else if inventory.IMEIType == 1 {
|
||
// 如果是非串码商品,只需拆分为1条数据
|
||
resp.List = append(resp.List, ExecuteData{
|
||
ErpPurchaseOrderId: inventory.ErpPurchaseOrderId,
|
||
ErpCommodityId: inventory.ErpCommodityId,
|
||
ErpCommodityName: inventory.ErpCommodityName,
|
||
CommoditySerialNumber: inventory.CommoditySerialNumber,
|
||
IMEIType: inventory.IMEIType,
|
||
IMEI: "",
|
||
Count: inventory.Count,
|
||
ImplementationPrice: inventory.ImplementationPrice,
|
||
EmployeePrice: inventory.EmployeePrice,
|
||
})
|
||
}
|
||
}
|
||
|
||
return resp, nil
|
||
}
|
||
|
||
func generateIMEI(commodityId uint32) (string, error) {
|
||
commodity, err := GetCommodity(commodityId)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
return GenerateSerialCode(commodity.ErpCategoryId)
|
||
}
|