1、同步dev_1.4.1最近修复的缺陷;

This commit is contained in:
chenlin 2024-09-18 17:11:39 +08:00
parent 2425d87284
commit 318541c3af
6 changed files with 146 additions and 24 deletions

View File

@ -35,6 +35,8 @@ func ErpOrderCreate(c *gin.Context) {
return
}
tools.RoundFloatFields(req)
// 如果用户是会员,手机号不能为空
if req.MemberType == model.ErpOrderMemberTypeMember && req.Tel == "" {
app.Error(c, http.StatusBadRequest, errors.New("参数错误:缺少会员手机号"), "参数错误:缺少会员手机号")

View File

@ -11,6 +11,7 @@ import (
"go-admin/tools/config"
"golang.org/x/sync/errgroup"
"gorm.io/gorm"
"math"
"math/rand"
"sort"
"strconv"
@ -1232,13 +1233,13 @@ func (m *StockImporter) processErpStocks(erpStocks []ErpStockCommodity) error {
})
}
err := m.ErpStockCountUpdate(begin) //更新or插入库存表
err := errGroup.Wait()
if err != nil {
begin.Rollback()
return err
}
err = errGroup.Wait()
err = m.ErpStockCountUpdate(begin) //更新or插入库存表
if err != nil {
begin.Rollback()
return err
@ -1262,8 +1263,26 @@ func createStockList(begin *gorm.DB, stockList []ErpStockCommodity) error {
return nil
}
// 合并导入数据的辅助函数
func mergeCensusMap(censusMap map[uint32]map[uint32]uint32) map[uint32]map[uint32]uint32 {
mergedMap := make(map[uint32]map[uint32]uint32)
for storeId, commodities := range censusMap {
if mergedMap[storeId] == nil {
mergedMap[storeId] = make(map[uint32]uint32)
}
for commodityId, count := range commodities {
mergedMap[storeId][commodityId] += count
}
}
return mergedMap
}
func (m *StockImporter) ErpStockCountUpdate(gdb *gorm.DB) error {
for k1, v1 := range m.CensusMap {
// 合并导入数据,避免同一商品多次重复处理
mergedCensusMap := mergeCensusMap(m.CensusMap)
//for k1, v1 := range m.CensusMap {
for k1, v1 := range mergedCensusMap {
for k2, v2 := range v1 {
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_stock WHERE store_id=%d AND erp_commodity_id=%d", k1, k2))
if err != nil {
@ -2440,8 +2459,8 @@ type ErpStockCommodityListResp struct {
Total int `json:"total"` // 数据总条数
PageIndex int `json:"pageIndex"` // 页码
PageSize int `json:"pageSize"` // 每页展示条数
TotalWholesalePrice int `json:"total_wholesale_price"` // 入库采购价之和
TotalStaffPrice int `json:"total_staff_price"` // 入库员工成本价之和
TotalWholesalePrice float64 `json:"total_wholesale_price"` // 入库采购价之和
TotalStaffPrice float64 `json:"total_staff_price"` // 入库员工成本价之和
ExportUrl string `json:"export_url"`
}
@ -2550,8 +2569,8 @@ func (m *ErpStockCommodityListReq) GetDetailList(c *gin.Context, nType uint32) (
resp.Total = int(count)
resp.PageIndex = page + 1
resp.PageSize = m.PageSize
resp.TotalWholesalePrice = int(nTotalCount.TotalWholesalePrice)
resp.TotalStaffPrice = int(nTotalCount.TotalStaffCostPrice + nTotalCount.TotalWholesalePrice)
resp.TotalWholesalePrice = math.Round(nTotalCount.TotalWholesalePrice*100) / 100
resp.TotalStaffPrice = math.Round((nTotalCount.TotalStaffCostPrice+nTotalCount.TotalWholesalePrice)*100) / 100
return resp, nil
}

View File

@ -1497,9 +1497,25 @@ func mergeOrderCommodities(orderCommodities []ErpOrderCommodity) []ErpOrderCommo
// 将map转换回orderCommodities列表
var mergedCommodities []ErpOrderCommodity
for _, commodity := range commodityMap {
// 对float64类型的字段进行四舍五入处理
commodity.SalesProfit = tools.RoundFloat(commodity.SalesProfit)
commodity.StaffProfit = tools.RoundFloat(commodity.StaffProfit)
commodity.SaleDiscount = tools.RoundFloat(commodity.SaleDiscount)
commodity.MemberDiscount = tools.RoundFloat(commodity.MemberDiscount)
commodity.ReceivedAmount = tools.RoundFloat(commodity.ReceivedAmount)
commodity.RejectedPrice = tools.RoundFloat(commodity.RejectedPrice)
commodity.RejectedAmount = tools.RoundFloat(commodity.RejectedAmount)
commodity.StaffCostPrice = tools.RoundFloat(commodity.StaffCostPrice)
commodity.WholesalePrice = tools.RoundFloat(commodity.WholesalePrice)
mergedCommodities = append(mergedCommodities, *commodity)
}
// 对mergedCommodities按ErpCommodityId进行排序
sort.Slice(mergedCommodities, func(i, j int) bool {
return mergedCommodities[i].ID < mergedCommodities[j].ID
})
return mergedCommodities
}
@ -4236,12 +4252,12 @@ func queryRetailDetailByJoin(req *ErpOrderRetailDetailReq, c *gin.Context) (*Erp
// 退货订单支付汇总:目前零售退货订单暂时不展示各个方式的付款金额
var rejectedCashier TotalCashierData
//rejectedCashierQs := qs
//rejectedCashier, err = getTotalCashierData(rejectedCashierQs, RetailTypeRejected)
//if err != nil {
// logger.Error("query erp_order_pay_way sum data err:", logger.Field("err", err))
// return resp, err
//}
rejectedCashierQs := qs
rejectedCashier, err = getTotalCashierData(rejectedCashierQs, RetailTypeRejected)
if err != nil {
logger.Error("query erp_order_pay_way sum data err:", logger.Field("err", err))
return resp, err
}
// 计算销售订单和退货订单汇总后的支付数据
cashier = subtractCashierData(cashier, rejectedCashier)
@ -5056,6 +5072,8 @@ func CreateErpOrder(req *ErpOrderCreateReq, c *gin.Context) error {
if err != nil {
return err
}
// 四舍五入
tools.RoundFloatFields(req)
begin := orm.Eloquent.Begin()
if req.Tel != "" {
@ -5436,8 +5454,8 @@ func checkOrderData(req *ErpOrderCreateReq, c *gin.Context) (*ErpOrder, error) {
req.ErpOrderCommodities[i].MemberDiscount = req.ErpOrderCommodities[i].MemberDiscount / float64(req.ErpOrderCommodities[i].Count)
// 单个商品实收金额
req.ErpOrderCommodities[i].ReceivedAmount = req.ErpOrderCommodities[i].ReceivedAmount / float64(req.ErpOrderCommodities[i].Count)
// 单个商品退货金额
req.ErpOrderCommodities[i].RejectedAmount = req.ErpOrderCommodities[i].RejectedAmount / float64(req.ErpOrderCommodities[i].Count)
//// 单个商品退货金额
//req.ErpOrderCommodities[i].RejectedAmount = req.ErpOrderCommodities[i].RejectedAmount / float64(req.ErpOrderCommodities[i].Count)
for j := 0; j < int(req.ErpOrderCommodities[i].Count); j++ {
stockIdList, _ := stringToIntArray(req.ErpOrderCommodities[i].ErpStockCommodityID)
@ -5560,6 +5578,7 @@ func checkOrderData(req *ErpOrderCreateReq, c *gin.Context) (*ErpOrder, error) {
}
req.ErpOrderCommodities = respErpOrderCommodities
tools.RoundFloatFields(erpOrder)
// 判断线上支付金额是否>0
if req.RetailType == RetailTypeSale {
@ -5606,7 +5625,7 @@ func checkOrderData(req *ErpOrderCreateReq, c *gin.Context) (*ErpOrder, error) {
// 订单总优惠
if req.RetailType == RetailTypeSale {
erpOrder.TotalDiscount = erpOrder.TotalRetailPrice - erpOrder.TotalAmount
erpOrder.TotalDiscount = math.Round((erpOrder.TotalRetailPrice-erpOrder.TotalAmount)*100) / 100
}
return erpOrder, nil

View File

@ -786,6 +786,33 @@ func MergeCommodities(commodities []ErpInventoryAllotCommodity) []ErpInventoryAl
return mergedCommodities
}
// MergeAllCommodities 遍历库存调拨商品信息将商品id相同的所有商品进行合并数量累加即可
func MergeAllCommodities(commodities []ErpInventoryAllotCommodity) []ErpInventoryAllotCommodity {
// 用于存储合并后的商品信息
mergedCommodities := make([]ErpInventoryAllotCommodity, 0)
// 用于记录无串码商品的合并信息
commodityMap := make(map[uint32]*ErpInventoryAllotCommodity)
for _, commodity := range commodities {
if existing, found := commodityMap[commodity.CommodityId]; found {
// 如果相同商品 ID 的无串码商品已存在,则数量累加
existing.Count += commodity.Count
commodityMap[commodity.CommodityId] = existing
} else {
// 否则,加入到 commodityMap 中
newCommodity := commodity
commodityMap[commodity.CommodityId] = &newCommodity
}
}
// 将合并后的无串码商品加入到合并后的列表中
for _, commodity := range commodityMap {
mergedCommodities = append(mergedCommodities, *commodity)
}
return mergedCommodities
}
// MergeChangeCommodities 遍历库存变动商品信息将商品id相同的非串码商品进行合并数量累加即可
func MergeChangeCommodities(commodities []ErpInventoryChangeCommodity) []ErpInventoryChangeCommodity {
// 用于存储合并后的商品信息
@ -1043,13 +1070,15 @@ func ReceiveAllotInventory(req *InventoryAllotReceiveReq, c *gin.Context) error
// 遍历库存调拨商品信息
for _, v := range trimCommodities {
var stockCommodity []ErpStockCommodity
err := orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? AND store_id = ? "+
err = orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? AND store_id = ? "+
"AND state = ? AND imei = ?", v.CommodityId, inventoryAllotOrder.DeliverStoreId, InAllot, v.IMEI).
Find(&stockCommodity).Error
if err != nil {
begin.Rollback()
return fmt.Errorf("查询商品库存失败:[%s]", err.Error())
}
if len(stockCommodity) == 0 {
begin.Rollback()
return fmt.Errorf("未找到商品库存信息")
}
@ -1059,18 +1088,37 @@ func ReceiveAllotInventory(req *InventoryAllotReceiveReq, c *gin.Context) error
stockCommodity[i].StoreName = inventoryAllotOrder.ReceiveStoreName
stockCommodity[i].State = InStock
stockCommodity[i].StockTime = time.Now()
err = begin.Model(&ErpStockCommodity{}).Where("id = ?", stockCommodity[i].ID).
Updates(stockCommodity[i]).Error
err = begin.Where("id", stockCommodity[i].ID).Omit("created_at").Save(&stockCommodity[i]).Error
//err = begin.Model(&ErpStockCommodity{}).Where("id = ?", stockCommodity[i].ID).
// Updates(stockCommodity[i]).Error
if err != nil {
begin.Rollback()
return fmt.Errorf("更新商品库存失败:%s", err.Error())
}
}
}
// 遍历库存调拨商品信息将商品id相同的非串码商品进行合并数量累加即可
trimAllCommodities := MergeAllCommodities(trimCommodities)
for _, v := range trimAllCommodities {
var stockCommodity []ErpStockCommodity
err = orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? AND store_id = ? "+
"AND state = ? AND imei = ?", v.CommodityId, inventoryAllotOrder.DeliverStoreId, InAllot, v.IMEI).
Find(&stockCommodity).Error
if err != nil {
begin.Rollback()
return fmt.Errorf("查询商品库存失败:[%s]", err.Error())
}
if len(stockCommodity) == 0 {
begin.Rollback()
return fmt.Errorf("未找到商品库存信息")
}
// 更新调入门店的库存数量
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_stock WHERE store_id=%d AND erp_commodity_id=%d",
inventoryAllotOrder.ReceiveStoreId, v.CommodityId))
if err != nil {
begin.Rollback()
logger.Errorf("exist err:", err)
return err
}
@ -1101,6 +1149,7 @@ func ReceiveAllotInventory(req *InventoryAllotReceiveReq, c *gin.Context) error
}
err = begin.Create(stock).Error
if err != nil {
begin.Rollback()
logger.Errorf("create stock err:", err)
return err
}
@ -1121,6 +1170,7 @@ func ReceiveAllotInventory(req *InventoryAllotReceiveReq, c *gin.Context) error
"UPDATE erp_stock SET dispatch_count = dispatch_count-%d WHERE store_id=%d AND erp_commodity_id=%d",
v.Count, inventoryAllotOrder.DeliverStoreId, v.CommodityId)).Error
if err != nil {
begin.Rollback()
logger.Errorf("update stock err:", err)
return err
}

View File

@ -4343,10 +4343,10 @@ func getReportByCommodityFromCommon(req *ErpPurchaseReportByCommodityReq, c *gin
}
resp.PlanCount = totalData.PlanCount
resp.PlanAmount = totalData.PlanAmount
resp.Amount = totalData.Amount
resp.PlanAmount = math.Round(totalData.PlanAmount*100) / 100
resp.Amount = math.Round(totalData.Amount*100) / 100
resp.Count = totalData.Count
resp.NonExecutionAmount = totalData.NonExecutionAmount
resp.NonExecutionAmount = math.Round(totalData.NonExecutionAmount*100) / 100
resp.NonExecutionCount = totalData.NonExecutionCount
if req.IsExport == 1 {
@ -4434,8 +4434,10 @@ func getPurchaseOrderAndCommodityData(orderID, commodityId uint32) (ErpCommodity
purchaseOrderData.Amount = purchaseData.Amount
purchaseOrderData.Price = purchaseData.Price
purchaseOrderData.Count = purchaseData.Count
if purchaseOrder.State != ErpPurchaseOrderEnd {
purchaseOrderData.NonExecutionAmount = purchaseData.NonExecutionAmount
purchaseOrderData.NonExecutionCount = purchaseData.NonExecutionCount
}
return purchaseOrderData, commodityData, nil
}

View File

@ -6,6 +6,7 @@ import (
"gorm.io/gorm"
"log"
"math"
"reflect"
"runtime"
"strconv"
"time"
@ -134,3 +135,32 @@ func StringSliceContains(slice []string, val string) bool {
}
return false
}
// RoundFloat 保留 float64 两位小数
func RoundFloat(f float64) float64 {
return math.Round(f*100) / 100
}
// RoundFloatFields 递归处理结构体中的 float64 字段,四舍五入保留两位小数
func RoundFloatFields(v interface{}) {
val := reflect.ValueOf(v).Elem()
for i := 0; i < val.NumField(); i++ {
field := val.Field(i)
switch field.Kind() {
case reflect.Float64:
// 对 float64 类型进行四舍五入
field.SetFloat(RoundFloat(field.Float()))
case reflect.Struct:
// 递归处理子结构体
RoundFloatFields(field.Addr().Interface())
case reflect.Slice:
// 对于 slice 中的结构体,逐个处理
for j := 0; j < field.Len(); j++ {
if field.Index(j).Kind() == reflect.Struct {
RoundFloatFields(field.Index(j).Addr().Interface())
}
}
}
}
}