1、查询门店经营入参门店字段改成可以复选;

2、库存调拨编辑查询详情时返回对应商品的库存数量;
3、采购入库优化,入库后不再更新审核时间;
4、查询采购报表(按单)剔除待入库且已入库数量为0的订单;
5、采购报表(按商品)剔除已终止的订单;
This commit is contained in:
chenlin 2024-10-31 18:05:55 +08:00
parent 95c7fd228e
commit dc134e138a
6 changed files with 236 additions and 70 deletions

View File

@ -253,13 +253,13 @@ type ErpOrderAddInvoiceReq struct {
// ErpOrderStoreManageDataReq 查询门店经营入参
type ErpOrderStoreManageDataReq struct {
StoreId uint32 `json:"store_id"` // 门店ID
StartTime string `json:"start_time"` // 开始时间
EndTime string `json:"end_time"` // 结束时间
PageIndex int `json:"pageIndex"` // 页码
PageSize int `json:"pageSize"` // 页面条数
IsExport uint32 `json:"is_export"` // 1-导出
SortType string `json:"sort_type"` // 排序类型desc 降序、asc 升序
StoreId []uint32 `json:"store_id"` // 门店ID
StartTime string `json:"start_time"` // 开始时间
EndTime string `json:"end_time"` // 结束时间
PageIndex int `json:"pageIndex"` // 页码
PageSize int `json:"pageSize"` // 页面条数
IsExport uint32 `json:"is_export"` // 1-导出
SortType string `json:"sort_type"` // 排序类型desc 降序、asc 升序
}
// ErpOrderStoreManageDataResp 查询门店经营出参
@ -2398,8 +2398,8 @@ func QueryStoreManageData(req *ErpOrderStoreManageDataReq, c *gin.Context) (*Erp
// 构建查询条件
qs := orm.Eloquent.Model(&ErpOrder{})
if req.StoreId != 0 {
qs = qs.Where("store_id = ?", req.StoreId)
if len(req.StoreId) != 0 {
qs.Where("erp_order.store_id in ?", req.StoreId)
}
// 非管理员才判断所属门店
if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
@ -2499,18 +2499,18 @@ func QueryStoreManageData(req *ErpOrderStoreManageDataReq, c *gin.Context) (*Erp
resp.TotalCount = summary.TotalCount
if req.IsExport == 1 { //导出excel
storeName := "所有门店"
if req.StoreId != 0 {
storeInfo, err := GetStore(req.StoreId)
if err != nil {
logger.Error("GetStore err:", logger.Field("err", err))
return nil, err
}
storeName = storeInfo.Name
}
//storeName := "所有门店"
//if req.StoreId != 0 {
// storeInfo, err := GetStore(req.StoreId)
// if err != nil {
// logger.Error("GetStore err:", logger.Field("err", err))
// return nil, err
// }
// storeName = storeInfo.Name
//}
finalStoreManageDataList = constructFinalStoreManageDataList(storeManageDataList, req)
filePath, err := storeManageDataExport(finalStoreManageDataList, storeName, summary, c)
filePath, err := storeManageDataExport(finalStoreManageDataList, "门店", summary, c)
if err != nil {
logger.Error("StoreManageDataExport err:", logger.Field("err", err))
return nil, err

View File

@ -787,40 +787,72 @@ func MergeCommodities(commodities []ErpInventoryAllotCommodity) []ErpInventoryAl
return mergedCommodities
}
// UpdateStockCounts 根据传入的 storeId 更新每个商品的库存数量。
// UpdateStockCounts 根据商品类型(串码或非串码)以及 storeId 更新每个商品的库存数量。
func UpdateStockCounts(commodities []ErpInventoryAllotCommodity, storeId uint32) ([]ErpInventoryAllotCommodity, error) {
// 收集商品 ID
var commodityIDs []uint32
for _, commodity := range commodities {
commodityIDs = append(commodityIDs, commodity.CommodityId)
}
// 创建映射表,分开存储串码商品和非串码商品
imeiMap := make(map[string]*ErpInventoryAllotCommodity) // 串码商品
nonImeiMap := make(map[uint32]*ErpInventoryAllotCommodity) // 非串码商品
// 查询数据库中的库存数量
var stockCounts []struct {
ErpCommodityID uint32 `gorm:"column:erp_commodity_id"`
StockCount int64 `gorm:"column:stock_count"`
}
err := orm.Eloquent.Table("erp_stock_commodity").
Where("erp_commodity_id IN (?) AND state = ? AND store_id = ?", commodityIDs, InStock, storeId).
Select("erp_commodity_id, COUNT(*) as stock_count").
Group("erp_commodity_id").
Scan(&stockCounts).Error
if err != nil {
return nil, err
}
// 创建库存数量映射
stockCountMap := make(map[uint32]int64)
for _, stock := range stockCounts {
stockCountMap[stock.ErpCommodityID] = stock.StockCount
}
// 更新商品的 StockCount 字段
// 将商品按串码和非串码分开
for i, commodity := range commodities {
if count, exists := stockCountMap[commodity.CommodityId]; exists {
commodities[i].StockCount = uint32(count)
} else {
commodities[i].StockCount = 0 // 如果没有库存记录,则默认为 0
if commodity.IMEIType == 2 {
imeiMap[commodity.IMEI] = &commodities[i]
} else if commodity.IMEIType == 1 {
nonImeiMap[commodity.CommodityId] = &commodities[i]
}
}
// 查询串码商品的库存数量
if len(imeiMap) > 0 {
var imeiKeys []string
for imei := range imeiMap {
imeiKeys = append(imeiKeys, imei)
}
var stockCounts []struct {
IMEI string `gorm:"column:imei"`
StockCount int64 `gorm:"column:stock_count"`
}
err := orm.Eloquent.Table("erp_stock_commodity").
Where("imei IN (?) AND state = ?", imeiKeys, InStock).
Select("imei, COUNT(*) as stock_count").
Group("imei").
Scan(&stockCounts).Error
if err != nil {
return nil, err
}
for _, stock := range stockCounts {
if commodity, exists := imeiMap[stock.IMEI]; exists {
commodity.StockCount = uint32(stock.StockCount)
}
}
}
// 查询非串码商品的库存数量
if len(nonImeiMap) > 0 {
var commodityIDs []uint32
for id := range nonImeiMap {
commodityIDs = append(commodityIDs, id)
}
var stockCounts []struct {
ErpCommodityID uint32 `gorm:"column:erp_commodity_id"`
StockCount int64 `gorm:"column:stock_count"`
}
err := orm.Eloquent.Table("erp_stock_commodity").
Where("erp_commodity_id IN (?) AND store_id = ? AND state = ?", commodityIDs, storeId, InStock).
Select("erp_commodity_id, COUNT(*) as stock_count").
Group("erp_commodity_id").
Scan(&stockCounts).Error
if err != nil {
return nil, err
}
for _, stock := range stockCounts {
if commodity, exists := nonImeiMap[stock.ErpCommodityID]; exists {
commodity.StockCount = uint32(stock.StockCount)
}
}
}

View File

@ -1254,7 +1254,7 @@ func CheckAndUpdatePurchaseOrderState(orderId uint32) error {
if order.PurchaseType == ErpProcureOrder && commodity.Count != uint32(commodity.InventoryCount) {
if err := orm.Eloquent.Model(&order).Updates(map[string]interface{}{
"state": ErpPurchaseOrderWaitInventory,
"audit_time": time.Now(),
"updated_at": time.Now(),
}).Error; err != nil {
return err
}
@ -1263,7 +1263,7 @@ func CheckAndUpdatePurchaseOrderState(orderId uint32) error {
if order.PurchaseType == ErpRejectOrder && commodity.RejectedCount != uint32(commodity.InventoryCount) {
if err := orm.Eloquent.Model(&order).Updates(map[string]interface{}{
"state": ErpPurchaseOrderWaitReject,
"audit_time": time.Now(),
"updated_at": time.Now(),
}).Error; err != nil {
return err
}
@ -1275,7 +1275,7 @@ func CheckAndUpdatePurchaseOrderState(orderId uint32) error {
if err := orm.Eloquent.Model(&order).
Updates(map[string]interface{}{
"state": ErpPurchaseOrderFinished,
"audit_time": time.Now(),
"updated_at": time.Now(),
}).Error; err != nil {
return err
}
@ -3414,32 +3414,35 @@ func getReportByOrderFromCommon(req *ErpPurchaseReportByOrderReq, c *gin.Context
PageIndex: page + 1,
PageSize: req.PageSize,
}
qs := orm.Eloquent.Table("erp_purchase_order").Where("state != ?", ErpPurchaseOrderUnAudit) // 未审核订单不展示
if req.SerialNumber != "" { // 单据编号
qs = qs.Where("serial_number=?", req.SerialNumber)
qs := orm.Eloquent.Table("erp_purchase_order").
Joins("JOIN erp_purchase_commodity ON erp_purchase_order.id = erp_purchase_commodity.erp_purchase_order_id").
Where("erp_purchase_order.state != ?", ErpPurchaseOrderUnAudit). // 未审核订单不展示
Where("NOT (erp_purchase_order.state = 2 AND erp_purchase_commodity.inventory_count = 0)") // 排除 commodity 表中 state=2 且 inventory_count = 0 的记录
if req.SerialNumber != "" { // 单据编号
qs = qs.Where("erp_purchase_order.serial_number=?", req.SerialNumber)
}
if req.PurchaseType != "" { // 采购类型
qs = qs.Where("purchase_type=?", req.PurchaseType)
qs = qs.Where("erp_purchase_order.purchase_type=?", req.PurchaseType)
}
if len(req.ErpSupplierId) > 0 { // 供应商复选
var supplierIDs []uint32
for _, supplier := range req.ErpSupplierId {
supplierIDs = append(supplierIDs, supplier)
}
qs = qs.Where("erp_supplier_id IN (?)", supplierIDs)
qs = qs.Where("erp_purchase_order.erp_supplier_id IN (?)", supplierIDs)
}
if len(req.StoreId) > 0 { // 门店复选
var storeIDs []uint32
for _, store := range req.StoreId {
storeIDs = append(storeIDs, store)
}
qs = qs.Where("store_id IN (?)", storeIDs)
qs = qs.Where("erp_purchase_order.store_id IN (?)", storeIDs)
}
if req.HandlerId != 0 { // 经手人id
qs = qs.Where("handler_id=?", req.HandlerId)
qs = qs.Where("erp_purchase_order.handler_id=?", req.HandlerId)
}
if req.State != 0 { // 订单状态
qs = qs.Where("state=?", req.State)
qs = qs.Where("erp_purchase_order.state=?", req.State)
}
if req.AuditTimeStart != "" { // 审核开始时间
parse, err := time.Parse(QueryTimeFormat, req.AuditTimeStart)
@ -3447,7 +3450,7 @@ func getReportByOrderFromCommon(req *ErpPurchaseReportByOrderReq, c *gin.Context
logger.Errorf("erpPurchaseOrderList err:", err)
return nil, err
}
qs = qs.Where("audit_time > ?", parse)
qs = qs.Where("erp_purchase_order.audit_time > ?", parse)
}
if req.AuditTimeEnd != "" { // 审核结束时间
parse, err := time.Parse(QueryTimeFormat, req.AuditTimeEnd)
@ -3456,11 +3459,11 @@ func getReportByOrderFromCommon(req *ErpPurchaseReportByOrderReq, c *gin.Context
return nil, err
}
//parse = parse.AddDate(0, 0, 1)
qs = qs.Where("audit_time < ?", parse)
qs = qs.Where("erp_purchase_order.audit_time < ?", parse)
}
var count int64
err := qs.Count(&count).Error
err := qs.Distinct("erp_purchase_order.id").Count(&count).Error
if err != nil {
logger.Error("getReportByOrderFromCommon count err:", logger.Field("err", err))
return resp, err
@ -3468,9 +3471,10 @@ func getReportByOrderFromCommon(req *ErpPurchaseReportByOrderReq, c *gin.Context
resp.Total = int(count)
var orders []ErpPurchaseOrder
if req.ErpCategoryID != 0 || req.ErpCommodityName != "" || req.IsExport == 1 {
err = qs.Order("id DESC").Find(&orders).Error
err = qs.Order("erp_purchase_order.id DESC").Distinct("erp_purchase_order.*").Find(&orders).Error
} else {
err = qs.Order("id DESC").Offset(page * req.PageSize).Limit(req.PageSize).Find(&orders).Error
err = qs.Order("erp_purchase_order.id DESC").Distinct("erp_purchase_order.*").
Offset(page * req.PageSize).Limit(req.PageSize).Find(&orders).Error
}
if err != nil && err != RecordNotFound {
logger.Error("getReportByOrderFromCommon erp_purchase_order err:", logger.Field("err", err))
@ -4175,7 +4179,8 @@ func getReportByCommodityFromCommon(req *ErpPurchaseReportByCommodityReq, c *gin
PageIndex: page + 1,
PageSize: req.PageSize,
}
qs := orm.Eloquent.Table("erp_purchase_order").Where("state != ?", ErpPurchaseOrderUnAudit)
qs := orm.Eloquent.Table("erp_purchase_order").
Where("state NOT IN (?, ?)", ErpPurchaseOrderUnAudit, ErpPurchaseOrderEnd)
if req.SerialNumber != "" { // 单据编号
qs = qs.Where("serial_number=?", req.SerialNumber)
}

View File

@ -8695,6 +8695,10 @@ const docTemplate = `{
"description": "备注",
"type": "string"
},
"stock_count": {
"description": "库存数量",
"type": "integer"
},
"updatedAt": {
"description": "更新时间",
"type": "string"
@ -10089,7 +10093,10 @@ const docTemplate = `{
},
"store_id": {
"description": "门店ID",
"type": "integer"
"type": "array",
"items": {
"type": "integer"
}
}
}
},
@ -10292,9 +10299,25 @@ const docTemplate = `{
"description": "商品名称",
"type": "string"
},
"first_erp_category_id": {
"description": "商品一级分类id",
"type": "integer"
},
"first_erp_category_name": {
"description": "商品一级分类名称",
"type": "string"
},
"price": {
"description": "已执行单价",
"type": "number"
},
"second_erp_category_id": {
"description": "商品二级分类id",
"type": "integer"
},
"second_erp_category_name": {
"description": "商品二级分类名称",
"type": "string"
}
}
},
@ -10862,6 +10885,10 @@ const docTemplate = `{
"type": "integer"
}
},
"first_erp_category_id": {
"description": "商品一级分类id",
"type": "integer"
},
"handler_id": {
"description": "经手人id",
"type": "integer"
@ -10882,6 +10909,10 @@ const docTemplate = `{
"description": "采购类型procure-采购 reject-退货",
"type": "string"
},
"second_erp_category_id": {
"description": "商品二级分类id",
"type": "integer"
},
"serial_number": {
"description": "单据编号",
"type": "string"
@ -15352,6 +15383,14 @@ const docTemplate = `{
"description": "商品名称",
"type": "string"
},
"first_erp_category_id": {
"description": "商品一级分类id",
"type": "integer"
},
"first_erp_category_name": {
"description": "商品一级分类名称",
"type": "string"
},
"non_execution_amount": {
"description": "未执行金额",
"type": "number"
@ -15386,6 +15425,14 @@ const docTemplate = `{
"price": {
"description": "已执行单价",
"type": "number"
},
"second_erp_category_id": {
"description": "商品二级分类id",
"type": "integer"
},
"second_erp_category_name": {
"description": "商品二级分类名称",
"type": "string"
}
}
},

View File

@ -8684,6 +8684,10 @@
"description": "备注",
"type": "string"
},
"stock_count": {
"description": "库存数量",
"type": "integer"
},
"updatedAt": {
"description": "更新时间",
"type": "string"
@ -10078,7 +10082,10 @@
},
"store_id": {
"description": "门店ID",
"type": "integer"
"type": "array",
"items": {
"type": "integer"
}
}
}
},
@ -10281,9 +10288,25 @@
"description": "商品名称",
"type": "string"
},
"first_erp_category_id": {
"description": "商品一级分类id",
"type": "integer"
},
"first_erp_category_name": {
"description": "商品一级分类名称",
"type": "string"
},
"price": {
"description": "已执行单价",
"type": "number"
},
"second_erp_category_id": {
"description": "商品二级分类id",
"type": "integer"
},
"second_erp_category_name": {
"description": "商品二级分类名称",
"type": "string"
}
}
},
@ -10851,6 +10874,10 @@
"type": "integer"
}
},
"first_erp_category_id": {
"description": "商品一级分类id",
"type": "integer"
},
"handler_id": {
"description": "经手人id",
"type": "integer"
@ -10871,6 +10898,10 @@
"description": "采购类型procure-采购 reject-退货",
"type": "string"
},
"second_erp_category_id": {
"description": "商品二级分类id",
"type": "integer"
},
"serial_number": {
"description": "单据编号",
"type": "string"
@ -15341,6 +15372,14 @@
"description": "商品名称",
"type": "string"
},
"first_erp_category_id": {
"description": "商品一级分类id",
"type": "integer"
},
"first_erp_category_name": {
"description": "商品一级分类名称",
"type": "string"
},
"non_execution_amount": {
"description": "未执行金额",
"type": "number"
@ -15375,6 +15414,14 @@
"price": {
"description": "已执行单价",
"type": "number"
},
"second_erp_category_id": {
"description": "商品二级分类id",
"type": "integer"
},
"second_erp_category_name": {
"description": "商品二级分类名称",
"type": "string"
}
}
},

View File

@ -1757,6 +1757,9 @@ definitions:
remark:
description: 备注
type: string
stock_count:
description: 库存数量
type: integer
updatedAt:
description: 更新时间
type: string
@ -2778,7 +2781,9 @@ definitions:
type: string
store_id:
description: 门店ID
type: integer
items:
type: integer
type: array
type: object
models.ErpOrderStoreManageDataResp:
properties:
@ -2926,9 +2931,21 @@ definitions:
erp_commodity_name:
description: 商品名称
type: string
first_erp_category_id:
description: 商品一级分类id
type: integer
first_erp_category_name:
description: 商品一级分类名称
type: string
price:
description: 已执行单价
type: number
second_erp_category_id:
description: 商品二级分类id
type: integer
second_erp_category_name:
description: 商品二级分类名称
type: string
type: object
models.ErpPurchaseCreateReq:
properties:
@ -3342,6 +3359,9 @@ definitions:
items:
type: integer
type: array
first_erp_category_id:
description: 商品一级分类id
type: integer
handler_id:
description: 经手人id
type: integer
@ -3357,6 +3377,9 @@ definitions:
purchase_type:
description: 采购类型procure-采购 reject-退货
type: string
second_erp_category_id:
description: 商品二级分类id
type: integer
serial_number:
description: 单据编号
type: string
@ -6569,6 +6592,12 @@ definitions:
erp_commodity_name:
description: 商品名称
type: string
first_erp_category_id:
description: 商品一级分类id
type: integer
first_erp_category_name:
description: 商品一级分类名称
type: string
non_execution_amount:
description: 未执行金额
type: number
@ -6595,6 +6624,12 @@ definitions:
price:
description: 已执行单价
type: number
second_erp_category_id:
description: 商品二级分类id
type: integer
second_erp_category_name:
description: 商品二级分类名称
type: string
type: object
models.ReportByOrderData:
properties: