1.修复缺陷:

(1)商品列表排序规则调整;
(2)零售订单商品表中,RetailPrice、SalePrice改为float64类型;
(3)新建采购订单时采购或退货数量需大于0;
(4)采购单入库时每条记录都单独生成入库编号;
This commit is contained in:
chenlin 2024-05-10 09:54:37 +08:00
parent c17e078290
commit 6f91388f05
11 changed files with 720 additions and 397 deletions

View File

@ -94,7 +94,11 @@ func GetInventoryDetail(c *gin.Context) {
list, err := req.GetDetailList(c)
if err != nil {
//logger.Error("erp stock err:", err)
app.Error(c, http.StatusInternalServerError, err, "查询失败:"+err.Error())
if err.Error() == "该商品在调拨中" {
app.Error(c, http.StatusInternalServerError, err, err.Error())
} else {
app.Error(c, http.StatusInternalServerError, err, "查询失败:"+err.Error())
}
return
}

View File

@ -228,9 +228,9 @@ func ErpPurchaseDetail(c *gin.Context) {
return
}
if purchaseOrder.PurchaseType == model.ErpProcureOrder {
v.DefaultEmployeePrice = v.Price + float64(erpCommodity.StaffCostPrice)
v.DefaultEmployeePrice = v.Price + erpCommodity.StaffCostPrice
} else if purchaseOrder.PurchaseType == model.ErpProcureOrder {
v.DefaultEmployeePrice = v.RejectedPrice + float64(erpCommodity.StaffCostPrice)
v.DefaultEmployeePrice = v.RejectedPrice + erpCommodity.StaffCostPrice
}
// 查询执行数量之和、平均执行单价、执行金额之和和平均员工成本价
@ -249,8 +249,32 @@ func ErpPurchaseDetail(c *gin.Context) {
v.ExecutionEmployeePrice = math.Round(v.ExecutionEmployeePrice*100) / 100
v.ExecutionPrice = math.Round(v.ExecutionPrice*100) / 100
serialNumber := purchaseOrder.SerialNumber
if purchaseOrder.PurchaseType == model.ErpRejectOrder { // 采购退货订单
serialNumber = purchaseOrder.RejectedSerialNumber
// 查询原始采购订单的信息
var rejectOrder model.ErpPurchaseOrder
err := orm.Eloquent.Table("erp_purchase_order").Where("serial_number=?", serialNumber).Find(&rejectOrder).Error
if err != nil {
logger.Error("purchase order err:", logger.Field("err", err))
app.Error(c, http.StatusBadRequest, err, "获取失败")
return
}
// 查询执行数量之和、平均执行单价、执行金额之和和平均员工成本价
rejectResult, err := model.GetTotalsAndAveragesByCommodityID(v.ErpCommodityId, rejectOrder.ID)
if err != nil {
logger.Error("GetTotalsAndAveragesByCommodityID err:", logger.Field("err", err))
app.Error(c, http.StatusBadRequest, err, "获取失败")
return
}
v.ExecutionCount = rejectResult.TotalCount
v.ExecutionPrice = rejectResult.AvgImplementationPrice
v.ExecutionAmount = rejectResult.TotalAmount
}
// 查询入库商品实际库存详情处剩余有效数,不包含已出库的数量
nCount, err := model.GetCommodityStockByPurchaseId(purchaseOrder.SerialNumber, v.ErpCommodityId)
nCount, err := model.GetCommodityStockByPurchaseId(serialNumber, v.ErpCommodityId)
if err != nil {
logger.Error("ErpPurchaseDetail GetCommodityStockByPurchaseId err:", logger.Field("err", err))
app.Error(c, http.StatusBadRequest, err, "获取失败")

View File

@ -12,6 +12,7 @@ import (
"golang.org/x/sync/errgroup"
"gorm.io/gorm"
"math/rand"
"sort"
"strconv"
"strings"
"sync"
@ -343,55 +344,151 @@ func (m *ErpCommodityListReq) List() (*ErpCommodityListResp, error) {
//logger.Error("count err:", err)
return resp, err
}
//resp.Total = int(count)/m.PageSize + 1
var commodities []ErpCommodity
err = qs.Order("id DESC").Find(&commodities).Error
if err != nil && err != RecordNotFound {
//logger.Error("dailys err:", err)
return resp, err
}
// 按商品编号进行排序
SortCommodities(commodities)
if m.IsExport == 1 {
err = qs.Order("id DESC").Find(&commodities).Error
if err != nil && err != RecordNotFound {
//logger.Error("dailys err:", err)
return resp, err
}
listExport, err := ErpCommodityListExport(commodities)
if err != nil {
//logger.Error("list export err:", err)
}
resp.ExportUrl = listExport
} else {
err = qs.Order("id DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&commodities).Error
if err != nil && err != RecordNotFound {
//logger.Error("erp commodity list err:", err)
return resp, err
for i, v := range commodities {
if v.IMEIType == 1 { //无串码
commodities[i].IsIMEI = 2 // 非串码
} else {
commodities[i].IsIMEI = 1 // 串码
}
// 查询库存数量
var stockCount int64
err = orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? and state = ?",
v.ID, InStock).Count(&stockCount).Error
if err != nil {
return nil, err
}
commodities[i].StockCount = uint32(stockCount)
}
resp.List = commodities
// 计算分页所需的切片索引
startIndex := page * m.PageSize
endIndex := (page + 1) * m.PageSize
if endIndex > len(commodities) {
endIndex = len(commodities)
}
resp.List = commodities[startIndex:endIndex]
//跟之前保持一致
resp.Total = int(count)
resp.PageIndex = page + 1
resp.PageSize = m.PageSize
}
for i, v := range resp.List {
if v.IMEIType == 1 { //无串码
resp.List[i].IsIMEI = 2 // 非串码
} else {
resp.List[i].IsIMEI = 1 // 串码
}
// 查询库存数量
var stockCount int64
err = orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? and state = ?",
resp.List[i].ID, InStock).Count(&stockCount).Error
if err != nil {
return nil, err
}
resp.List[i].StockCount = uint32(stockCount)
}
//跟之前保持一致
resp.Total = int(count)
resp.PageIndex = page + 1
resp.PageSize = m.PageSize
return resp, nil
}
// SortStockCommodities 对库存商品数组进行排序
func SortStockCommodities(commodities []ErpStock) {
// 定义排序函数
less := func(i, j int) bool {
// 解析商品编号,提取分类编号和商品编号的数字部分
catNumI, subCatNumI, threeSubCatNumI, itemNumI := parseSerialNumber(commodities[i].CommoditySerialNumber)
catNumJ, subCatNumJ, threeSubCatNumJ, itemNumJ := parseSerialNumber(commodities[j].CommoditySerialNumber)
// 按照分类编号从小到大排序
if catNumI != catNumJ {
return catNumI < catNumJ
}
// 如果分类编号相同,按照具体分类下的商品编号递增排序
if subCatNumI != subCatNumJ {
return subCatNumI < subCatNumJ
}
if threeSubCatNumI != threeSubCatNumJ {
return threeSubCatNumI < threeSubCatNumJ
}
// 如果具体分类编号也相同,按照商品编号递增排序
return itemNumI < itemNumJ
}
// 调用排序函数进行排序
sort.SliceStable(commodities, less)
}
// SortCommodities 对商品数组进行排序
func SortCommodities(commodities []ErpCommodity) {
// 定义排序函数
less := func(i, j int) bool {
// 解析商品编号,提取分类编号和商品编号的数字部分
catNumI, subCatNumI, threeSubCatNumI, itemNumI := parseSerialNumber(commodities[i].SerialNumber)
catNumJ, subCatNumJ, threeSubCatNumJ, itemNumJ := parseSerialNumber(commodities[j].SerialNumber)
// 按照分类编号从小到大排序
if catNumI != catNumJ {
return catNumI < catNumJ
}
// 如果分类编号相同,按照具体分类下的商品编号递增排序
if subCatNumI != subCatNumJ {
return subCatNumI < subCatNumJ
}
if threeSubCatNumI != threeSubCatNumJ {
return threeSubCatNumI < threeSubCatNumJ
}
// 如果具体分类编号也相同,按照商品编号递增排序
return itemNumI < itemNumJ
}
// 调用排序函数进行排序
sort.SliceStable(commodities, less)
}
// parseSerialNumber 解析商品编号,提取分类编号、具体分类编号和商品编号的数字部分
func parseSerialNumber(serialNumber string) (catNum, subCatNum, threeSubCatNum, itemNum int) {
if len(serialNumber) < 3 {
return 0, 0, 0, 0 // 如果商品编号长度不足3位则返回默认值
}
a := serialNumber[:3]
fmt.Println(a)
catNum, _ = strconv.Atoi(serialNumber[:3])
switch len(serialNumber) {
case 7: // 一级分类
subCatNum, _ = strconv.Atoi(serialNumber[3:7])
case 10: // 二级分类
b := serialNumber[3:6]
fmt.Println(b)
subCatNum, _ = strconv.Atoi(serialNumber[3:6])
threeSubCatNum = 0
c := serialNumber[6:]
fmt.Println(c)
itemNum, _ = strconv.Atoi(serialNumber[6:])
case 13: // 三级分类
subCatNum, _ = strconv.Atoi(serialNumber[3:6])
d := serialNumber[6:9]
fmt.Println(d)
threeSubCatNum, _ = strconv.Atoi(serialNumber[6:9])
e := serialNumber[9:]
fmt.Println(e)
itemNum, _ = strconv.Atoi(serialNumber[9:])
}
return catNum, subCatNum, threeSubCatNum, itemNum
}
type ErpCategoryListReq struct {
ErpCategoryId uint32 `json:"erp_category_id"`
Pid uint32 `json:"pid"`
@ -1502,6 +1599,8 @@ func (m *ErpStockListReq) stockIsEmptyList(c *gin.Context) (*ErpStockListResp, e
}
}
SortStockCommodities(stockList)
// Paginate results
startIndex := page * m.PageSize
endIndex := startIndex + m.PageSize
@ -1677,6 +1776,8 @@ func (m *ErpStockListReq) stockNoEmptyList(c *gin.Context) (*ErpStockListResp, e
}
}
SortStockCommodities(stockList)
// Paginate results
startIndex := page * m.PageSize
endIndex := startIndex + m.PageSize
@ -1852,6 +1953,8 @@ func (m *ErpStockListReq) allCommodityList(c *gin.Context) (*ErpStockListResp, e
stockList = append(stockList, stock)
}
SortStockCommodities(stockList)
//跟之前保持一致
resp.Total = int(count)
resp.PageIndex = page + 1
@ -1993,6 +2096,10 @@ func (m *ErpStockCommodityListReq) GetDetailList(c *gin.Context) (*ErpStockCommo
resp.List = commodities
}
if len(commodities) == 1 && commodities[0].State == InAllot && m.ScanCode != "" {
return nil, errors.New("该商品在调拨中")
}
//跟之前保持一致
resp.Total = int(count)
resp.PageIndex = page + 1
@ -2077,7 +2184,7 @@ func contains(s []int, e int) bool {
func (m *ErpStockCommodityListReq) buildQueryConditions(qs *gorm.DB) {
if m.ScanCode != "" {
qs = qs.Where("erp_barcode = ? or imei = ?", m.ScanCode, m.ScanCode)
qs = qs.Where("state = ?", InStock)
qs = qs.Where("state in (?)", []uint32{InStock, InAllot})
} else {
qs = qs.Where("state in (?)", []uint32{InStock, InAllot})
if m.ErpStockId != 0 { //库存id
@ -2454,7 +2561,8 @@ func GetCodeList(req *QueryCodeReq) (*QueryCodeResp, error) {
for _, commodity := range commodities {
if commodity.IMEI != "" && strings.Contains(commodity.IMEI, req.ScanCode) { // 串码非空且包含查找的数据
strCode = commodity.IMEI
} else if commodity.IMEI != "" && strings.Contains(commodity.ErpBarcode, req.ScanCode) { // 串码不为空,但条码包含扫码数据
//} else if commodity.IMEI != "" && strings.Contains(commodity.ErpBarcode, req.ScanCode) { // 串码不为空,但条码包含扫码数据
} else if commodity.IMEI != "" && commodity.ErpBarcode == req.ScanCode { // 串码不为空,但条码包含扫码数据
return nil, errors.New("串码类商品请直接输入串码")
} else {
strCode = commodity.ErpBarcode

View File

@ -102,8 +102,8 @@ type ErpOrderCommodity struct {
IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码
IMEI string `json:"imei" gorm:"index"` // 串码
PresentType uint32 `json:"present_type"` // 赠送类型:1-非赠送 2-赠送
RetailPrice int32 `json:"retail_price"` // 指导零售价
SalePrice int32 `json:"sale_price"` // 零售价
RetailPrice float64 `json:"retail_price"` // 指导零售价
SalePrice float64 `json:"sale_price"` // 零售价
Count int32 `json:"count"` // 销售数量
SaleDiscount float64 `json:"sale_discount"` // 零售优惠
MemberDiscount float64 `json:"member_discount"` // 会员优惠
@ -121,6 +121,7 @@ type ErpOrderCommodity struct {
SalesProfit float64 `json:"sales_profit"` // 销售毛利:实际零售价-采购单价;如果为退货订单,则为实际退货价-采购单价
StaffProfit float64 `json:"staff_profit"` // 员工毛利:实际零售价-员工成本价;如果为退货订单,则为实际退货价-员工成本价
ErpStockCommodityID string `json:"erp_stock_commodity_id"` // 库存商品表主键id
StaffPrice int32 `json:"staff_price" gorm:"-"` // 员工成本价
}
// ErpOrderCashier 订单收款方式
@ -174,8 +175,8 @@ type ErpOrderCreateReq struct {
RetailType string `json:"retail_type" binding:"required"` // 销售类型sale 零售销售; rejected 零售退货
Tel string `json:"tel" binding:"required"` // 会员手机号
MemberType string `json:"member_type" binding:"required"` // 会员类型general 普通; member 会员
TotalRetailPrice float64 `json:"total_retail_price" binding:"required"` // 订单总指导零售价
TotalAmount float64 `json:"total_amount" binding:"required"` // 订单实收金额
TotalRetailPrice float64 `json:"total_retail_price"` // 订单总指导零售价如果是赠送商品金额可以为0
TotalAmount float64 `json:"total_amount"` // 订单实收金额如果只有1个赠送商品金额可以为0
TotalCount uint32 `json:"total_count" binding:"required"` // 订单商品数量
VmAmount uint32 `json:"vm_count"` // 使用会员积分
Cashiers []ErpOrderCashier `json:"cashiers" binding:"required"` // 收付款方式
@ -1080,6 +1081,7 @@ func (m *ErpOrder) SetRetailDetailCommodity() {
item.StaffCostPrice = -item.StaffCostPrice
item.WholesalePrice = -item.WholesalePrice
}
item.StaffPrice = item.StaffCostPrice + item.WholesalePrice
if item.IMEIType == 2 || item.IMEIType == 3 || item.IMEI != "" { // 串码
respOrderCommodities = append(respOrderCommodities, item)
@ -1120,6 +1122,7 @@ func (m *ErpOrder) SetRetailDetailCommodity() {
orderCommodity.ErpSupplierName = stockCommodity.ErpSupplierName
orderCommodity.WholesalePrice = int32(stockCommodity.WholesalePrice)
orderCommodity.StaffCostPrice = int32(stockCommodity.StaffCostPrice)
orderCommodity.StaffPrice = orderCommodity.WholesalePrice + orderCommodity.StaffCostPrice
respOrderCommodities = append(respOrderCommodities, orderCommodity)
}
}
@ -1152,7 +1155,7 @@ func erpOrderListSetSalesman(list []ErpOrder) {
}
func (m *ErpOrder) SetOrderSalesman() error {
var salesProfit, staffProfit float64
var salesProfit, staffProfit, totalStaffProfit float64
//获取销售毛利、员工毛利数据
for _, item := range m.Commodities {
erpCommodity, err := GetCommodity(item.ErpCommodityId)
@ -1161,10 +1164,12 @@ func (m *ErpOrder) SetOrderSalesman() error {
}
salesProfit += item.SalesProfit * erpCommodity.Brokerage1 * 0.01
staffProfit += item.StaffProfit * erpCommodity.Brokerage2 * 0.01
totalStaffProfit += item.StaffProfit
}
// 四舍五入并保留两位小数
salesProfit = math.Round(salesProfit*100) / 100
staffProfit = math.Round(staffProfit*100) / 100
totalStaffProfit = math.Round(totalStaffProfit*100) / 100
var salesmanInfo []ErpOrderSales
err := orm.Eloquent.Model(&ErpOrderSales{}).Where("erp_order_id = ?", m.ID).Find(&salesmanInfo).Error
@ -1183,7 +1188,7 @@ func (m *ErpOrder) SetOrderSalesman() error {
logger.Error("GetSysUserInfoByUid err:", logger.Field("err", err))
}
item.Name = userInfo.NickName
item.SalesmanPer = staffProfit * userInfo.SalesCommRate / float64(len(salesmanInfo))
item.SalesmanPer = totalStaffProfit * userInfo.SalesCommRate * 0.01 / float64(len(salesmanInfo))
//if m.RetailType == RetailTypeRejected {
// item.SalesProfitPer = -item.SalesProfitPer
@ -1282,6 +1287,42 @@ func (m *ErpOrder) SetErpCashier() {
}
}
// 添加订单的付款信息
func erpRetailDetailSetCashier(list []ErpOrder) {
for i, _ := range list {
list[i].SetErpRetailDetailCashier()
}
}
func (m *ErpOrder) SetErpRetailDetailCashier() {
if m.CashierList != "" {
var cashiers []ErpOrderCashier
err := json.Unmarshal([]byte(m.CashierList), &cashiers)
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
}
}
var nTotalOtherAmount float64
var newCashiers []ErpOrderCashier
for _, item := range cashiers {
if item.CashierId > 4 {
nTotalOtherAmount += item.Amount
} else {
newCashiers = append(newCashiers, item)
}
}
// 将所有其他类型的支付方式合并到一起
newCashiers = append(newCashiers, ErpOrderCashier{8090, "", nTotalOtherAmount})
m.Cashiers = newCashiers
m.CashierList = ""
}
}
func GetErpOrderCommodityMap(ids []uint32) (map[uint32]ErpOrderCommodity, error) {
commodityMap := make(map[uint32]ErpOrderCommodity, 0)
if len(ids) == 0 {
@ -1852,19 +1893,26 @@ func QueryStoreManageData(req *ErpOrderStoreManageDataReq, c *gin.Context) (*Erp
} else {
qs = qs.Where("maker_time IS NOT NULL")
}
qs.Where("state = ?", ErpOrderStateAudited)
// 查询数据
if req.SortType == "asc" {
err = qs.Select("DATE_FORMAT(maker_time, '%Y-%m-%d') AS date, SUM(total_amount) AS total_sales_amount, " +
"(SUM(total_retail_price) - SUM(total_amount)) AS promotion_fee, " +
"SUM(total_sales_profit) AS sales_profit, SUM(total_staff_profit) AS staff_profit, SUM(total_count) AS count").
err = qs.Select("DATE_FORMAT(maker_time, '%Y-%m-%d') AS date, " +
"SUM(CASE WHEN retail_type = 'sale' THEN total_discount ELSE -total_discount END) AS promotion_fee, " +
"SUM(CASE WHEN retail_type = 'sale' THEN total_amount ELSE -total_amount END) AS total_sales_amount, " +
"SUM(CASE WHEN retail_type = 'sale' THEN total_sales_profit ELSE -total_sales_profit END) AS sales_profit, " +
"SUM(CASE WHEN retail_type = 'sale' THEN total_staff_profit ELSE -total_staff_profit END) AS staff_profit, " +
"SUM(CASE WHEN retail_type = 'sale' THEN total_count ELSE -total_count END) AS count").
Group("date").
Order("date ASC").
Find(&storeManageDataList).Error
} else {
err = qs.Select("DATE_FORMAT(maker_time, '%Y-%m-%d') AS date, SUM(total_amount) AS total_sales_amount, " +
"(SUM(total_retail_price) - SUM(total_amount)) AS promotion_fee, " +
"SUM(total_sales_profit) AS sales_profit, SUM(total_staff_profit) AS staff_profit, SUM(total_count) AS count").
err = qs.Select("DATE_FORMAT(maker_time, '%Y-%m-%d') AS date, " +
"SUM(CASE WHEN retail_type = 'sale' THEN total_discount ELSE -total_discount END) AS promotion_fee, " +
"SUM(CASE WHEN retail_type = 'sale' THEN total_amount ELSE -total_amount END) AS total_sales_amount, " +
"SUM(CASE WHEN retail_type = 'sale' THEN total_sales_profit ELSE -total_sales_profit END) AS sales_profit, " +
"SUM(CASE WHEN retail_type = 'sale' THEN total_staff_profit ELSE -total_staff_profit END) AS staff_profit, " +
"SUM(CASE WHEN retail_type = 'sale' THEN total_count ELSE -total_count END) AS count").
Group("date").
Order("date DESC").
Find(&storeManageDataList).Error
@ -2330,8 +2378,14 @@ func QueryRetailMargin(req *ErpOrderRetailMarginReq, c *gin.Context) (*ErpOrderR
}
resp.ExportUrl = filePath
} else {
resp.List = list
resp.Total = len(resp.List)
// 计算分页所需的切片索引
startIndex := page * req.PageSize
endIndex := (page + 1) * req.PageSize
if endIndex > len(list) {
endIndex = len(list)
}
resp.List = list[startIndex:endIndex]
resp.Total = len(list)
resp.PageIndex = req.PageIndex
resp.PageSize = req.PageSize
}
@ -2654,9 +2708,9 @@ func queryRetailDetailByJoin(req *ErpOrderRetailDetailReq, c *gin.Context) (*Erp
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+"%")
qs = qs.Where("erp_order_commodity.erp_commodity_name = ?", req.ErpCommodityName)
es = es.Where("erp_order_commodity.erp_commodity_name = ?", req.ErpCommodityName)
orderSumQs = orderSumQs.Where("oc.erp_commodity_name = ?", req.ErpCommodityName)
}
if req.RetailType != "" { // 销售类型
qs = qs.Where("erp_order.retail_type=?", req.RetailType)
@ -2797,6 +2851,12 @@ func queryRetailDetailByJoin(req *ErpOrderRetailDetailReq, c *gin.Context) (*Erp
sumData.TotalAmount = 0 // 订单实收金额
sumData.StorePer = 0 // 门店提成
sumData.ScanAmount = cashier.ScanAmount
sumData.CashAmount = cashier.CashAmount
sumData.PosAmount = cashier.PosAmount
sumData.StoreVmAmount = cashier.StoreVmAmount
sumData.OtherAmount = cashier.OtherAmount
var result []RetailDetailByJoin
if req.IsExport == 1 { //导出excel
@ -2836,9 +2896,9 @@ func queryRetailDetailByJoin(req *ErpOrderRetailDetailReq, c *gin.Context) (*Erp
}
orders := packData(result)
erpOrderListSetCashier(orders)
erpOrderListSetSalesman(orders)
pagedOrders := paginate(orders, page, req.PageSize)
//erpOrderListSetCashier(orders)
//erpOrderListSetSalesman(orders)
resp.List = pagedOrders
@ -3072,7 +3132,7 @@ func queryRetailDetailCommon(req *ErpOrderRetailDetailReq, c *gin.Context) (*Erp
// 计算销售订单和退货订单汇总后的提成数据
totalPerData = subtractTotalPerData(totalPerData, rejectedTotalPerData)
// 销售订单支汇总
// 销售订单支汇总
var cashier TotalCashierData
cashierQs := qs
cashier, err = getTotalCashierData(cashierQs, RetailTypeSale)
@ -3096,6 +3156,11 @@ func queryRetailDetailCommon(req *ErpOrderRetailDetailReq, c *gin.Context) (*Erp
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
@ -3582,12 +3647,6 @@ func CheckUserStore(userStoreId uint32, sysUser *SysUser) bool {
// checkOrderData 校验订单数据
func checkOrderData(req *ErpOrderCreateReq, c *gin.Context) (*ErpOrder, error) {
jCashier, err := json.Marshal(req.Cashiers)
if err != nil {
logger.Error("cashiers marshal err:", logger.Field("err", err))
return nil, errors.New("操作失败:" + err.Error())
}
sysUser, err := GetSysUserByCtx(c)
if err != nil {
return nil, errors.New("操作失败:" + err.Error())
@ -3600,13 +3659,19 @@ func checkOrderData(req *ErpOrderCreateReq, c *gin.Context) (*ErpOrder, error) {
}
if req.RetailType == RetailTypeSale {
// 校验商品是否有库存
err = checkOrderCommodityStock(req)
// 校验商品是否有库存,是否是对应门店库存商品
err = checkOrderCommodityStock(req, sysUser)
if err != nil {
return nil, err
}
}
jCashier, err := json.Marshal(req.Cashiers)
if err != nil {
logger.Error("cashiers marshal err:", logger.Field("err", err))
return nil, errors.New("操作失败:" + err.Error())
}
// 通过手机号查询用户id如果没有则新建一个用户id
userInfo, err := GetUserInfoByTel(req.Tel)
if err != nil {
@ -3709,6 +3774,7 @@ func checkOrderData(req *ErpOrderCreateReq, c *gin.Context) (*ErpOrder, error) {
}
}
bCheckFlag := false
// 校验商品相关金额是否符合要求
for i, _ := range req.ErpOrderCommodities {
if req.RetailType == RetailTypeRejected { // 零售退货订单
@ -3762,6 +3828,10 @@ func checkOrderData(req *ErpOrderCreateReq, c *gin.Context) (*ErpOrder, error) {
req.ErpOrderCommodities[i].StaffProfit = StaffProfit // 员工毛利
erpOrder.TotalSalesProfit += salesProfit
erpOrder.TotalStaffProfit += StaffProfit
if v.PresentType == 1 { // 有非赠送商品
bCheckFlag = true
}
} else if req.RetailType == RetailTypeSale { // 零售订单
var v ErpStockCommodity
var ok bool
@ -3790,7 +3860,7 @@ func checkOrderData(req *ErpOrderCreateReq, c *gin.Context) (*ErpOrder, error) {
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].RetailPrice = v.RetailPrice // 指导零售价
req.ErpOrderCommodities[i].MemberDiscount = v.MemberDiscount // 会员优惠
req.ErpOrderCommodities[i].StaffCostPrice = int32(v.StaffCostPrice) // 员工成本价加价
req.ErpOrderCommodities[i].WholesalePrice = int32(v.WholesalePrice) // 指导采购价
@ -3800,7 +3870,7 @@ func checkOrderData(req *ErpOrderCreateReq, c *gin.Context) (*ErpOrder, error) {
return nil, errors.New("赠送商品最低零售价不为0不符合赠送条件请检查")
}
if req.ErpOrderCommodities[i].SalePrice < int32(v.MinRetailPrice) { //零售价不能低于最低零售价
if req.ErpOrderCommodities[i].SalePrice < v.MinRetailPrice { //零售价不能低于最低零售价
logger.Error("SalePrice less than MinRetailPrice")
return nil, errors.New("零售价不能低于最低零售价,请检查")
}
@ -3825,6 +3895,41 @@ func checkOrderData(req *ErpOrderCreateReq, c *gin.Context) (*ErpOrder, error) {
req.ErpOrderCommodities[i].StaffProfit = StaffProfit // 员工毛利
erpOrder.TotalSalesProfit += salesProfit
erpOrder.TotalStaffProfit += StaffProfit
if req.ErpOrderCommodities[i].PresentType == 1 { // 有非赠送商品
bCheckFlag = true
}
}
}
if erpOrder.TotalAmount == 0 && bCheckFlag {
return nil, errors.New("订单包含非赠送商品实收金额不能为0")
}
// 判断线上支付金额是否>0
if req.RetailType == RetailTypeSale {
onlinePayFlag := false
onlinePayAmount := erpOrder.TotalAmount
var nWaitPayAmount float64
for _, item := range req.Cashiers {
if item.CashierId == 1 { // 线上支付
onlinePayFlag = true
} else {
onlinePayAmount -= item.Amount
}
nWaitPayAmount += item.Amount
}
if onlinePayFlag && onlinePayAmount <= 0 { // 线上支付且金额小于0则报错
logger.Error("线上支付金额小于0")
return nil, errors.New("扫码付金额需>0")
}
if nWaitPayAmount > erpOrder.TotalAmount { // 收款金额大于订单金额
logger.Error("收款金额大于订单金额")
return nil, errors.New("收款金额大于订单金额")
}
if nWaitPayAmount < erpOrder.TotalAmount { // 收款金额小于订单金额
logger.Error("收款金额小于订单金额")
return nil, errors.New("收款金额小于订单金额")
}
}
@ -3849,7 +3954,7 @@ func checkOrderData(req *ErpOrderCreateReq, c *gin.Context) (*ErpOrder, error) {
}
// 校验商品是否有库存
func checkOrderCommodityStock(req *ErpOrderCreateReq) error {
func checkOrderCommodityStock(req *ErpOrderCreateReq, sysUser *SysUser) error {
if len(req.ErpOrderCommodities) != 0 {
// 统计串码和非串码商品信息
commodityMap := make(map[uint32]uint32) // 记录非串码商品id及其数量
@ -3890,18 +3995,21 @@ func checkOrderCommodityStock(req *ErpOrderCreateReq) error {
}
if len(imeiCommodityMap) != 0 { // 查询串码商品库存
var count int64
for commodityId, imei := range imeiCommodityMap {
var imeiStockCommodity ErpStockCommodity
err := orm.Eloquent.Table("erp_stock_commodity").Where("imei = ? and state = ?", imei, InStock).
Count(&count).Error
Find(&imeiStockCommodity).Error
if err != nil {
return err
}
if count == 0 {
if imeiStockCommodity.ID == 0 {
// 获取商品名称
return errors.New("商品" + "[" + commodityNameMap[commodityId] + "]库存不足")
}
if !CheckUserStore(imeiStockCommodity.StoreId, sysUser) {
return errors.New(commodityNameMap[commodityId] + "商品非所选门店库存,请检查")
}
}
}

View File

@ -1492,8 +1492,10 @@ func ExpireMemberSMSSendDay(day uint32, nowTime time.Time) {
end := start.AddDate(0, 0, 1)
var users []UserInfo
//err := orm.Eloquent.Table("user").Where("member_expire > ?", start).Where("member_expire < ?", end).
// Where("member_level in (?)", []uint32{2, 3, 4, 5}).Find(&users).Error
err := orm.Eloquent.Table("user").Where("member_expire > ?", start).Where("member_expire < ?", end).
Where("member_level in (?)", []uint32{2, 3, 4, 5}).Find(&users).Error
Where("member_level = ", MemberLevelUser).Find(&users).Error
if err != nil {
logger.Error(err.Error())
return

View File

@ -862,14 +862,8 @@ func ReceiveAllotInventory(req *InventoryAllotReceiveReq) error {
begin := orm.Eloquent.Begin()
// 遍历库存调拨商品信息
for _, v := range commodities {
commodityInfo, err := GetCommodity(v.CommodityId)
if err != nil {
logger.Errorf("GetCommodity err:", err)
return err
}
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.ReceiveStoreId, InAllot, v.IMEI).
Find(&stockCommodity).Error
if err != nil {
@ -890,42 +884,14 @@ func ReceiveAllotInventory(req *InventoryAllotReceiveReq) error {
}
}
// 更新库存商品数量
exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_stock WHERE store_id=%d AND erp_commodity_id=%d",
inventoryAllotOrder.ReceiveStoreId, v.CommodityId))
// 更新库存商品数量,扣减库存调拨数量
err = begin.Exec(fmt.Sprintf(
"UPDATE erp_stock SET count=count+%d, dispatch_count = dispatch_count-%d WHERE store_id=%d AND erp_commodity_id=%d",
v.Count, v.Count, inventoryAllotOrder.ReceiveStoreId, v.CommodityId)).Error
if err != nil {
logger.Errorf("exist err:", err)
logger.Errorf("update stock err:", err)
return err
}
if exist {
err = begin.Exec(fmt.Sprintf(
"UPDATE erp_stock SET count=count+%d WHERE store_id=%d AND erp_commodity_id=%d",
v.Count, inventoryAllotOrder.ReceiveStoreId, v.CommodityId)).Error
if err != nil {
logger.Errorf("update stock err:", err)
return err
}
} else {
stock := &ErpStock{
StoreId: inventoryAllotOrder.ReceiveStoreId,
StoreName: inventoryAllotOrder.ReceiveStoreName,
ErpCommodityId: v.CommodityId,
ErpCommodityName: v.CommodityName,
ErpCategoryId: commodityInfo.ErpCategoryId,
ErpCategoryName: commodityInfo.ErpCategoryName,
CommoditySerialNumber: commodityInfo.SerialNumber,
IMEIType: v.IMEIType,
RetailPrice: commodityInfo.RetailPrice,
MinRetailPrice: commodityInfo.MinRetailPrice,
Count: v.Count,
DispatchCount: 0,
}
err = begin.Create(stock).Error
if err != nil {
logger.Errorf("create stock err:", err)
return err
}
}
}
// 更新调拨订单的状态为:已完成

View File

@ -586,18 +586,18 @@ func (m *InventoryReportByAllotReq) ReportAllotList(c *gin.Context) (*InventoryR
for _, commodityName := range m.CommodityName {
commodityNames = append(commodityNames, commodityName)
}
qs = qs.Where("erp_inventory_allot_order.commodity_name IN (?)", commodityNames)
countQuery = countQuery.Where("erp_inventory_allot_order.commodity_name IN (?)", commodityNames)
qs = qs.Where("erp_inventory_allot_commodity.commodity_name IN (?)", commodityNames)
countQuery = countQuery.Where("erp_inventory_allot_commodity.commodity_name IN (?)", commodityNames)
}
if len(m.CategoryID) > 0 { // 商品分类id
var categoryIDs []uint32
for _, category := range m.CategoryID {
categoryIDs = append(categoryIDs, category)
}
qs = qs.Where("erp_inventory_allot_order.category_id IN (?)", categoryIDs)
countQuery = countQuery.Where("erp_inventory_allot_order.category_id IN (?)", categoryIDs)
}
//if len(m.CategoryID) > 0 { // 商品分类id
// var categoryIDs []uint32
// for _, category := range m.CategoryID {
// categoryIDs = append(categoryIDs, category)
// }
// qs = qs.Where("erp_inventory_allot_order.category_id IN (?)", categoryIDs)
// countQuery = countQuery.Where("erp_inventory_allot_order.category_id IN (?)", categoryIDs)
//}
if m.State != 0 { // 调拨状态
switch m.State {
@ -669,9 +669,6 @@ func (m *InventoryReportByAllotReq) ReportAllotList(c *gin.Context) (*InventoryR
summaryMap := make(map[string]*ReportByAllotData)
// 遍历 commodities 切片
for _, item := range commodities {
nTotalAllotCount += item.AllotCount
nTotalAllotAmount += item.AllotAmount
// 生成键
key := fmt.Sprintf("%d_%d_%d", item.DeliverStoreId, item.ReceiveStoreId, item.State)
// 检查是否已经存在该键的汇总数据
@ -707,10 +704,20 @@ func (m *InventoryReportByAllotReq) ReportAllotList(c *gin.Context) (*InventoryR
if err != nil {
logger.Error("SetCategory err:", logger.Field("err", err))
}
// 判断分类信息是否有筛选
if len(m.CategoryID) > 0 { // 商品分类id
if !tools.Uint32SliceContains(m.CategoryID, commodityInfo.ErpCategoryId) {
continue
}
}
summaryMap[i].CategoryID = commodityInfo.ErpCategoryId
summaryMap[i].CategoryName = commodityInfo.ErpCategoryName
summaryList = append(summaryList, *summary)
nTotalAllotCount += summary.AllotCount
nTotalAllotAmount += summary.AllotAmount
}
// 排序规则:商品编号小>调出店铺编号小>调入门店编号小>状态为已完成
@ -734,7 +741,7 @@ func (m *InventoryReportByAllotReq) ReportAllotList(c *gin.Context) (*InventoryR
endIndex = len(summaryList)
}
resp.Total = len(summaryMap)
resp.Total = len(summaryList)
resp.TotalAllotCount = nTotalAllotCount
resp.TotalAllotAmount = nTotalAllotAmount
resp.List = summaryList[startIndex:endIndex]

View File

@ -474,20 +474,21 @@ type ErpPurchaseReportBySupplierResp struct {
}
type PurchaseReportData struct {
ErpPurchaseOrderId uint32 `json:"erp_purchase_order_id"` // 采购订单id
StoreId uint32 `json:"store_id"` // 门店id
StoreName string `json:"store_name"` // 门店名称
PurchaseType string `json:"purchase_type"` // 采购类型:procure-采购 reject-退货
ErpSupplierId uint32 `json:"erp_supplier_id"` // 供应商id
ErpSupplierName string `json:"erp_supplier_name"` // 供应商名称
ErpCommodityId uint32 `json:"erp_commodity_id"` // 商品id
ErpCommodityName string `json:"erp_commodity_name"` // 商品名称
ErpCategoryID uint32 `json:"erp_category_id"` // 商品分类id
ErpCategoryName string `json:"erp_category_name"` // 商品分类名称
Count int32 `json:"count"` // 采购数量
Amount float64 `json:"amount"` // 采购金额
RejectAmount float64 `json:"reject_amount"` // 退货金额
Difference float64 `json:"difference"` // 差额
ErpPurchaseOrderId uint32 `json:"erp_purchase_order_id"` // 采购订单id
SerialNumber string `json:"serial_number" gorm:"index"` // 入库编号
StoreId uint32 `json:"store_id"` // 门店id
StoreName string `json:"store_name"` // 门店名称
PurchaseType string `json:"purchase_type"` // 采购类型:procure-采购 reject-退货
ErpSupplierId uint32 `json:"erp_supplier_id"` // 供应商id
ErpSupplierName string `json:"erp_supplier_name"` // 供应商名称
ErpCommodityId uint32 `json:"erp_commodity_id"` // 商品id
ErpCommodityName string `json:"erp_commodity_name"` // 商品名称
ErpCategoryID uint32 `json:"erp_category_id"` // 商品分类id
ErpCategoryName string `json:"erp_category_name"` // 商品分类名称
Count int32 `json:"count"` // 采购数量
Amount float64 `json:"amount"` // 采购金额
RejectAmount float64 `json:"reject_amount"` // 退货金额
Difference float64 `json:"difference"` // 差额
}
// ErpPurchaseReportDetailReq 采购明细入参
@ -795,10 +796,20 @@ func CheckCreateErpPurchaseOrderParam(req *ErpPurchaseCreateReq) error {
if req.DeliveryTime == "" {
return errors.New("操作失败:交货日期为空")
}
for _, item := range req.ErpPurchaseCommodities {
if item.Count <= 0 {
return errors.New("操作失败:采购数量需大于0")
}
}
} else if req.PurchaseType == ErpRejectOrder { // 退货单
if req.PurchaseOrderSn == "" {
return errors.New("操作失败:采购退货单据编号为空")
}
for _, item := range req.ErpPurchaseCommodities {
if item.RejectedCount <= 0 {
return errors.New("操作失败:采购退货数量需大于0")
}
}
} else {
return errors.New("操作失败:采购类型有误")
}
@ -1108,7 +1119,6 @@ func InventoryErpPurchase(req *ErpPurchaseInventoryReq, c *gin.Context) error {
begin := orm.Eloquent.Begin()
var inventoryList []ErpPurchaseInventory
for i, v := range req.Inventories {
v.SerialNumber = GetPurchaseInventorySn()
req.Inventories[i].SerialNumber = v.SerialNumber
// 更新采购商品表的执行数量
// todo 如果用户在同一个采购单中新建了同一个商品的2条采购信息可能采购价不同需要区分入库的是哪一条(已修改)
@ -1127,6 +1137,7 @@ func InventoryErpPurchase(req *ErpPurchaseInventoryReq, c *gin.Context) error {
nCount := v.Count
nAmount := v.Amount
for j := 0; j < int(nCount); j++ { // 采购入库记录表都是单笔数据
v.SerialNumber = GetPurchaseInventorySn()
v.ID = 0
v.Count = 1
v.Amount = nAmount / float64(nCount) // 前端传的执行金额是总金额
@ -1364,7 +1375,7 @@ func InventoryErpPurchaseUpdateRejectStock(gdb *gorm.DB, list []ErpPurchaseInven
// 通过首次入库订单编号查找状态为1-在库的非串码商品
err = orm.Eloquent.Table("erp_stock_commodity").
Where("erp_commodity_id = ? and state = ? and imei_type = ? and original_sn = ?",
list[i].ErpCommodityId, purchaseOrder.StoreId, InStock, 1, purchaseOrder.RejectedSerialNumber).
list[i].ErpCommodityId, InStock, 1, purchaseOrder.RejectedSerialNumber).
Order("id DESC").Find(&stockCommodity).Error
if err != nil {
logger.Error("RetailTypeRejected commodities err:", logger.Field("err", err))
@ -1547,6 +1558,9 @@ func ExecuteErpPurchase(req *ErpPurchaseExecuteReq, c *gin.Context) (*ErpPurchas
}
for _, inventory := range req.Inventories {
if inventory.Count == 0 {
continue
}
// 获取商品信息
commodityInfo, err := GetCommodity(inventory.ErpCommodityId)
if err != nil {
@ -2387,18 +2401,14 @@ func getErpPurchaseDemandAll(req *GetErpPurchaseDemandReq) (*GetErpPurchaseDeman
}
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
}
err := qs.Order("id DESC").Find(&commodities).Error
if err != nil && err != RecordNotFound {
return resp, err
}
// 按商品编号进行排序
SortCommodities(commodities)
// 批量查询门店信息
stores, err := GetOnlineStores()
if err != nil {
@ -2433,7 +2443,13 @@ func getErpPurchaseDemandAll(req *GetErpPurchaseDemandReq) (*GetErpPurchaseDeman
return nil, err
}
} else {
resp.List = demandDataList
// 计算分页所需的切片索引
startIndex := page * req.PageSize
endIndex := (page + 1) * req.PageSize
if endIndex > len(demandDataList) {
endIndex = len(demandDataList)
}
resp.List = demandDataList[startIndex:endIndex]
resp.Total = count
}
@ -2602,7 +2618,7 @@ func convertToDemandData(commodity ErpCommodity, stores []Store) (DemandData, er
var lastWholesalePrices map[uint32]float64
var stockCounts map[uint32]uint32
var lastMonthSales uint32
var lastMonthSales map[uint32]uint32
go func() {
defer wg.Done()
@ -2640,7 +2656,7 @@ func convertToDemandData(commodity ErpCommodity, stores []Store) (DemandData, er
demandData.StoreList[i].StoreName = store.Name
demandData.StoreList[i].StockCount = stockCounts[store.ID]
demandData.StoreList[i].LastMonthSales = lastMonthSales
demandData.StoreList[i].LastMonthSales = lastMonthSales[store.ID]
// 设置最近采购价
demandData.LastWholesalePrice = lastWholesalePrices[commodity.ID]
@ -2758,7 +2774,7 @@ func GetCommodityStockByPurchaseId(serialNumber string, orderId uint32) (uint32,
}
// GetCommodityLastMonthSales 批量查询商品的上月销售数量
func GetCommodityLastMonthSales(commodityID uint32, stores []Store) (uint32, error) {
func GetCommodityLastMonthSales(commodityID uint32, stores []Store) (map[uint32]uint32, error) {
// 获取上个月的时间范围
firstDay, lastDay := GetLastMonthRange()
@ -2766,21 +2782,17 @@ func GetCommodityLastMonthSales(commodityID uint32, stores []Store) (uint32, err
var wg sync.WaitGroup
wg.Add(len(stores))
var totalSales uint32
result := make(map[uint32]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
var sales int64
err := orm.Eloquent.Table("erp_stock_commodity").
Where("state = ? AND erp_commodity_id = ? AND store_id = ? AND updated_at BETWEEN ? AND ?",
SoldOut, commodityID, storeID, firstDay, lastDay).Count(&sales).Error
if err != nil {
// Handle error
return
@ -2789,13 +2801,13 @@ func GetCommodityLastMonthSales(commodityID uint32, stores []Store) (uint32, err
// 保护 totalSales 的并发访问
mu.Lock()
defer mu.Unlock()
totalSales += sales
result[storeID] = uint32(sales)
}(store.ID)
}
wg.Wait()
return totalSales, nil
return result, nil
}
// GetLastMonthRange 获取上个月的时间范围
@ -2839,6 +2851,24 @@ func GetTotalsAndAveragesByCommodityID(commodityID, orderID uint32) (Result, err
return result, nil
}
type ResultPrice struct {
TotalWholesalePrice float64 `gorm:"column:total_wholesale_price"`
}
// GetTotalWholesalePrice 查询采购退货订单对应的采购金额
func GetTotalWholesalePrice(commodityID uint32, serialNumber string) (ResultPrice, error) {
var result ResultPrice
err := orm.Eloquent.Table("erp_stock_commodity").
Select("SUM(`wholesale_price`) AS total_wholesale_price").
Where("erp_commodity_id = ? and stock_sn = ?", commodityID, serialNumber).
Scan(&result).Error
if err != nil {
return ResultPrice{}, err
}
return result, nil
}
// UpdateRetailPrice 更新指导零售价
func UpdateRetailPrice(begin *gorm.DB, commodityId uint32, retailPrice float64) error {
// 更新商品信息表
@ -3117,7 +3147,8 @@ func getReportByOrderFromCommodityOrCategory(req *ErpPurchaseReportByOrderReq, c
// 遍历 inventoryList将不同的 ErpCommodityId 存入 map 中
for _, inventory := range inventoryList {
commodityMap[inventory.ErpCommodityId] = inventory.ErpPurchaseOrderId
//commodityMap[inventory.ErpCommodityId] = inventory.ErpPurchaseOrderId
commodityMap[inventory.ErpPurchaseOrderId] = inventory.ErpCommodityId
}
// 计算不同的 ErpCommodityId 的数量
differentCommodityCount := len(commodityMap)
@ -3126,7 +3157,7 @@ func getReportByOrderFromCommodityOrCategory(req *ErpPurchaseReportByOrderReq, c
var nTotalAmount float64
var nTotalCount int32
// 查询采购订单信息
for _, v := range commodityMap {
for k, _ := range commodityMap {
var purchaseOrder ErpPurchaseOrder
var commodityList []ErpPurchaseCommodityData
@ -3139,7 +3170,7 @@ func getReportByOrderFromCommodityOrCategory(req *ErpPurchaseReportByOrderReq, c
query = query.Where("erp_purchase_order.store_id IN (?)", req.StoreId)
}
err = query.Where("id = ?", v).Find(&purchaseOrder).Error
err = query.Where("id = ?", k).Find(&purchaseOrder).Error
if err != nil {
return nil, err
}
@ -4024,6 +4055,7 @@ func getReportByCommodityFromCommon(req *ErpPurchaseReportByCommodityReq, c *gin
go getPurchaseOrderAndCommodityDataAsync(v.ID, commodityID, ch, &wg)
}
}
wg.Wait()
close(ch)
@ -4130,7 +4162,15 @@ func getReportByCommodityFromCommon(req *ErpPurchaseReportByCommodityReq, c *gin
sortByCommodityIDDesc(dataList)
resp.Total = len(dataList)
resp.List = dataList
// 计算分页所需的切片索引
startIndex := page * req.PageSize
endIndex := (page + 1) * req.PageSize
if endIndex > len(dataList) {
endIndex = len(dataList)
}
resp.List = dataList[startIndex:endIndex]
resp.PlanCount = totalData.PlanCount
resp.PlanAmount = totalData.PlanAmount
resp.Amount = totalData.Amount
@ -4315,18 +4355,23 @@ func getSignalPurchaseData(erpPurchaseOrderId, commodityId uint32) (PurchaseData
func getAllOrderCommodity(pageIndex, pageSize, isExport int) (map[uint32][]uint32, error) {
var commodityMap = make(map[uint32][]uint32)
var query string
if isExport == 1 { //导出excel
// 执行原生 SQL 查询联结表格按照每个商品ID列出所有的订单ID
query = fmt.Sprintf(`
// if isExport == 1 { //导出excel
// // 执行原生 SQL 查询联结表格按照每个商品ID列出所有的订单ID
// query = fmt.Sprintf(`
// SELECT erp_commodity_id, GROUP_CONCAT(erp_purchase_order_id) AS order_ids FROM erp_purchase_commodity
//GROUP BY erp_commodity_id`)
// } else {
// // 执行原生 SQL 查询联结表格按照每个商品ID列出所有的订单ID
// query = fmt.Sprintf(`
// SELECT erp_commodity_id, GROUP_CONCAT(erp_purchase_order_id) AS order_ids FROM erp_purchase_commodity
//GROUP BY erp_commodity_id
// LIMIT %d OFFSET %d`, pageSize, pageIndex*pageSize)
// }
// 执行原生 SQL 查询联结表格按照每个商品ID列出所有的订单ID
query = fmt.Sprintf(`
SELECT erp_commodity_id, GROUP_CONCAT(erp_purchase_order_id) AS order_ids FROM erp_purchase_commodity
GROUP BY erp_commodity_id`)
} else {
// 执行原生 SQL 查询联结表格按照每个商品ID列出所有的订单ID
query = fmt.Sprintf(`
SELECT erp_commodity_id, GROUP_CONCAT(erp_purchase_order_id) AS order_ids FROM erp_purchase_commodity
GROUP BY erp_commodity_id
LIMIT %d OFFSET %d`, pageSize, pageIndex*pageSize)
}
rows, err := orm.Eloquent.Raw(query).Rows()
if err != nil {
@ -4593,7 +4638,8 @@ func GetReportBySupplier(req *ErpPurchaseReportBySupplierReq, c *gin.Context) (
// 构建查询条件
query := orm.Eloquent.Model(&ErpPurchaseInventory{}).
Select("erp_purchase_inventory.erp_purchase_order_id, erp_purchase_inventory.purchase_type, " +
Select("erp_purchase_inventory.erp_purchase_order_id, " +
"erp_purchase_inventory.purchase_type, erp_purchase_inventory.serial_number, " +
"erp_purchase_order.store_id, erp_purchase_order.store_name, erp_purchase_order.erp_supplier_id, " +
"erp_purchase_order.erp_supplier_name, " +
"erp_purchase_inventory.erp_commodity_id, erp_purchase_inventory.erp_commodity_name, " +
@ -4605,7 +4651,8 @@ func GetReportBySupplier(req *ErpPurchaseReportBySupplierReq, c *gin.Context) (
"erp_purchase_inventory.erp_commodity_name, erp_purchase_inventory.erp_category_id")
countQuery := orm.Eloquent.Model(&ErpPurchaseInventory{}).
Select("erp_purchase_inventory.erp_purchase_order_id, erp_purchase_inventory.purchase_type, " +
Select("erp_purchase_inventory.erp_purchase_order_id, " +
"erp_purchase_inventory.purchase_type, erp_purchase_inventory.serial_number, " +
"erp_purchase_order.store_id, erp_purchase_order.store_name, erp_purchase_order.erp_supplier_id, " +
"erp_purchase_order.erp_supplier_name, " +
"erp_purchase_inventory.erp_commodity_id, erp_purchase_inventory.erp_commodity_name, " +
@ -4661,14 +4708,8 @@ func GetReportBySupplier(req *ErpPurchaseReportBySupplierReq, c *gin.Context) (
countQuery.Count(&total)
resp.Total = int(total)
// 分页查询
var err error
if req.IsExport == 1 { // 导出excel
err = query.Find(&resp.List).Error
} else {
//err = query.Offset((req.PageIndex - 1) * req.PageSize).Limit(req.PageSize).Find(&resp.List).Error
err = query.Find(&resp.List).Error
}
err = query.Find(&resp.List).Error
if err != nil {
return nil, err
}
@ -4706,23 +4747,23 @@ func GetReportBySupplier(req *ErpPurchaseReportBySupplierReq, c *gin.Context) (
}
if data.PurchaseType == "reject" {
// 查询退货商品的采购金额
var oldOrderInfo ErpPurchaseOrder
err = orm.Eloquent.Where("serial_number = ?", po.SerialNumber).First(&oldOrderInfo).Error
if err != nil {
return nil, err
}
//// 查询退货商品的采购金额
//var oldOrderInfo ErpPurchaseOrder
//err = orm.Eloquent.Where("serial_number = ?", po.SerialNumber).First(&oldOrderInfo).Error
//if err != nil {
// return nil, err
//}
// 查找对应的采购入库记录
var resultInfo Result
resultInfo, err = GetTotalsAndAveragesByCommodityID(respItem.ErpCommodityId, oldOrderInfo.ID)
var resultInfo ResultPrice
resultInfo, err = GetTotalWholesalePrice(respItem.ErpCommodityId, respItem.SerialNumber)
if err != nil {
return nil, err
}
data.Difference = -(resultInfo.TotalWholesalePrice - data.Amount)
data.RejectAmount = -data.Amount
data.Amount = -resultInfo.AvgImplementationPrice * float64(data.Count)
data.Difference = data.RejectAmount - data.Amount
data.Amount = -resultInfo.TotalWholesalePrice
data.Count = -data.Count
}
@ -4746,23 +4787,22 @@ func GetReportBySupplier(req *ErpPurchaseReportBySupplierReq, c *gin.Context) (
resp.List[i].ErpSupplierName = purchaseOrderInfo.ErpSupplierName
if resp.List[i].PurchaseType == "reject" {
// 查询退货商品的采购金额
var oldOrderInfo ErpPurchaseOrder
err = orm.Eloquent.Where("serial_number = ?", purchaseOrderInfo.SerialNumber).First(&oldOrderInfo).Error
if err != nil {
return nil, err
}
//// 查询退货商品的采购金额
//var oldOrderInfo ErpPurchaseOrder
//err = orm.Eloquent.Where("serial_number = ?", purchaseOrderInfo.SerialNumber).First(&oldOrderInfo).Error
//if err != nil {
// return nil, err
//}
// 查找对应的采购入库记录
var resultInfo Result
resultInfo, err = GetTotalsAndAveragesByCommodityID(resp.List[i].ErpCommodityId, oldOrderInfo.ID)
var resultInfo ResultPrice
resultInfo, err = GetTotalWholesalePrice(resp.List[i].ErpCommodityId, resp.List[i].SerialNumber)
if err != nil {
return nil, err
}
resp.List[i].Difference = -(resultInfo.TotalWholesalePrice - resp.List[i].Amount)
resp.List[i].RejectAmount = -resp.List[i].Amount
resp.List[i].Amount = -resultInfo.AvgImplementationPrice * float64(resp.List[i].Count)
resp.List[i].Difference = resp.List[i].RejectAmount - resp.List[i].Amount
resp.List[i].Amount = -resultInfo.TotalWholesalePrice
resp.List[i].Count = -resp.List[i].Count
}
}
@ -4788,6 +4828,26 @@ func GetReportBySupplier(req *ErpPurchaseReportBySupplierReq, c *gin.Context) (
resp.Difference = totalDifference
resp.Total = len(mergedData)
// 排序规则:供应商编号小>商品编号小>店铺编号小>类型为采购入库
sort.Slice(mergedData, func(i, j int) bool {
if mergedData[i].ErpSupplierId != mergedData[j].ErpSupplierId {
return mergedData[i].ErpSupplierId < mergedData[j].ErpSupplierId
}
if mergedData[i].ErpCommodityId != mergedData[j].ErpCommodityId {
return mergedData[i].ErpCommodityId < mergedData[j].ErpCommodityId
}
if mergedData[i].StoreId != mergedData[j].StoreId {
return mergedData[i].StoreId < mergedData[j].StoreId
}
if mergedData[i].PurchaseType == ErpProcureOrder && mergedData[j].PurchaseType != ErpProcureOrder {
return true
}
if mergedData[i].PurchaseType != ErpProcureOrder && mergedData[j].PurchaseType == ErpProcureOrder {
return false
}
return false // 默认情况下相等
})
// 分页处理
startIdx := (resp.PageIndex - 1) * resp.PageSize
endIdx := resp.PageIndex * resp.PageSize

View File

@ -7254,6 +7254,75 @@ const docTemplate = `{
}
}
},
"models.DecisionSumData": {
"type": "object",
"properties": {
"total_allot_in": {
"description": "调拨入库",
"type": "integer"
},
"total_allot_out": {
"description": "调拨出库",
"type": "integer"
},
"total_allot_wait_in": {
"description": "在途库存(入库)",
"type": "integer"
},
"total_allot_wait_out": {
"description": "在途库存(出库)",
"type": "integer"
},
"total_begin_amount": {
"description": "期初金额",
"type": "number"
},
"total_begin_stock": {
"description": "期初库存",
"type": "integer"
},
"total_check_in": {
"description": "盘点入库",
"type": "integer"
},
"total_check_out": {
"description": "盘点出库",
"type": "integer"
},
"total_end_amount": {
"description": "期末金额",
"type": "number"
},
"total_end_stock": {
"description": "期末数量",
"type": "integer"
},
"total_order_reject": {
"description": "零售退货",
"type": "integer"
},
"total_order_sale": {
"description": "零售销售",
"type": "integer"
},
"total_product_in": {
"description": "产品入库",
"type": "integer"
},
"total_purchase_return": {
"description": "采购退货",
"type": "integer"
},
"total_purchase_stock": {
"description": "采购进货",
"type": "integer"
},
"total_system_out": {
"description": "系统出库",
"type": "integer"
}
}
},
"models.DefaultUserNameAndPasswordResp": {
"type": "object",
"properties": {
@ -7859,6 +7928,7 @@ const docTemplate = `{
"type": "string"
},
"list": {
"description": "明细数据",
"type": "array",
"items": {
"$ref": "#/definitions/models.DecisionReportData"
@ -7872,73 +7942,17 @@ const docTemplate = `{
"description": "页面条数",
"type": "integer"
},
"sum_data": {
"description": "汇总数据",
"allOf": [
{
"$ref": "#/definitions/models.DecisionSumData"
}
]
},
"total": {
"description": "总条数/记录数",
"type": "integer"
},
"total_allot_in": {
"description": "调拨入库",
"type": "integer"
},
"total_allot_out": {
"description": "调拨出库",
"type": "integer"
},
"total_allot_wait_in": {
"description": "在途库存(入库)",
"type": "integer"
},
"total_allot_wait_out": {
"description": "在途库存(出库)",
"type": "integer"
},
"total_begin_amount": {
"description": "期初金额",
"type": "number"
},
"total_begin_stock": {
"description": "期初库存",
"type": "integer"
},
"total_check_in": {
"description": "盘点入库",
"type": "integer"
},
"total_check_out": {
"description": "盘点出库",
"type": "integer"
},
"total_end_amount": {
"description": "期末金额",
"type": "number"
},
"total_end_stock": {
"description": "期末数量",
"type": "integer"
},
"total_order_reject": {
"description": "零售退货",
"type": "integer"
},
"total_order_sale": {
"description": "零售销售",
"type": "integer"
},
"total_product_in": {
"description": "产品入库",
"type": "integer"
},
"total_purchase_return": {
"description": "采购退货",
"type": "integer"
},
"total_purchase_stock": {
"description": "采购进货",
"type": "integer"
},
"total_system_out": {
"description": "系统出库",
"type": "integer"
}
}
},
@ -8694,6 +8708,10 @@ const docTemplate = `{
"description": "员工成本价加价加价50不是加价后的价格",
"type": "integer"
},
"staff_price": {
"description": "员工成本价",
"type": "integer"
},
"staff_profit": {
"description": "员工毛利:实际零售价-员工成本价;如果为退货订单,则为实际退货价-员工成本价",
"type": "number"
@ -8719,7 +8737,6 @@ const docTemplate = `{
"store_id",
"store_name",
"tel",
"total_amount",
"total_count",
"total_retail_price"
],
@ -8770,7 +8787,7 @@ const docTemplate = `{
"type": "string"
},
"total_amount": {
"description": "订单实收金额",
"description": "订单实收金额如果只有1个赠送商品金额可以为0",
"type": "number"
},
"total_count": {

View File

@ -7243,6 +7243,75 @@
}
}
},
"models.DecisionSumData": {
"type": "object",
"properties": {
"total_allot_in": {
"description": "调拨入库",
"type": "integer"
},
"total_allot_out": {
"description": "调拨出库",
"type": "integer"
},
"total_allot_wait_in": {
"description": "在途库存(入库)",
"type": "integer"
},
"total_allot_wait_out": {
"description": "在途库存(出库)",
"type": "integer"
},
"total_begin_amount": {
"description": "期初金额",
"type": "number"
},
"total_begin_stock": {
"description": "期初库存",
"type": "integer"
},
"total_check_in": {
"description": "盘点入库",
"type": "integer"
},
"total_check_out": {
"description": "盘点出库",
"type": "integer"
},
"total_end_amount": {
"description": "期末金额",
"type": "number"
},
"total_end_stock": {
"description": "期末数量",
"type": "integer"
},
"total_order_reject": {
"description": "零售退货",
"type": "integer"
},
"total_order_sale": {
"description": "零售销售",
"type": "integer"
},
"total_product_in": {
"description": "产品入库",
"type": "integer"
},
"total_purchase_return": {
"description": "采购退货",
"type": "integer"
},
"total_purchase_stock": {
"description": "采购进货",
"type": "integer"
},
"total_system_out": {
"description": "系统出库",
"type": "integer"
}
}
},
"models.DefaultUserNameAndPasswordResp": {
"type": "object",
"properties": {
@ -7848,6 +7917,7 @@
"type": "string"
},
"list": {
"description": "明细数据",
"type": "array",
"items": {
"$ref": "#/definitions/models.DecisionReportData"
@ -7861,73 +7931,17 @@
"description": "页面条数",
"type": "integer"
},
"sum_data": {
"description": "汇总数据",
"allOf": [
{
"$ref": "#/definitions/models.DecisionSumData"
}
]
},
"total": {
"description": "总条数/记录数",
"type": "integer"
},
"total_allot_in": {
"description": "调拨入库",
"type": "integer"
},
"total_allot_out": {
"description": "调拨出库",
"type": "integer"
},
"total_allot_wait_in": {
"description": "在途库存(入库)",
"type": "integer"
},
"total_allot_wait_out": {
"description": "在途库存(出库)",
"type": "integer"
},
"total_begin_amount": {
"description": "期初金额",
"type": "number"
},
"total_begin_stock": {
"description": "期初库存",
"type": "integer"
},
"total_check_in": {
"description": "盘点入库",
"type": "integer"
},
"total_check_out": {
"description": "盘点出库",
"type": "integer"
},
"total_end_amount": {
"description": "期末金额",
"type": "number"
},
"total_end_stock": {
"description": "期末数量",
"type": "integer"
},
"total_order_reject": {
"description": "零售退货",
"type": "integer"
},
"total_order_sale": {
"description": "零售销售",
"type": "integer"
},
"total_product_in": {
"description": "产品入库",
"type": "integer"
},
"total_purchase_return": {
"description": "采购退货",
"type": "integer"
},
"total_purchase_stock": {
"description": "采购进货",
"type": "integer"
},
"total_system_out": {
"description": "系统出库",
"type": "integer"
}
}
},
@ -8683,6 +8697,10 @@
"description": "员工成本价加价加价50不是加价后的价格",
"type": "integer"
},
"staff_price": {
"description": "员工成本价",
"type": "integer"
},
"staff_profit": {
"description": "员工毛利:实际零售价-员工成本价;如果为退货订单,则为实际退货价-员工成本价",
"type": "number"
@ -8708,7 +8726,6 @@
"store_id",
"store_name",
"tel",
"total_amount",
"total_count",
"total_retail_price"
],
@ -8759,7 +8776,7 @@
"type": "string"
},
"total_amount": {
"description": "订单实收金额",
"description": "订单实收金额如果只有1个赠送商品金额可以为0",
"type": "number"
},
"total_count": {

View File

@ -987,6 +987,57 @@ definitions:
description: 系统出库
type: integer
type: object
models.DecisionSumData:
properties:
total_allot_in:
description: 调拨入库
type: integer
total_allot_out:
description: 调拨出库
type: integer
total_allot_wait_in:
description: 在途库存(入库)
type: integer
total_allot_wait_out:
description: 在途库存(出库)
type: integer
total_begin_amount:
description: 期初金额
type: number
total_begin_stock:
description: 期初库存
type: integer
total_check_in:
description: 盘点入库
type: integer
total_check_out:
description: 盘点出库
type: integer
total_end_amount:
description: 期末金额
type: number
total_end_stock:
description: 期末数量
type: integer
total_order_reject:
description: 零售退货
type: integer
total_order_sale:
description: 零售销售
type: integer
total_product_in:
description: 产品入库
type: integer
total_purchase_return:
description: 采购退货
type: integer
total_purchase_stock:
description: 采购进货
type: integer
total_system_out:
description: 系统出库
type: integer
type: object
models.DefaultUserNameAndPasswordResp:
properties:
password:
@ -1426,6 +1477,7 @@ definitions:
description: 导出excel路径
type: string
list:
description: 明细数据
items:
$ref: '#/definitions/models.DecisionReportData'
type: array
@ -1435,57 +1487,13 @@ definitions:
pageSize:
description: 页面条数
type: integer
sum_data:
allOf:
- $ref: '#/definitions/models.DecisionSumData'
description: 汇总数据
total:
description: 总条数/记录数
type: integer
total_allot_in:
description: 调拨入库
type: integer
total_allot_out:
description: 调拨出库
type: integer
total_allot_wait_in:
description: 在途库存(入库)
type: integer
total_allot_wait_out:
description: 在途库存(出库)
type: integer
total_begin_amount:
description: 期初金额
type: number
total_begin_stock:
description: 期初库存
type: integer
total_check_in:
description: 盘点入库
type: integer
total_check_out:
description: 盘点出库
type: integer
total_end_amount:
description: 期末金额
type: number
total_end_stock:
description: 期末数量
type: integer
total_order_reject:
description: 零售退货
type: integer
total_order_sale:
description: 零售销售
type: integer
total_product_in:
description: 产品入库
type: integer
total_purchase_return:
description: 采购退货
type: integer
total_purchase_stock:
description: 采购进货
type: integer
total_system_out:
description: 系统出库
type: integer
type: object
models.ErpInventoryAllotCommodity:
properties:
@ -2042,6 +2050,9 @@ definitions:
staff_cost_price:
description: 员工成本价加价加价50不是加价后的价格
type: integer
staff_price:
description: 员工成本价
type: integer
staff_profit:
description: 员工毛利:实际零售价-员工成本价;如果为退货订单,则为实际退货价-员工成本价
type: number
@ -2088,7 +2099,7 @@ definitions:
description: 会员手机号
type: string
total_amount:
description: 订单实收金额
description: 订单实收金额如果只有1个赠送商品金额可以为0
type: number
total_count:
description: 订单商品数量
@ -2108,7 +2119,6 @@ definitions:
- store_id
- store_name
- tel
- total_amount
- total_count
- total_retail_price
type: object