1.新增接口:库存调拨汇总、库存调拨明细

This commit is contained in:
chenlin 2024-04-23 18:20:49 +08:00
parent a51445ecb0
commit 49970e13d2
3 changed files with 707 additions and 28 deletions

View File

@ -51,7 +51,14 @@ func InventoryReportByAllot(c *gin.Context) {
return
}
app.OK(c, "", "OK")
resp, err := req.ReportAllotList(c)
if err != nil {
//logger.Error("erp commodity list err:", err)
app.Error(c, http.StatusInternalServerError, err, "查询失败:"+err.Error())
return
}
app.OK(c, resp, "OK")
return
}
@ -70,7 +77,14 @@ func InventoryReportAllotDetail(c *gin.Context) {
return
}
app.OK(c, "", "OK")
resp, err := req.ReportAllotDetailList(c)
if err != nil {
//logger.Error("erp commodity list err:", err)
app.Error(c, http.StatusInternalServerError, err, "查询失败:"+err.Error())
return
}
app.OK(c, resp, "OK")
return
}

View File

@ -45,13 +45,14 @@ type ErpInventoryAllotOrder struct {
// ErpInventoryAllotCommodity 库存调拨商品信息表
type ErpInventoryAllotCommodity struct {
Model
AllotOrderId uint32 `json:"allot_order_id" gorm:"index"` // 库存调拨订单表id
CommodityId uint32 `json:"commodity_id" gorm:"index"` // 商品id
CommodityName string `json:"commodity_name"` // 商品名称
IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码
IMEI string `json:"imei"` // 商品串码
Count uint32 `json:"count"` // 数量
Remark string `json:"remark"` // 备注
AllotOrderId uint32 `json:"allot_order_id" gorm:"index"` // 库存调拨订单表id
CommodityId uint32 `json:"commodity_id" gorm:"index"` // 商品id
CommodityName string `json:"commodity_name"` // 商品名称
IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码
IMEI string `json:"imei"` // 商品串码
Count uint32 `json:"count"` // 数量
Amount float64 `json:"amount"` // 金额(采购价)
Remark string `json:"remark"` // 备注
}
// InventoryAllotAddReq 新增库存调拨入参
@ -584,7 +585,7 @@ func allotAuditAndUpdateStock(gdb *gorm.DB, allotOrder ErpInventoryAllotOrder) e
var stockCommodity []ErpStockCommodity
err = orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? AND store_id = ? "+
"AND state = ? AND imei = ?", v.CommodityId, allotOrder.DeliverStoreId, InStock, v.IMEI).
Find(&stockCommodity).Error
Order("first_stock_time ASC").Find(&stockCommodity).Error
if err != nil {
return fmt.Errorf("审核失败,查询商品库存失败:[%s]", err.Error())
}
@ -599,6 +600,7 @@ func allotAuditAndUpdateStock(gdb *gorm.DB, allotOrder ErpInventoryAllotOrder) e
}
// 更新库存商品表商品状态为:调拨中
var nAmount float64
for i := 0; i < int(v.Count); i++ {
stockCommodity[i].StoreId = allotOrder.ReceiveStoreId
stockCommodity[i].StoreName = allotOrder.ReceiveStoreName
@ -607,6 +609,17 @@ func allotAuditAndUpdateStock(gdb *gorm.DB, allotOrder ErpInventoryAllotOrder) e
Updates(stockCommodity[i]).Error; err != nil {
return fmt.Errorf("审核失败,更新商品库存失败:%s", err.Error())
}
nAmount += stockCommodity[i].WholesalePrice
}
// 更新库存调拨商品信息表的调拨金额
err = gdb.Table("erp_inventory_allot_commodity").Where("id = ?", v.ID).
Updates(map[string]interface{}{
"amount": nAmount,
}).Error
if err != nil {
logger.Errorf("update erp_inventory_allot_commodity amount err:", err)
return err
}
// 更新库存商品数量
@ -645,8 +658,8 @@ func allotAuditAndUpdateStock(gdb *gorm.DB, allotOrder ErpInventoryAllotOrder) e
IMEIType: v.IMEIType,
RetailPrice: stockCommodity[0].RetailPrice,
MinRetailPrice: stockCommodity[0].MinRetailPrice,
Count: v.Count,
DispatchCount: 0,
Count: 0,
DispatchCount: v.Count,
}
err = gdb.Create(stock).Error
if err != nil {

View File

@ -9,6 +9,7 @@ import (
"go-admin/logger"
"go-admin/tools"
"go-admin/tools/config"
"sort"
"strconv"
"time"
)
@ -83,24 +84,26 @@ type InventoryReportByAllotResp struct {
// ReportByAllotData 库存调拨数据
type ReportByAllotData struct {
DeliverStoreId uint32 `json:"deliver_store_id"` // 调出门店id
DeliverStoreName string `json:"deliver_store_name"` // 调出门店名称
ReceiveStoreId uint32 `json:"receive_store_id"` // 调入门店id
ReceiveStoreName string `json:"receive_store_name"` // 调入门店名称
CommodityId uint32 `json:"commodity_id"` // 商品id
CommodityName string `json:"commodity_name"` // 商品名称
CategoryID uint32 `json:"category_id"` // 商品分类id
CategoryName string `json:"category_name"` // 商品分类名称
State uint32 `json:"state"` // 调拨状态1-调拨中 2-已完成
AllotCount uint32 `json:"allot_count"` // 调拨数量
AllotAmount float64 `json:"allot_amount"` // 调拨金额
DeliverStoreId uint32 `json:"deliver_store_id"` // 调出门店id
DeliverStoreName string `json:"deliver_store_name"` // 调出门店名称
ReceiveStoreId uint32 `json:"receive_store_id"` // 调入门店id
ReceiveStoreName string `json:"receive_store_name"` // 调入门店名称
CommodityId uint32 `json:"commodity_id"` // 商品id
CommodityName string `json:"commodity_name"` // 商品名称
CategoryID uint32 `json:"category_id"` // 商品分类id
CategoryName string `json:"category_name"` // 商品分类名称
AuditTime *time.Time `json:"audit_time"` // 审核时间
ReceiveTime *time.Time `json:"receive_time"` // 收货时间/调入时间
State uint32 `json:"state"` // 调拨状态1-调拨中 2-已完成
AllotCount uint32 `json:"allot_count"` // 调拨数量
AllotAmount float64 `json:"allot_amount"` // 调拨金额
}
// InventoryReportAllotDetailReq 库存调拨明细入参
type InventoryReportAllotDetailReq struct {
SerialNumber string `json:"serial_number"` // 单据编号
DeliverStoreId uint32 `json:"deliver_store_id"` // 调出门店id
ReceiveStoreId uint32 `json:"receive_store_id"` // 调入门店id
DeliverStoreId []uint32 `json:"deliver_store_id"` // 调出门店id
ReceiveStoreId []uint32 `json:"receive_store_id"` // 调入门店id
CommodityName []string `json:"commodity_name"` // 商品名称
CategoryID []uint32 `json:"category_id"` // 商品分类id
State uint32 `json:"state"` // 调拨状态1-调拨中 2-已完成
@ -115,7 +118,7 @@ type InventoryReportAllotDetailReq struct {
// InventoryReportAllotDetailResp 库存调拨明细出参
type InventoryReportAllotDetailResp struct {
Total int `json:"total"` // 总条数/记录数
Total int64 `json:"total"` // 总条数/记录数
PageIndex int `json:"pageIndex"` // 页码
PageSize int `json:"pageSize"` // 页面条数
ExportUrl string `json:"export_url"` // 导出excel路径
@ -131,6 +134,7 @@ type ReportAllotDetailData struct {
ReceiveStoreName string `json:"receive_store_name"` // 调入门店名称
MakerTime *time.Time `json:"maker_time"` // 制单时间/发起时间
AuditTime *time.Time `json:"audit_time"` // 审核时间
ReceiveTime *time.Time `json:"receive_time"` // 收货时间/调入时间
State uint32 `json:"state"` // 调拨状态1-调拨中 2-已完成
CommodityId uint32 `json:"commodity_id"` // 商品id
CommodityName string `json:"commodity_name"` // 商品名称
@ -138,6 +142,7 @@ type ReportAllotDetailData struct {
CategoryName string `json:"category_name"` // 商品分类名称
IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码
IMEI string `json:"imei"` // 商品串码
Remark string `json:"remark"` // 备注
}
// InventoryReportByOtherReq 其他出入库汇总入参
@ -297,9 +302,9 @@ func (m *InventoryReportByProductReq) ReportByProductList(c *gin.Context) (*Inve
var commodities []ErpStock
if m.IsExport == 1 { // 导出excel
err = qs.Find(&commodities).Error
err = qs.Order("erp_commodity_id, store_id desc").Find(&commodities).Error
} else {
err = qs.Offset(page * m.PageSize).Limit(m.PageSize).Find(&commodities).Error
err = qs.Order("erp_commodity_id, store_id desc").Offset(page * m.PageSize).Limit(m.PageSize).Find(&commodities).Error
}
if err != nil && err != RecordNotFound {
logger.Error("查询无库存列表失败", logger.Field("err", err))
@ -498,3 +503,650 @@ func reportByProductExport(req *InventoryReportByProductResp) (string, error) {
}
return url + fileName, nil
}
// ReportAllotList 库存调拨汇总
func (m *InventoryReportByAllotReq) ReportAllotList(c *gin.Context) (*InventoryReportByAllotResp, error) {
// 非管理员才判断所属门店
if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
sysUser, err := GetSysUserByCtx(c)
if err != nil {
return nil, errors.New("操作失败:" + err.Error())
}
// 返回sysUser未过期的门店id列表
storeList := GetValidStoreIDs(sysUser.StoreData)
if len(storeList) > 0 {
m.DeliverStoreId = CompareLists(storeList, m.DeliverStoreId)
m.ReceiveStoreId = CompareLists(storeList, m.ReceiveStoreId)
if len(m.DeliverStoreId) == 0 && len(m.ReceiveStoreId) == 0 { // 没有匹配的数据,表示入参门店不是用户有权限的门店
return &InventoryReportByAllotResp{}, nil
}
} else {
return nil, errors.New("用户未绑定门店")
}
}
resp := &InventoryReportByAllotResp{
PageIndex: m.PageIndex,
PageSize: m.PageSize,
}
page := m.PageIndex - 1
if page < 0 {
page = 0
}
if m.PageSize == 0 {
m.PageSize = 10
}
qs := orm.Eloquent.Debug().Table("erp_inventory_allot_order").
Select("erp_inventory_allot_order.deliver_store_id, "+
"erp_inventory_allot_order.deliver_store_name, "+
"erp_inventory_allot_order.receive_store_id, "+
"erp_inventory_allot_order.receive_store_name, "+
"erp_inventory_allot_order.audit_time, "+
"erp_inventory_allot_order.receive_time, "+
"CASE "+
"WHEN erp_inventory_allot_order.state IN (2, 3) THEN 1 "+
"WHEN erp_inventory_allot_order.state = 4 THEN 2 "+
"ELSE erp_inventory_allot_order.state "+
"END AS state, "+
"erp_inventory_allot_commodity.commodity_id, "+
"erp_inventory_allot_commodity.commodity_name, "+
"erp_inventory_allot_commodity.count as allot_count, "+
"erp_inventory_allot_commodity.amount as allot_amount").
Joins("JOIN erp_inventory_allot_commodity ON erp_inventory_allot_commodity.allot_order_id = erp_inventory_allot_order.id").
Where("erp_inventory_allot_order.state <> ?", ErpInventoryAllotOrderUnAudit) // 排除待审核的订单
// 创建一个新的查询对象,用于 count 查询
countQuery := orm.Eloquent.Debug().Table("erp_inventory_allot_order").
Joins("JOIN erp_inventory_allot_commodity ON erp_inventory_allot_commodity.allot_order_id = erp_inventory_allot_order.id").
Where("erp_inventory_allot_order.state <> ?", ErpInventoryAllotOrderUnAudit) // 排除待审核的订单
if len(m.DeliverStoreId) > 0 { // 调出门店id复选
var storeIDs []uint32
for _, store := range m.DeliverStoreId {
storeIDs = append(storeIDs, store)
}
qs = qs.Where("erp_inventory_allot_order.deliver_store_id IN (?)", storeIDs)
countQuery = countQuery.Where("erp_inventory_allot_order.deliver_store_id IN (?)", storeIDs)
}
if len(m.ReceiveStoreId) > 0 { // 调入门店id复选
var storeIDs []uint32
for _, store := range m.ReceiveStoreId {
storeIDs = append(storeIDs, store)
}
qs = qs.Where("erp_inventory_allot_order.receive_store_id IN (?)", storeIDs)
countQuery = countQuery.Where("erp_inventory_allot_order.receive_store_id IN (?)", storeIDs)
}
if len(m.CommodityName) > 0 { // 商品名称
var commodityNames []string
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)
}
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 {
case 1: // 调拨中
qs = qs.Where("erp_inventory_allot_order.state IN (?)",
ErpInventoryAllotOrderWaitSend, ErpInventoryAllotOrderWaitReceive)
countQuery = countQuery.Where("erp_inventory_allot_order.state IN (?)",
ErpInventoryAllotOrderWaitSend, ErpInventoryAllotOrderWaitReceive)
case 2: // 已完成
qs = qs.Where("erp_inventory_allot_order.state = ?", ErpInventoryAllotOrderFinished)
countQuery = countQuery.Where("erp_inventory_allot_order.state = ?", ErpInventoryAllotOrderFinished)
}
}
if m.AuditTimeStart != "" { // 审核开始时间
parse, err := time.Parse(QueryTimeFormat, m.AuditTimeStart)
if err != nil {
logger.Errorf("ReportAllotList err:", err)
return nil, err
}
qs = qs.Where("erp_inventory_allot_order.audit_time > ?", parse)
countQuery = countQuery.Where("erp_inventory_allot_order.audit_time > ?", parse)
}
if m.AuditTimeEnd != "" { // 审核结束时间
parse, err := time.Parse(QueryTimeFormat, m.AuditTimeEnd)
if err != nil {
logger.Errorf("ReportAllotList err:", err)
return nil, err
}
qs = qs.Where("erp_inventory_allot_order.audit_time < ?", parse)
countQuery = countQuery.Where("erp_inventory_allot_order.audit_time < ?", parse)
}
if m.ReceiveTimeStart != "" { // 调入开始时间
parse, err := time.Parse(QueryTimeFormat, m.ReceiveTimeStart)
if err != nil {
logger.Errorf("ReportAllotList err:", err)
return nil, err
}
qs = qs.Where("erp_inventory_allot_order.receive_time > ?", parse)
countQuery = countQuery.Where("erp_inventory_allot_order.receive_time > ?", parse)
}
if m.ReceiveTimeEnd != "" { // 调入结束时间
parse, err := time.Parse(QueryTimeFormat, m.ReceiveTimeEnd)
if err != nil {
logger.Errorf("ReportAllotList err:", err)
return nil, err
}
qs = qs.Where("erp_inventory_allot_order.receive_time < ?", parse)
countQuery = countQuery.Where("erp_inventory_allot_order.receive_time < ?", parse)
}
var count int64
err := countQuery.Count(&count).Error
if err != nil {
logger.Error("ReportAllotList 查询失败", logger.Field("err", err))
return nil, err
}
var commodities []ReportByAllotData
err = qs.Find(&commodities).Error
if err != nil {
return nil, err
}
var nTotalAllotCount uint32
var nTotalAllotAmount float64
// 创建 map 用于存储汇总数据
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)
// 检查是否已经存在该键的汇总数据
if summary, ok := summaryMap[key]; ok {
// 如果已经存在,累加调拨数量和调拨金额
summary.AllotCount += item.AllotCount
// 假设商品金额在 item.CommodityAmount 中
summary.AllotAmount += item.AllotAmount
} else {
// 如果不存在,创建新的汇总数据并添加到 map 中
summaryMap[key] = &ReportByAllotData{
DeliverStoreId: item.DeliverStoreId,
DeliverStoreName: item.DeliverStoreName,
ReceiveStoreId: item.ReceiveStoreId,
ReceiveStoreName: item.ReceiveStoreName,
CommodityId: item.CommodityId,
CommodityName: item.CommodityName,
CategoryID: item.CategoryID,
CategoryName: item.CategoryName,
AuditTime: item.AuditTime,
ReceiveTime: item.ReceiveTime,
State: item.State, // 调拨中状态为 1
AllotCount: item.AllotCount, // 初始化为 1
AllotAmount: item.AllotAmount,
}
}
}
var summaryList []ReportByAllotData
for i, summary := range summaryMap {
// 添加分类信息
commodityInfo, err := GetCommodity(summary.CommodityId)
if err != nil {
logger.Error("SetCategory err:", logger.Field("err", err))
}
summaryMap[i].CategoryID = commodityInfo.ErpCategoryId
summaryMap[i].CategoryName = commodityInfo.ErpCategoryName
summaryList = append(summaryList, *summary)
}
// 排序规则:商品编号小>调出店铺编号小>调入门店编号小>状态为已完成
sort.Slice(summaryList, func(i, j int) bool {
if summaryList[i].CommodityId != summaryList[j].CommodityId {
return summaryList[i].CommodityId < summaryList[j].CommodityId
}
if summaryList[i].DeliverStoreId != summaryList[j].DeliverStoreId {
return summaryList[i].DeliverStoreId < summaryList[j].DeliverStoreId
}
if summaryList[i].ReceiveStoreId != summaryList[j].ReceiveStoreId {
return summaryList[i].ReceiveStoreId < summaryList[j].ReceiveStoreId
}
return summaryList[i].State < summaryList[j].State
})
// 计算分页所需的切片索引
startIndex := page * m.PageSize
endIndex := (page + 1) * m.PageSize
if endIndex > len(summaryList) {
endIndex = len(summaryList)
}
resp.Total = len(summaryMap)
resp.TotalAllotCount = nTotalAllotCount
resp.TotalAllotAmount = nTotalAllotAmount
resp.List = summaryList[startIndex:endIndex]
if m.IsExport == 1 {
resp.ExportUrl, err = reportAllotExport(resp)
if err != nil {
return nil, err
}
resp.List = []ReportByAllotData{}
}
return resp, nil
}
// reportAllotExport 库存调拨汇总导出excel
func reportAllotExport(req *InventoryReportByAllotResp) (string, error) {
file := excelize.NewFile()
fSheet := "Sheet1"
url := ExportUrl
fileName := time.Now().Format(TimeFormat) + "库存调拨汇总" + ".xlsx"
fmt.Println("url fileName:", url+fileName)
// 组合标题栏数据
title := []interface{}{"调出门店", "调入门店", "商品名称", "商品分类", "调拨状态", "调拨数量", "调拨金额"}
for i, _ := range title {
cell, _ := excelize.CoordinatesToCellName(1+i, 1)
err := file.SetCellValue(fSheet, cell, title[i])
if err != nil {
logger.Error("file set value err:", logger.Field("err", err))
}
}
var row1 []interface{}
nExcelStartRow := 0
for _, reportData := range req.List {
var allotState string
switch reportData.State {
case 1: // 调拨中
allotState = "调拨中"
case 2: // 已完成
allotState = "已完成"
}
row1 = []interface{}{
reportData.DeliverStoreName, // 调出门店
reportData.ReceiveStoreName, // 调入门店
reportData.CommodityName, // 商品名称
reportData.CategoryName, // 商品分类
allotState, // 调拨状态
reportData.AllotCount, // 调拨数量
reportData.AllotAmount, // 调拨金额
}
for j, _ := range row1 {
cell, _ := excelize.CoordinatesToCellName(1+j, nExcelStartRow+2)
err := file.SetCellValue(fSheet, cell, row1[j])
if err != nil {
logger.Error("file set value err:", logger.Field("err", err))
}
}
nExcelStartRow++
}
totalData := "记录数:" + strconv.FormatInt(int64(req.Total), 10)
end := []interface{}{totalData, "", "", "", "", req.TotalAllotCount, req.TotalAllotAmount}
for i, _ := range end {
cell, _ := excelize.CoordinatesToCellName(1+i, nExcelStartRow+2)
err := file.SetCellValue(fSheet, cell, end[i])
if err != nil {
logger.Error("file set value err:", logger.Field("err", err))
}
}
// 设置所有单元格的样式: 居中、加边框
style, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"},
"border":[{"type":"left","color":"000000","style":1},
{"type":"top","color":"000000","style":1},
{"type":"right","color":"000000","style":1},
{"type":"bottom","color":"000000","style":1}]}`)
//设置单元格高度
file.SetRowHeight("Sheet1", 1, 20)
// 设置单元格大小
file.SetColWidth("Sheet1", "A", "A", 28)
file.SetColWidth("Sheet1", "B", "B", 28)
file.SetColWidth("Sheet1", "C", "C", 23)
file.SetColWidth("Sheet1", "D", "D", 15)
endRow := fmt.Sprintf("G"+"%d", nExcelStartRow+2)
// 应用样式到整个表格
_ = file.SetCellStyle("Sheet1", "A1", endRow, style)
fmt.Println("save fileName:", config.ExportConfig.Path+fileName)
if err := file.SaveAs(config.ExportConfig.Path + fileName); err != nil {
fmt.Println(err)
}
return url + fileName, nil
}
// ReportAllotDetailList 库存调拨明细
func (m *InventoryReportAllotDetailReq) ReportAllotDetailList(c *gin.Context) (*InventoryReportAllotDetailResp, error) {
// 非管理员才判断所属门店
if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
sysUser, err := GetSysUserByCtx(c)
if err != nil {
return nil, errors.New("操作失败:" + err.Error())
}
// 返回sysUser未过期的门店id列表
storeList := GetValidStoreIDs(sysUser.StoreData)
if len(storeList) > 0 {
m.DeliverStoreId = CompareLists(storeList, m.DeliverStoreId)
m.ReceiveStoreId = CompareLists(storeList, m.ReceiveStoreId)
if len(m.DeliverStoreId) == 0 && len(m.ReceiveStoreId) == 0 { // 没有匹配的数据,表示入参门店不是用户有权限的门店
return &InventoryReportAllotDetailResp{}, nil
}
} else {
return nil, errors.New("用户未绑定门店")
}
}
resp := &InventoryReportAllotDetailResp{
PageIndex: m.PageIndex,
PageSize: m.PageSize,
}
page := m.PageIndex - 1
if page < 0 {
page = 0
}
if m.PageSize == 0 {
m.PageSize = 10
}
qs := orm.Eloquent.Debug().Table("erp_inventory_allot_order").
Select("erp_inventory_allot_order.serial_number, "+
"erp_inventory_allot_order.deliver_store_id, "+
"erp_inventory_allot_order.deliver_store_name, "+
"erp_inventory_allot_order.receive_store_id, "+
"erp_inventory_allot_order.receive_store_name, "+
"erp_inventory_allot_order.maker_time, "+
"erp_inventory_allot_order.audit_time, "+
"erp_inventory_allot_order.receive_time, "+
"CASE "+
"WHEN erp_inventory_allot_order.state IN (2, 3) THEN 1 "+
"WHEN erp_inventory_allot_order.state = 4 THEN 2 "+
"ELSE erp_inventory_allot_order.state "+
"END AS state, "+
"erp_inventory_allot_commodity.commodity_id, "+
"erp_inventory_allot_commodity.commodity_name, "+
"erp_inventory_allot_commodity.imei_type, "+
"erp_inventory_allot_commodity.imei, "+
"erp_inventory_allot_commodity.count, "+
"erp_inventory_allot_commodity.remark").
Joins("JOIN erp_inventory_allot_commodity ON erp_inventory_allot_commodity.allot_order_id = erp_inventory_allot_order.id").
Where("erp_inventory_allot_order.state <> ?", ErpInventoryAllotOrderUnAudit) // 排除待审核的订单
// 创建一个新的查询对象,用于 count 查询
countQuery := orm.Eloquent.Debug().Table("erp_inventory_allot_order").
Joins("JOIN erp_inventory_allot_commodity ON erp_inventory_allot_commodity.allot_order_id = erp_inventory_allot_order.id").
Where("erp_inventory_allot_order.state <> ?", ErpInventoryAllotOrderUnAudit) // 排除待审核的订单
if m.SerialNumber != "" { // 单据编号
qs = qs.Where("erp_inventory_allot_order.serial_number = ?", m.SerialNumber)
countQuery = countQuery.Where("erp_inventory_allot_order.serial_number = ?", m.SerialNumber)
}
if len(m.DeliverStoreId) > 0 { // 调出门店id复选
var storeIDs []uint32
for _, store := range m.DeliverStoreId {
storeIDs = append(storeIDs, store)
}
qs = qs.Where("erp_inventory_allot_order.deliver_store_id IN (?)", storeIDs)
countQuery = countQuery.Where("erp_inventory_allot_order.deliver_store_id IN (?)", storeIDs)
}
if len(m.ReceiveStoreId) > 0 { // 调入门店id复选
var storeIDs []uint32
for _, store := range m.ReceiveStoreId {
storeIDs = append(storeIDs, store)
}
qs = qs.Where("erp_inventory_allot_order.receive_store_id IN (?)", storeIDs)
countQuery = countQuery.Where("erp_inventory_allot_order.receive_store_id IN (?)", storeIDs)
}
if len(m.CommodityName) > 0 { // 商品名称
var commodityNames []string
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)
}
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 {
case 1: // 调拨中
qs = qs.Where("erp_inventory_allot_order.state IN (?)",
ErpInventoryAllotOrderWaitSend, ErpInventoryAllotOrderWaitReceive)
countQuery = countQuery.Where("erp_inventory_allot_order.state IN (?)",
ErpInventoryAllotOrderWaitSend, ErpInventoryAllotOrderWaitReceive)
case 2: // 已完成
qs = qs.Where("erp_inventory_allot_order.state = ?", ErpInventoryAllotOrderFinished)
countQuery = countQuery.Where("erp_inventory_allot_order.state = ?", ErpInventoryAllotOrderFinished)
}
}
if m.AuditTimeStart != "" { // 审核开始时间
parse, err := time.Parse(QueryTimeFormat, m.AuditTimeStart)
if err != nil {
logger.Errorf("ReportAllotDetailList err:", err)
return nil, err
}
qs = qs.Where("erp_inventory_allot_order.audit_time > ?", parse)
countQuery = countQuery.Where("erp_inventory_allot_order.audit_time > ?", parse)
}
if m.AuditTimeEnd != "" { // 审核结束时间
parse, err := time.Parse(QueryTimeFormat, m.AuditTimeEnd)
if err != nil {
logger.Errorf("ReportAllotDetailList err:", err)
return nil, err
}
qs = qs.Where("erp_inventory_allot_order.audit_time < ?", parse)
countQuery = countQuery.Where("erp_inventory_allot_order.audit_time < ?", parse)
}
if m.ReceiveTimeStart != "" { // 调入开始时间
parse, err := time.Parse(QueryTimeFormat, m.ReceiveTimeStart)
if err != nil {
logger.Errorf("ReportAllotDetailList err:", err)
return nil, err
}
qs = qs.Where("erp_inventory_allot_order.receive_time > ?", parse)
countQuery = countQuery.Where("erp_inventory_allot_order.receive_time > ?", parse)
}
if m.ReceiveTimeEnd != "" { // 调入结束时间
parse, err := time.Parse(QueryTimeFormat, m.ReceiveTimeEnd)
if err != nil {
logger.Errorf("ReportAllotDetailList err:", err)
return nil, err
}
qs = qs.Where("erp_inventory_allot_order.receive_time < ?", parse)
countQuery = countQuery.Where("erp_inventory_allot_order.receive_time < ?", parse)
}
var count int64
err := countQuery.Count(&count).Error
if err != nil {
logger.Error("查询无库存列表数量失败", logger.Field("err", err))
return nil, err
}
var commodities []ReportAllotDetailData
if m.IsExport == 1 { // 导出excel
err = qs.Order("audit_time DESC").Find(&commodities).Error
} else {
err = qs.Order("audit_time DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&commodities).Error
}
if err != nil {
return nil, err
}
// 添加分类信息
reportAllotDetailSetCategory(commodities)
resp.Total = count
resp.List = commodities
if m.IsExport == 1 {
resp.ExportUrl, err = reportAllotDetailExport(resp)
if err != nil {
return nil, err
}
resp.List = []ReportAllotDetailData{}
}
return resp, nil
}
// 添加订单的添加分类信息
func reportAllotDetailSetCategory(list []ReportAllotDetailData) {
for i, _ := range list {
list[i].SetCategory()
}
}
func (m *ReportAllotDetailData) SetCategory() {
commodityInfo, err := GetCommodity(m.CommodityId)
if err != nil {
logger.Error("SetCategory err:", logger.Field("err", err))
}
m.CategoryID = commodityInfo.ErpCategoryId
m.CategoryName = commodityInfo.ErpCategoryName
}
// reportAllotDetailExport 库存调拨明细导出excel
func reportAllotDetailExport(req *InventoryReportAllotDetailResp) (string, error) {
file := excelize.NewFile()
fSheet := "Sheet1"
url := ExportUrl
fileName := time.Now().Format(TimeFormat) + "库存调拨明细" + ".xlsx"
fmt.Println("url fileName:", url+fileName)
// 组合标题栏数据
title := []interface{}{"单据编号", "调出门店", "调入门店", "订单审核时间", "调入时间", "调拨状态", "商品名称",
"商品分类", "是否串码", "串码"}
for i, _ := range title {
cell, _ := excelize.CoordinatesToCellName(1+i, 1)
err := file.SetCellValue(fSheet, cell, title[i])
if err != nil {
logger.Error("file set value err:", logger.Field("err", err))
}
}
var row1 []interface{}
nExcelStartRow := 0
for _, reportData := range req.List {
var allotState string
switch reportData.State {
case 1: // 调拨中
allotState = "调拨中"
case 2: // 已完成
allotState = "已完成"
}
var IMEIType string
switch reportData.IMEIType {
case 1:
IMEIType = "非串码"
case 2, 3:
IMEIType = "串码类"
}
var receiveTime, auditTime string
if reportData.ReceiveTime != nil {
receiveTime = reportData.ReceiveTime.Format(TimeFormat)
}
if reportData.AuditTime != nil {
auditTime = reportData.AuditTime.Format(TimeFormat)
}
row1 = []interface{}{
reportData.SerialNumber, // 单据编号
reportData.DeliverStoreName, // 调出门店
reportData.ReceiveStoreName, // 调入门店
auditTime, // 订单审核时间
receiveTime, // 调入时间
allotState, // 调拨状态
reportData.CommodityName, // 商品名称
reportData.CategoryName, // 商品分类
IMEIType, // 是否串码
reportData.IMEI, // 串码
}
for j, _ := range row1 {
cell, _ := excelize.CoordinatesToCellName(1+j, nExcelStartRow+2)
err := file.SetCellValue(fSheet, cell, row1[j])
if err != nil {
logger.Error("file set value err:", logger.Field("err", err))
}
}
nExcelStartRow++
}
totalData := "记录数:" + strconv.FormatInt(int64(req.Total), 10)
end := []interface{}{totalData, "", "", "", "", "", "", "", "", ""}
for i, _ := range end {
cell, _ := excelize.CoordinatesToCellName(1+i, nExcelStartRow+2)
err := file.SetCellValue(fSheet, cell, end[i])
if err != nil {
logger.Error("file set value err:", logger.Field("err", err))
}
}
// 设置所有单元格的样式: 居中、加边框
style, _ := file.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center"},
"border":[{"type":"left","color":"000000","style":1},
{"type":"top","color":"000000","style":1},
{"type":"right","color":"000000","style":1},
{"type":"bottom","color":"000000","style":1}]}`)
//设置单元格高度
file.SetRowHeight("Sheet1", 1, 20)
// 设置单元格大小
file.SetColWidth("Sheet1", "A", "A", 13)
file.SetColWidth("Sheet1", "B", "B", 28)
file.SetColWidth("Sheet1", "C", "C", 28)
file.SetColWidth("Sheet1", "D", "D", 18)
file.SetColWidth("Sheet1", "E", "E", 18)
file.SetColWidth("Sheet1", "G", "G", 23)
file.SetColWidth("Sheet1", "H", "H", 15)
file.SetColWidth("Sheet1", "J", "J", 15)
endRow := fmt.Sprintf("J"+"%d", nExcelStartRow+2)
// 应用样式到整个表格
_ = file.SetCellStyle("Sheet1", "A1", endRow, style)
fmt.Println("save fileName:", config.ExportConfig.Path+fileName)
if err := file.SaveAs(config.ExportConfig.Path + fileName); err != nil {
fmt.Println(err)
}
return url + fileName, nil
}