2376 lines
81 KiB
Go
2376 lines
81 KiB
Go
package models
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
"github.com/xuri/excelize/v2"
|
||
orm "go-admin/common/global"
|
||
"go-admin/logger"
|
||
"go-admin/tools/config"
|
||
"gorm.io/gorm"
|
||
"math/rand"
|
||
"strings"
|
||
"sync"
|
||
"time"
|
||
)
|
||
|
||
const (
|
||
ErpPurchaseOrderUnAudit = 1 // 待审核
|
||
ErpPurchaseOrderWaitInventory = 2 // 待入库
|
||
ErpPurchaseOrderWaitReject = 3 // 待退货
|
||
ErpPurchaseOrderFinished = 4 // 已完成
|
||
ErpPurchaseOrderEnd = 5 // 已终止
|
||
ErpPurchaseOrderInInventory = 6 // 入库中,部分入库
|
||
ErpPurchaseOrderInReject = 7 // 退货中,部分退货
|
||
|
||
ErpProcureOrder = "procure" // 采购入库订单
|
||
ErpRejectOrder = "reject" // 采购退货订单
|
||
|
||
ErpDemandStateWait = 1 // 待采购
|
||
ErpDemandStateFinish = 2 // 完成采购
|
||
)
|
||
|
||
// 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"` // 供应商名称
|
||
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"` // 审核人名称
|
||
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"` // 交货日期,如:2024-02-23
|
||
DeliveryAddress string `json:"delivery_address"` // 交货地址
|
||
Remark string `json:"remark"` // 备注
|
||
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"` // 商品串码
|
||
RetailPrice uint32 `json:"retail_price"` // 指导零售价
|
||
Count uint32 `json:"count"` // 计划采购数量
|
||
Price float64 `json:"price"` // 计划采购单价
|
||
Amount float64 `json:"amount"` // 计划采购金额
|
||
Remark string `json:"remark"` // 备注
|
||
RejectedPrice float64 `json:"rejected_price"` // 计划退货单价
|
||
RejectedCount uint32 `json:"rejected_count"` // 计划退货数量
|
||
RejectedAmount float64 `json:"rejected_amount"` // 计划退货金额
|
||
InventoryCount int32 `json:"inventory_count"` // 入库数量(=执行数量)
|
||
ExecutionCount uint32 `json:"execute_count" gorm:"-"` // 执行数量
|
||
ExecutionPrice float64 `json:"execute_price" gorm:"-"` // 平均采购单价
|
||
ExecutionEmployeePrice float64 `json:"execute_employee_price" gorm:"-"` // 平均员工成本价
|
||
ExecutionAmount float64 `json:"execute_amount" gorm:"-"` // 执行金额
|
||
}
|
||
|
||
// ErpPurchaseInventory 采购入库执行信息
|
||
type ErpPurchaseInventory struct {
|
||
Model
|
||
ErpPurchaseOrderId uint32 `json:"erp_purchase_order_id" gorm:"index"` // 商品采购订单id
|
||
ErpPurchaseCommodityId uint32 `json:"erp_purchase_commodity_id" gorm:"index"` // 采购订单商品表id
|
||
PurchaseType string `json:"purchase_type" binding:"required"` // 采购类型:procure-采购 reject-退货
|
||
SerialNumber string `json:"serial_number" gorm:"index"` // 入库编号
|
||
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 float64 `json:"implementation_price"` // 执行单价
|
||
Amount float64 `json:"amount"` // 执行金额
|
||
EmployeePrice float64 `json:"employee_price"` // 员工成本价
|
||
}
|
||
|
||
type ErpPurchaseCreateReq struct {
|
||
PurchaseType string `json:"purchase_type" binding:"required"` // 采购类型:procure-采购 reject-退货
|
||
PurchaseOrderSn string `json:"purchase_order_sn"` // 采购退货订单号
|
||
StoreId uint32 `json:"store_id"` // 门店id
|
||
DeliveryAddress string `json:"delivery_address"` // 交货地址
|
||
HandlerId uint32 `json:"handler_id" gorm:"index"` // 经手人id
|
||
HandlerName string `json:"handler_name"` // 经手人名称
|
||
ErpSupplierId uint32 `json:"erp_supplier_id"` // 供应商id
|
||
ErpCashierId uint32 `json:"erp_cashier_id"` // 付款方式
|
||
AccountHolder string `json:"account_holder"` // 收款人
|
||
OpeningBank string `json:"opening_bank" ` // 开户行
|
||
BankAccount string `json:"bank_account" ` // 银行卡号
|
||
DeliveryTime string `json:"delivery_time" ` // 交货日期
|
||
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"` // 交货地址
|
||
HandlerId uint32 `json:"handler_id" gorm:"index"` // 经手人id
|
||
HandlerName string `json:"handler_name"` // 经手人名称
|
||
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
|
||
PurchaseType string `json:"purchase_type" binding:"required"` // 采购类型:procure-采购 reject-退货
|
||
Inventories []ErpPurchaseInventory `json:"inventories" 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"` // 单据编号
|
||
Remark string `json:"remark" binding:"required"` // 备注
|
||
}
|
||
|
||
// ErpPurchaseExecuteResp 执行(入库/退货)出参
|
||
type ErpPurchaseExecuteResp struct {
|
||
List []ExecuteData `json:"list"`
|
||
Total int `json:"total"` // 总条数
|
||
}
|
||
|
||
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 float64 `json:"implementation_price"` // 执行单价
|
||
EmployeePrice float64 `json:"employee_price"` // 员工成本价
|
||
}
|
||
|
||
type ErpPurchaseDemand struct {
|
||
Model
|
||
ErpCommodityId uint32 `json:"erp_commodity_id" gorm:"index"` // 商品id
|
||
ErpCommoditySerialNumber string `json:"erp_commodity_serial_number"` // 商品编号
|
||
ErpCommodityName string `json:"erp_commodity_name" gorm:"index"` // 商品名称
|
||
StoreId uint32 `json:"store_id"` // 门店id
|
||
StoreName string `json:"store_name"` // 门店名称
|
||
Count uint32 `json:"count"` // 需采购数量
|
||
State uint32 `json:"state"` // 1-待采购 2-已采购
|
||
MakerId uint32 `json:"maker_id"` // 制单人id
|
||
PurchaserId uint32 `json:"purchaser_id"` // 采购人id
|
||
FinishTime *time.Time `json:"finish_time"` // 完成采购时间
|
||
Remark string `json:"remark"` // 备注
|
||
}
|
||
|
||
type ErpPurchaseDemandRecord struct {
|
||
Model
|
||
ErpCommodityId uint32 `json:"erp_commodity_id" gorm:"index"` // 商品id
|
||
StoreId uint32 `json:"store_id" binding:"required"` // 门店id
|
||
StoreName string `json:"store_name" binding:"required"` // 门店名称
|
||
Count uint32 `json:"count"` // 数量
|
||
MakerId uint32 `json:"maker_id" gorm:"index"` // 制单人id
|
||
State uint32 `json:"state"` // 1-待采购 2-已采购
|
||
}
|
||
|
||
type GetErpPurchaseDemandReq struct {
|
||
ErpCategoryId uint32 `json:"erp_category_id"` // 商品分类id
|
||
ErpCommoditySerialNumber string `json:"erp_commodity_serial_number"` // 商品编号
|
||
ErpCommodityName string `json:"erp_commodity_name"` // 商品名称
|
||
HideFlag string `json:"hide_flag"` // 隐藏标记(默认关闭):ON-开启,隐藏无采购需求的商品,OFF-关闭,展示所有
|
||
PageIndex int `json:"pageIndex"` // 页码
|
||
PageSize int `json:"pageSize"` // 每页展示数据条数
|
||
IsExport uint32 `json:"is_export"` // 1-导出
|
||
}
|
||
|
||
type DemandData struct {
|
||
ErpCommodityID uint32 `json:"erp_commodity_id"` // 商品id
|
||
ErpCommoditySerialNumber string `json:"erp_commodity_serial_number"` // 商品编号
|
||
ErpCommodityName string `json:"erp_commodity_name"` // 商品名称
|
||
ErpCategoryID uint32 `json:"erp_category_id"` // 商品分类id
|
||
ErpCategoryName string `json:"erp_category_name"` // 商品分类名称
|
||
RetailPrice uint32 `json:"retail_price"` // 指导零售价
|
||
LastWholesalePrice float64 `json:"last_wholesale_price"` // 最近采购价
|
||
TotalCount uint32 `json:"total_count"` // 需采购总数量
|
||
TotalAmount float64 `json:"total_amount"` // 需采购总金额
|
||
Remark string `json:"remark"` // 备注
|
||
StoreList []struct {
|
||
StoreID uint32 `json:"store_id"` // 门店id
|
||
StoreName string `json:"store_name"` // 门店名称
|
||
LastMonthSales uint32 `json:"last_month_sales"` // 上月销售数
|
||
StockCount uint32 `json:"stock_count"` // 库存数量
|
||
NeedCount uint32 `json:"need_count"` // 需采购数
|
||
} `json:"store_list"`
|
||
}
|
||
|
||
type GetErpPurchaseDemandResp struct {
|
||
List []DemandData `json:"list"`
|
||
Total int64 `json:"total"` // 数据总条数
|
||
PageIndex int `json:"pageIndex"` // 页码
|
||
PageSize int `json:"pageSize"` // 每页展示条数
|
||
ExportUrl string `json:"export_url"` // 文件路径
|
||
}
|
||
|
||
type CreateErpPurchaseDemandReq struct {
|
||
ErpCommodityID uint32 `json:"erp_commodity_id"` // 商品id
|
||
ErpCommoditySerialNumber string `json:"erp_commodity_serial_number"` // 商品编号
|
||
ErpCommodityName string `json:"erp_commodity_name"` // 商品名称
|
||
Remark string `json:"remark"` // 备注
|
||
List []struct {
|
||
StoreID uint32 `json:"store_id"` // 门店id
|
||
StoreName string `json:"store_name"` // 门店名称
|
||
NeedCount uint32 `json:"need_count"` // 需采购数
|
||
} `json:"list"`
|
||
}
|
||
|
||
type FinishErpPurchaseDemandReq struct {
|
||
ErpCommodityID uint32 `json:"erp_commodity_id" binding:"required"` // 商品id
|
||
}
|
||
|
||
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 = float64(purchaseCommodities[i].Count) * purchaseCommodities[i].Price
|
||
}
|
||
if purchaseCommodities[i].RejectedCount != 0 {
|
||
purchaseCommodities[i].RejectedAmount = float64(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 ""
|
||
}
|
||
}
|
||
|
||
// 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,
|
||
HandlerId: req.HandlerId,
|
||
HandlerName: req.HandlerName,
|
||
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,
|
||
DeliveryAddress: req.DeliveryAddress,
|
||
Remark: req.Remark,
|
||
}
|
||
err = purchaseOrder.IdInit()
|
||
} else if req.PurchaseType == ErpRejectOrder { // 采购退货订单
|
||
if req.PurchaseOrderSn == "" {
|
||
return nil, errors.New("新建失败:采购退货订单号为空")
|
||
}
|
||
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,
|
||
HandlerId: req.HandlerId,
|
||
HandlerName: req.HandlerName,
|
||
MakerId: uint32(sysUser.UserId),
|
||
MakerName: sysUser.NickName,
|
||
State: ErpPurchaseOrderUnAudit, // 1-待审核
|
||
ErpCashierId: req.ErpCashierId,
|
||
Remark: req.Remark,
|
||
}
|
||
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.HandlerId = req.HandlerId
|
||
purchaseOrder.HandlerName = req.HandlerName
|
||
purchaseOrder.MakerId = uint32(sysUser.UserId)
|
||
purchaseOrder.MakerName = sysUser.NickName
|
||
purchaseOrder.ErpCashierId = req.ErpCashierId
|
||
purchaseOrder.AccountHolder = req.AccountHolder
|
||
purchaseOrder.OpeningBank = req.OpeningBank
|
||
purchaseOrder.BankAccount = req.BankAccount
|
||
purchaseOrder.DeliveryTime = req.DeliveryTime
|
||
purchaseOrder.DeliveryAddress = req.DeliveryAddress
|
||
purchaseOrder.Remark = req.Remark
|
||
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 {
|
||
v.SerialNumber = GetPurchaseInventorySn()
|
||
// 更新采购商品表的执行数量
|
||
// todo 如果用户在同一个采购单中新建了同一个商品的2条采购信息,可能采购价不同,需要区分入库的是哪一条(已修改)
|
||
err = begin.Model(&ErpPurchaseCommodity{}).
|
||
Where("id = ?", v.ErpPurchaseCommodityId).
|
||
UpdateColumn("inventory_count", gorm.Expr("inventory_count + ?", v.Count)).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
|
||
}
|
||
}
|
||
|
||
// 查询采购订单信息
|
||
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 err
|
||
}
|
||
|
||
// 更新库存信息表
|
||
if purchaseOrder.PurchaseType == ErpProcureOrder { //采购入库订单
|
||
err = InventoryErpPurchaseUpdateStock(begin, req, purchaseOrder)
|
||
} else if purchaseOrder.PurchaseType == ErpRejectOrder { // 采购退货订单
|
||
err = InventoryErpPurchaseUpdateRejectStock(begin, req, purchaseOrder)
|
||
} else {
|
||
return errors.New("订单类型有误")
|
||
}
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("update stock err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
err = begin.Commit().Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("commit err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// InventoryErpPurchaseUpdateStock 采购订单入库更新库存信息
|
||
func InventoryErpPurchaseUpdateStock(gdb *gorm.DB, req *ErpPurchaseInventoryReq, purchaseOrder ErpPurchaseOrder) error {
|
||
// 遍历采购入库商品信息
|
||
var stockList []ErpStockCommodity
|
||
for _, v := range req.Inventories {
|
||
commodityInfo, err := GetCommodity(v.ErpCommodityId)
|
||
if err != nil {
|
||
logger.Errorf("GetCommodity err:", err)
|
||
return err
|
||
}
|
||
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_stock WHERE store_id=%d AND erp_commodity_id=%d",
|
||
purchaseOrder.StoreId, v.ErpCommodityId))
|
||
if err != nil {
|
||
logger.Errorf("exist err:", err)
|
||
return err
|
||
}
|
||
if exist {
|
||
err = gdb.Exec(fmt.Sprintf(
|
||
"UPDATE erp_stock SET count=count+%d WHERE store_id=%d AND erp_commodity_id=%d;",
|
||
v.Count, purchaseOrder.StoreId, v.ErpCommodityId)).Error
|
||
if err != nil {
|
||
logger.Errorf("update stock err:", err)
|
||
return err
|
||
}
|
||
} else {
|
||
stock := &ErpStock{
|
||
StoreId: purchaseOrder.StoreId,
|
||
StoreName: purchaseOrder.StoreName,
|
||
ErpCommodityId: v.ErpCommodityId,
|
||
ErpCommodityName: v.ErpCommodityName,
|
||
ErpCategoryId: commodityInfo.ErpCategoryId,
|
||
ErpCategoryName: commodityInfo.ErpCategoryName,
|
||
CommoditySerialNumber: v.CommoditySerialNumber,
|
||
IMEIType: v.IMEIType,
|
||
RetailPrice: commodityInfo.RetailPrice,
|
||
MinRetailPrice: commodityInfo.MinRetailPrice,
|
||
Count: v.Count,
|
||
DispatchCount: 0,
|
||
}
|
||
err = gdb.Create(stock).Error
|
||
if err != nil {
|
||
logger.Errorf("create stock err:", err)
|
||
return err
|
||
}
|
||
}
|
||
|
||
nowTime := time.Now()
|
||
stockCommodity := ErpStockCommodity{
|
||
StoreId: purchaseOrder.StoreId,
|
||
StoreName: purchaseOrder.StoreName,
|
||
ErpCommodityId: v.ErpCommodityId,
|
||
ErpCommodityName: v.ErpCommodityName,
|
||
CommoditySerialNumber: v.CommoditySerialNumber,
|
||
ErpCategoryId: commodityInfo.ErpCategoryId,
|
||
ErpCategoryName: commodityInfo.ErpCategoryName,
|
||
ErpSupplierId: purchaseOrder.ErpSupplierId,
|
||
ErpSupplierName: purchaseOrder.ErpSupplierName,
|
||
StaffCostPrice: uint32(v.EmployeePrice - v.ImplementationPrice),
|
||
WholesalePrice: uint32(v.ImplementationPrice),
|
||
State: 1,
|
||
StorageType: 1,
|
||
FirstStockTime: nowTime,
|
||
StockTime: nowTime,
|
||
Count: v.Count,
|
||
ErpBarcode: commodityInfo.ErpBarcode, // 240106新增商品条码
|
||
IMEIType: v.IMEIType,
|
||
IMEI: v.IMEI,
|
||
Remark: "",
|
||
MemberDiscount: commodityInfo.MemberDiscount,
|
||
MinRetailPrice: commodityInfo.MinRetailPrice,
|
||
RetailPrice: commodityInfo.RetailPrice,
|
||
}
|
||
stockList = append(stockList, stockCommodity)
|
||
}
|
||
|
||
err := gdb.Debug().Create(&stockList).Error
|
||
if err != nil {
|
||
logger.Errorf("create stock commodity err:", err)
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// InventoryErpPurchaseUpdateRejectStock 采购退货更新库存信息
|
||
func InventoryErpPurchaseUpdateRejectStock(gdb *gorm.DB, req *ErpPurchaseInventoryReq, purchaseOrder ErpPurchaseOrder) error {
|
||
for i, _ := range req.Inventories {
|
||
if req.Inventories[i].IMEIType == 2 { // 串码商品
|
||
if req.Inventories[i].IMEI == "" {
|
||
return errors.New("串码为空")
|
||
}
|
||
|
||
// 判断该串码商品是否已经销售
|
||
var stockCommodityInfo ErpStockCommodity
|
||
err := orm.Eloquent.Table("erp_stock_commodity").Where("imei = ?", req.Inventories[i].IMEI).
|
||
Find(&stockCommodityInfo).Error
|
||
if err != nil {
|
||
logger.Error("Inventory RejectStock query commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
if stockCommodityInfo.State == SoldOut {
|
||
return fmt.Errorf("商品[%s]已经消息,不能退货", stockCommodityInfo.ErpCommodityName)
|
||
} else if stockCommodityInfo.State == OnSale {
|
||
return fmt.Errorf("商品[%s]在销售锁定中,不能退货", stockCommodityInfo.ErpCommodityName)
|
||
}
|
||
|
||
err = gdb.Table("erp_stock_commodity").Where("imei = ?", req.Inventories[i].IMEI).
|
||
Update("state", PurchaseReturn).Error // 状态更新为采购退货
|
||
if err != nil {
|
||
logger.Error("RetailTypeRejected commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
err = gdb.Table("erp_stock").Where("store_id = ? and erp_commodity_id = ?",
|
||
purchaseOrder.StoreId, req.Inventories[i].ErpCommodityId).
|
||
Updates(map[string]interface{}{"count": gorm.Expr("count - ?", 1)}).Error // 库存数量-1
|
||
if err != nil {
|
||
logger.Error("RetailTypeRejected commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
} else { // 非串码商品
|
||
var stockCommodity []ErpStockCommodity
|
||
// 通过门店id,商品id,查找状态为1-在库的非串码商品
|
||
err := orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? and store_id = ? "+
|
||
"and state = ? and imei_type = ?", req.Inventories[i].ErpCommodityId, purchaseOrder.StoreId, InStock, 1).
|
||
Order("id DESC").Find(&stockCommodity).Error
|
||
if err != nil {
|
||
logger.Error("RetailTypeRejected commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
if stockCommodity == nil {
|
||
return errors.New("RetailTypeRejected find no stock commodity")
|
||
}
|
||
|
||
err = gdb.Table("erp_stock_commodity").Where("id = ?", stockCommodity[0].ID).
|
||
Update("state", PurchaseReturn).Error // 状态更新为采购退货
|
||
if err != nil {
|
||
logger.Error("RetailTypeRejected commodities err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
err = gdb.Table("erp_stock").Where("store_id = ? and erp_commodity_id = ?",
|
||
purchaseOrder.StoreId, req.Inventories[i].ErpCommodityId).
|
||
Updates(map[string]interface{}{"count": gorm.Expr("count - ?", 1)}).Error // 库存数量-1
|
||
if err != nil {
|
||
logger.Error("RetailTypeRejected commodities 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]uint32)
|
||
for _, inventory := range req.Inventories {
|
||
countMap[inventory.ErpCommodityId] += inventory.Count
|
||
|
||
// 如果该商品是串码商品,判断其串码是否会重复
|
||
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 req.PurchaseType == ErpProcureOrder {
|
||
if commodity.Count-uint32(commodity.InventoryCount) < inventoryCount {
|
||
return fmt.Errorf("本次入库商品[%s]数量[%d]超出该商品未入库数量[%d]", commodity.ErpCommodityName,
|
||
inventoryCount, int32(commodity.Count)-commodity.InventoryCount)
|
||
}
|
||
} else if req.PurchaseType == ErpRejectOrder {
|
||
if commodity.RejectedCount-uint32(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 {
|
||
// 如果是串码商品,根据 Count 拆分成对应数量的数据
|
||
for i := 0; i < int(inventory.Count); i++ {
|
||
imei := "" // 默认退货单执行时不需要串码
|
||
if inventory.PurchaseType == ErpProcureOrder { // 采购单
|
||
// 调用函数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,
|
||
})
|
||
}
|
||
}
|
||
|
||
resp.Total = len(resp.List)
|
||
|
||
return resp, nil
|
||
}
|
||
|
||
// 生成串码
|
||
func generateIMEI(commodityId uint32) (string, error) {
|
||
commodity, err := GetCommodity(commodityId)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
return GenerateSerialCode(commodity.ErpCategoryId)
|
||
}
|
||
|
||
// CreateErpPurchaseDemand 创建采购需求单
|
||
func CreateErpPurchaseDemand(req *CreateErpPurchaseDemandReq, sysUser *SysUser) error {
|
||
var demandInfo ErpPurchaseDemand
|
||
var demandList []ErpPurchaseDemand
|
||
|
||
demandInfo.ErpCommodityId = req.ErpCommodityID
|
||
demandInfo.ErpCommoditySerialNumber = req.ErpCommoditySerialNumber
|
||
demandInfo.ErpCommodityName = req.ErpCommodityName
|
||
demandInfo.Remark = req.Remark
|
||
demandInfo.State = ErpDemandStateWait // 待采购
|
||
for _, v := range req.List {
|
||
demandInfo.StoreId = v.StoreID
|
||
demandInfo.StoreName = v.StoreName
|
||
demandInfo.Count = v.NeedCount
|
||
demandInfo.MakerId = uint32(sysUser.UserId)
|
||
demandList = append(demandList, demandInfo)
|
||
}
|
||
|
||
begin := orm.Eloquent.Begin()
|
||
// 查询当前表格,有记录则更新,没有则插入新记录
|
||
for _, v := range demandList {
|
||
var demand ErpPurchaseDemand
|
||
err := orm.Eloquent.Table("erp_purchase_demand").Where("erp_commodity_id = ? and store_id = ? and state = 1",
|
||
v.ErpCommodityId, v.StoreId).Find(&demand).Error
|
||
if err != nil {
|
||
logger.Error("query erp_purchase_demand err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
if demand.StoreId != 0 { // 有记录
|
||
if demand.Count == v.Count { // 值没变则不更新
|
||
continue
|
||
} else {
|
||
err = begin.Model(&ErpPurchaseDemand{}).Where("erp_commodity_id = ? and store_id = ? and state = 1",
|
||
v.ErpCommodityId, v.StoreId).Updates(v).Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("update erp_order err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
}
|
||
} else { // 无记录,新建
|
||
err = begin.Create(&v).Error
|
||
if err != nil {
|
||
logger.Error("query erp_purchase_demand err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
}
|
||
}
|
||
|
||
err := begin.Commit().Error
|
||
if err != nil {
|
||
begin.Rollback()
|
||
logger.Error("commit err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// FinishErpPurchaseDemand 完成采购需求
|
||
func FinishErpPurchaseDemand(req *FinishErpPurchaseDemandReq, sysUser *SysUser) error {
|
||
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_purchase_demand WHERE erp_commodity_id='%d'",
|
||
req.ErpCommodityID))
|
||
if err != nil {
|
||
logger.Error("exist sn err")
|
||
}
|
||
if !exist {
|
||
return fmt.Errorf("商品编号[%d]的商品不在采购需求单中", req.ErpCommodityID)
|
||
}
|
||
|
||
// 批量更新状态
|
||
err = orm.Eloquent.Table("erp_purchase_demand").Where("erp_commodity_id=?", req.ErpCommodityID).
|
||
Updates(map[string]interface{}{
|
||
"state": ErpDemandStateFinish,
|
||
"finish_time": time.Now(),
|
||
"purchaser_id": sysUser.UserId,
|
||
}).Error
|
||
if err != nil {
|
||
logger.Error("update err:", logger.Field("err", err))
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
//// GetErpPurchaseDemand 获取采购需求
|
||
//func GetErpPurchaseDemand(req *GetErpPurchaseDemandReq) (*GetErpPurchaseDemandResp, error) {
|
||
// resp := &GetErpPurchaseDemandResp{
|
||
// PageIndex: req.PageIndex,
|
||
// PageSize: req.PageSize,
|
||
// }
|
||
// page := req.PageIndex - 1
|
||
// if page < 0 {
|
||
// page = 0
|
||
// }
|
||
// if req.PageSize == 0 {
|
||
// req.PageSize = 10
|
||
// }
|
||
//
|
||
// qs := orm.Eloquent.Debug().Table("erp_commodity")
|
||
// if req.ErpCategoryId != 0 {
|
||
// qs = qs.Where("erp_category_id=?", req.ErpCategoryId)
|
||
// }
|
||
//
|
||
// var commodities []ErpCommodity
|
||
// err := qs.Order("id DESC").Offset(page * req.PageSize).Limit(req.PageSize).Find(&commodities).Error
|
||
// if err != nil && err != RecordNotFound {
|
||
// //logger.Error("erp commodity list err:", err)
|
||
// return resp, err
|
||
// }
|
||
//
|
||
// // 组合数据
|
||
// resp, err = convertToDemandResp(commodities)
|
||
//
|
||
// return resp, nil
|
||
//}
|
||
//
|
||
//func convertToDemandResp(commodities []ErpCommodity) (*GetErpPurchaseDemandResp, error) {
|
||
// resp := new(GetErpPurchaseDemandResp)
|
||
// var demandData DemandData
|
||
// var demandList []DemandData
|
||
//
|
||
// // 查询所有在线门店信息
|
||
// var stores []Store
|
||
// err := orm.Eloquent.Table("store").Where("is_online = ?", 1).Find(&stores).Error
|
||
// if err != nil {
|
||
// logger.Error("stores err:", logger.Field("err", err))
|
||
// return nil, err
|
||
// }
|
||
//
|
||
// demandData.List = make([]struct {
|
||
// StoreID uint32 `json:"store_id"`
|
||
// StoreName string `json:"store_name"`
|
||
// LastMonthSales uint32 `json:"last_month_sales"`
|
||
// StockCount uint32 `json:"stock_count"`
|
||
// NeedCount uint32 `json:"need_count"`
|
||
// }, len(stores))
|
||
//
|
||
// var totalCount uint32 // 总需采购数量
|
||
//
|
||
// // 遍历所有商品
|
||
// for _, v := range commodities {
|
||
// // 初始化 NeedCount 为 0
|
||
// var totalNeedCount uint32
|
||
//
|
||
// for i, store := range stores {
|
||
// demandData.List[i].StoreID = store.ID
|
||
// demandData.List[i].StoreName = store.Name
|
||
//
|
||
// // 初始化 NeedCount 为 0
|
||
// demandData.List[i].NeedCount = 0
|
||
//
|
||
// // 设置商品相关信息
|
||
// demandData.ErpCommodityID = v.ID
|
||
// demandData.ErpCommoditySerialNumber = v.SerialNumber
|
||
// demandData.ErpCommodityName = v.Name
|
||
// demandData.ErpCategoryID = v.ErpCategoryId
|
||
// demandData.ErpCategoryName = v.ErpCategoryName
|
||
// demandData.RetailPrice = v.RetailPrice
|
||
// // 最近采购价
|
||
// demandData.LastWholesalePrice, _ = GetCommodityLastWholesalePrice(v.ID)
|
||
//
|
||
// // 查询采购需求单
|
||
// var demand []ErpPurchaseDemand
|
||
// err = orm.Eloquent.Table("erp_purchase_demand").Where("erp_commodity_id = ? AND state = 1 AND store_id = ?",
|
||
// v.ID, store.ID).Find(&demand).Error
|
||
// if err != nil {
|
||
// logger.Error("query erp_purchase_demand err:", logger.Field("err", err))
|
||
// return nil, err
|
||
// }
|
||
//
|
||
// if len(demand) > 0 {
|
||
// totalNeedCount += demand[0].Count
|
||
// demandData.List[i].NeedCount = demand[0].Count
|
||
// }
|
||
//
|
||
// // 查询某个门店某个商品的库存情况
|
||
// demandData.List[i].StockCount, _ = GetCommodityStockByStoreId(v.ID, store.ID)
|
||
// // 查询某个门店某件商品的上月销售数量
|
||
// demandData.List[i].LastMonthSales, _ = GetCommodityLastMonthSalesByStoreId(v.ID, store.ID)
|
||
// }
|
||
// totalCount += totalNeedCount
|
||
// demandData.TotalCount = totalCount
|
||
// demandData.TotalAmount = float64(totalCount) * demandData.LastWholesalePrice
|
||
// demandList = append(demandList, demandData)
|
||
// }
|
||
// resp.List = demandList
|
||
//
|
||
// return resp, nil
|
||
//}
|
||
//
|
||
//// GetCommodityStockByStoreId 查询某个门店某个商品的库存情况
|
||
//func GetCommodityStockByStoreId(commodityId, storeId uint32) (uint32, error) {
|
||
// var count int64
|
||
// err := orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? and store_id = ? and state = 1",
|
||
// commodityId, storeId).Count(&count).Error
|
||
// if err != nil {
|
||
// logger.Error("GetCommodityStockByStoreId count err:", logger.Field("err", err))
|
||
// return 0, err
|
||
// }
|
||
//
|
||
// return uint32(count), nil
|
||
//}
|
||
//
|
||
//// GetCommodityLastMonthSalesByStoreId 查询某个门店某件商品的上月销售数量
|
||
//func GetCommodityLastMonthSalesByStoreId(commodityId, storeId uint32) (uint32, error) {
|
||
// var lastMonthSales uint32
|
||
//
|
||
// // 获取当前时间
|
||
// now := time.Now()
|
||
// year, month, _ := now.Date()
|
||
// firstDay := time.Date(year, month-1, 1, 0, 0, 0, 0, now.Location())
|
||
// lastDay := firstDay.AddDate(0, 1, -1)
|
||
//
|
||
// // 执行查询
|
||
// err := orm.Eloquent.Model(&ErpOrderCommodity{}).
|
||
// Joins("JOIN erp_order ON erp_order_commodity.erp_order_id = erp_order.id").
|
||
// Select("SUM(erp_order_commodity.count) AS last_month_sales").
|
||
// Where("erp_order.pay_status = ? AND erp_order_commodity.erp_commodity_id = ? AND erp_order.store_id = ? "+
|
||
// "AND erp_order_commodity.created_at BETWEEN ? AND ?",
|
||
// HavePaid, commodityId, storeId, firstDay, lastDay).
|
||
// Scan(&lastMonthSales).Error
|
||
// if err != nil {
|
||
// logger.Error("GetCommodityLastMonthSalesByStoreId err:", logger.Field("err", err))
|
||
// return 0, err
|
||
// }
|
||
//
|
||
// return lastMonthSales, nil
|
||
//}
|
||
//
|
||
//// GetCommodityLastWholesalePrice 查询某个商品的最近采购价
|
||
//func GetCommodityLastWholesalePrice(commodityId uint32) (float64, error) {
|
||
// var implementationPrice float64
|
||
//
|
||
// // 执行查询
|
||
// err := orm.Eloquent.Table("erp_purchase_inventory").
|
||
// Select("implementation_price").
|
||
// Where("erp_commodity_id = ? AND purchase_type = ?", 167, "procure").
|
||
// Order("created_at DESC").
|
||
// Limit(1).
|
||
// Scan(&implementationPrice).Error
|
||
// if err != nil {
|
||
// logger.Error("GetCommodityLastMonthSalesByStoreId err:", logger.Field("err", err))
|
||
// return 0, err
|
||
// }
|
||
//
|
||
// return implementationPrice, nil
|
||
//}
|
||
|
||
// 222222222
|
||
//// GetErpPurchaseDemand 获取采购需求
|
||
//func GetErpPurchaseDemand(req *GetErpPurchaseDemandReq) (*GetErpPurchaseDemandResp, error) {
|
||
// resp := &GetErpPurchaseDemandResp{
|
||
// PageIndex: req.PageIndex,
|
||
// PageSize: req.PageSize,
|
||
// }
|
||
// page := req.PageIndex - 1
|
||
// if page < 0 {
|
||
// page = 0
|
||
// }
|
||
// if req.PageSize == 0 {
|
||
// req.PageSize = 10
|
||
// }
|
||
//
|
||
// qs := orm.Eloquent.Debug().Table("erp_commodity")
|
||
// if req.ErpCategoryId != 0 {
|
||
// qs = qs.Where("erp_category_id=?", req.ErpCategoryId)
|
||
// }
|
||
//
|
||
// var commodities []ErpCommodity
|
||
// err := qs.Order("id DESC").Offset(page * req.PageSize).Limit(req.PageSize).Find(&commodities).Error
|
||
// if err != nil && err != RecordNotFound {
|
||
// return resp, err
|
||
// }
|
||
//
|
||
// // 批量查询门店信息
|
||
// stores, err := GetOnlineStores()
|
||
// if err != nil {
|
||
// return nil, err
|
||
// }
|
||
//
|
||
// // 批量查询商品信息
|
||
// demandDataList := make([]DemandData, 0, len(commodities))
|
||
// for _, v := range commodities {
|
||
// demandData, err := convertToDemandData(v, stores)
|
||
// if err != nil {
|
||
// return nil, err
|
||
// }
|
||
// demandDataList = append(demandDataList, demandData)
|
||
// }
|
||
//
|
||
// resp.List = demandDataList
|
||
//
|
||
// return resp, nil
|
||
//}
|
||
//
|
||
//// convertToDemandData 将商品转换为采购需求数据
|
||
//func convertToDemandData(commodity ErpCommodity, stores []Store) (DemandData, error) {
|
||
// demandData := DemandData{
|
||
// ErpCommodityID: commodity.ID,
|
||
// ErpCommoditySerialNumber: commodity.SerialNumber,
|
||
// ErpCommodityName: commodity.Name,
|
||
// ErpCategoryID: commodity.ErpCategoryId,
|
||
// ErpCategoryName: commodity.ErpCategoryName,
|
||
// RetailPrice: commodity.RetailPrice,
|
||
// }
|
||
//
|
||
// // 批量查询最近采购价
|
||
// lastWholesalePrices, err := GetCommodityLastWholesalePrices(commodity.ID)
|
||
// if err != nil {
|
||
// return DemandData{}, err
|
||
// }
|
||
//
|
||
// for i, store := range stores {
|
||
// demandData.List = append(demandData.List, struct {
|
||
// StoreID uint32 `json:"store_id"`
|
||
// StoreName string `json:"store_name"`
|
||
// LastMonthSales uint32 `json:"last_month_sales"`
|
||
// StockCount uint32 `json:"stock_count"`
|
||
// NeedCount uint32 `json:"need_count"`
|
||
// }{
|
||
// StoreID: store.ID,
|
||
// StoreName: store.Name,
|
||
// })
|
||
//
|
||
// // 批量查询库存情况
|
||
// stockCounts, err := GetCommodityStocksByStoreID(commodity.ID, store.ID)
|
||
// if err != nil {
|
||
// return DemandData{}, err
|
||
// }
|
||
// demandData.List[i].StockCount = stockCounts[store.ID]
|
||
//
|
||
// // 批量查询上月销售数量
|
||
// lastMonthSales, err := GetCommodityLastMonthSales(commodity.ID, store.ID)
|
||
// if err != nil {
|
||
// return DemandData{}, err
|
||
// }
|
||
// demandData.List[i].LastMonthSales = lastMonthSales
|
||
//
|
||
// // 设置最近采购价
|
||
// demandData.LastWholesalePrice = lastWholesalePrices[commodity.ID]
|
||
// }
|
||
//
|
||
// return demandData, nil
|
||
//}
|
||
//
|
||
//// GetCommodityLastWholesalePrices 批量查询商品的最近采购价
|
||
//func GetCommodityLastWholesalePrices(commodityID uint32) (map[uint32]float64, error) {
|
||
// // 查询最近采购价
|
||
// var prices []struct {
|
||
// CommodityID uint32
|
||
// Price float64
|
||
// }
|
||
// err := orm.Eloquent.Table("erp_purchase_inventory").
|
||
// Select("erp_commodity_id, implementation_price AS price").
|
||
// Where("erp_commodity_id IN (?) AND purchase_type = ?", commodityID, "procure").
|
||
// Group("erp_commodity_id").
|
||
// Order("created_at DESC").
|
||
// Find(&prices).Error
|
||
// if err != nil {
|
||
// return nil, err
|
||
// }
|
||
//
|
||
// // 构建结果
|
||
// result := make(map[uint32]float64)
|
||
// for _, p := range prices {
|
||
// result[p.CommodityID] = p.Price
|
||
// }
|
||
// return result, nil
|
||
//}
|
||
//
|
||
//// GetCommodityStocksByStoreID 批量查询商品的库存情况
|
||
//func GetCommodityStocksByStoreID(commodityID, storeID uint32) (map[uint32]uint32, error) {
|
||
// // 查询库存情况
|
||
// var stocks []struct {
|
||
// StoreID uint32
|
||
// CommodityID uint32
|
||
// StockCount uint32
|
||
// }
|
||
// err := orm.Eloquent.Table("erp_stock_commodity").
|
||
// Select("store_id, erp_commodity_id, COUNT(*) AS stock_count").
|
||
// Where("erp_commodity_id IN (?) AND store_id = ? AND state = 1", commodityID, storeID).
|
||
// Group("store_id, erp_commodity_id").
|
||
// Find(&stocks).Error
|
||
// if err != nil {
|
||
// return nil, err
|
||
// }
|
||
//
|
||
// // 构建结果
|
||
// result := make(map[uint32]uint32)
|
||
// for _, s := range stocks {
|
||
// result[s.StoreID] = s.StockCount
|
||
// }
|
||
// return result, nil
|
||
//}
|
||
//
|
||
//// GetCommodityLastMonthSales 批量查询商品的上月销售数量
|
||
//func GetCommodityLastMonthSales(commodityID, storeID uint32) (uint32, error) {
|
||
// // 获取上个月的时间范围
|
||
// firstDay, lastDay := GetLastMonthRange()
|
||
//
|
||
// // 查询上月销售数量
|
||
// var lastMonthSales struct {
|
||
// Sales uint32
|
||
// }
|
||
// err := orm.Eloquent.Table("erp_order_commodity").
|
||
// Joins("JOIN erp_order ON erp_order_commodity.erp_order_id = erp_order.id").
|
||
// Where("erp_order.pay_status = ? AND erp_order_commodity.erp_commodity_id = ? AND erp_order.store_id = ? "+
|
||
// "AND erp_order_commodity.created_at BETWEEN ? AND ?",
|
||
// HavePaid, commodityID, storeID, firstDay, lastDay).
|
||
// Select("SUM(erp_order_commodity.count) AS sales").
|
||
// Scan(&lastMonthSales).Error
|
||
// if err != nil {
|
||
// return 0, err
|
||
// }
|
||
//
|
||
// return lastMonthSales.Sales, nil
|
||
//}
|
||
//
|
||
//// GetLastMonthRange 获取上个月的时间范围
|
||
//func GetLastMonthRange() (time.Time, time.Time) {
|
||
// now := time.Now()
|
||
// year, month, _ := now.Date()
|
||
// firstDay := time.Date(year, month-1, 1, 0, 0, 0, 0, now.Location())
|
||
// lastDay := firstDay.AddDate(0, 1, -1)
|
||
// return firstDay, lastDay
|
||
//}
|
||
//
|
||
//// GetOnlineStores 查询所有在线门店信息
|
||
//func GetOnlineStores() ([]Store, error) {
|
||
// var stores []Store
|
||
// err := orm.Eloquent.Table("store").Where("is_online = ?", 1).Find(&stores).Error
|
||
// if err != nil {
|
||
// return nil, err
|
||
// }
|
||
// return stores, nil
|
||
//}
|
||
|
||
// 3333
|
||
//// GetErpPurchaseDemand 获取采购需求
|
||
//func GetErpPurchaseDemand(req *GetErpPurchaseDemandReq) (*GetErpPurchaseDemandResp, error) {
|
||
// resp := &GetErpPurchaseDemandResp{
|
||
// PageIndex: req.PageIndex,
|
||
// PageSize: req.PageSize,
|
||
// }
|
||
// page := req.PageIndex - 1
|
||
// if page < 0 {
|
||
// page = 0
|
||
// }
|
||
// if req.PageSize == 0 {
|
||
// req.PageSize = 10
|
||
// }
|
||
//
|
||
// qs := orm.Eloquent.Debug().Table("erp_commodity")
|
||
// if req.ErpCategoryId != 0 {
|
||
// qs = qs.Where("erp_category_id=?", req.ErpCategoryId)
|
||
// }
|
||
//
|
||
// var commodities []ErpCommodity
|
||
// err := qs.Order("id DESC").Offset(page * req.PageSize).Limit(req.PageSize).Find(&commodities).Error
|
||
// if err != nil && err != RecordNotFound {
|
||
// return resp, err
|
||
// }
|
||
//
|
||
// // 批量查询门店信息
|
||
// stores, err := GetOnlineStores()
|
||
// if err != nil {
|
||
// return nil, err
|
||
// }
|
||
//
|
||
// // 并行查询需求数据
|
||
// var wg sync.WaitGroup
|
||
// demandDataList := make([]DemandData, len(commodities))
|
||
//
|
||
// for i, v := range commodities {
|
||
// wg.Add(1)
|
||
// go func(index int, commodity ErpCommodity) {
|
||
// defer wg.Done()
|
||
// demandData, err := convertToDemandData(commodity, stores)
|
||
// if err != nil {
|
||
// // Handle error
|
||
// return
|
||
// }
|
||
// demandDataList[index] = demandData
|
||
// }(i, v)
|
||
// }
|
||
//
|
||
// wg.Wait()
|
||
//
|
||
// resp.List = demandDataList
|
||
//
|
||
// return resp, nil
|
||
//}
|
||
//
|
||
//// convertToDemandData 将商品转换为采购需求数据
|
||
//func convertToDemandData(commodity ErpCommodity, stores []Store) (DemandData, error) {
|
||
// demandData := DemandData{
|
||
// ErpCommodityID: commodity.ID,
|
||
// ErpCommoditySerialNumber: commodity.SerialNumber,
|
||
// ErpCommodityName: commodity.Name,
|
||
// ErpCategoryID: commodity.ErpCategoryId,
|
||
// ErpCategoryName: commodity.ErpCategoryName,
|
||
// RetailPrice: commodity.RetailPrice,
|
||
// }
|
||
//
|
||
// // 并行查询最近采购价、库存情况、上月销售数量
|
||
// var wg sync.WaitGroup
|
||
// wg.Add(3)
|
||
//
|
||
// var lastWholesalePrices map[uint32]float64
|
||
// var stockCounts map[uint32]uint32
|
||
// var lastMonthSales uint32
|
||
// var err1, err2, err3 error
|
||
//
|
||
// go func() {
|
||
// defer wg.Done()
|
||
// lastWholesalePrices, err1 = GetCommodityLastWholesalePrices(commodity.ID)
|
||
// }()
|
||
//
|
||
// go func() {
|
||
// defer wg.Done()
|
||
// stockCounts, err2 = GetCommodityStocksByStoreID(commodity.ID, stores)
|
||
// }()
|
||
//
|
||
// go func() {
|
||
// defer wg.Done()
|
||
// lastMonthSales, err3 = GetCommodityLastMonthSales(commodity.ID, stores)
|
||
// }()
|
||
//
|
||
// wg.Wait()
|
||
//
|
||
// if err1 != nil || err2 != nil || err3 != nil {
|
||
// // Handle error
|
||
// return DemandData{}, err1
|
||
// }
|
||
//
|
||
// // 构建需求数据
|
||
// demandData.List = make([]struct {
|
||
// StoreID uint32 `json:"store_id"`
|
||
// StoreName string `json:"store_name"`
|
||
// LastMonthSales uint32 `json:"last_month_sales"`
|
||
// StockCount uint32 `json:"stock_count"`
|
||
// NeedCount uint32 `json:"need_count"`
|
||
// }, len(stores))
|
||
//
|
||
// for i, store := range stores {
|
||
// demandData.List[i].StoreID = store.ID
|
||
// demandData.List[i].StoreName = store.Name
|
||
//
|
||
// demandData.List[i].StockCount = stockCounts[store.ID]
|
||
// demandData.List[i].LastMonthSales = lastMonthSales
|
||
//
|
||
// // 设置最近采购价
|
||
// demandData.LastWholesalePrice = lastWholesalePrices[commodity.ID]
|
||
// }
|
||
//
|
||
// return demandData, nil
|
||
//}
|
||
//
|
||
//// GetCommodityLastWholesalePrices 批量查询商品的最近采购价
|
||
//func GetCommodityLastWholesalePrices(commodityID uint32) (map[uint32]float64, error) {
|
||
// // 查询最近采购价
|
||
// var prices []struct {
|
||
// CommodityID uint32
|
||
// Price float64
|
||
// }
|
||
// err := orm.Eloquent.Table("erp_purchase_inventory").
|
||
// Select("erp_commodity_id, implementation_price AS price").
|
||
// Where("erp_commodity_id IN (?) AND purchase_type = ?", commodityID, "procure").
|
||
// Group("erp_commodity_id").
|
||
// Order("created_at DESC").
|
||
// Find(&prices).Error
|
||
// if err != nil {
|
||
// return nil, err
|
||
// }
|
||
//
|
||
// // 构建结果
|
||
// result := make(map[uint32]float64)
|
||
// for _, p := range prices {
|
||
// result[p.CommodityID] = p.Price
|
||
// }
|
||
// return result, nil
|
||
//}
|
||
//
|
||
//// GetCommodityStocksByStoreID 批量查询商品的库存情况
|
||
//func GetCommodityStocksByStoreID(commodityID uint32, stores []Store) (map[uint32]uint32, error) {
|
||
// // 并行查询库存情况
|
||
// var wg sync.WaitGroup
|
||
// wg.Add(len(stores))
|
||
//
|
||
// result := make(map[uint32]uint32)
|
||
//
|
||
// for _, store := range stores {
|
||
// go func(storeID uint32) {
|
||
// defer wg.Done()
|
||
// // 查询库存情况
|
||
// var stockCount int64
|
||
// err := orm.Eloquent.Table("erp_stock_commodity").
|
||
// Where("erp_commodity_id = ? AND store_id = ? AND state = 1", commodityID, storeID).
|
||
// Count(&stockCount).Error
|
||
// if err != nil {
|
||
// // Handle error
|
||
// return
|
||
// }
|
||
// result[storeID] = uint32(stockCount)
|
||
// }(store.ID)
|
||
// }
|
||
//
|
||
// wg.Wait()
|
||
//
|
||
// return result, nil
|
||
//}
|
||
//
|
||
//// GetCommodityLastMonthSales 批量查询商品的上月销售数量
|
||
//func GetCommodityLastMonthSales(commodityID uint32, stores []Store) (uint32, error) {
|
||
// // 获取上个月的时间范围
|
||
// firstDay, lastDay := GetLastMonthRange()
|
||
//
|
||
// // 并行查询上月销售数量
|
||
// var wg sync.WaitGroup
|
||
// wg.Add(len(stores))
|
||
//
|
||
// var totalSales uint32
|
||
// var mu sync.Mutex // 用于保护 totalSales 的并发访问
|
||
//
|
||
// for _, store := range stores {
|
||
// go func(storeID uint32) {
|
||
// defer wg.Done()
|
||
// // 查询上月销售数量
|
||
// var sales uint32
|
||
// err := orm.Eloquent.Table("erp_order_commodity").
|
||
// Joins("JOIN erp_order ON erp_order_commodity.erp_order_id = erp_order.id").
|
||
// Where("erp_order.pay_status = ? AND erp_order_commodity.erp_commodity_id = ? AND erp_order.store_id = ? "+
|
||
// "AND erp_order_commodity.created_at BETWEEN ? AND ?",
|
||
// HavePaid, commodityID, storeID, firstDay, lastDay).
|
||
// Select("SUM(erp_order_commodity.count) AS sales").
|
||
// Scan(&sales).Error
|
||
// if err != nil {
|
||
// // Handle error
|
||
// return
|
||
// }
|
||
//
|
||
// // 累加销售数量
|
||
// mu.Lock()
|
||
// totalSales += sales
|
||
// mu.Unlock()
|
||
// }(store.ID)
|
||
// }
|
||
//
|
||
// wg.Wait()
|
||
//
|
||
// return totalSales, nil
|
||
//}
|
||
//
|
||
//// GetLastMonthRange 获取上个月的时间范围
|
||
//func GetLastMonthRange() (time.Time, time.Time) {
|
||
// now := time.Now()
|
||
// year, month, _ := now.Date()
|
||
// firstDay := time.Date(year, month-1, 1, 0, 0, 0, 0, now.Location())
|
||
// lastDay := firstDay.AddDate(0, 1, -1)
|
||
// return firstDay, lastDay
|
||
//}
|
||
//
|
||
//// GetOnlineStores 查询所有在线门店信息
|
||
//func GetOnlineStores() ([]Store, error) {
|
||
// var stores []Store
|
||
// err := orm.Eloquent.Table("store").Where("is_online = ?", 1).Find(&stores).Error
|
||
// if err != nil {
|
||
// return nil, err
|
||
// }
|
||
// return stores, nil
|
||
//}
|
||
|
||
// GetErpPurchaseDemand 获取采购需求
|
||
func GetErpPurchaseDemand(req *GetErpPurchaseDemandReq) (*GetErpPurchaseDemandResp, error) {
|
||
var err error
|
||
resp := new(GetErpPurchaseDemandResp)
|
||
if req.HideFlag == "ON" { // 隐藏无采购需求的商品
|
||
resp, err = getErpPurchaseDemandHide(req)
|
||
} else { // 展示所有
|
||
resp, err = getErpPurchaseDemandAll(req)
|
||
}
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
return resp, nil
|
||
}
|
||
|
||
// 展示所有采购需求
|
||
func getErpPurchaseDemandAll(req *GetErpPurchaseDemandReq) (*GetErpPurchaseDemandResp, error) {
|
||
page := req.PageIndex - 1
|
||
if page < 0 {
|
||
page = 0
|
||
}
|
||
if req.PageSize == 0 {
|
||
req.PageSize = 10
|
||
}
|
||
|
||
resp := &GetErpPurchaseDemandResp{
|
||
PageIndex: page + 1,
|
||
PageSize: req.PageSize,
|
||
}
|
||
|
||
qs := orm.Eloquent.Debug().Table("erp_commodity")
|
||
if req.ErpCategoryId != 0 {
|
||
qs = qs.Where("erp_category_id=?", req.ErpCategoryId)
|
||
}
|
||
if req.ErpCommoditySerialNumber != "" {
|
||
qs = qs.Where("serial_number=?", req.ErpCommoditySerialNumber)
|
||
}
|
||
if req.ErpCommodityName != "" {
|
||
qs = qs.Where("name=?", req.ErpCommodityName)
|
||
}
|
||
|
||
var count int64
|
||
if err := qs.Count(&count).Error; err != nil {
|
||
logger.Error("count err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
|
||
var commodities []ErpCommodity
|
||
if req.IsExport == 1 { // 导出excel
|
||
err := qs.Order("id DESC").Find(&commodities).Error
|
||
if err != nil && err != RecordNotFound {
|
||
return resp, err
|
||
}
|
||
} else {
|
||
err := qs.Order("id DESC").Offset(page * req.PageSize).Limit(req.PageSize).Find(&commodities).Error
|
||
if err != nil && err != RecordNotFound {
|
||
return resp, err
|
||
}
|
||
}
|
||
|
||
// 批量查询门店信息
|
||
stores, err := GetOnlineStores()
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 并行查询需求数据
|
||
var wg sync.WaitGroup
|
||
demandDataList := make([]DemandData, len(commodities))
|
||
|
||
for i, v := range commodities {
|
||
wg.Add(1)
|
||
go func(index int, commodity ErpCommodity) {
|
||
defer wg.Done()
|
||
demandData, err := convertToDemandData(commodity, stores)
|
||
if err != nil {
|
||
// Handle error
|
||
return
|
||
}
|
||
demandDataList[index] = demandData
|
||
}(i, v)
|
||
}
|
||
|
||
wg.Wait()
|
||
|
||
if req.IsExport == 1 { // 导出excel
|
||
if len(demandDataList) == 0 {
|
||
return nil, errors.New("未查询到数据")
|
||
}
|
||
resp.ExportUrl, err = demandDataExport(demandDataList)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
} else {
|
||
resp.List = demandDataList
|
||
resp.Total = count
|
||
}
|
||
|
||
return resp, nil
|
||
}
|
||
|
||
// 隐藏无采购需求的商品
|
||
func getErpPurchaseDemandHide(req *GetErpPurchaseDemandReq) (*GetErpPurchaseDemandResp, error) {
|
||
page := req.PageIndex - 1
|
||
if page < 0 {
|
||
page = 0
|
||
}
|
||
if req.PageSize == 0 {
|
||
req.PageSize = 10
|
||
}
|
||
|
||
resp := &GetErpPurchaseDemandResp{
|
||
PageIndex: page + 1,
|
||
PageSize: req.PageSize,
|
||
}
|
||
|
||
// 查询采购需求单信息,筛选出有采购需求的商品id
|
||
var demand []ErpPurchaseDemand
|
||
err := orm.Eloquent.Table("erp_purchase_demand").
|
||
Where("state = 1").Find(&demand).Error
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
// 用 map 存储已经出现过的 ErpCommodityId
|
||
commodityIds := make(map[uint32]bool)
|
||
var uniqueCommodityIds []uint32
|
||
|
||
for _, d := range demand {
|
||
if _, ok := commodityIds[d.ErpCommodityId]; !ok {
|
||
commodityIds[d.ErpCommodityId] = true
|
||
uniqueCommodityIds = append(uniqueCommodityIds, d.ErpCommodityId)
|
||
}
|
||
}
|
||
|
||
// 查询商品信息
|
||
qs := orm.Eloquent.Debug().Table("erp_commodity")
|
||
if req.ErpCategoryId != 0 {
|
||
qs = qs.Where("erp_category_id=?", req.ErpCategoryId)
|
||
}
|
||
if req.ErpCommoditySerialNumber != "" {
|
||
qs = qs.Where("serial_number=?", req.ErpCommoditySerialNumber)
|
||
}
|
||
if req.ErpCommodityName != "" {
|
||
qs = qs.Where("name=?", req.ErpCommodityName)
|
||
}
|
||
|
||
var count int64
|
||
if err := qs.Count(&count).Error; err != nil {
|
||
logger.Error("count err:", logger.Field("err", err))
|
||
return resp, err
|
||
}
|
||
|
||
var commodities []ErpCommodity
|
||
if req.IsExport == 1 { // 导出excel
|
||
err := qs.Order("id DESC").Find(&commodities).Error
|
||
if err != nil && err != RecordNotFound {
|
||
return resp, err
|
||
}
|
||
} else {
|
||
err := qs.Order("id DESC").Offset(page * req.PageSize).Limit(req.PageSize).Find(&commodities).Error
|
||
if err != nil && err != RecordNotFound {
|
||
return resp, err
|
||
}
|
||
}
|
||
|
||
// 匹配商品id,有则继续查询返回数据,没有则不返回
|
||
var matchedCommodities []ErpCommodity
|
||
for _, c := range commodities {
|
||
for _, uniqueID := range uniqueCommodityIds {
|
||
if c.ID == uniqueID {
|
||
matchedCommodities = append(matchedCommodities, c)
|
||
break // 找到匹配的商品后跳出内层循环,继续下一个商品
|
||
}
|
||
}
|
||
}
|
||
|
||
if len(matchedCommodities) == 0 {
|
||
resp.List = nil
|
||
} else {
|
||
// 批量查询门店信息
|
||
stores, err := GetOnlineStores()
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 并行查询需求数据
|
||
var wg sync.WaitGroup
|
||
demandDataList := make([]DemandData, len(matchedCommodities))
|
||
|
||
for i, v := range matchedCommodities {
|
||
wg.Add(1)
|
||
go func(index int, commodity ErpCommodity) {
|
||
defer wg.Done()
|
||
demandData, err := convertToDemandData(commodity, stores)
|
||
if err != nil {
|
||
// Handle error
|
||
return
|
||
}
|
||
demandDataList[index] = demandData
|
||
}(i, v)
|
||
}
|
||
|
||
wg.Wait()
|
||
|
||
if req.IsExport == 1 { // 导出excel
|
||
if len(demandDataList) == 0 {
|
||
return nil, errors.New("未查询到数据")
|
||
}
|
||
resp.ExportUrl, err = demandDataExport(demandDataList)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
} else {
|
||
resp.List = demandDataList
|
||
resp.Total = int64(len(matchedCommodities))
|
||
}
|
||
}
|
||
|
||
return resp, nil
|
||
}
|
||
|
||
// convertToDemandData 将商品转换为采购需求数据
|
||
func convertToDemandData(commodity ErpCommodity, stores []Store) (DemandData, error) {
|
||
demandData := DemandData{
|
||
ErpCommodityID: commodity.ID,
|
||
ErpCommoditySerialNumber: commodity.SerialNumber,
|
||
ErpCommodityName: commodity.Name,
|
||
ErpCategoryID: commodity.ErpCategoryId,
|
||
ErpCategoryName: commodity.ErpCategoryName,
|
||
RetailPrice: commodity.RetailPrice,
|
||
}
|
||
|
||
// 查询采购需求单
|
||
demands, err := GetCommodityPurchaseDemands(commodity.ID, stores)
|
||
if err != nil {
|
||
// Handle error
|
||
return DemandData{}, err
|
||
}
|
||
if len(demands) != 0 {
|
||
demandData.Remark = demands[0].Remark
|
||
}
|
||
|
||
// 使用 WaitGroup 进行并行查询
|
||
var wg sync.WaitGroup
|
||
wg.Add(3)
|
||
|
||
var lastWholesalePrices map[uint32]float64
|
||
var stockCounts map[uint32]uint32
|
||
var lastMonthSales uint32
|
||
|
||
go func() {
|
||
defer wg.Done()
|
||
lastWholesalePrices, err = GetCommodityLastWholesalePrices(commodity.ID)
|
||
}()
|
||
|
||
go func() {
|
||
defer wg.Done()
|
||
stockCounts, err = GetCommodityStocksByStoreID(commodity.ID, stores)
|
||
}()
|
||
|
||
go func() {
|
||
defer wg.Done()
|
||
lastMonthSales, err = GetCommodityLastMonthSales(commodity.ID, stores)
|
||
}()
|
||
|
||
wg.Wait()
|
||
if err != nil {
|
||
// Handle error
|
||
return DemandData{}, err
|
||
}
|
||
|
||
var totalCount uint32 // 总需采购数量
|
||
// 构建需求数据
|
||
demandData.StoreList = make([]struct {
|
||
StoreID uint32 `json:"store_id"`
|
||
StoreName string `json:"store_name"`
|
||
LastMonthSales uint32 `json:"last_month_sales"`
|
||
StockCount uint32 `json:"stock_count"`
|
||
NeedCount uint32 `json:"need_count"`
|
||
}, len(stores))
|
||
|
||
for i, store := range stores {
|
||
demandData.StoreList[i].StoreID = store.ID
|
||
demandData.StoreList[i].StoreName = store.Name
|
||
|
||
demandData.StoreList[i].StockCount = stockCounts[store.ID]
|
||
demandData.StoreList[i].LastMonthSales = lastMonthSales
|
||
|
||
// 设置最近采购价
|
||
demandData.LastWholesalePrice = lastWholesalePrices[commodity.ID]
|
||
|
||
// 设置采购需求量
|
||
for _, demand := range demands {
|
||
if demand.StoreId == store.ID {
|
||
demandData.StoreList[i].NeedCount = demand.Count
|
||
totalCount += demand.Count
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
demandData.TotalCount = totalCount
|
||
demandData.TotalAmount = float64(totalCount) * demandData.LastWholesalePrice
|
||
|
||
return demandData, nil
|
||
}
|
||
|
||
// GetCommodityPurchaseDemands 查询商品的采购需求单
|
||
func GetCommodityPurchaseDemands(commodityID uint32, stores []Store) ([]ErpPurchaseDemand, error) {
|
||
var wg sync.WaitGroup
|
||
var mu sync.Mutex
|
||
var demands []ErpPurchaseDemand
|
||
wg.Add(len(stores))
|
||
|
||
for _, store := range stores {
|
||
go func(storeID uint32) {
|
||
defer wg.Done()
|
||
var demand ErpPurchaseDemand
|
||
err := orm.Eloquent.Table("erp_purchase_demand").
|
||
Where("erp_commodity_id = ? AND state = 1 AND store_id = ?", commodityID, storeID).
|
||
First(&demand).Error
|
||
if err != nil {
|
||
// Handle error
|
||
return
|
||
}
|
||
|
||
mu.Lock()
|
||
defer mu.Unlock()
|
||
demands = append(demands, demand)
|
||
}(store.ID)
|
||
}
|
||
|
||
wg.Wait()
|
||
|
||
return demands, nil
|
||
}
|
||
|
||
// GetCommodityLastWholesalePrices 批量查询商品的最近采购价
|
||
func GetCommodityLastWholesalePrices(commodityID uint32) (map[uint32]float64, error) {
|
||
// 查询最近采购价
|
||
var prices []struct {
|
||
CommodityID uint32
|
||
Price float64
|
||
}
|
||
err := orm.Eloquent.Table("erp_purchase_inventory").
|
||
Select("erp_commodity_id, implementation_price AS price").
|
||
Where("erp_commodity_id IN (?) AND purchase_type = ?", commodityID, "procure").
|
||
Group("erp_commodity_id").
|
||
Order("created_at DESC").
|
||
Find(&prices).Error
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 构建结果
|
||
result := make(map[uint32]float64)
|
||
for _, p := range prices {
|
||
result[p.CommodityID] = p.Price
|
||
}
|
||
return result, nil
|
||
}
|
||
|
||
// GetCommodityStocksByStoreID 批量查询商品的库存情况
|
||
func GetCommodityStocksByStoreID(commodityID uint32, stores []Store) (map[uint32]uint32, error) {
|
||
// 并行查询库存情况
|
||
var wg sync.WaitGroup
|
||
wg.Add(len(stores))
|
||
|
||
result := make(map[uint32]uint32)
|
||
|
||
for _, store := range stores {
|
||
go func(storeID uint32) {
|
||
defer wg.Done()
|
||
// 查询库存情况
|
||
var stockCount int64
|
||
err := orm.Eloquent.Table("erp_stock_commodity").
|
||
Where("erp_commodity_id = ? AND store_id = ? AND state = 1", commodityID, storeID).
|
||
Count(&stockCount).Error
|
||
if err != nil {
|
||
// Handle error
|
||
return
|
||
}
|
||
result[storeID] = uint32(stockCount)
|
||
}(store.ID)
|
||
}
|
||
|
||
wg.Wait()
|
||
|
||
return result, nil
|
||
}
|
||
|
||
// GetCommodityLastMonthSales 批量查询商品的上月销售数量
|
||
func GetCommodityLastMonthSales(commodityID uint32, stores []Store) (uint32, error) {
|
||
// 获取上个月的时间范围
|
||
firstDay, lastDay := GetLastMonthRange()
|
||
|
||
// 并行查询上月销售数量
|
||
var wg sync.WaitGroup
|
||
wg.Add(len(stores))
|
||
|
||
var totalSales uint32
|
||
var mu sync.Mutex // 用于保护 totalSales 的并发访问
|
||
|
||
for _, store := range stores {
|
||
go func(storeID uint32) {
|
||
defer wg.Done()
|
||
// 查询上月销售数量
|
||
var sales uint32
|
||
err := orm.Eloquent.Table("erp_order_commodity").
|
||
Joins("JOIN erp_order ON erp_order_commodity.erp_order_id = erp_order.id").
|
||
Where("erp_order.pay_status = ? AND erp_order_commodity.erp_commodity_id = ? AND erp_order.store_id = ? "+
|
||
"AND erp_order_commodity.created_at BETWEEN ? AND ?",
|
||
HavePaid, commodityID, storeID, firstDay, lastDay).
|
||
Select("SUM(erp_order_commodity.count) AS sales").
|
||
Scan(&sales).Error
|
||
if err != nil {
|
||
// Handle error
|
||
return
|
||
}
|
||
|
||
// 保护 totalSales 的并发访问
|
||
mu.Lock()
|
||
defer mu.Unlock()
|
||
totalSales += sales
|
||
}(store.ID)
|
||
}
|
||
|
||
wg.Wait()
|
||
|
||
return totalSales, nil
|
||
}
|
||
|
||
// GetLastMonthRange 获取上个月的时间范围
|
||
func GetLastMonthRange() (time.Time, time.Time) {
|
||
now := time.Now()
|
||
year, month, _ := now.Date()
|
||
firstDay := time.Date(year, month-1, 1, 0, 0, 0, 0, now.Location())
|
||
lastDay := firstDay.AddDate(0, 1, -1)
|
||
return firstDay, lastDay
|
||
}
|
||
|
||
// GetOnlineStores 查询所有在线门店信息
|
||
func GetOnlineStores() ([]Store, error) {
|
||
var stores []Store
|
||
err := orm.Eloquent.Table("store").Where("is_online = ?", 1).Find(&stores).Error
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return stores, nil
|
||
}
|
||
|
||
type Result struct {
|
||
TotalCount uint32 `gorm:"column:total_count"`
|
||
AvgImplementationPrice float64 `gorm:"column:avg_implementation_price"`
|
||
TotalAmount float64 `gorm:"column:total_amount"`
|
||
AvgEmployeePrice float64 `gorm:"column:avg_employee_price"`
|
||
}
|
||
|
||
// GetTotalsAndAveragesByCommodityID 查询执行数量之和、平均执行单价、执行金额之和和平均员工成本价
|
||
func GetTotalsAndAveragesByCommodityID(commodityID uint32) (Result, error) {
|
||
var result Result
|
||
err := orm.Eloquent.Table("erp_purchase_inventory").
|
||
Select("SUM(`count`) AS total_count, AVG(`implementation_price`) AS avg_implementation_price, "+
|
||
"SUM(`amount`) AS total_amount, AVG(`employee_price`) AS avg_employee_price").
|
||
Where("erp_commodity_id = ?", commodityID).
|
||
Scan(&result).Error
|
||
if err != nil {
|
||
return Result{}, err
|
||
}
|
||
|
||
return result, nil
|
||
}
|
||
|
||
// UpdateRetailPrice 更新指导零售价
|
||
func UpdateRetailPrice(begin *gorm.DB, commodityId, retailPrice uint32) error {
|
||
// 更新商品信息表
|
||
err := begin.Table("erp_commodity").Where("id=?", commodityId).
|
||
Updates(map[string]interface{}{
|
||
"retail_price": retailPrice,
|
||
}).Error
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 更新库存表
|
||
err = begin.Table("erp_stock").Where("erp_commodity_id=?", commodityId).
|
||
Updates(map[string]interface{}{
|
||
"retail_price": retailPrice,
|
||
}).Error
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// 更新库存商品表
|
||
err = begin.Table("erp_stock_commodity").Where("erp_commodity_id=? and state not in (2,5)", commodityId).
|
||
Updates(map[string]interface{}{
|
||
"retail_price": retailPrice,
|
||
}).Error
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// 导出采购需求excel
|
||
func demandDataExport(list []DemandData) (string, error) {
|
||
file := excelize.NewFile()
|
||
fSheet := "Sheet1"
|
||
|
||
url := ExportUrl
|
||
fileName := time.Now().Format(TimeFormat) + "采购需求" + ".xlsx"
|
||
fmt.Println("url fileName:", url+fileName)
|
||
|
||
// 组合标题栏第一行数据
|
||
title1 := []interface{}{"商品编号", "商品名称", "商品分类", "指导零售价", "最近采购价"}
|
||
storeCount := len(list[0].StoreList)
|
||
var mergeCells []string // 存储需要合并的单元格范围
|
||
|
||
for _, v := range list[0].StoreList {
|
||
for i := 0; i < 3; i++ {
|
||
title1 = append(title1, v.StoreName)
|
||
}
|
||
}
|
||
|
||
for i := 0; i < storeCount; i++ {
|
||
// 计算每个商户名称的起始和结束单元格
|
||
startCol, _ := excelize.ColumnNumberToName(6 + i*3) // 从第6列开始,每个商户占3列
|
||
endCol, _ := excelize.ColumnNumberToName(8 + i*3)
|
||
mergeCell := startCol + "1:" + endCol + "1"
|
||
mergeCells = append(mergeCells, mergeCell)
|
||
}
|
||
|
||
title1 = append(title1, "需采购总数量")
|
||
title1 = append(title1, "需采购总金额")
|
||
title1 = append(title1, "备注")
|
||
|
||
// 合并单元格
|
||
for _, mergeCell := range mergeCells {
|
||
startCell, endCell := splitMergeCellCoordinates(mergeCell)
|
||
_ = file.MergeCell(fSheet, startCell, endCell)
|
||
}
|
||
|
||
// 组合标题栏第二行数据
|
||
title2 := []interface{}{"商品编号", "商品名称", "商品分类", "指导零售价", "最近采购价"}
|
||
for _, _ = range list[0].StoreList {
|
||
title2 = append(title2, "上月销售数")
|
||
title2 = append(title2, "库存数量")
|
||
title2 = append(title2, "需采购数")
|
||
}
|
||
title2 = append(title2, "需采购总数量")
|
||
title2 = append(title2, "需采购总金额")
|
||
title2 = append(title2, "备注")
|
||
|
||
for i, _ := range title1 {
|
||
cell, _ := excelize.CoordinatesToCellName(1+i, 1)
|
||
err := file.SetCellValue(fSheet, cell, title1[i])
|
||
if err != nil {
|
||
logger.Error("file set value err:", logger.Field("err", err))
|
||
}
|
||
}
|
||
|
||
for i, _ := range title2 {
|
||
cell, _ := excelize.CoordinatesToCellName(1+i, 2)
|
||
err := file.SetCellValue(fSheet, cell, title2[i])
|
||
if err != nil {
|
||
logger.Error("file set value err:", logger.Field("err", err))
|
||
}
|
||
}
|
||
|
||
var row []interface{}
|
||
nExcelStartRow := 0
|
||
for i := 0; i < len(list); i++ {
|
||
row = []interface{}{
|
||
list[i].ErpCommoditySerialNumber, // 商品编号
|
||
list[i].ErpCommodityName, // 商品名称
|
||
list[i].ErpCategoryName, // 商品分类名称
|
||
list[i].RetailPrice, // 指导零售价
|
||
list[i].LastWholesalePrice, // 最近采购价
|
||
}
|
||
|
||
for _, v := range list[i].StoreList {
|
||
row = append(row, v.LastMonthSales) // 上月销售数
|
||
row = append(row, v.StockCount) // 库存数量
|
||
row = append(row, v.NeedCount) // 需采购数
|
||
}
|
||
|
||
row = append(row, list[i].TotalCount) // 需采购总数量
|
||
row = append(row, list[i].TotalAmount) // 需采购总金额
|
||
row = append(row, list[i].Remark) // 备注
|
||
|
||
for j, _ := range row {
|
||
cell, _ := excelize.CoordinatesToCellName(1+j, nExcelStartRow+3)
|
||
err := file.SetCellValue(fSheet, cell, row[j])
|
||
if err != nil {
|
||
logger.Error("file set value err:", logger.Field("err", err))
|
||
}
|
||
}
|
||
nExcelStartRow++
|
||
}
|
||
|
||
// 合并 "需采购总数量","需采购总金额" 和 "备注" 列的单元格
|
||
strTotalCountCol, strTotalAmountCol, strRemarkCol := computeExtraColumns("E", storeCount)
|
||
_ = file.MergeCell(fSheet, strTotalCountCol+"1", strTotalCountCol+"2")
|
||
_ = file.MergeCell(fSheet, strTotalAmountCol+"1", strTotalAmountCol+"2")
|
||
_ = file.MergeCell(fSheet, strRemarkCol+"1", strRemarkCol+"2")
|
||
|
||
// 设置所有单元格的样式: 居中、加边框
|
||
style, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"},
|
||
"border":[{"type":"left","color":"000000","style":1},
|
||
{"type":"top","color":"000000","style":1},
|
||
{"type":"right","color":"000000","style":1},
|
||
{"type":"bottom","color":"000000","style":1}]}`)
|
||
|
||
endRow := fmt.Sprintf(strRemarkCol+"%d", nExcelStartRow+2)
|
||
// 应用样式到整个表格
|
||
_ = file.SetCellStyle("Sheet1", "A1", endRow, style)
|
||
|
||
_ = file.MergeCell(fSheet, "A1", "A2")
|
||
_ = file.MergeCell(fSheet, "B1", "B2")
|
||
_ = file.MergeCell(fSheet, "C1", "C2")
|
||
_ = file.MergeCell(fSheet, "D1", "D2")
|
||
_ = file.MergeCell(fSheet, "E1", "E2")
|
||
|
||
fmt.Println("save fileName:", config.ExportConfig.Path+fileName)
|
||
if err := file.SaveAs(config.ExportConfig.Path + fileName); err != nil {
|
||
fmt.Println(err)
|
||
}
|
||
return url + fileName, nil
|
||
}
|
||
|
||
// 根据合并单元格的字符串获取左上角和右下角的坐标
|
||
func splitMergeCellCoordinates(cell string) (string, string) {
|
||
split := strings.Split(cell, ":")
|
||
if len(split) != 2 {
|
||
return "", ""
|
||
}
|
||
return split[0], split[1]
|
||
}
|
||
|
||
// 计算 "需采购总数量","需采购总金额" 和 "备注" 列的坐标字符串
|
||
func computeExtraColumns(startCol string, storeCount int) (string, string, string) {
|
||
// "需采购总数量" 列在商户列表结束后的下一列
|
||
totalCountCol := convertColumnToLetters(convertLettersToColumn(startCol) + storeCount*3 + 1)
|
||
|
||
// "需采购总金额" 列在 "需采购总数量" 列的下一列
|
||
totalAmountCol := convertColumnToLetters(convertLettersToColumn(totalCountCol) + 1)
|
||
|
||
// "备注" 列在 "需采购总金额" 列的下一列
|
||
remarkCol := convertColumnToLetters(convertLettersToColumn(totalAmountCol) + 1)
|
||
|
||
return totalCountCol, totalAmountCol, remarkCol
|
||
}
|
||
|
||
// 将列号转换为字母
|
||
func convertColumnToLetters(column int) string {
|
||
var result string
|
||
for column > 0 {
|
||
column--
|
||
result = string('A'+column%26) + result
|
||
column /= 26
|
||
}
|
||
return result
|
||
}
|
||
|
||
// 将字母转换为列号
|
||
func convertLettersToColumn(letters string) int {
|
||
result := 0
|
||
for _, letter := range letters {
|
||
result *= 26
|
||
result += int(letter) - 'A' + 1
|
||
}
|
||
return result
|
||
}
|