diff --git a/app/admin/apis/purchasemanage/purchase.go b/app/admin/apis/purchasemanage/purchase.go index 80c8350..2e8f341 100644 --- a/app/admin/apis/purchasemanage/purchase.go +++ b/app/admin/apis/purchasemanage/purchase.go @@ -207,7 +207,11 @@ func ErpPurchaseDetail(c *gin.Context) { app.Error(c, http.StatusBadRequest, err, "获取失败") return } - v.DefaultEmployeePrice = v.Price + float64(erpCommodity.StaffCostPrice) + if purchaseOrder.PurchaseType == model.ErpProcureOrder { + v.DefaultEmployeePrice = v.Price + float64(erpCommodity.StaffCostPrice) + } else if purchaseOrder.PurchaseType == model.ErpProcureOrder { + v.DefaultEmployeePrice = v.RejectedPrice + float64(erpCommodity.StaffCostPrice) + } // 查询执行数量之和、平均执行单价、执行金额之和和平均员工成本价 result, err := model.GetTotalsAndAveragesByCommodityID(v.ErpCommodityId, v.ErpPurchaseOrderId) diff --git a/app/admin/models/commodity.go b/app/admin/models/commodity.go index da4083e..ed551fc 100644 --- a/app/admin/models/commodity.go +++ b/app/admin/models/commodity.go @@ -1357,16 +1357,34 @@ func (m *ErpStockListReq) stockIsEmptyList() (*ErpStockListResp, error) { ***/ qs := orm.Eloquent.Debug().Table("erp_commodity") + es := orm.Eloquent.Debug().Table("erp_commodity") if m.StoreId != 0 { // 传门店id - qs = qs.Select("erp_commodity.*, COALESCE(erp_stock.count, 0) AS count"). - Joins("LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id"). - Joins("JOIN erp_category c ON erp_commodity.erp_category_id = c.id"). - Where("erp_stock.count = 0 AND erp_stock.store_id = ?", m.StoreId). + qs = qs.Select("erp_commodity.*, COALESCE(erp_stock.count, 0) AS total_count"). + Joins("LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id AND erp_stock.store_id = ?", m.StoreId). + //Joins("LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id"). + Joins("LEFT JOIN erp_category c ON erp_commodity.erp_category_id = c.id"). + //Where("erp_stock.count = 0 AND erp_stock.store_id = ?", m.StoreId). + Order("CASE WHEN c.pid = 0 THEN CAST(c.number AS SIGNED) " + + "ELSE CAST(SUBSTRING(c.number, 1, 3) AS SIGNED) END, " + + "CAST(c.pid AS SIGNED), CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)") + es = es.Select("erp_commodity.*, COALESCE(erp_stock.count, 0) AS total_count"). + Joins("LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id AND erp_stock.store_id = ?", m.StoreId). + //Joins("LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id"). + Joins("LEFT JOIN erp_category c ON erp_commodity.erp_category_id = c.id"). + //Where("erp_stock.count = 0 AND erp_stock.store_id = ?", m.StoreId). Order("CASE WHEN c.pid = 0 THEN CAST(c.number AS SIGNED) " + "ELSE CAST(SUBSTRING(c.number, 1, 3) AS SIGNED) END, " + "CAST(c.pid AS SIGNED), CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)") } else { // 没传门店id,则子查询先求库存表中erp_commodity_id相同的count之和 - qs = qs.Select("erp_commodity.*, COALESCE(erp_stock.count, 0) AS count"). + qs = qs.Select("erp_commodity.*, COALESCE(erp_stock.count, 0) AS total_count"). + Joins("LEFT JOIN (SELECT erp_commodity_id, SUM(count) AS count FROM erp_stock GROUP BY erp_commodity_id) " + + "erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id"). + Joins("JOIN erp_category c ON erp_commodity.erp_category_id = c.id"). + Where("erp_stock.count IS NULL OR erp_stock.count = 0"). + Order("CASE WHEN c.pid = 0 THEN CAST(c.number AS SIGNED) " + + "ELSE CAST(SUBSTRING(c.number, 1, 3) AS SIGNED) END, " + + "CAST(c.pid AS SIGNED), CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)") + es = es.Select("erp_commodity.*, COALESCE(erp_stock.count, 0) AS total_count"). Joins("LEFT JOIN (SELECT erp_commodity_id, SUM(count) AS count FROM erp_stock GROUP BY erp_commodity_id) " + "erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id"). Joins("JOIN erp_category c ON erp_commodity.erp_category_id = c.id"). @@ -1378,52 +1396,71 @@ func (m *ErpStockListReq) stockIsEmptyList() (*ErpStockListResp, error) { if m.SerialNumber != "" { qs = qs.Where("erp_commodity.serial_number=?", m.SerialNumber) + es = es.Where("erp_commodity.serial_number=?", m.SerialNumber) } if m.CommodityName != "" { qs = qs.Where("erp_commodity.name Like '%" + m.CommodityName + "%'") + es = es.Where("erp_commodity.name Like '%" + m.CommodityName + "%'") //qs = qs.Where("name LIKE ?", m.Name) } if m.ErpCategoryId != 0 { qs = qs.Where("erp_commodity.erp_category_id=?", m.ErpCategoryId) - } - - var commodities []ErpCommodity - err := qs.Offset(page * m.PageSize).Limit(m.PageSize).Find(&commodities).Error - if err != nil && err != RecordNotFound { - logger.Error("查询无库存列表失败", logger.Field("err", err)) - return nil, err + es = es.Where("erp_commodity.erp_category_id=?", m.ErpCategoryId) } var count int64 - err = qs.Count(&count).Error + err := es.Count(&count).Error if err != nil { logger.Error("查询无库存列表数量失败", logger.Field("err", err)) return nil, err } + var commodities []struct { + ErpCommodity + TotalCount int + } + //err = qs.Offset(page * m.PageSize).Limit(m.PageSize).Find(&commodities).Error + err = qs.Find(&commodities).Error + if err != nil && err != RecordNotFound { + logger.Error("查询无库存列表失败", logger.Field("err", err)) + return nil, err + } + //遍历商品资料,转换为库存列表数据 var stockList []ErpStock for _, commodity := range commodities { - var stock ErpStock - stock.ErpCommodityId = commodity.ID - stock.ErpCommodityName = commodity.Name - stock.ErpCategoryId = commodity.ErpCategoryId - stock.ErpCategoryName = commodity.ErpCategoryName - stock.CommoditySerialNumber = commodity.SerialNumber - stock.IMEIType = commodity.IMEIType - stock.RetailPrice = commodity.RetailPrice - stock.MinRetailPrice = commodity.MinRetailPrice - stock.Count = 0 - stock.DispatchCount = 0 + if commodity.TotalCount == 0 { + var stock ErpStock + stock.ErpCommodityId = commodity.ID + stock.ErpCommodityName = commodity.Name + stock.ErpCategoryId = commodity.ErpCategoryId + stock.ErpCategoryName = commodity.ErpCategoryName + stock.CommoditySerialNumber = commodity.SerialNumber + stock.IMEIType = commodity.IMEIType + stock.RetailPrice = commodity.RetailPrice + stock.MinRetailPrice = commodity.MinRetailPrice + stock.Count = 0 + stock.DispatchCount = 0 - stockList = append(stockList, stock) + stockList = append(stockList, stock) + } } + // Paginate results + startIndex := page * m.PageSize + endIndex := startIndex + m.PageSize + if endIndex > len(stockList) { + endIndex = len(stockList) + } + + // Slice the users based on pagination + pagedList := stockList[startIndex:endIndex] + //跟之前保持一致 - resp.Total = int(count) + resp.Total = len(stockList) resp.PageIndex = page + 1 resp.PageSize = m.PageSize - resp.List = stockList + resp.List = pagedList return resp, nil } @@ -1462,6 +1499,7 @@ func (m *ErpStockListReq) stockNoEmptyList() (*ErpStockListResp, error) { ***/ qs := orm.Eloquent.Debug().Table("erp_commodity") + es := orm.Eloquent.Debug().Table("erp_commodity") if m.StoreId == 0 { // 没指定门店,连表查询并计算总数量 qs = qs.Select("erp_commodity.*, COALESCE(SUM(erp_stock.count), 0) AS total_count, erp_stock.id AS erp_stock_id"). Joins("LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id AND erp_stock.count != 0"). @@ -1471,6 +1509,14 @@ func (m *ErpStockListReq) stockNoEmptyList() (*ErpStockListResp, error) { "ELSE CAST(SUBSTRING((SELECT number FROM erp_category WHERE id = (SELECT pid FROM erp_category WHERE id = erp_commodity.erp_category_id)), 1, 3) AS SIGNED) " + "END, CAST((SELECT pid FROM erp_category WHERE id = erp_commodity.erp_category_id) AS SIGNED), " + "CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)") + es = es.Select("erp_commodity.*, COALESCE(SUM(erp_stock.count), 0) AS total_count, erp_stock.id AS erp_stock_id"). + Joins("LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id AND erp_stock.count != 0"). + Group("erp_commodity.id"). + Order("CASE WHEN erp_commodity.erp_category_id IN (SELECT id FROM erp_category WHERE pid = 0) " + + "THEN CAST((SELECT number FROM erp_category WHERE id = erp_commodity.erp_category_id) AS SIGNED) " + + "ELSE CAST(SUBSTRING((SELECT number FROM erp_category WHERE id = (SELECT pid FROM erp_category WHERE id = erp_commodity.erp_category_id)), 1, 3) AS SIGNED) " + + "END, CAST((SELECT pid FROM erp_category WHERE id = erp_commodity.erp_category_id) AS SIGNED), " + + "CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)") } else { // 指定了门店,连表查询指定store_id的count qs = qs.Select("erp_commodity.*, COALESCE(SUM(erp_stock.count), 0) AS total_count, erp_stock.id AS erp_stock_id"). Joins("LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id "+ @@ -1481,16 +1527,28 @@ func (m *ErpStockListReq) stockNoEmptyList() (*ErpStockListResp, error) { "CAST(erp_category.pid AS SIGNED), " + "CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)"). Joins("JOIN erp_category ON erp_commodity.erp_category_id = erp_category.id") + es = es.Select("erp_commodity.*, COALESCE(SUM(erp_stock.count), 0) AS total_count, erp_stock.id AS erp_stock_id"). + Joins("LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id "+ + "AND erp_stock.count != 0 AND erp_stock.store_id = ?", m.StoreId). + Group("erp_commodity.id"). + Order("CASE WHEN erp_category.pid = 0 THEN CAST(erp_category.number AS SIGNED) " + + "ELSE CAST(SUBSTRING(erp_category.number, 1, 3) AS SIGNED) END, " + + "CAST(erp_category.pid AS SIGNED), " + + "CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)"). + Joins("JOIN erp_category ON erp_commodity.erp_category_id = erp_category.id") } if m.SerialNumber != "" { qs = qs.Where("erp_commodity.serial_number=?", m.SerialNumber) + es = es.Where("erp_commodity.serial_number=?", m.SerialNumber) } if m.CommodityName != "" { qs = qs.Where("erp_commodity.name Like '%" + m.CommodityName + "%'") + es = es.Where("erp_commodity.name Like '%" + m.CommodityName + "%'") } if m.ErpCategoryId != 0 { qs = qs.Where("erp_commodity.erp_category_id=?", m.ErpCategoryId) + es = es.Where("erp_commodity.erp_category_id=?", m.ErpCategoryId) } var commodities []struct { @@ -1499,16 +1557,17 @@ func (m *ErpStockListReq) stockNoEmptyList() (*ErpStockListResp, error) { ErpStockId int } - err := qs.Offset(page * m.PageSize).Limit(m.PageSize).Find(&commodities).Error - if err != nil && err != RecordNotFound { - logger.Error("commodityList err", logger.Field("err", err)) + var count int64 + err := es.Count(&count).Error + if err != nil { + logger.Error("commodityList count err", logger.Field("err", err)) return resp, err } - var count int64 - err = qs.Count(&count).Error - if err != nil { - logger.Error("commodityList count err", logger.Field("err", err)) + //err = qs.Offset(page * m.PageSize).Limit(m.PageSize).Find(&commodities).Error + err = qs.Find(&commodities).Error + if err != nil && err != RecordNotFound { + logger.Error("commodityList err", logger.Field("err", err)) return resp, err } @@ -1531,14 +1590,23 @@ func (m *ErpStockListReq) stockNoEmptyList() (*ErpStockListResp, error) { stockList = append(stockList, stock) } - } + // Paginate results + startIndex := page * m.PageSize + endIndex := startIndex + m.PageSize + if endIndex > len(stockList) { + endIndex = len(stockList) + } + + // Slice the users based on pagination + pagedList := stockList[startIndex:endIndex] + //跟之前保持一致 resp.Total = len(stockList) resp.PageIndex = page + 1 resp.PageSize = m.PageSize - resp.List = stockList + resp.List = pagedList return resp, nil } @@ -1580,15 +1648,19 @@ func (m *ErpStockListReq) allCommodityList() (*ErpStockListResp, error) { ***/ qs := orm.Eloquent.Debug().Table("erp_commodity") + es := orm.Eloquent.Debug().Table("erp_commodity") if m.SerialNumber != "" { qs = qs.Where("erp_commodity.serial_number=?", m.SerialNumber) + es = es.Where("erp_commodity.serial_number=?", m.SerialNumber) } if m.CommodityName != "" { qs = qs.Where("erp_commodity.name Like '%" + m.CommodityName + "%'") + es = es.Where("erp_commodity.name Like '%" + m.CommodityName + "%'") } if m.ErpCategoryId != 0 { qs = qs.Where("erp_commodity.erp_category_id=?", m.ErpCategoryId) + es = es.Where("erp_commodity.erp_category_id=?", m.ErpCategoryId) } if m.StoreId == 0 { // 没指定门店,连表查询并计算总数量 @@ -1600,6 +1672,14 @@ func (m *ErpStockListReq) allCommodityList() (*ErpStockListResp, error) { "ELSE CAST(SUBSTRING((SELECT number FROM erp_category WHERE id = (SELECT pid FROM erp_category WHERE id = erp_commodity.erp_category_id)), 1, 3) AS SIGNED) " + "END, CAST((SELECT pid FROM erp_category WHERE id = erp_commodity.erp_category_id) AS SIGNED), " + "CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)") + es = es.Select("erp_commodity.*, COALESCE(SUM(erp_stock.count), 0) AS total_count, erp_stock.id AS erp_stock_id"). + Joins("LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id"). + Group("erp_commodity.id"). + Order("CASE WHEN erp_commodity.erp_category_id IN (SELECT id FROM erp_category WHERE pid = 0) " + + "THEN CAST((SELECT number FROM erp_category WHERE id = erp_commodity.erp_category_id) AS SIGNED) " + + "ELSE CAST(SUBSTRING((SELECT number FROM erp_category WHERE id = (SELECT pid FROM erp_category WHERE id = erp_commodity.erp_category_id)), 1, 3) AS SIGNED) " + + "END, CAST((SELECT pid FROM erp_category WHERE id = erp_commodity.erp_category_id) AS SIGNED), " + + "CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)") } else { // 指定了门店,连表查询指定store_id的count qs = qs.Select("erp_commodity.*, COALESCE(SUM(erp_stock.count), 0) AS total_count, erp_stock.id AS erp_stock_id"). Joins("LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id "+ @@ -1610,6 +1690,15 @@ func (m *ErpStockListReq) allCommodityList() (*ErpStockListResp, error) { "CAST(erp_category.pid AS SIGNED), " + "CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)"). Joins("JOIN erp_category ON erp_commodity.erp_category_id = erp_category.id") + es = es.Select("erp_commodity.*, COALESCE(SUM(erp_stock.count), 0) AS total_count, erp_stock.id AS erp_stock_id"). + Joins("LEFT JOIN erp_stock ON erp_commodity.id = erp_stock.erp_commodity_id "+ + "AND erp_stock.store_id = ?", m.StoreId). + Group("erp_commodity.id"). + Order("CASE WHEN erp_category.pid = 0 THEN CAST(erp_category.number AS SIGNED) " + + "ELSE CAST(SUBSTRING(erp_category.number, 1, 3) AS SIGNED) END, " + + "CAST(erp_category.pid AS SIGNED), " + + "CAST(SUBSTRING(erp_commodity.serial_number, -4) AS SIGNED)"). + Joins("JOIN erp_category ON erp_commodity.erp_category_id = erp_category.id") } var commodities []struct { @@ -1618,16 +1707,16 @@ func (m *ErpStockListReq) allCommodityList() (*ErpStockListResp, error) { ErpStockId int } - err := qs.Offset(page * m.PageSize).Limit(m.PageSize).Find(&commodities).Error - if err != nil && err != RecordNotFound { - logger.Error("commodityList err", logger.Field("err", err)) + var count int64 + err := es.Count(&count).Error + if err != nil { + logger.Error("commodityList count err", logger.Field("err", err)) return resp, err } - var count int64 - err = qs.Count(&count).Error - if err != nil { - logger.Error("commodityList count err", logger.Field("err", err)) + err = qs.Offset(page * m.PageSize).Limit(m.PageSize).Find(&commodities).Error + if err != nil && err != RecordNotFound { + logger.Error("commodityList err", logger.Field("err", err)) return resp, err } diff --git a/app/admin/models/erp_order.go b/app/admin/models/erp_order.go index fae9a94..c810f1d 100644 --- a/app/admin/models/erp_order.go +++ b/app/admin/models/erp_order.go @@ -67,7 +67,7 @@ type ErpOrder struct { State string `json:"state" gorm:"index"` // 订单状态:un_audit 待审核; audited 已审核 TotalRetailPrice float64 `json:"total_retail_price"` // 订单总指导零售价 TotalAmount float64 `json:"total_amount"` // 订单实收金额 - TotalCount uint32 `json:"total_count"` // 订单商品数量 + TotalCount int32 `json:"total_count"` // 订单商品数量 TotalSalesProfit float64 `json:"total_sales_profit"` // 订单总销售毛利 TotalStaffProfit float64 `json:"total_staff_profit"` // 订单总员工毛利 VmCount uint32 `json:"vm_count"` // 使用会员积分 @@ -100,9 +100,9 @@ type ErpOrderCommodity struct { IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码 IMEI string `json:"imei" gorm:"index"` // 串码 PresentType uint32 `json:"present_type"` // 赠送类型:1-非赠送 2-赠送 - RetailPrice uint32 `json:"retail_price"` // 指导零售价 - SalePrice uint32 `json:"sale_price"` // 零售价 - Count uint32 `json:"count"` // 销售数量 + RetailPrice int32 `json:"retail_price"` // 指导零售价 + SalePrice int32 `json:"sale_price"` // 零售价 + Count int32 `json:"count"` // 销售数量 SaleDiscount float64 `json:"sale_discount"` // 零售优惠 MemberDiscount float64 `json:"member_discount"` // 会员优惠 VmDiscount float64 `json:"vm_discount"` // 会员积分抵扣 @@ -114,8 +114,8 @@ type ErpOrderCommodity struct { RejectedCount uint32 `json:"rejected_count"` // 退货数量 RejectedAmount float64 `json:"rejected_amount"` // 退货金额 RejectedOrderCommodityId uint32 `json:"rejected_order_commodity_id"` // 退货订单商品id - StaffCostPrice uint32 `json:"staff_cost_price"` // 员工成本价加价(如:加价50,不是加价后的价格) - WholesalePrice uint32 `json:"wholesale_price"` // 指导采购价 + StaffCostPrice int32 `json:"staff_cost_price"` // 员工成本价加价(如:加价50,不是加价后的价格) + WholesalePrice int32 `json:"wholesale_price"` // 指导采购价 SalesProfit float64 `json:"sales_profit"` // 销售毛利:实际零售价-采购单价;如果为退货订单,则为实际退货价-采购单价 StaffProfit float64 `json:"staff_profit"` // 员工毛利:实际零售价-员工成本价;如果为退货订单,则为实际退货价-员工成本价 ErpStockCommodityID string `json:"erp_stock_commodity_id"` // 库存商品表主键id @@ -341,15 +341,15 @@ type ErpOrderRetailDetailResp struct { // RetailDetailTotalData 零售明细相关金额汇总 type RetailDetailTotalData struct { - Count uint32 `json:"count"` // 销售数量 - RetailPrice uint32 `json:"retail_price"` // 指导零售价 - SalePrice uint32 `json:"sale_price"` // 零售价 + Count int32 `json:"count"` // 销售数量 + RetailPrice int32 `json:"retail_price"` // 指导零售价 + SalePrice int32 `json:"sale_price"` // 零售价 SaleDiscount float64 `json:"sale_discount"` // 零售优惠 MemberDiscount float64 `json:"member_discount"` // 会员优惠 VmDiscount float64 `json:"vm_discount"` // 会员积分抵扣 Amount float64 `json:"amount"` // 实际零售价 - WholesalePrice uint32 `json:"wholesale_price"` // 采购单价 - StaffPrice uint32 `json:"staff_price"` // 员工成本价 + WholesalePrice int32 `json:"wholesale_price"` // 采购单价 + StaffPrice int32 `json:"staff_price"` // 员工成本价 SalesProfit float64 `json:"sales_profit"` // 销售毛利 StaffProfit float64 `json:"staff_profit"` // 员工毛利 TotalRetailPrice float64 `json:"total_retail_price"` // 订单总指导零售价 @@ -930,6 +930,17 @@ func NewErpBillSn() string { func ErpOrderRetailDetailSetCommodity(list []ErpOrder) { for i, _ := range list { list[i].SetRetailDetailCommodity() + list[i].StorePer = tools.RoundToTwoDecimalPlaces(list[i].StorePer) + if list[i].RetailType == RetailTypeRejected { // 退货订单,金额需要转换为负值 + list[i].TotalRetailPrice = -math.Abs(list[i].TotalRetailPrice) + list[i].TotalAmount = -math.Abs(list[i].TotalAmount) + list[i].TotalCount = -int32(math.Abs(float64(list[i].TotalCount))) + list[i].TotalSalesProfit = -math.Abs(list[i].TotalSalesProfit) + list[i].TotalStaffProfit = -math.Abs(list[i].TotalStaffProfit) + list[i].TotalDiscount = -math.Abs(list[i].TotalDiscount) + list[i].VmCount = -uint32(math.Abs(float64(list[i].VmCount))) + list[i].StorePer = -math.Abs(list[i].StorePer) + } } } @@ -942,6 +953,22 @@ func (m *ErpOrder) SetRetailDetailCommodity() { var respOrderCommodities []ErpOrderCommodity for _, item := range orderCommodities { + if m.RetailType == RetailTypeRejected { // 退货订单,金额需要转换为负值 + item.Count = -item.Count + item.RetailPrice = -item.RetailPrice + item.SalePrice = -item.SalePrice + item.Amount = -item.Amount + item.SaleDiscount = -item.SaleDiscount + item.MemberDiscount = -item.MemberDiscount + item.VmDiscount = -item.VmDiscount + item.ReceivedAmount = -item.ReceivedAmount + item.RejectedAmount = -item.RejectedAmount + item.SalesProfit = -item.SalesProfit + item.StaffProfit = -item.StaffProfit + item.StaffCostPrice = -item.StaffCostPrice + item.WholesalePrice = -item.WholesalePrice + } + if item.IMEIType == 2 || item.IMEIType == 3 || item.IMEI != "" { // 串码 respOrderCommodities = append(respOrderCommodities, item) } else { // 非串码 @@ -954,14 +981,19 @@ func (m *ErpOrder) SetRetailDetailCommodity() { for _, stockCommodityId := range idList { var orderCommodity ErpOrderCommodity orderCommodity = item - orderCommodity.Count = 1 - orderCommodity.SaleDiscount = item.SaleDiscount / float64(item.Count) - //orderCommodity.MemberDiscount = item.MemberDiscount / float64(item.Count) - orderCommodity.VmDiscount = item.VmDiscount / float64(item.Count) - orderCommodity.ReceivedAmount = item.ReceivedAmount / float64(item.Count) - orderCommodity.RejectedAmount = item.RejectedAmount / float64(item.Count) - orderCommodity.SalesProfit = item.SalesProfit / float64(item.Count) - orderCommodity.StaffProfit = item.StaffProfit / float64(item.Count) + if m.RetailType == RetailTypeRejected { // 退货订单,数量需要转换为负值 + orderCommodity.Count = -1 + } else { + orderCommodity.Count = 1 + } + + nCount := math.Abs(float64(item.Count)) + orderCommodity.SaleDiscount = item.SaleDiscount / nCount + orderCommodity.VmDiscount = item.VmDiscount / nCount + orderCommodity.ReceivedAmount = item.ReceivedAmount / nCount + orderCommodity.RejectedAmount = item.RejectedAmount / nCount + orderCommodity.SalesProfit = item.SalesProfit / nCount + orderCommodity.StaffProfit = item.StaffProfit / nCount // 查询库存商品信息 var stockCommodity ErpStockCommodity @@ -974,8 +1006,8 @@ func (m *ErpOrder) SetRetailDetailCommodity() { orderCommodity.ErpSupplierId = stockCommodity.ErpSupplierId orderCommodity.ErpSupplierName = stockCommodity.ErpSupplierName - orderCommodity.WholesalePrice = stockCommodity.WholesalePrice - orderCommodity.StaffCostPrice = stockCommodity.StaffCostPrice + orderCommodity.WholesalePrice = int32(stockCommodity.WholesalePrice) + orderCommodity.StaffCostPrice = int32(stockCommodity.StaffCostPrice) respOrderCommodities = append(respOrderCommodities, orderCommodity) } } @@ -1041,6 +1073,12 @@ func (m *ErpOrder) SetOrderSalesman() error { item.Name = userInfo.NickName item.SalesmanPer = staffProfit * userInfo.SalesCommRate / float64(len(salesmanInfo)) + if m.RetailType == RetailTypeRejected { + item.SalesProfitPer = -item.SalesProfitPer + item.StaffProfitPer = -item.StaffProfitPer + item.SalesmanPer = -item.SalesmanPer + } + salesmanList = append(salesmanList, item) } @@ -1122,6 +1160,11 @@ func (m *ErpOrder) SetErpCashier() { if err != nil { logger.Error("unmarshal err:", logger.Field("err", err)) } + if m.RetailType == RetailTypeRejected { + for i, _ := range cashiers { + cashiers[i].Amount = -cashiers[i].Amount + } + } m.Cashiers = cashiers m.CashierList = "" } @@ -1995,7 +2038,7 @@ func QueryRetailMargin(req *ErpOrderRetailMarginReq) (*ErpOrderRetailMarginResp, // 如果存在,说明已经有数据,进行合并操作 existingData.Count += nCount existingData.SalesAmount += item.ReceivedAmount - existingData.SalesCost += float64(item.WholesalePrice * item.Count) + existingData.SalesCost += float64(int32(item.WholesalePrice) * item.Count) existingData.SalesMargin = existingData.SalesAmount - existingData.SalesCost existingData.GrossMargins = float64ToPercentage(existingData.SalesMargin / existingData.SalesAmount) @@ -2017,9 +2060,9 @@ func QueryRetailMargin(req *ErpOrderRetailMarginReq) (*ErpOrderRetailMarginResp, ErpCategoryName: item.ErpCategoryName, Count: nCount, SalesAmount: item.ReceivedAmount, - SalesCost: float64(item.WholesalePrice * item.Count), - SalesMargin: item.ReceivedAmount - float64(item.WholesalePrice*item.Count), - GrossMargins: float64ToPercentage((item.ReceivedAmount - float64(item.WholesalePrice*item.Count)) / item.ReceivedAmount), + SalesCost: float64(int32(item.WholesalePrice) * item.Count), + SalesMargin: item.ReceivedAmount - float64(int32(item.WholesalePrice)*item.Count), + GrossMargins: float64ToPercentage((item.ReceivedAmount - float64(int32(item.WholesalePrice)*item.Count)) / item.ReceivedAmount), } // 如果是拒绝的销售,进行相应的处理 @@ -2369,26 +2412,47 @@ func queryRetailDetailByJoin(req *ErpOrderRetailDetailReq) (*ErpOrderRetailDetai Select("erp_order_commodity.*, erp_order.*"). Joins("JOIN erp_order ON erp_order_commodity.erp_order_id = erp_order.id") + es := orm.Eloquent.Debug().Table("erp_order_commodity"). + Select("erp_order_commodity.*, erp_order.*"). + Joins("JOIN erp_order ON erp_order_commodity.erp_order_id = erp_order.id") + + orderSumQs := orm.Eloquent.Table("erp_order_commodity AS oc").Select("oc.*, eo.*"). + Joins("JOIN erp_order AS eo ON oc.erp_order_id = eo.id") + if req.ErpCategoryId != 0 { // 商品分类 qs = qs.Where("erp_order_commodity.erp_category_id=?", req.ErpCategoryId) + es = es.Where("erp_order_commodity.erp_category_id=?", req.ErpCategoryId) + orderSumQs = orderSumQs.Where("oc.erp_category_id=?", req.ErpCategoryId) } if req.ErpCommodityName != "" { // 商品名称 qs = qs.Where("erp_order_commodity.erp_commodity_name like ?", "%"+req.ErpCommodityName+"%") + es = es.Where("erp_order_commodity.erp_commodity_name like ?", "%"+req.ErpCommodityName+"%") + orderSumQs = orderSumQs.Where("oc.erp_commodity_name like ?", "%"+req.ErpCommodityName+"%") } if req.RetailType != "" { // 销售类型 qs = qs.Where("erp_order.retail_type=?", req.RetailType) + qs = qs.Where("erp_order.retail_type=?", req.RetailType) + orderSumQs = orderSumQs.Where("eo.retail_type=?", req.RetailType) } if req.Uid != 0 { // 用户ID qs = qs.Where("erp_order.uid=?", req.Uid) + es = es.Where("erp_order.uid=?", req.Uid) + orderSumQs = orderSumQs.Where("eo.uid=?", req.Uid) } if req.Tel != "" { // 用户手机号 qs = qs.Where("erp_order.tel=?", req.Tel) + qs = qs.Where("erp_order.tel=?", req.Tel) + orderSumQs = orderSumQs.Where("eo.tel=?", req.Tel) } if req.StoreId != 0 { // 门店ID qs = qs.Where("erp_order.store_id=?", req.StoreId) + es = es.Where("erp_order.store_id=?", req.StoreId) + orderSumQs = orderSumQs.Where("eo.store_id=?", req.StoreId) } if req.Salesman != 0 { // 销售员 qs = qs.Where("JSON_CONTAINS(erp_order.salesman_list, ?)", fmt.Sprintf(`{"uid":%d}`, req.Salesman)) + es = es.Where("JSON_CONTAINS(erp_order.salesman_list, ?)", fmt.Sprintf(`{"uid":%d}`, req.Salesman)) + orderSumQs = orderSumQs.Where("JSON_CONTAINS(eo.salesman_list, ?)", fmt.Sprintf(`{"uid":%d}`, req.Salesman)) } if req.StartTime != "" { // 审核开始时间 parse, err := time.Parse(QueryTimeFormat, req.StartTime) @@ -2396,6 +2460,8 @@ func queryRetailDetailByJoin(req *ErpOrderRetailDetailReq) (*ErpOrderRetailDetai logger.Errorf("err:", err) } qs = qs.Where("erp_order.audit_time > ?", parse) + es = es.Where("erp_order.audit_time > ?", parse) + orderSumQs = orderSumQs.Where("eo.audit_time > ?", parse) } if req.EndTime != "" { // 审核结束时间 parse, err := time.Parse(QueryTimeFormat, req.EndTime) @@ -2404,73 +2470,79 @@ func queryRetailDetailByJoin(req *ErpOrderRetailDetailReq) (*ErpOrderRetailDetai } //parse = parse.AddDate(0, 0, 1) qs = qs.Where("erp_order.audit_time < ?", parse) + es = es.Where("erp_order.audit_time < ?", parse) + orderSumQs = orderSumQs.Where("eo.audit_time < ?", parse) } if showConfig.ShowAll == "OFF" { - qs = qs.Where("is_print = ? or retail_type = ?", HavePrinted, RetailTypeRejected) + qs = qs.Where("erp_order.is_print = ? or erp_order.retail_type = ?", HavePrinted, RetailTypeRejected) + es = es.Where("erp_order.is_print = ? or erp_order.retail_type = ?", HavePrinted, RetailTypeRejected) + orderSumQs = orderSumQs.Where("eo.is_print = ? or eo.retail_type = ?", HavePrinted, RetailTypeRejected) } qs.Where("erp_order.pay_status = ? or (erp_order.retail_type = ? and erp_order.state != ?)", HavePaid, RetailTypeRejected, ErpOrderStateUnAudit) - es := qs + es.Where("erp_order.pay_status = ? or (erp_order.retail_type = ? and erp_order.state != ?)", + HavePaid, RetailTypeRejected, ErpOrderStateUnAudit) + orderSumQs.Where("eo.pay_status = ? or (eo.retail_type = ? and eo.state != ?)", + HavePaid, RetailTypeRejected, ErpOrderStateUnAudit) + // 销售订单的汇总数据 var sumData RetailDetailTotalData - orderSumQs := qs - totalPerQs := qs - cashierQs := qs - err = orderSumQs.Debug().Select("SUM(erp_order_commodity.count) as count, " + - "SUM(erp_order_commodity.retail_price) as retail_price, " + - "SUM(erp_order_commodity.sale_price) as sale_price, " + - "SUM(erp_order_commodity.sale_discount) as sale_discount, " + - "SUM(erp_order_commodity.member_discount) as member_discount, " + - "SUM(erp_order_commodity.Amount) as Amount, " + - "SUM(erp_order_commodity.wholesale_price) as wholesale_price, " + - "(SUM(erp_order_commodity.wholesale_price) + SUM(erp_order_commodity.staff_cost_price)) as staff_price, " + - "SUM(erp_order_commodity.sales_profit) as sales_profit, " + - "SUM(erp_order_commodity.staff_profit) as staff_profit, " + - "SUM(erp_order.total_retail_price) as total_retail_price, " + - "(SUM(erp_order.total_retail_price) - SUM(erp_order.total_amount)) as total_discount, " + - "SUM(erp_order.total_amount) as total_amount, " + - "SUM(erp_order.total_sales_profit) as total_sales_profit, " + - "SUM(erp_order.total_staff_profit) as total_staff_profit, " + - "SUM(erp_order.store_per) as store_per"). - Scan(&sumData).Error + sumData, err = getRetailDetailTotalDataJoinErpOrder(orderSumQs, RetailTypeSale) if err != nil { logger.Error("query sum data err:", logger.Field("err", err)) return resp, err } + // 退货订单的汇总数据 + var rejectedSumData RetailDetailTotalData + rejectedOrderSumQs := orderSumQs + rejectedSumData, err = getRetailDetailTotalDataJoinErpOrder(rejectedOrderSumQs, RetailTypeRejected) + if err != nil { + logger.Error("query sum data err:", logger.Field("err", err)) + return resp, err + } + // 计算销售订单和退货订单汇总后的销售数据 + sumData = subtractRetailData(sumData, rejectedSumData) + // 销售订单提成汇总 var totalPerData TotalPerData - err = totalPerQs.Debug().Select("SUM(erp_order_sales.sales_profit_per) as total_sales_profit_per, " + - "SUM(erp_order_sales.staff_profit_per) as total_staff_profit_per, " + - "SUM(erp_order_sales.salesman_per) as salesman_per"). - Joins("JOIN erp_order_sales ON erp_order_sales.erp_order_id = erp_order.id"). - Scan(&totalPerData).Error + totalPerQs := qs + totalPerData, err = getTotalPerData(totalPerQs, RetailTypeSale) if err != nil { logger.Error("query erp_order_sales sum data err:", logger.Field("err", err)) return resp, err } + // 退货订单提成汇总 + var rejectedTotalPerData TotalPerData + rejectedTotalPerQs := qs + rejectedTotalPerData, err = getTotalPerData(rejectedTotalPerQs, RetailTypeRejected) + if err != nil { + logger.Error("query erp_order_sales sum data err:", logger.Field("err", err)) + return resp, err + } + // 计算销售订单和退货订单汇总后的提成数据 + totalPerData = subtractTotalPerData(totalPerData, rejectedTotalPerData) + // 销售订单支持汇总 var cashier TotalCashierData - err = cashierQs.Debug().Select( - "SUM(CASE WHEN erp_order_pay_way.cashier_id = 1 THEN erp_order_pay_way.amount ELSE 0 END) AS scan_amount," + - "SUM(CASE WHEN erp_order_pay_way.cashier_id = 2 THEN erp_order_pay_way.amount ELSE 0 END) AS cash_amount," + - "SUM(CASE WHEN erp_order_pay_way.cashier_id = 3 THEN erp_order_pay_way.amount ELSE 0 END) AS pos_amount," + - "SUM(CASE WHEN erp_order_pay_way.cashier_id = 4 THEN erp_order_pay_way.amount ELSE 0 END) AS store_vm_amount," + - "SUM(CASE WHEN erp_order_pay_way.cashier_id not in (1,2,3,4) THEN erp_order_pay_way.amount ELSE 0 END) AS other_amount"). - Joins("JOIN erp_order_pay_way ON erp_order_pay_way.erp_order_id = erp_order.id"). - Scan(&cashier).Error + cashierQs := qs + cashier, err = getTotalCashierData(cashierQs, RetailTypeSale) if err != nil { logger.Error("query erp_order_pay_way sum data err:", logger.Field("err", err)) return resp, err } + // 退货订单支付汇总 + 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 + } + // 计算销售订单和退货订单汇总后的支付数据 + cashier = subtractCashierData(cashier, rejectedCashier) - //sumData.TotalSalesProfitPer = totalPerData.TotalSalesProfitPer - //sumData.TotalStaffProfitPer = totalPerData.TotalStaffProfitPer - //sumData.SalesmanPer = totalPerData.SalesmanPer - //sumData.ScanAmount = cashier.ScanAmount - //sumData.CashAmount = cashier.CashAmount - //sumData.PosAmount = cashier.PosAmount - //sumData.StoreVmAmount = cashier.StoreVmAmount - //sumData.OtherAmount = cashier.OtherAmount + // 处理汇总数据,四舍五入保留2位小数 + roundValues(&sumData, &totalPerData, &cashier) sumData.TotalSalesProfit = 0 // 订单总销售毛利 sumData.TotalStaffProfit = 0 // 订单总员工毛利 @@ -2503,7 +2575,8 @@ func queryRetailDetailByJoin(req *ErpOrderRetailDetailReq) (*ErpOrderRetailDetai } resp.ExportUrl = fileUrl } else { - err = qs.Order("erp_order.audit_time DESC").Offset(page * req.PageSize).Limit(req.PageSize).Find(&result).Error + //err = qs.Order("erp_order.audit_time DESC").Offset(page * req.PageSize).Limit(req.PageSize).Find(&result).Error + err = qs.Order("erp_order.audit_time DESC").Find(&result).Error if err != nil && err != RecordNotFound { logger.Error("erp commodity list err:", logger.Field("err", err)) return resp, err @@ -2517,13 +2590,14 @@ func queryRetailDetailByJoin(req *ErpOrderRetailDetailReq) (*ErpOrderRetailDetai } orders := packData(result) + pagedOrders := paginate(orders, page, req.PageSize) //erpOrderListSetCashier(orders) //erpOrderListSetSalesman(orders) - resp.List = orders + resp.List = pagedOrders //跟之前保持一致 - resp.Total = int(count) + resp.Total = len(orders) resp.PageIndex = page + 1 resp.PageSize = req.PageSize resp.SumData = sumData @@ -2532,6 +2606,22 @@ func queryRetailDetailByJoin(req *ErpOrderRetailDetailReq) (*ErpOrderRetailDetai return resp, nil } +// 分页函数 +func paginate(orders []ErpOrder, page int, pageSize int) []ErpOrder { + start := page * pageSize + end := start + pageSize + + if start >= len(orders) { + return []ErpOrder{} + } + + if end > len(orders) { + end = len(orders) + } + + return orders[start:end] +} + // 组合数据 func packData(result []RetailDetailByJoin) []ErpOrder { var orders []ErpOrder @@ -2683,66 +2773,68 @@ func queryRetailDetailCommon(req *ErpOrderRetailDetailReq) (*ErpOrderRetailDetai HavePaid, RetailTypeRejected, ErpOrderStateUnAudit) es := qs - var sumData RetailDetailTotalData + // 销售订单的汇总数据 orderSumQs := qs - totalPerQs := qs - cashierQs := qs - err = orderSumQs.Debug().Select("SUM(erp_order_commodity.count) as count, " + - "SUM(erp_order_commodity.retail_price) as retail_price, " + - "SUM(erp_order_commodity.sale_price) as sale_price, " + - "SUM(erp_order_commodity.sale_discount) as sale_discount, " + - "SUM(erp_order_commodity.member_discount) as member_discount, " + - "SUM(erp_order_commodity.Amount) as Amount, " + - "SUM(erp_order_commodity.wholesale_price) as wholesale_price, " + - "(SUM(erp_order_commodity.wholesale_price) + SUM(erp_order_commodity.staff_cost_price)) as staff_price, " + - "(SUM(erp_order_commodity.Amount) - SUM(erp_order_commodity.wholesale_price)) as sales_profit, " + - "(SUM(erp_order_commodity.Amount) - SUM(erp_order_commodity.wholesale_price) - SUM(erp_order_commodity.staff_cost_price)) as staff_profit, " + - "SUM(erp_order.total_retail_price) as total_retail_price, " + - "(SUM(erp_order.total_retail_price) - SUM(erp_order.total_amount)) as total_discount, " + - "SUM(erp_order.total_amount) as total_amount, " + - "SUM(erp_order.total_sales_profit) as total_sales_profit, " + - "SUM(erp_order.total_staff_profit) as total_staff_profit, " + - "SUM(erp_order.store_per) as store_per"). - Joins("JOIN erp_order_commodity ON erp_order_commodity.erp_order_id = erp_order.id"). - Scan(&sumData).Error + var sumData RetailDetailTotalData + sumData, err = getRetailDetailTotalData(orderSumQs, RetailTypeSale) if err != nil { logger.Error("query sum data err:", logger.Field("err", err)) return resp, err } + // 退货订单的汇总数据 + var rejectedSumData RetailDetailTotalData + rejectedOrderSumQs := qs + rejectedSumData, err = getRetailDetailTotalData(rejectedOrderSumQs, RetailTypeRejected) + if err != nil { + logger.Error("query sum data err:", logger.Field("err", err)) + return resp, err + } + // 计算销售订单和退货订单汇总后的销售数据 + sumData = subtractRetailData(sumData, rejectedSumData) + // 销售订单提成汇总 var totalPerData TotalPerData - err = totalPerQs.Debug().Select("SUM(erp_order_sales.sales_profit_per) as total_sales_profit_per, " + - "SUM(erp_order_sales.staff_profit_per) as total_staff_profit_per, " + - "SUM(erp_order_sales.salesman_per) as salesman_per"). - Joins("JOIN erp_order_sales ON erp_order_sales.erp_order_id = erp_order.id"). - Scan(&totalPerData).Error + totalPerQs := qs + totalPerData, err = getTotalPerData(totalPerQs, RetailTypeSale) if err != nil { logger.Error("query erp_order_sales sum data err:", logger.Field("err", err)) return resp, err } + // 退货订单提成汇总 + var rejectedTotalPerData TotalPerData + rejectedTotalPerQs := qs + rejectedTotalPerData, err = getTotalPerData(rejectedTotalPerQs, RetailTypeRejected) + if err != nil { + logger.Error("query erp_order_sales sum data err:", logger.Field("err", err)) + return resp, err + } + // 计算销售订单和退货订单汇总后的提成数据 + totalPerData = subtractTotalPerData(totalPerData, rejectedTotalPerData) + // 销售订单支持汇总 var cashier TotalCashierData - err = cashierQs.Debug().Select( - "SUM(CASE WHEN erp_order_pay_way.cashier_id = 1 THEN erp_order_pay_way.amount ELSE 0 END) AS scan_amount," + - "SUM(CASE WHEN erp_order_pay_way.cashier_id = 2 THEN erp_order_pay_way.amount ELSE 0 END) AS cash_amount," + - "SUM(CASE WHEN erp_order_pay_way.cashier_id = 3 THEN erp_order_pay_way.amount ELSE 0 END) AS pos_amount," + - "SUM(CASE WHEN erp_order_pay_way.cashier_id = 4 THEN erp_order_pay_way.amount ELSE 0 END) AS store_vm_amount," + - "SUM(CASE WHEN erp_order_pay_way.cashier_id not in (1,2,3,4) THEN erp_order_pay_way.amount ELSE 0 END) AS other_amount"). - Joins("JOIN erp_order_pay_way ON erp_order_pay_way.erp_order_id = erp_order.id"). - Scan(&cashier).Error + cashierQs := qs + cashier, err = getTotalCashierData(cashierQs, RetailTypeSale) if err != nil { logger.Error("query erp_order_pay_way sum data err:", logger.Field("err", err)) return resp, err } + // 退货订单支付汇总 + 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 + } + // 计算销售订单和退货订单汇总后的支付数据 + cashier = subtractCashierData(cashier, rejectedCashier) + // 处理汇总数据,四舍五入保留2位小数 + roundValues(&sumData, &totalPerData, &cashier) sumData.TotalSalesProfitPer = totalPerData.TotalSalesProfitPer sumData.TotalStaffProfitPer = totalPerData.TotalStaffProfitPer sumData.SalesmanPer = totalPerData.SalesmanPer - sumData.ScanAmount = cashier.ScanAmount - sumData.CashAmount = cashier.CashAmount - sumData.PosAmount = cashier.PosAmount - sumData.StoreVmAmount = cashier.StoreVmAmount - sumData.OtherAmount = cashier.OtherAmount if req.IsExport == 1 { // 导出excel var orders []ErpOrder @@ -2792,6 +2884,154 @@ func queryRetailDetailCommon(req *ErpOrderRetailDetailReq) (*ErpOrderRetailDetai return resp, nil } +// 四舍五入保留2位小数 +func roundValues(data *RetailDetailTotalData, totalPerData *TotalPerData, cashier *TotalCashierData) { + roundMap := map[*float64]*float64{ + &data.StorePer: &data.StorePer, + &totalPerData.TotalSalesProfitPer: &totalPerData.TotalSalesProfitPer, + &totalPerData.TotalStaffProfitPer: &totalPerData.TotalStaffProfitPer, + &totalPerData.SalesmanPer: &totalPerData.SalesmanPer, + &cashier.ScanAmount: &cashier.ScanAmount, + &cashier.CashAmount: &cashier.CashAmount, + &cashier.PosAmount: &cashier.PosAmount, + &cashier.StoreVmAmount: &cashier.StoreVmAmount, + &cashier.OtherAmount: &cashier.OtherAmount, + } + + for original, rounded := range roundMap { + *rounded = tools.RoundToTwoDecimalPlaces(*original) + } +} + +// 查询零售订单的汇总数据 +func getRetailDetailTotalData(qs *gorm.DB, retailType string) (RetailDetailTotalData, error) { + var sumData RetailDetailTotalData + err := qs.Debug().Select("SUM(erp_order_commodity.count) as count, "+ + "SUM(erp_order_commodity.retail_price) as retail_price, "+ + "SUM(erp_order_commodity.sale_price) as sale_price, "+ + "SUM(erp_order_commodity.sale_discount) as sale_discount, "+ + "SUM(erp_order_commodity.member_discount) as member_discount, "+ + "SUM(erp_order_commodity.Amount) as Amount, "+ + "SUM(erp_order_commodity.wholesale_price) as wholesale_price, "+ + "(SUM(erp_order_commodity.wholesale_price) + SUM(erp_order_commodity.staff_cost_price)) as staff_price, "+ + "(SUM(erp_order_commodity.Amount) - SUM(erp_order_commodity.wholesale_price)) as sales_profit, "+ + "(SUM(erp_order_commodity.Amount) - SUM(erp_order_commodity.wholesale_price) - SUM(erp_order_commodity.staff_cost_price)) as staff_profit, "+ + "SUM(erp_order.total_retail_price) as total_retail_price, "+ + "(SUM(erp_order.total_retail_price) - SUM(erp_order.total_amount)) as total_discount, "+ + "SUM(erp_order.total_amount) as total_amount, "+ + "SUM(erp_order.total_sales_profit) as total_sales_profit, "+ + "SUM(erp_order.total_staff_profit) as total_staff_profit, "+ + "SUM(erp_order.store_per) as store_per"). + Joins("JOIN erp_order_commodity ON erp_order_commodity.erp_order_id = erp_order.id and erp_order.retail_type = ?", retailType). + Scan(&sumData).Error + if err != nil { + logger.Error("query sum data err:", logger.Field("err", err)) + return sumData, err + } + return sumData, nil +} + +// 查询零售订单的汇总数据 +func getRetailDetailTotalDataJoinErpOrder(qs *gorm.DB, retailType string) (RetailDetailTotalData, error) { + var sumData RetailDetailTotalData + qs = qs.Where("eo.retail_type = ?", retailType) // 添加额外的条件 + err := qs.Debug().Select("SUM(oc.count) as count, " + + "SUM(oc.retail_price) as retail_price, " + + "SUM(oc.sale_price) as sale_price, " + + "SUM(oc.sale_discount) as sale_discount, " + + "SUM(oc.member_discount) as member_discount, " + + "SUM(oc.Amount) as Amount, " + + "SUM(oc.wholesale_price) as wholesale_price, " + + "(SUM(oc.wholesale_price) + SUM(oc.staff_cost_price)) as staff_price, " + + "(SUM(oc.Amount) - SUM(oc.wholesale_price)) as sales_profit, " + + "(SUM(oc.Amount) - SUM(oc.wholesale_price) - SUM(oc.staff_cost_price)) as staff_profit"). + Scan(&sumData).Error + if err != nil { + logger.Error("query sum data err:", logger.Field("err", err)) + return sumData, err + } + return sumData, nil +} + +// 查询零售订单的提成汇总数据 +func getTotalPerData(qs *gorm.DB, retailType string) (TotalPerData, error) { + var totalPerData TotalPerData + err := qs.Debug().Select("SUM(erp_order_sales.sales_profit_per) as total_sales_profit_per, "+ + "SUM(erp_order_sales.staff_profit_per) as total_staff_profit_per, "+ + "SUM(erp_order_sales.salesman_per) as salesman_per"). + Joins("JOIN erp_order_sales ON erp_order_sales.erp_order_id = erp_order.id and erp_order.retail_type = ?", retailType). + Scan(&totalPerData).Error + if err != nil { + logger.Error("query erp_order_sales sum data err:", logger.Field("err", err)) + return totalPerData, err + } + return totalPerData, nil +} + +// 查询零售订单的支付汇总数据 +func getTotalCashierData(qs *gorm.DB, retailType string) (TotalCashierData, error) { + var cashier TotalCashierData + err := qs.Debug().Select( + "SUM(CASE WHEN erp_order_pay_way.cashier_id = 1 THEN erp_order_pay_way.amount ELSE 0 END) AS scan_amount,"+ + "SUM(CASE WHEN erp_order_pay_way.cashier_id = 2 THEN erp_order_pay_way.amount ELSE 0 END) AS cash_amount,"+ + "SUM(CASE WHEN erp_order_pay_way.cashier_id = 3 THEN erp_order_pay_way.amount ELSE 0 END) AS pos_amount,"+ + "SUM(CASE WHEN erp_order_pay_way.cashier_id = 4 THEN erp_order_pay_way.amount ELSE 0 END) AS store_vm_amount,"+ + "SUM(CASE WHEN erp_order_pay_way.cashier_id not in (1,2,3,4) THEN erp_order_pay_way.amount ELSE 0 END) AS other_amount"). + Joins("JOIN erp_order_pay_way ON erp_order_pay_way.erp_order_id = erp_order.id and erp_order.retail_type = ?", retailType). + Scan(&cashier).Error + if err != nil { + logger.Error("query erp_order_pay_way sum data err:", logger.Field("err", err)) + return cashier, err + } + return cashier, nil +} + +// 计算销售订单和退货订单汇总后的销售数据 +func subtractRetailData(sumData, rejectedSumData RetailDetailTotalData) RetailDetailTotalData { + result := RetailDetailTotalData{ + Count: sumData.Count - rejectedSumData.Count, + RetailPrice: sumData.RetailPrice - rejectedSumData.RetailPrice, + SalePrice: sumData.SalePrice - rejectedSumData.SalePrice, + SaleDiscount: sumData.SaleDiscount - rejectedSumData.SaleDiscount, + MemberDiscount: sumData.MemberDiscount - rejectedSumData.MemberDiscount, + VmDiscount: sumData.VmDiscount - rejectedSumData.VmDiscount, + Amount: sumData.Amount - rejectedSumData.Amount, + WholesalePrice: sumData.WholesalePrice - rejectedSumData.WholesalePrice, + StaffPrice: sumData.StaffPrice - rejectedSumData.StaffPrice, + SalesProfit: sumData.SalesProfit - rejectedSumData.SalesProfit, + StaffProfit: sumData.StaffProfit - rejectedSumData.StaffProfit, + TotalRetailPrice: sumData.TotalRetailPrice - rejectedSumData.TotalRetailPrice, + TotalDiscount: sumData.TotalDiscount - rejectedSumData.TotalDiscount, + TotalAmount: sumData.TotalAmount - rejectedSumData.TotalAmount, + TotalSalesProfit: sumData.TotalSalesProfit - rejectedSumData.TotalSalesProfit, + TotalStaffProfit: sumData.TotalStaffProfit - rejectedSumData.TotalStaffProfit, + StorePer: sumData.StorePer - rejectedSumData.StorePer, + } + return result +} + +// 计算销售订单和退货订单汇总后的提成数据 +func subtractTotalPerData(totalPerData, rejectedTotalPerData TotalPerData) TotalPerData { + result := TotalPerData{ + TotalSalesProfitPer: totalPerData.TotalSalesProfitPer - rejectedTotalPerData.TotalSalesProfitPer, + TotalStaffProfitPer: totalPerData.TotalStaffProfitPer - rejectedTotalPerData.TotalStaffProfitPer, + SalesmanPer: totalPerData.SalesmanPer - rejectedTotalPerData.SalesmanPer, + } + return result +} + +// 计算销售订单和退货订单汇总后的支付数据 +func subtractCashierData(cashier, rejectedCashier TotalCashierData) TotalCashierData { + result := TotalCashierData{ + ScanAmount: cashier.ScanAmount - rejectedCashier.ScanAmount, + CashAmount: cashier.CashAmount - rejectedCashier.CashAmount, + PosAmount: cashier.PosAmount - rejectedCashier.PosAmount, + StoreVmAmount: cashier.StoreVmAmount - rejectedCashier.StoreVmAmount, + OtherAmount: cashier.OtherAmount - rejectedCashier.OtherAmount, + } + return result +} + // QueryReceiptData 查询小票数据 func QueryReceiptData(req *ErpOrderDeleteReq) (*ErpOrderReceiptDataResp, error) { var orders []ErpOrder @@ -2847,9 +3087,9 @@ func QueryReceiptData(req *ErpOrderDeleteReq) (*ErpOrderReceiptDataResp, error) for i, item := range order.Commodities { var tableData TableData tableData.Name = item.ErpCommodityName - tableData.SL = item.Count - tableData.DJ = item.RetailPrice - tableData.JE = item.Count * item.RetailPrice + tableData.SL = uint32(item.Count) + tableData.DJ = uint32(item.RetailPrice) + tableData.JE = uint32(item.Count) * uint32(item.RetailPrice) key := fmt.Sprintf("commodity_%d", i) commodityMap[key] = tableData @@ -2861,7 +3101,7 @@ func QueryReceiptData(req *ErpOrderDeleteReq) (*ErpOrderReceiptDataResp, error) resp.ChandiseObj = commodityMap resp.TotalRetailP = order.TotalRetailPrice - resp.TotalNum = order.TotalCount + resp.TotalNum = uint32(order.TotalCount) resp.ToDealWith = order.TotalAmount cashierMap := make(map[string]ErpOrderCashier, 0) @@ -3181,7 +3421,7 @@ func checkOrderData(req *ErpOrderCreateReq, sysUser *SysUser) (*ErpOrder, error) logger.Error("rejected price gt retail price ") return nil, errors.New("退货单价大于实际零售价") } - if req.ErpOrderCommodities[i].RejectedCount > req.ErpOrderCommodities[i].Count { // 退货数量不能大于销售数量 + if int32(req.ErpOrderCommodities[i].RejectedCount) > req.ErpOrderCommodities[i].Count { // 退货数量不能大于销售数量 logger.Error("rejected count gt retail count ") return nil, errors.New("退货数量大于销售数量") } @@ -3190,16 +3430,16 @@ func checkOrderData(req *ErpOrderCreateReq, sysUser *SysUser) (*ErpOrder, error) //erpOrder.RejectedTotalAmount += req.ErpOrderCommodities[i].RejectedAmount //erpOrder.RejectedTotalCount += req.ErpOrderCommodities[i].RejectedCount erpOrder.TotalAmount += req.ErpOrderCommodities[i].ReceivedAmount - erpOrder.TotalCount += req.ErpOrderCommodities[i].Count + erpOrder.TotalCount += int32(req.ErpOrderCommodities[i].Count) // 销售毛利 // todo 待测试核实 备注:产品说有亏本销售的情况,不用判断毛利是否<0 - salesProfit := v.ReceivedAmount - float64(v.WholesalePrice*v.Count) + salesProfit := v.ReceivedAmount - float64(int32(v.WholesalePrice)*v.Count) //if salesProfit < 0 { // logger.Error("rejected salesProfit less than 0") // return nil, errors.New("商品销售毛利小于0,请检查") //} // 员工毛利 // todo 待测试核实 - StaffProfit := salesProfit - float64(v.StaffCostPrice*v.Count) + StaffProfit := salesProfit - float64(int32(v.StaffCostPrice)*v.Count) //if StaffProfit < 0 { // logger.Error("rejected TotalStaffProfit less than 0") // return nil, errors.New("商品员工毛利小于0,请检查") @@ -3231,39 +3471,39 @@ func checkOrderData(req *ErpOrderCreateReq, sysUser *SysUser) (*ErpOrder, error) } req.ErpOrderCommodities[i].ID = 0 - req.ErpOrderCommodities[i].ErpCommodityId = v.ErpCommodityId // 商品id - req.ErpOrderCommodities[i].ErpCommodityName = v.ErpCommodityName // 商品名称 - req.ErpOrderCommodities[i].ErpCategoryId = v.ErpCategoryId // 分类id - req.ErpOrderCommodities[i].ErpCategoryName = v.ErpCategoryName // 分类名称 - req.ErpOrderCommodities[i].ErpSupplierId = v.ErpSupplierId // 供应商id - req.ErpOrderCommodities[i].ErpSupplierName = v.ErpSupplierName // 供应商名称 - req.ErpOrderCommodities[i].RetailPrice = v.RetailPrice // 指导零售价 - req.ErpOrderCommodities[i].MemberDiscount = v.MemberDiscount // 会员优惠 - req.ErpOrderCommodities[i].StaffCostPrice = v.StaffCostPrice // 员工成本价加价 - req.ErpOrderCommodities[i].WholesalePrice = v.WholesalePrice // 指导采购价 + req.ErpOrderCommodities[i].ErpCommodityId = v.ErpCommodityId // 商品id + req.ErpOrderCommodities[i].ErpCommodityName = v.ErpCommodityName // 商品名称 + req.ErpOrderCommodities[i].ErpCategoryId = v.ErpCategoryId // 分类id + req.ErpOrderCommodities[i].ErpCategoryName = v.ErpCategoryName // 分类名称 + req.ErpOrderCommodities[i].ErpSupplierId = v.ErpSupplierId // 供应商id + req.ErpOrderCommodities[i].ErpSupplierName = v.ErpSupplierName // 供应商名称 + req.ErpOrderCommodities[i].RetailPrice = int32(v.RetailPrice) // 指导零售价 + req.ErpOrderCommodities[i].MemberDiscount = v.MemberDiscount // 会员优惠 + req.ErpOrderCommodities[i].StaffCostPrice = int32(v.StaffCostPrice) // 员工成本价加价 + req.ErpOrderCommodities[i].WholesalePrice = int32(v.WholesalePrice) // 指导采购价 if req.ErpOrderCommodities[i].PresentType == 2 && v.MinRetailPrice != 0 { // 赠送类型商品进行校验,最低零售价为0才能赠送 logger.Error("PresentType is 2, MinRetailPrice no equal 0") return nil, errors.New("赠送商品最低零售价不为0,不符合赠送条件,请检查") } - if req.ErpOrderCommodities[i].SalePrice < v.MinRetailPrice { //零售价不能低于最低零售价 + if req.ErpOrderCommodities[i].SalePrice < int32(v.MinRetailPrice) { //零售价不能低于最低零售价 logger.Error("SalePrice less than MinRetailPrice") return nil, errors.New("零售价不能低于最低零售价,请检查") } // 更新订单表总金额和数量 erpOrder.TotalAmount += req.ErpOrderCommodities[i].ReceivedAmount - erpOrder.TotalCount += req.ErpOrderCommodities[i].Count + erpOrder.TotalCount += int32(req.ErpOrderCommodities[i].Count) // 销售毛利 备注:产品说有亏本销售的情况,不用判断毛利是否<0 salesProfit := req.ErpOrderCommodities[i].ReceivedAmount - - float64(req.ErpOrderCommodities[i].WholesalePrice*req.ErpOrderCommodities[i].Count) + float64(int32(req.ErpOrderCommodities[i].WholesalePrice)*req.ErpOrderCommodities[i].Count) //if salesProfit < 0 { // logger.Error("salesProfit less than 0") // return nil, errors.New("商品销售毛利小于0,请检查") //} // 员工毛利 - StaffProfit := salesProfit - float64(req.ErpOrderCommodities[i].StaffCostPrice*req.ErpOrderCommodities[i].Count) + StaffProfit := salesProfit - float64(int32(req.ErpOrderCommodities[i].StaffCostPrice)*req.ErpOrderCommodities[i].Count) //if StaffProfit < 0 { // logger.Error("TotalStaffProfit less than 0") // return nil, errors.New("商品员工毛利小于0,请检查") @@ -3306,9 +3546,9 @@ func checkOrderCommodityStock(req *ErpOrderCreateReq) error { if commodity.IMEIType == 1 { _, ok := commodityMap[commodity.ErpCommodityId] if !ok { // 没有则直接添加 - commodityMap[commodity.ErpCommodityId] = commodity.Count + commodityMap[commodity.ErpCommodityId] = uint32(commodity.Count) } else { - commodityMap[commodity.ErpCommodityId] += commodity.Count + commodityMap[commodity.ErpCommodityId] += uint32(commodity.Count) } commodityNameMap[commodity.ErpCommodityId] = commodity.ErpCommodityName } else { diff --git a/app/admin/models/file.go b/app/admin/models/file.go index 460b59d..ca53ad5 100644 --- a/app/admin/models/file.go +++ b/app/admin/models/file.go @@ -349,8 +349,8 @@ func hasDuplicateNames(sheetCols [][]string) (string, bool) { // 确保每一列数据都有相同数量的行数 rowsCount := len(sheetCols[0]) - for _, col := range sheetCols { - if len(col) != rowsCount { + for i, col := range sheetCols { + if len(col) != rowsCount && i != 2 { return "每列数据的行数不一致", true } } @@ -366,6 +366,9 @@ func hasDuplicateNames(sheetCols [][]string) (string, bool) { //} // 检查第二列 + if len(sheetCols[1]) < i+1 { + continue + } secondColName := sheetCols[1][i] if secondColName != "" { if firstCol, exists := secondColMap[secondColName]; exists && firstCol != sheetCols[0][i] { @@ -375,6 +378,9 @@ func hasDuplicateNames(sheetCols [][]string) (string, bool) { } // 检查第三列 + if len(sheetCols[2]) < i+1 { + continue + } thirdColName := sheetCols[2][i] if thirdColName != "" { if _, exists := thirdColMap[thirdColName]; exists { @@ -786,15 +792,24 @@ func ImportCategoryData(colsMap []map[string]interface{}, businessId uint32) err } // 插入或获取一级分类 - err := orm.Eloquent.Debug().FirstOrCreate(&firstCategory, - Category{ - Name: item.FirstCategory, - Pid: 0, - Display: 1, - CooperativeBusinessId: businessId, - }).Error + err := orm.Eloquent.Debug().Table("erp_category").Where("name = ? and pid = ? and display = ? "+ + "and cooperative_business_id = ?", item.FirstCategory, 0, 1, businessId). + First(&firstCategory).Error if err != nil { - return err + if errors.Is(err, gorm.ErrRecordNotFound) { + firstCategory.Name = item.FirstCategory + firstCategory.Pid = 0 + firstCategory.Display = 1 + firstCategory.CooperativeBusinessId = businessId + firstCategory.ID = 0 + // 如果没有符合条件的记录,则创建新记录 + err = orm.Eloquent.Debug().Create(&firstCategory).Error + if err != nil { + return err + } + } else { + return err + } } // 插入或获取二级分类 @@ -850,11 +865,20 @@ func hasDuplicateInDb(data []CategoryExcel) (string, bool) { if exists := isCategoryExists(item.FirstCategory); exists { return item.FirstCategory, true } - case 2: // 导入二级分类 + case 2: // 导入二级分类:查看二级分类名称是否重复;查询一级分类名称跟二/三级分类是否重复 + if exists := isFirstCategoryDuplicate(item.FirstCategory); exists { + return item.FirstCategory, true + } if exists := isCategoryExists(item.SecondCategory); exists { return item.SecondCategory, true } - case 3: // 导入三级分类 + case 3: // 导入三级分类:查看三级分类名称是否重复;查询一级分类名称跟二/三级分类是否重复,查询二级分类跟一,三级是否重复 + if exists := isFirstCategoryDuplicate(item.FirstCategory); exists { + return item.FirstCategory, true + } + if exists := isSecondCategoryDuplicate(item.SecondCategory); exists { + return item.SecondCategory, true + } if exists := isCategoryExists(item.ThreeCategory); exists { return item.ThreeCategory, true } @@ -864,6 +888,26 @@ func hasDuplicateInDb(data []CategoryExcel) (string, bool) { return "", false } +// 查询一级分类名称跟二/三级分类是否重复 +func isFirstCategoryDuplicate(categoryName string) bool { + var count int64 + orm.Eloquent.Debug().Model(&Category{}). + Where("name = ? and pid != ?", categoryName, 0). + Count(&count) + + return count > 0 +} + +// 查询二级分类跟一,三级是否重复 +func isSecondCategoryDuplicate(categoryName string) bool { + var count int64 + orm.Eloquent.Debug().Model(&Category{}). + Where("name = ? and len(number) != ?", categoryName, 6). + Count(&count) + + return count > 0 +} + // 判断分类是否存在 func isCategoryExists(categoryName string) bool { var count int64 diff --git a/app/admin/models/purchase.go b/app/admin/models/purchase.go index b5a1e53..78a3045 100644 --- a/app/admin/models/purchase.go +++ b/app/admin/models/purchase.go @@ -1582,7 +1582,11 @@ func CreateErpPurchaseDemand(req *CreateErpPurchaseDemandReq, sysUser *SysUser) continue } else { err = begin.Model(&ErpPurchaseDemand{}).Where("erp_commodity_id = ? and store_id = ? and state = 1", - v.ErpCommodityId, v.StoreId).Updates(v).Error + v.ErpCommodityId, v.StoreId).Updates(map[string]interface{}{ + "count": v.Count, + "state": v.State, + "maker_id": v.MakerId, + }).Error if err != nil { begin.Rollback() logger.Error("update erp_order err:", logger.Field("err", err)) @@ -1610,7 +1614,11 @@ func CreateErpPurchaseDemand(req *CreateErpPurchaseDemandReq, sysUser *SysUser) if demandRemarkInfo.ErpCommodityId != 0 { // 有记录 if demandRemarkInfo.Remark != req.Remark { // 备注有变化才更新 err := begin.Model(&ErpPurchaseDemandRemark{}).Where("erp_commodity_id = ? and state = 1", - req.ErpCommodityID).Updates(demandRemark).Error + req.ErpCommodityID).Updates(map[string]interface{}{ + "state": demandRemark.State, + "remark": demandRemark.Remark, + "maker_id": demandRemark.MakerId, + }).Error if err != nil { begin.Rollback() logger.Error("update erp_purchase_demand_remark err:", logger.Field("err", err)) @@ -2522,7 +2530,7 @@ func convertToDemandData(commodity ErpCommodity, stores []Store) (DemandData, er // demandData.Remark = demands[0].Remark //} - // 使用 WaitGroup 进行并行查询 + //使用 WaitGroup 进行并行查询 var wg sync.WaitGroup wg.Add(3) @@ -2548,7 +2556,7 @@ func convertToDemandData(commodity ErpCommodity, stores []Store) (DemandData, er wg.Wait() if err != nil { // Handle error - return DemandData{}, err + //return DemandData{}, err 备注:有时会提示没记录,不做处理 } var totalCount uint32 // 总需采购数量 diff --git a/config/settings.yml b/config/settings.yml index d04a4e5..d0b7a0a 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -43,6 +43,7 @@ settings: # source: root:myTest@921@tcp(127.0.0.1:3306)/mh_dev?charset=utf8&parseTime=True&loc=Local&timeout=1000ms source: mh_dev:d9qy46ONI0ZTF9eH@tcp(112.33.14.191:3306)/mh_dev?charset=utf8&parseTime=True&loc=Local&timeout=1000ms # source: mh_pro:c5JBW3X6EEVQluYM@tcp(39.108.188.218:3306)/mh_pro?charset=utf8&parseTime=True&loc=Local&timeout=1000ms +# source: mh_test:GPLzZ8rMmbJbKtMh@tcp(112.33.14.191:3306)/mh_test?charset=utf8&parseTime=True&loc=Local&timeout=1000ms gen: # 代码生成读取的数据库名称 diff --git a/tools/utils.go b/tools/utils.go index 71a13f9..56149f0 100644 --- a/tools/utils.go +++ b/tools/utils.go @@ -109,3 +109,8 @@ func ConvertTimeToStringByPoint(t *time.Time) string { } return t.Format("2006-01-02 15:04:05") } + +// RoundToTwoDecimalPlaces 将float64类型四舍五入保留2位小数 +func RoundToTwoDecimalPlaces(num float64) float64 { + return math.Round(num*100) / 100 +}