1.修复缺陷:

(1)采购执行入库时入库编号规则调整,采购为入库编号,退货为采购单单据号;
(2)采购入库更新库存信息时,遍历库存信息,合并重复数据,避免插入多条相同数据;
(3)采购报表(按单)调整筛选条件查询,支持组合查询,改为1个函数;
(4)采购报表(按商品)调整筛选条件查询,支持组合查询,改为1个函数;
This commit is contained in:
chenlin 2024-05-11 10:03:52 +08:00
parent 6f91388f05
commit 4696c63778
2 changed files with 269 additions and 127 deletions

View File

@ -250,7 +250,7 @@ func ErpPurchaseDetail(c *gin.Context) {
v.ExecutionPrice = math.Round(v.ExecutionPrice*100) / 100
serialNumber := purchaseOrder.SerialNumber
if purchaseOrder.PurchaseType == model.ErpRejectOrder { // 采购退货订单
if purchaseOrder.PurchaseType == model.ErpRejectOrder && purchaseOrder.State == model.ErpPurchaseOrderUnAudit { // 采购退货订单
serialNumber = purchaseOrder.RejectedSerialNumber
// 查询原始采购订单的信息

View File

@ -1137,7 +1137,12 @@ func InventoryErpPurchase(req *ErpPurchaseInventoryReq, c *gin.Context) error {
nCount := v.Count
nAmount := v.Amount
for j := 0; j < int(nCount); j++ { // 采购入库记录表都是单笔数据
v.SerialNumber = GetPurchaseInventorySn()
if v.PurchaseType == ErpProcureOrder {
v.SerialNumber = GetPurchaseInventorySn()
} else {
v.SerialNumber = purchaseOrder.SerialNumber
}
v.ID = 0
v.Count = 1
v.Amount = nAmount / float64(nCount) // 前端传的执行金额是总金额
@ -1231,6 +1236,7 @@ func GetInventoryIdAndName(orderId uint32) (uint32, string, error) {
func InventoryErpPurchaseUpdateStock(gdb *gorm.DB, list []ErpPurchaseInventory, purchaseOrder ErpPurchaseOrder) error {
// 遍历采购入库商品信息
var stockList []ErpStockCommodity
var waitCreateStockList []ErpStock
for _, v := range list {
commodityInfo, err := GetCommodity(v.ErpCommodityId)
if err != nil {
@ -1252,7 +1258,8 @@ func InventoryErpPurchaseUpdateStock(gdb *gorm.DB, list []ErpPurchaseInventory,
return err
}
} else {
stock := &ErpStock{
// 如果同时入库多个商品,刚好之前又没有记录,则可能生成多条记录
stock := ErpStock{
StoreId: purchaseOrder.StoreId,
StoreName: purchaseOrder.StoreName,
ErpCommodityId: v.ErpCommodityId,
@ -1266,11 +1273,13 @@ func InventoryErpPurchaseUpdateStock(gdb *gorm.DB, list []ErpPurchaseInventory,
Count: v.Count,
DispatchCount: 0,
}
err = gdb.Create(stock).Error
if err != nil {
logger.Errorf("create stock err:", err)
return err
}
waitCreateStockList = append(waitCreateStockList, stock)
//err = gdb.Create(stock).Error
//if err != nil {
// logger.Errorf("create stock err:", err)
// return err
//}
}
nowTime := time.Now()
@ -1304,15 +1313,63 @@ func InventoryErpPurchaseUpdateStock(gdb *gorm.DB, list []ErpPurchaseInventory,
stockList = append(stockList, stockCommodity)
}
err := gdb.Debug().Create(&stockList).Error
// 遍历库存信息,合并重复数据
newStockList := combineStocks(waitCreateStockList)
err := gdb.Debug().Create(&newStockList).Error
if err != nil {
logger.Errorf("create stock commodity err:", err)
logger.Errorf("create erp_stock err:", err)
return err
}
err = gdb.Debug().Create(&stockList).Error
if err != nil {
logger.Errorf("create erp_stock_commodity err:", err)
return err
}
return nil
}
func combineStocks(waitCreateStockList []ErpStock) []ErpStock {
// 创建一个map用于存储相同 StoreId 和 ErpCommodityId 的库存信息
stockMap := make(map[string]*ErpStock)
// 遍历待处理的库存列表
for _, stock := range waitCreateStockList {
// 构建库存信息的唯一标识
key := fmt.Sprintf("%d_%d", stock.StoreId, stock.ErpCommodityId)
// 如果该库存信息已经存在于 map 中,则累加数量
if existingStock, found := stockMap[key]; found {
existingStock.Count += stock.Count
} else {
// 否则,将该库存信息添加到 map 中
stockMap[key] = &ErpStock{
StoreId: stock.StoreId,
StoreName: stock.StoreName,
ErpCommodityId: stock.ErpCommodityId,
ErpCommodityName: stock.ErpCommodityName,
ErpCategoryId: stock.ErpCategoryId,
ErpCategoryName: stock.ErpCategoryName,
CommoditySerialNumber: stock.CommoditySerialNumber,
IMEIType: stock.IMEIType,
RetailPrice: stock.RetailPrice,
MinRetailPrice: stock.MinRetailPrice,
Count: stock.Count,
DispatchCount: stock.DispatchCount,
}
}
}
// 将 map 中的库存信息转换为列表
var combinedStocks []ErpStock
for _, stock := range stockMap {
combinedStocks = append(combinedStocks, *stock)
}
return combinedStocks
}
// InventoryErpPurchaseUpdateRejectStock 采购退货更新库存信息
func InventoryErpPurchaseUpdateRejectStock(gdb *gorm.DB, list []ErpPurchaseInventory, purchaseOrder ErpPurchaseOrder) error {
usedStockCommodityIdList := make(map[uint32]bool)
@ -3075,13 +3132,15 @@ func convertLettersToColumn(letters string) int {
func GetReportByOrder(req *ErpPurchaseReportByOrderReq, c *gin.Context) (*ErpPurchaseReportByOrderResp, error) {
var err error
resp := new(ErpPurchaseReportByOrderResp)
if req.ErpCommodityName != "" || req.ErpCategoryID != 0 { // 商品名称、商品分类不为空
// 先筛选商品入库信息表,然后再补充采购订单信息
resp, err = getReportByOrderFromCommodityOrCategory(req, c)
} else {
// 先筛选采购订单表,再补充商品入库信息
resp, err = getReportByOrderFromCommon(req, c)
}
//if req.ErpCommodityName != "" || req.ErpCategoryID != 0 { // 商品名称、商品分类不为空
// // 先筛选商品入库信息表,然后再补充采购订单信息
// resp, err = getReportByOrderFromCommodityOrCategory(req, c)
//} else {
// // 先筛选采购订单表,再补充商品入库信息
// resp, err = getReportByOrderFromCommon(req, c)
//}
resp, err = getReportByOrderFromCommon(req, c)
if err != nil {
return nil, err
}
@ -3316,50 +3375,49 @@ func getReportByOrderFromCommon(req *ErpPurchaseReportByOrderReq, c *gin.Context
PageIndex: page + 1,
PageSize: req.PageSize,
}
qs := orm.Eloquent.Table("erp_purchase_order").Where("state != 1") // 未审核订单不展示
if req.SerialNumber != "" { // 单据编号
qs := orm.Eloquent.Table("erp_purchase_order").Where("state != ?", ErpPurchaseOrderUnAudit) // 未审核订单不展示
if req.SerialNumber != "" { // 单据编号
qs = qs.Where("serial_number=?", req.SerialNumber)
} else {
if req.PurchaseType != "" { // 采购类型
qs = qs.Where("purchase_type=?", req.PurchaseType)
}
if req.PurchaseType != "" { // 采购类型
qs = qs.Where("purchase_type=?", req.PurchaseType)
}
if len(req.ErpSupplierId) > 0 { // 供应商复选
var supplierIDs []uint32
for _, supplier := range req.ErpSupplierId {
supplierIDs = append(supplierIDs, supplier)
}
if len(req.ErpSupplierId) > 0 { // 供应商复选
var supplierIDs []uint32
for _, supplier := range req.ErpSupplierId {
supplierIDs = append(supplierIDs, supplier)
}
qs = qs.Where("erp_supplier_id IN (?)", supplierIDs)
qs = qs.Where("erp_supplier_id IN (?)", supplierIDs)
}
if len(req.StoreId) > 0 { // 门店复选
var storeIDs []uint32
for _, store := range req.StoreId {
storeIDs = append(storeIDs, store)
}
if len(req.StoreId) > 0 { // 门店复选
var storeIDs []uint32
for _, store := range req.StoreId {
storeIDs = append(storeIDs, store)
}
qs = qs.Where("store_id IN (?)", storeIDs)
qs = qs.Where("store_id IN (?)", storeIDs)
}
if req.HandlerId != 0 { // 经手人id
qs = qs.Where("handler_id=?", req.HandlerId)
}
if req.State != 0 { // 订单状态
qs = qs.Where("state=?", req.State)
}
if req.AuditTimeStart != "" { // 审核开始时间
parse, err := time.Parse(QueryTimeFormat, req.AuditTimeStart)
if err != nil {
logger.Errorf("erpPurchaseOrderList err:", err)
return nil, err
}
if req.HandlerId != 0 { // 经手人id
qs = qs.Where("handler_id=?", req.HandlerId)
}
if req.State != 0 { // 订单状态
qs = qs.Where("state=?", req.State)
}
if req.AuditTimeStart != "" { // 审核开始时间
parse, err := time.Parse(QueryTimeFormat, req.AuditTimeStart)
if err != nil {
logger.Errorf("erpPurchaseOrderList err:", err)
return nil, err
}
qs = qs.Where("audit_time > ?", parse)
}
if req.AuditTimeEnd != "" { // 审核结束时间
parse, err := time.Parse(QueryTimeFormat, req.AuditTimeEnd)
if err != nil {
logger.Errorf("erpPurchaseOrderList err:", err)
return nil, err
}
//parse = parse.AddDate(0, 0, 1)
qs = qs.Where("audit_time < ?", parse)
qs = qs.Where("audit_time > ?", parse)
}
if req.AuditTimeEnd != "" { // 审核结束时间
parse, err := time.Parse(QueryTimeFormat, req.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
@ -3370,8 +3428,7 @@ func getReportByOrderFromCommon(req *ErpPurchaseReportByOrderReq, c *gin.Context
}
resp.Total = int(count)
var orders []ErpPurchaseOrder
if req.IsExport == 1 { // 导出excel
if req.ErpCategoryID != 0 || req.ErpCommodityName != "" || req.IsExport == 1 {
err = qs.Order("id DESC").Find(&orders).Error
} else {
err = qs.Order("id DESC").Offset(page * req.PageSize).Limit(req.PageSize).Find(&orders).Error
@ -3388,6 +3445,7 @@ func getReportByOrderFromCommon(req *ErpPurchaseReportByOrderReq, c *gin.Context
var reportByOrderData ReportByOrderData
var nAmount float64
var nCount int32
reportByOrderData.ErpPurchaseOrderId = v.ID
reportByOrderData.SerialNumber = v.SerialNumber
reportByOrderData.PurchaseType = v.PurchaseType
@ -3418,11 +3476,15 @@ func getReportByOrderFromCommon(req *ErpPurchaseReportByOrderReq, c *gin.Context
reportByOrderData.AuditTime = v.AuditTime
}
reportByOrderData.CommodityData, nAmount, nCount, err = getOrderInventoryInfo(v.ID)
reportByOrderData.CommodityData, nAmount, nCount, err = getOrderInventoryInfo(req, v.ID)
if err != nil {
return nil, err
}
if reportByOrderData.CommodityData == nil {
continue
}
reportByOrderData.Amount = nAmount
reportByOrderData.Count = nCount
if nCount != 0 {
@ -3432,10 +3494,25 @@ func getReportByOrderFromCommon(req *ErpPurchaseReportByOrderReq, c *gin.Context
nTotalAmount += nAmount
nTotalCount += nCount
}
resp.List = reportByOrderDataList
resp.Total = len(reportByOrderDataList)
if req.ErpCategoryID != 0 || req.ErpCommodityName != "" {
// 计算分页所需的切片索引
startIndex := page * req.PageSize
endIndex := (page + 1) * req.PageSize
if endIndex > len(reportByOrderDataList) {
endIndex = len(reportByOrderDataList)
}
resp.List = reportByOrderDataList[startIndex:endIndex]
} else {
resp.List = reportByOrderDataList
}
resp.Amount = nTotalAmount
resp.Count = nTotalCount
resp.Total = int(count)
//resp.Total = int(count)
if req.IsExport == 1 {
filePath, err := reportByOrderExport(resp)
@ -3450,7 +3527,7 @@ func getReportByOrderFromCommon(req *ErpPurchaseReportByOrderReq, c *gin.Context
}
// 查询采购订单的入库信息
func getOrderInventoryInfo(erpPurchaseOrderId uint32) ([]ErpPurchaseCommodityData, float64, int32, error) {
func getOrderInventoryInfo(req *ErpPurchaseReportByOrderReq, erpPurchaseOrderId uint32) ([]ErpPurchaseCommodityData, float64, int32, error) {
var inventoryList []ErpPurchaseInventory
err := orm.Eloquent.Table("erp_purchase_inventory").
Where("erp_purchase_order_id = ?", erpPurchaseOrderId).
@ -3474,6 +3551,15 @@ func getOrderInventoryInfo(erpPurchaseOrderId uint32) ([]ErpPurchaseCommodityDat
for _, v := range inventoryList {
var vCount int32
var vAmount float64
// 商品名称和分类筛选
if req.ErpCommodityName != "" && v.ErpCommodityName != req.ErpCommodityName {
continue
}
if req.ErpCategoryID != 0 && v.ErpCategoryID != req.ErpCategoryID {
continue
}
if v.PurchaseType == ErpRejectOrder { // 退货单金额和数量取负值
vAmount = -v.Amount
vCount = -int32(v.Count)
@ -3665,13 +3751,15 @@ func reportByOrderExport(req *ErpPurchaseReportByOrderResp) (string, error) {
func GetReportByCommodity(req *ErpPurchaseReportByCommodityReq, c *gin.Context) (*ErpPurchaseReportByCommodityResp, error) {
var err error
resp := new(ErpPurchaseReportByCommodityResp)
if req.ErpCommodityName != "" || req.ErpCategoryID != 0 { // 商品名称、商品分类不为空
// 先筛选商品入库信息表,然后再补充采购订单信息
resp, err = getReportByCommodityFromCommodityOrCategory(req, c)
} else {
// 先筛选采购订单表,再补充商品入库信息
resp, err = getReportByCommodityFromCommon(req, c)
}
//if req.ErpCommodityName != "" || req.ErpCategoryID != 0 { // 商品名称、商品分类不为空
// // 先筛选商品入库信息表,然后再补充采购订单信息
// resp, err = getReportByCommodityFromCommodityOrCategory(req, c)
//} else {
// // 先筛选采购订单表,再补充商品入库信息
// resp, err = getReportByCommodityFromCommon(req, c)
//}
resp, err = getReportByCommodityFromCommon(req, c)
if err != nil {
return nil, err
}
@ -3729,11 +3817,7 @@ func getReportByCommodityFromCommodityOrCategory(req *ErpPurchaseReportByCommodi
}
var inventoryList []ErpPurchaseInventory
if req.IsExport == 1 { // 导出excel
err = qs.Order("id DESC").Find(&inventoryList).Error
} else {
err = qs.Order("id DESC").Offset(page * req.PageSize).Limit(req.PageSize).Find(&inventoryList).Error
}
err = qs.Order("id DESC").Find(&inventoryList).Error
if err != nil && err != RecordNotFound {
logger.Error("getReportByOrderFromCommodityOrCategory erp_purchase_inventory err:", logger.Field("err", err))
return resp, err
@ -3761,10 +3845,13 @@ func getReportByCommodityFromCommodityOrCategory(req *ErpPurchaseReportByCommodi
for _, orderIdSet := range commodityIDMap {
var reportByCommodityData ReportByCommodityData
if len(orderIdSet) != 0 {
reportByCommodityData.ErpCommodityId = orderIdSet[0].ErpPurchaseCommodityId
reportByCommodityData.ErpCommodityName = orderIdSet[0].ErpCommodityName
reportByCommodityData.ErpCategoryID = orderIdSet[0].ErpCategoryID
reportByCommodityData.ErpCategoryName = orderIdSet[0].ErpCategoryName
for _, item := range orderIdSet {
reportByCommodityData.ErpCommodityId = item.ErpCommodityId
reportByCommodityData.ErpCommodityName = item.ErpCommodityName
reportByCommodityData.ErpCategoryID = item.ErpCategoryID
reportByCommodityData.ErpCategoryName = item.ErpCategoryName
break
}
}
var totalPurchaseData PurchaseData
@ -3807,7 +3894,17 @@ func getReportByCommodityFromCommodityOrCategory(req *ErpPurchaseReportByCommodi
reportByCommodityDataList = append(reportByCommodityDataList, reportByCommodityData)
}
resp.List = reportByCommodityDataList
sortByCommodityIDDesc(reportByCommodityDataList)
resp.Total = len(reportByCommodityDataList)
// 计算分页所需的切片索引
startIndex := page * req.PageSize
endIndex := (page + 1) * req.PageSize
if endIndex > len(reportByCommodityDataList) {
endIndex = len(reportByCommodityDataList)
}
resp.List = reportByCommodityDataList[startIndex:endIndex]
resp.PlanCount = totalData.PlanCount
resp.PlanAmount = totalData.PlanAmount
resp.Amount = totalData.Amount
@ -3966,42 +4063,41 @@ func getReportByCommodityFromCommon(req *ErpPurchaseReportByCommodityReq, c *gin
PageIndex: page + 1,
PageSize: req.PageSize,
}
qs := orm.Eloquent.Table("erp_purchase_order").Where("state != 1")
qs := orm.Eloquent.Table("erp_purchase_order").Where("state != ?", ErpPurchaseOrderUnAudit)
if req.SerialNumber != "" { // 单据编号
qs = qs.Where("serial_number=?", req.SerialNumber)
} else {
if req.PurchaseType != "" { // 采购类型
qs = qs.Where("purchase_type=?", req.PurchaseType)
}
if req.PurchaseType != "" { // 采购类型
qs = qs.Where("purchase_type=?", req.PurchaseType)
}
if len(req.ErpSupplierId) > 0 { // 供应商复选
qs = qs.Where("erp_supplier_id IN (?)", req.ErpSupplierId)
}
if len(req.StoreId) > 0 { // 门店复选
qs = qs.Where("store_id IN (?)", req.StoreId)
}
if req.HandlerId != 0 { // 经手人id
qs = qs.Where("handler_id=?", req.HandlerId)
}
if req.State != 0 { // 订单状态
qs = qs.Where("state=?", req.State)
}
if req.AuditTimeStart != "" { // 审核开始时间
parse, err := time.Parse(QueryTimeFormat, req.AuditTimeStart)
if err != nil {
logger.Errorf("erpPurchaseOrderList err:", err)
return nil, err
}
if len(req.ErpSupplierId) > 0 { // 供应商复选
qs = qs.Where("erp_supplier_id IN (?)", req.ErpSupplierId)
}
if len(req.StoreId) > 0 { // 门店复选
qs = qs.Where("store_id IN (?)", req.StoreId)
}
if req.HandlerId != 0 { // 经手人id
qs = qs.Where("handler_id=?", req.HandlerId)
}
if req.State != 0 { // 订单状态
qs = qs.Where("state=?", req.State)
}
if req.AuditTimeStart != "" { // 审核开始时间
parse, err := time.Parse(QueryTimeFormat, req.AuditTimeStart)
if err != nil {
logger.Errorf("erpPurchaseOrderList err:", err)
return nil, err
}
qs = qs.Where("audit_time > ?", parse)
}
if req.AuditTimeEnd != "" { // 审核结束时间
parse, err := time.Parse(QueryTimeFormat, req.AuditTimeEnd)
if err != nil {
logger.Errorf("erpPurchaseOrderList err:", err)
return nil, err
}
//parse = parse.AddDate(0, 0, 1)
qs = qs.Where("audit_time < ?", parse)
qs = qs.Where("audit_time > ?", parse)
}
if req.AuditTimeEnd != "" { // 审核结束时间
parse, err := time.Parse(QueryTimeFormat, req.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
@ -4069,6 +4165,13 @@ func getReportByCommodityFromCommon(req *ErpPurchaseReportByCommodityReq, c *gin
for _, tempDataList := range tempDataMap {
var reportData ReportByCommodityData
for _, v := range tempDataList {
// 商品名称和分类筛选
if req.ErpCommodityName != "" && v.ErpCommodityName != req.ErpCommodityName {
continue
}
if req.ErpCategoryID != 0 && v.ErpCategoryID != req.ErpCategoryID {
continue
}
reportData.ErpCategoryID = v.ErpCategoryID
reportData.ErpCategoryName = v.ErpCategoryName
reportData.ErpCommodityId = v.ErpCommodityId
@ -4149,6 +4252,9 @@ func getReportByCommodityFromCommon(req *ErpPurchaseReportByCommodityReq, c *gin
reportData.OrderInfo = append(reportData.OrderInfo, purchaseOrderData)
}
if reportData.ErpCategoryID == 0 || len(reportData.OrderInfo) == 0 {
continue
}
dataList = append(dataList, reportData)
@ -4274,23 +4380,59 @@ func getSignalPurchaseData(erpPurchaseOrderId, commodityId uint32) (PurchaseData
var purchaseData PurchaseData
var commodityData CommodityData
//err := orm.Eloquent.Raw(`
// SELECT
// SUM(pc.count) AS plan_count,
// AVG(pc.price) AS plan_price,
// SUM(pc.amount) AS plan_amount,
// SUM(pi.count) AS count,
// AVG(pi.implementation_price) AS price,
// SUM(pi.amount) AS amount
// FROM
// erp_purchase_commodity pc
// JOIN
// erp_purchase_inventory pi ON pc.erp_purchase_order_id = pi.erp_purchase_order_id
// WHERE
// pc.erp_purchase_order_id = ? and pc.erp_commodity_id = ?
// GROUP BY
// pc.erp_purchase_order_id
//`, erpPurchaseOrderId, commodityId).Scan(&purchaseData).Error
err := orm.Eloquent.Raw(`
SELECT
SUM(pc.count) AS plan_count,
AVG(pc.price) AS plan_price,
SUM(pc.amount) AS plan_amount,
SUM(pi.count) AS count,
AVG(pi.implementation_price) AS price,
SUM(pi.amount) AS amount
FROM
erp_purchase_commodity pc
JOIN
erp_purchase_inventory pi ON pc.erp_purchase_order_id = pi.erp_purchase_order_id
WHERE
pc.erp_purchase_order_id = ? and pc.erp_commodity_id = ?
GROUP BY
pc.erp_purchase_order_id
`, erpPurchaseOrderId, commodityId).Scan(&purchaseData).Error
SELECT
plan.plan_count AS plan_count,
plan.plan_price AS plan_price,
plan.plan_amount AS plan_amount,
inventory.count AS count,
inventory.price AS price,
inventory.amount AS amount
FROM
(
SELECT
SUM(pc.count) AS plan_count,
AVG(pc.price) AS plan_price,
SUM(pc.amount) AS plan_amount
FROM
erp_purchase_commodity pc
WHERE
pc.erp_purchase_order_id = ? AND pc.erp_commodity_id = ?
GROUP BY
pc.erp_purchase_order_id
) AS plan
JOIN
(
SELECT
SUM(pi.count) AS count,
AVG(pi.implementation_price) AS price,
SUM(pi.amount) AS amount
FROM
erp_purchase_inventory pi
WHERE
pi.erp_purchase_order_id = ? AND pi.erp_commodity_id = ?
GROUP BY
pi.erp_purchase_order_id
) AS inventory ON 1 = 1
`, erpPurchaseOrderId, commodityId, erpPurchaseOrderId, commodityId).Scan(&purchaseData).Error
if err != nil {
logger.Error("getPurchaseData err:", logger.Field("err", err))
return PurchaseData{}, CommodityData{}, err