2024-04-02 10:21:20 +00:00
|
|
|
|
package models
|
|
|
|
|
|
2024-04-22 10:12:19 +00:00
|
|
|
|
import (
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
|
"github.com/xuri/excelize/v2"
|
|
|
|
|
orm "go-admin/common/global"
|
|
|
|
|
"go-admin/logger"
|
|
|
|
|
"go-admin/tools"
|
|
|
|
|
"go-admin/tools/config"
|
2024-05-15 03:08:46 +00:00
|
|
|
|
"math"
|
2024-04-23 10:20:49 +00:00
|
|
|
|
"sort"
|
2024-04-22 10:12:19 +00:00
|
|
|
|
"strconv"
|
|
|
|
|
"time"
|
|
|
|
|
)
|
2024-04-02 10:21:20 +00:00
|
|
|
|
|
|
|
|
|
// InventoryReportByProductReq 产品库存汇总(按门店)入参
|
|
|
|
|
type InventoryReportByProductReq struct {
|
|
|
|
|
StoreId []uint32 `json:"store_id"` // 门店id
|
|
|
|
|
CommoditySerialNumber []string `json:"commodity_serial_number"` // 商品编号
|
|
|
|
|
CommodityName []string `json:"commodity_name"` // 商品名称
|
|
|
|
|
CategoryID []uint32 `json:"category_id"` // 商品分类id
|
|
|
|
|
IsExport uint32 `json:"is_export"` // 1-导出
|
|
|
|
|
PageIndex int `json:"pageIndex"` // 页码
|
|
|
|
|
PageSize int `json:"pageSize"` // 页面条数
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// InventoryReportByProductResp 产品库存汇总(按门店)出参
|
|
|
|
|
type InventoryReportByProductResp struct {
|
2024-05-15 03:08:46 +00:00
|
|
|
|
Total uint32 `json:"total"` // 总条数/记录数
|
|
|
|
|
PageIndex int `json:"pageIndex"` // 页码
|
|
|
|
|
PageSize int `json:"pageSize"` // 页面条数
|
|
|
|
|
ReportByProductSumData
|
|
|
|
|
ExportUrl string `json:"export_url"` // 导出excel路径
|
|
|
|
|
List []ReportByProductData `json:"list"` //
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ReportByProductSumData struct {
|
|
|
|
|
TotalEffectiveCount uint32 `json:"total_effective_count"` // 有效库存数
|
|
|
|
|
TotalTransferCount uint32 `json:"total_transfer_count"` // 调入中数量
|
|
|
|
|
TotalCount uint32 `json:"total_count"` // 总数量
|
|
|
|
|
TotalEffectiveAmount float64 `json:"total_effective_amount"` // 有效库存金额
|
|
|
|
|
TotalTransferAmount float64 `json:"total_transfer_amount"` // 调入中金额
|
2024-04-02 10:21:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ReportByProductData 产品库存汇总(按门店)数据
|
|
|
|
|
type ReportByProductData struct {
|
|
|
|
|
StoreId uint32 `json:"store_id"` // 门店id
|
|
|
|
|
StoreName string `json:"store_name"` // 门店名称
|
|
|
|
|
CommoditySerialNumber string `json:"commodity_serial_number"` // 商品编号
|
|
|
|
|
CommodityId uint32 `json:"commodity_id"` // 商品id
|
|
|
|
|
CommodityName string `json:"commodity_name"` // 商品名称
|
|
|
|
|
CategoryID uint32 `json:"category_id"` // 商品分类id
|
|
|
|
|
CategoryName string `json:"category_name"` // 商品分类名称
|
|
|
|
|
EffectiveCount uint32 `json:"effective_count"` // 有效库存数
|
|
|
|
|
TransferCount uint32 `json:"transfer_count"` // 调入中数量
|
|
|
|
|
Count uint32 `json:"count"` // 总数量
|
|
|
|
|
EffectiveAmount float64 `json:"effective_amount"` // 有效库存金额
|
|
|
|
|
TransferAmount float64 `json:"transfer_amount"` // 调入中金额
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// InventoryReportByAllotReq 库存调拨入参
|
|
|
|
|
type InventoryReportByAllotReq struct {
|
|
|
|
|
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-已完成
|
|
|
|
|
AuditTimeStart string `json:"audit_time_start"` // 审核/发起开始时间
|
|
|
|
|
AuditTimeEnd string `json:"audit_time_end"` // 审核/发起结束时间
|
|
|
|
|
ReceiveTimeStart string `json:"receive_time_start"` // 调入开始时间
|
|
|
|
|
ReceiveTimeEnd string `json:"receive_time_end"` // 调入结束时间
|
|
|
|
|
IsExport uint32 `json:"is_export"` // 1-导出
|
|
|
|
|
PageIndex int `json:"pageIndex"` // 页码
|
|
|
|
|
PageSize int `json:"pageSize"` // 页面条数
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// InventoryReportByAllotResp 库存调拨出参
|
|
|
|
|
type InventoryReportByAllotResp struct {
|
|
|
|
|
Total int `json:"total"` // 总条数/记录数
|
|
|
|
|
PageIndex int `json:"pageIndex"` // 页码
|
|
|
|
|
PageSize int `json:"pageSize"` // 页面条数
|
|
|
|
|
TotalAllotCount uint32 `json:"total_allot_count"` // 调拨数量
|
|
|
|
|
TotalAllotAmount float64 `json:"total_allot_amount"` // 调拨金额
|
|
|
|
|
ExportUrl string `json:"export_url"` // 导出excel路径
|
|
|
|
|
List []ReportByAllotData `json:"list"` //
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ReportByAllotData 库存调拨数据
|
|
|
|
|
type ReportByAllotData struct {
|
2024-04-23 10:20:49 +00:00
|
|
|
|
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"` // 调拨金额
|
2024-04-02 10:21:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// InventoryReportAllotDetailReq 库存调拨明细入参
|
|
|
|
|
type InventoryReportAllotDetailReq struct {
|
|
|
|
|
SerialNumber string `json:"serial_number"` // 单据编号
|
2024-04-23 10:20:49 +00:00
|
|
|
|
DeliverStoreId []uint32 `json:"deliver_store_id"` // 调出门店id
|
|
|
|
|
ReceiveStoreId []uint32 `json:"receive_store_id"` // 调入门店id
|
2024-04-02 10:21:20 +00:00
|
|
|
|
CommodityName []string `json:"commodity_name"` // 商品名称
|
|
|
|
|
CategoryID []uint32 `json:"category_id"` // 商品分类id
|
2024-05-27 03:08:39 +00:00
|
|
|
|
IMEI string `json:"imei"` // 串码
|
2024-04-02 10:21:20 +00:00
|
|
|
|
State uint32 `json:"state"` // 调拨状态:1-调拨中 2-已完成
|
|
|
|
|
AuditTimeStart string `json:"audit_time_start"` // 审核/发起开始时间
|
|
|
|
|
AuditTimeEnd string `json:"audit_time_end"` // 审核/发起结束时间
|
|
|
|
|
ReceiveTimeStart string `json:"receive_time_start"` // 调入开始时间
|
|
|
|
|
ReceiveTimeEnd string `json:"receive_time_end"` // 调入结束时间
|
|
|
|
|
IsExport uint32 `json:"is_export"` // 1-导出
|
|
|
|
|
PageIndex int `json:"pageIndex"` // 页码
|
|
|
|
|
PageSize int `json:"pageSize"` // 页面条数
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// InventoryReportAllotDetailResp 库存调拨明细出参
|
|
|
|
|
type InventoryReportAllotDetailResp struct {
|
2024-04-23 10:20:49 +00:00
|
|
|
|
Total int64 `json:"total"` // 总条数/记录数
|
2024-04-02 10:21:20 +00:00
|
|
|
|
PageIndex int `json:"pageIndex"` // 页码
|
|
|
|
|
PageSize int `json:"pageSize"` // 页面条数
|
|
|
|
|
ExportUrl string `json:"export_url"` // 导出excel路径
|
|
|
|
|
List []ReportAllotDetailData `json:"list"` //
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ReportAllotDetailData 库存调拨明细数据
|
|
|
|
|
type ReportAllotDetailData struct {
|
|
|
|
|
SerialNumber string `json:"serial_number"` // 单据编号
|
|
|
|
|
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"` // 调入门店名称
|
|
|
|
|
MakerTime *time.Time `json:"maker_time"` // 制单时间/发起时间
|
|
|
|
|
AuditTime *time.Time `json:"audit_time"` // 审核时间
|
2024-04-23 10:20:49 +00:00
|
|
|
|
ReceiveTime *time.Time `json:"receive_time"` // 收货时间/调入时间
|
2024-04-02 10:21:20 +00:00
|
|
|
|
State uint32 `json:"state"` // 调拨状态:1-调拨中 2-已完成
|
|
|
|
|
CommodityId uint32 `json:"commodity_id"` // 商品id
|
|
|
|
|
CommodityName string `json:"commodity_name"` // 商品名称
|
|
|
|
|
CategoryID uint32 `json:"category_id"` // 商品分类id
|
|
|
|
|
CategoryName string `json:"category_name"` // 商品分类名称
|
|
|
|
|
IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码
|
|
|
|
|
IMEI string `json:"imei"` // 商品串码
|
2024-04-23 10:20:49 +00:00
|
|
|
|
Remark string `json:"remark"` // 备注
|
2024-04-02 10:21:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// InventoryReportByOtherReq 其他出入库汇总入参
|
|
|
|
|
type InventoryReportByOtherReq struct {
|
|
|
|
|
StoreId []uint32 `json:"store_id"` // 门店id
|
|
|
|
|
CommodityName []string `json:"commodity_name"` // 商品名称
|
|
|
|
|
CategoryID []uint32 `json:"category_id"` // 商品分类id
|
2024-04-24 09:14:44 +00:00
|
|
|
|
Type uint32 `json:"type"` // 出入库方式:1-产品入库 2-盘点入库 3-系统出库 4-盘点出库
|
2024-04-02 10:21:20 +00:00
|
|
|
|
StartTime string `json:"start_time"` // 开始时间/入库时间
|
|
|
|
|
EndTime string `json:"end_time"` // 结束时间/出库时间
|
|
|
|
|
IsExport uint32 `json:"is_export"` // 1-导出
|
|
|
|
|
PageIndex int `json:"pageIndex"` // 页码
|
|
|
|
|
PageSize int `json:"pageSize"` // 页面条数
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// InventoryReportByOtherResp 其他出入库汇总出参
|
|
|
|
|
type InventoryReportByOtherResp struct {
|
|
|
|
|
Total int `json:"total"` // 总条数/记录数
|
|
|
|
|
PageIndex int `json:"pageIndex"` // 页码
|
|
|
|
|
PageSize int `json:"pageSize"` // 页面条数
|
2024-04-24 08:53:14 +00:00
|
|
|
|
TotalCount uint32 `json:"total_count"` // 总数量
|
2024-04-02 10:21:20 +00:00
|
|
|
|
TotalAmount float64 `json:"total_amount"` // 总金额
|
|
|
|
|
ExportUrl string `json:"export_url"` // 导出excel路径
|
|
|
|
|
List []ReportByOtherData `json:"list"` //
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ReportByOtherData 其他出入库汇总数据
|
|
|
|
|
type ReportByOtherData struct {
|
2024-04-24 09:14:44 +00:00
|
|
|
|
StoreId uint32 `json:"store_id"` // 门店id
|
|
|
|
|
StoreName string `json:"store_name"` // 门店名称
|
|
|
|
|
CommodityId uint32 `json:"commodity_id"` // 商品id
|
|
|
|
|
CommodityName string `json:"commodity_name"` // 商品名称
|
|
|
|
|
CategoryID uint32 `json:"category_id"` // 商品分类id
|
|
|
|
|
CategoryName string `json:"category_name"` // 商品分类名称
|
|
|
|
|
StockTime *time.Time `json:"stock_time"` // 出入库时间
|
|
|
|
|
Type uint32 `json:"type"` // 出入库方式:1-产品入库 2-盘点入库 3-系统出库 4-盘点出库
|
|
|
|
|
Count int64 `json:"count"` // 数量
|
|
|
|
|
Amount float64 `json:"amount"` // 金额
|
2024-04-02 10:21:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// InventoryReportOtherDetailReq 其他出入库明细入参
|
|
|
|
|
type InventoryReportOtherDetailReq struct {
|
|
|
|
|
SerialNumber string `json:"serial_number"` // 单据编号
|
|
|
|
|
StoreId []uint32 `json:"store_id"` // 门店id
|
|
|
|
|
CommodityName []string `json:"commodity_name"` // 商品名称
|
|
|
|
|
CategoryID []uint32 `json:"category_id"` // 商品分类id
|
2024-04-24 08:53:14 +00:00
|
|
|
|
Type uint32 `json:"type"` // 出入库方式:1-产品入库 2-盘点入库 3-系统出库 4-盘点出库
|
2024-05-27 03:08:39 +00:00
|
|
|
|
IMEI string `json:"imei"` // 串码
|
2024-04-02 10:21:20 +00:00
|
|
|
|
StartTime string `json:"start_time"` // 开始时间/入库时间
|
|
|
|
|
EndTime string `json:"end_time"` // 结束时间/出库时间
|
|
|
|
|
IsExport uint32 `json:"is_export"` // 1-导出
|
|
|
|
|
PageIndex int `json:"pageIndex"` // 页码
|
|
|
|
|
PageSize int `json:"pageSize"` // 页面条数
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// InventoryReportOtherDetailResp 其他出入库明细出参
|
|
|
|
|
type InventoryReportOtherDetailResp struct {
|
|
|
|
|
Total int `json:"total"` // 总条数/记录数
|
|
|
|
|
PageIndex int `json:"pageIndex"` // 页码
|
|
|
|
|
PageSize int `json:"pageSize"` // 页面条数
|
|
|
|
|
TotalPurchasePrice float64 `json:"total_purchase_price"` // 总入库采购价
|
|
|
|
|
TotalEmployeePrice float64 `json:"total_employee_price"` // 总入库员工成本价
|
|
|
|
|
ExportUrl string `json:"export_url"` // 导出excel路径
|
|
|
|
|
List []ReportOtherDetailData `json:"list"` //
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ReportOtherDetailData 其他出入库明细数据
|
|
|
|
|
type ReportOtherDetailData struct {
|
|
|
|
|
CommodityId uint32 `json:"commodity_id"` // 商品id
|
|
|
|
|
CommodityName string `json:"commodity_name"` // 商品名称
|
|
|
|
|
CategoryID uint32 `json:"category_id"` // 商品分类id
|
|
|
|
|
CategoryName string `json:"category_name"` // 商品分类名称
|
|
|
|
|
IMEIType uint32 `json:"imei_type"` // 1-无串码 2-串码
|
|
|
|
|
IMEI string `json:"imei"` // 商品串码
|
|
|
|
|
StoreId uint32 `json:"store_id"` // 门店id
|
|
|
|
|
StoreName string `json:"store_name"` // 门店名称
|
|
|
|
|
SupplierId uint32 `json:"supplier_id"` // 供应商id
|
|
|
|
|
SupplierName string `json:"supplier_name"` // 供应商名称
|
|
|
|
|
StockTime *time.Time `json:"stock_time"` // 出入库时间
|
2024-04-24 08:53:14 +00:00
|
|
|
|
Type uint32 `json:"type"` // 调拨状态:1-产品入库 2-盘点入库 3-系统出库 4-盘点出库
|
2024-04-02 10:21:20 +00:00
|
|
|
|
SerialNumber string `json:"serial_number"` // 单据编号
|
|
|
|
|
PurchasePrice float64 `json:"purchase_price"` // 入库采购价
|
|
|
|
|
EmployeePrice float64 `json:"employee_price"` // 入库员工成本价
|
|
|
|
|
}
|
2024-04-22 10:12:19 +00:00
|
|
|
|
|
|
|
|
|
// ReportByProductList 产品库存汇总(按门店)
|
|
|
|
|
func (m *InventoryReportByProductReq) ReportByProductList(c *gin.Context) (*InventoryReportByProductResp, 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.StoreId = CompareLists(storeList, m.StoreId)
|
|
|
|
|
if len(m.StoreId) == 0 { // 没有匹配的数据,表示入参门店不是用户有权限的门店
|
|
|
|
|
return &InventoryReportByProductResp{}, nil
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return nil, errors.New("用户未绑定门店")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resp := &InventoryReportByProductResp{
|
|
|
|
|
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_stock")
|
|
|
|
|
|
|
|
|
|
if len(m.StoreId) > 0 { // 门店复选
|
|
|
|
|
var storeIDs []uint32
|
|
|
|
|
for _, store := range m.StoreId {
|
|
|
|
|
storeIDs = append(storeIDs, store)
|
|
|
|
|
}
|
|
|
|
|
qs = qs.Where("store_id IN (?)", storeIDs)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(m.CategoryID) > 0 { // 商品分类id
|
|
|
|
|
var categoryIDs []uint32
|
|
|
|
|
for _, category := range m.CategoryID {
|
|
|
|
|
categoryIDs = append(categoryIDs, category)
|
|
|
|
|
}
|
2024-05-15 03:08:46 +00:00
|
|
|
|
qs = qs.Where("erp_category_id IN (?)", categoryIDs)
|
2024-04-22 10:12:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(m.CommoditySerialNumber) > 0 { // 商品编号
|
|
|
|
|
var serialNumbers []string
|
|
|
|
|
for _, serialNumber := range m.CommoditySerialNumber {
|
|
|
|
|
serialNumbers = append(serialNumbers, serialNumber)
|
|
|
|
|
}
|
|
|
|
|
qs = qs.Where("commodity_serial_number IN (?)", serialNumbers)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(m.CommodityName) > 0 { // 商品名称
|
|
|
|
|
var commodityNames []string
|
|
|
|
|
for _, commodityName := range m.CommodityName {
|
|
|
|
|
commodityNames = append(commodityNames, commodityName)
|
|
|
|
|
}
|
2024-05-15 03:08:46 +00:00
|
|
|
|
qs = qs.Where("erp_commodity_name IN (?)", commodityNames)
|
2024-04-22 10:12:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var count int64
|
|
|
|
|
err := qs.Count(&count).Error
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("查询无库存列表数量失败", logger.Field("err", err))
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var commodities []ErpStock
|
|
|
|
|
if m.IsExport == 1 { // 导出excel
|
2024-04-23 10:20:49 +00:00
|
|
|
|
err = qs.Order("erp_commodity_id, store_id desc").Find(&commodities).Error
|
2024-04-22 10:12:19 +00:00
|
|
|
|
} else {
|
2024-04-23 10:20:49 +00:00
|
|
|
|
err = qs.Order("erp_commodity_id, store_id desc").Offset(page * m.PageSize).Limit(m.PageSize).Find(&commodities).Error
|
2024-04-22 10:12:19 +00:00
|
|
|
|
}
|
|
|
|
|
if err != nil && err != RecordNotFound {
|
|
|
|
|
logger.Error("查询无库存列表失败", logger.Field("err", err))
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var reportList []ReportByProductData
|
|
|
|
|
var nTotalEffectiveCount, nTotalTransferCount uint32
|
|
|
|
|
var nTotalEffectiveAmount, nTotalTransferAmount float64
|
|
|
|
|
// 遍历库存列表,计算有效库存金额,调入中金额
|
|
|
|
|
for _, item := range commodities {
|
|
|
|
|
var reportData ReportByProductData
|
|
|
|
|
reportData.StoreId = item.StoreId
|
|
|
|
|
reportData.StoreName = item.StoreName
|
|
|
|
|
reportData.CommoditySerialNumber = item.CommoditySerialNumber
|
|
|
|
|
reportData.CommodityId = item.ErpCommodityId
|
|
|
|
|
reportData.CommodityName = item.ErpCommodityName
|
|
|
|
|
reportData.CategoryID = item.ErpCategoryId
|
|
|
|
|
reportData.CategoryName = item.ErpCategoryName
|
|
|
|
|
reportData.EffectiveCount = item.Count
|
|
|
|
|
reportData.TransferCount = item.DispatchCount
|
|
|
|
|
reportData.Count = item.Count + item.DispatchCount
|
|
|
|
|
|
|
|
|
|
// 查询有效库存金额
|
|
|
|
|
if item.Count != 0 {
|
|
|
|
|
reportData.EffectiveAmount, err = getStockCommodityAmount(item.StoreId, item.ErpCommodityId)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 查询调入中金额
|
|
|
|
|
if item.DispatchCount != 0 {
|
|
|
|
|
reportData.TransferAmount, err = getDispatchCommodityAmount(item.StoreId, item.ErpCommodityId)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nTotalEffectiveCount += reportData.EffectiveCount
|
|
|
|
|
nTotalTransferCount += reportData.TransferCount
|
|
|
|
|
|
|
|
|
|
nTotalEffectiveAmount += reportData.EffectiveAmount
|
|
|
|
|
nTotalTransferAmount += reportData.TransferAmount
|
|
|
|
|
|
|
|
|
|
reportList = append(reportList, reportData)
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-15 03:08:46 +00:00
|
|
|
|
sumData, err := getReportByProductSumData()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resp.TotalEffectiveCount = sumData.TotalEffectiveCount
|
|
|
|
|
resp.TotalTransferCount = sumData.TotalTransferCount
|
|
|
|
|
resp.TotalCount = sumData.TotalCount
|
|
|
|
|
resp.TotalEffectiveAmount = sumData.TotalEffectiveAmount
|
|
|
|
|
resp.TotalTransferAmount = sumData.TotalTransferAmount
|
|
|
|
|
resp.Total = uint32(count)
|
2024-04-22 10:12:19 +00:00
|
|
|
|
resp.List = reportList
|
|
|
|
|
|
|
|
|
|
if m.IsExport == 1 { // 导出excel
|
|
|
|
|
resp.ExportUrl, err = reportByProductExport(resp)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
resp.List = []ReportByProductData{}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return resp, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 查询有效库存金额
|
|
|
|
|
func getStockCommodityAmount(storeId, commodityId uint32) (float64, error) {
|
|
|
|
|
var nCount int64
|
|
|
|
|
err := orm.Eloquent.Debug().Table("erp_stock_commodity").
|
|
|
|
|
Where("store_id = ? and erp_commodity_id = ? and state = ?",
|
|
|
|
|
storeId, commodityId, InStock).Count(&nCount).Error
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
if nCount == 0 {
|
|
|
|
|
return 0, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var nStockCommodityAmount float64
|
|
|
|
|
err = orm.Eloquent.Debug().Table("erp_stock_commodity").Select("SUM(wholesale_price) AS "+
|
|
|
|
|
"nStockCommodityAmount").Where("store_id = ? and erp_commodity_id = ? and state = ?",
|
|
|
|
|
storeId, commodityId, InStock).Find(&nStockCommodityAmount).Error
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nStockCommodityAmount, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 查询调入中金额
|
|
|
|
|
func getDispatchCommodityAmount(storeId, commodityId uint32) (float64, error) {
|
|
|
|
|
var nCount int64
|
|
|
|
|
err := orm.Eloquent.Debug().Table("erp_stock_commodity").
|
|
|
|
|
Where("store_id = ? and erp_commodity_id = ? and state = ?",
|
|
|
|
|
storeId, commodityId, InAllot).Count(&nCount).Error
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
if nCount == 0 {
|
|
|
|
|
return 0, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var nDispatchCommodityAmount float64
|
|
|
|
|
err = orm.Eloquent.Debug().Table("erp_stock_commodity").Select("SUM(wholesale_price) AS "+
|
|
|
|
|
"nStockCommodityAmount").Where("store_id = ? and erp_commodity_id = ? and state = ?",
|
|
|
|
|
storeId, commodityId, InAllot).Find(&nDispatchCommodityAmount).Error
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nDispatchCommodityAmount, nil
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-15 03:08:46 +00:00
|
|
|
|
// 查询产品库存汇总(按门店)的汇总数据:总有效库存数、总调入中数量、总数量、总有效库存金额、总调入中金额
|
|
|
|
|
func getReportByProductSumData() (ReportByProductSumData, error) {
|
|
|
|
|
var data ReportByProductSumData
|
|
|
|
|
|
|
|
|
|
// 查询汇总数据
|
|
|
|
|
err := orm.Eloquent.Debug().Table("erp_stock_commodity").
|
|
|
|
|
Select(`
|
|
|
|
|
SUM(CASE WHEN state = ? THEN wholesale_price ELSE 0 END) AS total_effective_amount,
|
|
|
|
|
SUM(CASE WHEN state = ? THEN wholesale_price ELSE 0 END) AS total_transfer_amount,
|
|
|
|
|
SUM(CASE WHEN state = ? THEN Count ELSE 0 END) AS total_effective_count,
|
|
|
|
|
SUM(CASE WHEN state = ? THEN Count ELSE 0 END) AS total_transfer_count,
|
|
|
|
|
SUM(CASE WHEN state IN (?, ?) THEN Count ELSE 0 END) AS total_count
|
|
|
|
|
`, InStock, InAllot, InStock, InAllot, InStock, InAllot).
|
|
|
|
|
Find(&data).Error
|
|
|
|
|
if err != nil {
|
|
|
|
|
return data, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data.TotalEffectiveAmount = math.Round(data.TotalEffectiveAmount*100) / 100
|
|
|
|
|
data.TotalTransferAmount = math.Round(data.TotalTransferAmount*100) / 100
|
|
|
|
|
|
|
|
|
|
return data, nil
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-22 10:12:19 +00:00
|
|
|
|
// reportByProductExport 产品库存汇总(按门店)导出excel
|
|
|
|
|
func reportByProductExport(req *InventoryReportByProductResp) (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 {
|
|
|
|
|
row1 = []interface{}{
|
|
|
|
|
reportData.StoreName, // 门店
|
|
|
|
|
reportData.CommoditySerialNumber, // 商品编号
|
|
|
|
|
reportData.CommodityName, // 商品名称
|
|
|
|
|
reportData.CategoryName, // 商品分类
|
|
|
|
|
reportData.EffectiveCount, // 有效库存数
|
|
|
|
|
reportData.TransferCount, // 调入中数量
|
|
|
|
|
reportData.Count, // 总数量
|
|
|
|
|
reportData.EffectiveAmount, // 有效库存金额
|
|
|
|
|
reportData.TransferAmount, // 调入中金额
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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.TotalEffectiveCount, req.TotalTransferCount, req.TotalCount,
|
|
|
|
|
req.TotalEffectiveAmount, req.TotalTransferAmount}
|
|
|
|
|
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", 30)
|
|
|
|
|
file.SetColWidth("Sheet1", "C", "C", 25)
|
|
|
|
|
file.SetColWidth("Sheet1", "D", "D", 15)
|
|
|
|
|
file.SetColWidth("Sheet1", "E", "E", 15)
|
|
|
|
|
file.SetColWidth("Sheet1", "F", "F", 15)
|
|
|
|
|
file.SetColWidth("Sheet1", "H", "H", 15)
|
|
|
|
|
file.SetColWidth("Sheet1", "I", "I", 15)
|
|
|
|
|
|
|
|
|
|
endRow := fmt.Sprintf("I"+"%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
|
|
|
|
|
}
|
2024-04-23 10:20:49 +00:00
|
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
|
}
|
2024-05-10 01:54:37 +00:00
|
|
|
|
qs = qs.Where("erp_inventory_allot_commodity.commodity_name IN (?)", commodityNames)
|
|
|
|
|
countQuery = countQuery.Where("erp_inventory_allot_commodity.commodity_name IN (?)", commodityNames)
|
2024-04-23 10:20:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-10 01:54:37 +00:00
|
|
|
|
//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)
|
|
|
|
|
//}
|
2024-04-23 10:20:49 +00:00
|
|
|
|
|
|
|
|
|
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 {
|
|
|
|
|
// 生成键
|
|
|
|
|
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))
|
|
|
|
|
}
|
2024-05-10 01:54:37 +00:00
|
|
|
|
|
|
|
|
|
// 判断分类信息是否有筛选
|
|
|
|
|
if len(m.CategoryID) > 0 { // 商品分类id
|
|
|
|
|
if !tools.Uint32SliceContains(m.CategoryID, commodityInfo.ErpCategoryId) {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-23 10:20:49 +00:00
|
|
|
|
summaryMap[i].CategoryID = commodityInfo.ErpCategoryId
|
|
|
|
|
summaryMap[i].CategoryName = commodityInfo.ErpCategoryName
|
|
|
|
|
|
|
|
|
|
summaryList = append(summaryList, *summary)
|
2024-05-10 01:54:37 +00:00
|
|
|
|
nTotalAllotCount += summary.AllotCount
|
|
|
|
|
nTotalAllotAmount += summary.AllotAmount
|
2024-04-23 10:20:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 排序规则:商品编号小>调出店铺编号小>调入门店编号小>状态为已完成
|
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-10 01:54:37 +00:00
|
|
|
|
resp.Total = len(summaryList)
|
2024-04-23 10:20:49 +00:00
|
|
|
|
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, "+
|
2024-05-15 03:08:46 +00:00
|
|
|
|
"erp_inventory_allot_commodity.category_id, "+
|
|
|
|
|
"erp_inventory_allot_commodity.category_name, "+
|
2024-04-23 10:20:49 +00:00
|
|
|
|
"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)
|
|
|
|
|
}
|
2024-05-15 03:08:46 +00:00
|
|
|
|
qs = qs.Where("erp_inventory_allot_commodity.commodity_name IN (?)", commodityNames)
|
|
|
|
|
countQuery = countQuery.Where("erp_inventory_allot_commodity.commodity_name IN (?)", commodityNames)
|
2024-04-23 10:20:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(m.CategoryID) > 0 { // 商品分类id
|
|
|
|
|
var categoryIDs []uint32
|
|
|
|
|
for _, category := range m.CategoryID {
|
|
|
|
|
categoryIDs = append(categoryIDs, category)
|
|
|
|
|
}
|
2024-05-15 03:08:46 +00:00
|
|
|
|
qs = qs.Where("erp_inventory_allot_commodity.category_id IN (?)", categoryIDs)
|
|
|
|
|
countQuery = countQuery.Where("erp_inventory_allot_commodity.category_id IN (?)", categoryIDs)
|
2024-04-23 10:20:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-27 03:08:39 +00:00
|
|
|
|
if m.IMEI != "" {
|
|
|
|
|
qs = qs.Where("erp_inventory_allot_commodity.imei = ?", m.IMEI)
|
|
|
|
|
countQuery = countQuery.Where("erp_inventory_allot_commodity.imei = ?", m.IMEI)
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-23 10:20:49 +00:00
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-15 03:08:46 +00:00
|
|
|
|
//// 添加分类信息
|
|
|
|
|
//reportAllotDetailSetCategory(commodities)
|
2024-04-23 10:20:49 +00:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|
2024-04-24 08:53:14 +00:00
|
|
|
|
|
|
|
|
|
// ReportByOtherList 其他出入库汇总
|
|
|
|
|
func (m *InventoryReportByOtherReq) ReportByOtherList(c *gin.Context) (*InventoryReportByOtherResp, 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.StoreId = CompareLists(storeList, m.StoreId)
|
|
|
|
|
if len(m.StoreId) == 0 { // 没有匹配的数据,表示入参门店不是用户有权限的门店
|
|
|
|
|
return &InventoryReportByOtherResp{}, nil
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return nil, errors.New("用户未绑定门店")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resp := &InventoryReportByOtherResp{
|
|
|
|
|
PageIndex: m.PageIndex,
|
|
|
|
|
PageSize: m.PageSize,
|
|
|
|
|
}
|
|
|
|
|
page := m.PageIndex - 1
|
|
|
|
|
if page < 0 {
|
|
|
|
|
page = 0
|
|
|
|
|
}
|
|
|
|
|
if m.PageSize == 0 {
|
|
|
|
|
m.PageSize = 10
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 查询产品入库数据
|
|
|
|
|
var err error
|
|
|
|
|
var productList []ReportOtherDetailData
|
|
|
|
|
productList, err = getProductOrderData()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 查询盘点出入库数据
|
|
|
|
|
var changeList []ReportOtherDetailData
|
|
|
|
|
changeList, err = getChangeOrderData()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 查询系统出库数据
|
|
|
|
|
var systemList []ReportOtherDetailData
|
|
|
|
|
systemList, err = getSystemOutData()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 合并数据
|
|
|
|
|
allData := append(productList, changeList...)
|
|
|
|
|
allData = append(allData, systemList...)
|
|
|
|
|
|
|
|
|
|
// 创建 map 用于存储汇总数据
|
|
|
|
|
summaryMap := make(map[string]*ReportByOtherData)
|
|
|
|
|
// 遍历切片
|
|
|
|
|
for _, item := range allData {
|
|
|
|
|
// 生成键
|
|
|
|
|
key := fmt.Sprintf("%d_%d_%d", item.CommodityId, item.StoreId, item.Type)
|
|
|
|
|
// 检查是否已经存在该键的汇总数据
|
|
|
|
|
if summary, ok := summaryMap[key]; ok {
|
|
|
|
|
// 如果已经存在,累加调拨数量和调拨金额
|
|
|
|
|
summary.Count += 1
|
|
|
|
|
// 假设商品金额在 item.CommodityAmount 中
|
|
|
|
|
summary.Amount += item.PurchasePrice
|
|
|
|
|
} else {
|
|
|
|
|
// 如果不存在,创建新的汇总数据并添加到 map 中
|
|
|
|
|
summaryMap[key] = &ReportByOtherData{
|
|
|
|
|
StoreId: item.StoreId,
|
|
|
|
|
StoreName: item.StoreName,
|
|
|
|
|
CommodityId: item.CommodityId,
|
|
|
|
|
CommodityName: item.CommodityName,
|
|
|
|
|
CategoryID: item.CategoryID,
|
|
|
|
|
CategoryName: item.CategoryName,
|
2024-04-24 09:14:44 +00:00
|
|
|
|
StockTime: item.StockTime,
|
2024-04-24 08:53:14 +00:00
|
|
|
|
Type: item.Type,
|
|
|
|
|
Count: 1, // 初始化为 1
|
|
|
|
|
Amount: item.PurchasePrice,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var summaryList []ReportByOtherData
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
if summary.Type == 3 || summary.Type == 4 {
|
|
|
|
|
summaryMap[i].Count = -summaryMap[i].Count
|
|
|
|
|
summaryMap[i].Amount = -summaryMap[i].Amount
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
summaryList = append(summaryList, *summary)
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-24 09:14:44 +00:00
|
|
|
|
// 进行条件查询
|
|
|
|
|
var startTime time.Time
|
|
|
|
|
if m.StartTime != "" { // 出入库开始时间
|
|
|
|
|
startTime, err = time.Parse(QueryTimeFormat, m.StartTime)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Errorf("ReportByOtherDetailList err:", err)
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
var endTime time.Time
|
|
|
|
|
if m.EndTime != "" { // 出入库结束时间
|
|
|
|
|
endTime, err = time.Parse(QueryTimeFormat, m.EndTime)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Errorf("ReportByOtherDetailList err:", err)
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var nTotalAllotCount uint32
|
|
|
|
|
var nTotalAllotAmount float64
|
|
|
|
|
filteredData := make([]ReportByOtherData, 0)
|
|
|
|
|
for _, data := range summaryList {
|
|
|
|
|
if (len(m.StoreId) == 0 || tools.Uint32SliceContains(m.StoreId, data.StoreId)) &&
|
|
|
|
|
(len(m.CommodityName) == 0 || tools.StringSliceContains(m.CommodityName, data.CommodityName)) &&
|
|
|
|
|
(len(m.CategoryID) == 0 || tools.Uint32SliceContains(m.CategoryID, data.CategoryID)) &&
|
|
|
|
|
(m.Type == 0 || m.Type == data.Type) &&
|
|
|
|
|
((m.StartTime == "" && m.EndTime == "") || (data.StockTime.After(startTime) && data.StockTime.Before(endTime))) {
|
|
|
|
|
nTotalAllotCount += 1
|
|
|
|
|
nTotalAllotAmount += data.Amount
|
|
|
|
|
|
|
|
|
|
filteredData = append(filteredData, data)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-24 08:53:14 +00:00
|
|
|
|
// 使用排序规则函数对汇总数据进行排序
|
2024-04-24 09:14:44 +00:00
|
|
|
|
sortSummaryList(filteredData)
|
2024-04-24 08:53:14 +00:00
|
|
|
|
|
|
|
|
|
// 计算分页所需的切片索引
|
|
|
|
|
startIndex := page * m.PageSize
|
|
|
|
|
endIndex := (page + 1) * m.PageSize
|
2024-04-24 09:14:44 +00:00
|
|
|
|
if endIndex > len(filteredData) {
|
|
|
|
|
endIndex = len(filteredData)
|
2024-04-24 08:53:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
2024-04-24 09:14:44 +00:00
|
|
|
|
resp.Total = len(filteredData)
|
2024-04-24 08:53:14 +00:00
|
|
|
|
resp.TotalCount = nTotalAllotCount
|
|
|
|
|
resp.TotalAmount = tools.RoundToTwoDecimalPlaces(nTotalAllotAmount)
|
|
|
|
|
|
|
|
|
|
if m.IsExport == 1 {
|
2024-04-24 09:14:44 +00:00
|
|
|
|
resp.List = filteredData
|
2024-04-24 08:53:14 +00:00
|
|
|
|
resp.ExportUrl, err = reportOtherExport(resp)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
resp.List = []ReportByOtherData{}
|
|
|
|
|
resp.TotalCount = 0
|
|
|
|
|
resp.TotalAmount = 0
|
|
|
|
|
} else {
|
2024-04-24 09:14:44 +00:00
|
|
|
|
resp.List = filteredData[startIndex:endIndex]
|
2024-04-24 08:53:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return resp, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 排序规则函数
|
|
|
|
|
// 排序规则:商品编号小>门店编号小>产品入库>盘点入库>系统出库>盘点出库
|
|
|
|
|
func sortSummaryList(summaryList []ReportByOtherData) {
|
|
|
|
|
sort.Slice(summaryList, func(i, j int) bool {
|
|
|
|
|
// 按 CommodityId 排序
|
|
|
|
|
if summaryList[i].CommodityId != summaryList[j].CommodityId {
|
|
|
|
|
return summaryList[i].CommodityId < summaryList[j].CommodityId
|
|
|
|
|
}
|
|
|
|
|
// 如果 CommodityId 相同,则按 StoreId 排序
|
|
|
|
|
if summaryList[i].StoreId != summaryList[j].StoreId {
|
|
|
|
|
return summaryList[i].StoreId < summaryList[j].StoreId
|
|
|
|
|
}
|
|
|
|
|
// 如果 StoreId 相同, 按 Type 排序
|
|
|
|
|
if summaryList[i].Type != summaryList[j].Type {
|
|
|
|
|
return summaryList[i].Type < summaryList[j].Type
|
|
|
|
|
}
|
|
|
|
|
// 如果 Type 相同,则按 Amount 排序
|
|
|
|
|
return summaryList[i].Amount < summaryList[j].Amount
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// reportOtherExport 其他出入库汇总导出excel
|
|
|
|
|
func reportOtherExport(req *InventoryReportByOtherResp) (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 inventoryType string
|
|
|
|
|
switch reportData.Type {
|
|
|
|
|
case 1:
|
|
|
|
|
inventoryType = "产品入库"
|
|
|
|
|
case 2:
|
|
|
|
|
inventoryType = "盘点入库"
|
|
|
|
|
case 3:
|
|
|
|
|
inventoryType = "系统出库"
|
|
|
|
|
case 4:
|
|
|
|
|
inventoryType = "盘点出库"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
row1 = []interface{}{
|
|
|
|
|
reportData.StoreName, // 门店
|
|
|
|
|
reportData.CommodityName, // 商品名称
|
|
|
|
|
reportData.CategoryName, // 商品分类
|
|
|
|
|
inventoryType, // 出入库方式
|
|
|
|
|
reportData.Count, // 数量
|
|
|
|
|
reportData.Amount, // 金额
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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.TotalCount, req.TotalAmount}
|
|
|
|
|
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", 20)
|
|
|
|
|
file.SetColWidth("Sheet1", "D", "D", 20)
|
|
|
|
|
|
|
|
|
|
endRow := fmt.Sprintf("F"+"%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
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ReportByOtherDetailList 其他出入库明细
|
|
|
|
|
func (m *InventoryReportOtherDetailReq) ReportByOtherDetailList(c *gin.Context) (*InventoryReportOtherDetailResp, 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.StoreId = CompareLists(storeList, m.StoreId)
|
|
|
|
|
if len(m.StoreId) == 0 { // 没有匹配的数据,表示入参门店不是用户有权限的门店
|
|
|
|
|
return &InventoryReportOtherDetailResp{}, nil
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return nil, errors.New("用户未绑定门店")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resp := &InventoryReportOtherDetailResp{
|
|
|
|
|
PageIndex: m.PageIndex,
|
|
|
|
|
PageSize: m.PageSize,
|
|
|
|
|
}
|
|
|
|
|
page := m.PageIndex - 1
|
|
|
|
|
if page < 0 {
|
|
|
|
|
page = 0
|
|
|
|
|
}
|
|
|
|
|
if m.PageSize == 0 {
|
|
|
|
|
m.PageSize = 10
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 查询产品入库数据
|
|
|
|
|
var err error
|
|
|
|
|
var productList []ReportOtherDetailData
|
|
|
|
|
productList, err = getProductOrderData()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 查询盘点出入库数据
|
|
|
|
|
var changeList []ReportOtherDetailData
|
|
|
|
|
changeList, err = getChangeOrderData()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 查询系统出库数据
|
|
|
|
|
var systemList []ReportOtherDetailData
|
|
|
|
|
systemList, err = getSystemOutData()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 合并数据
|
|
|
|
|
allData := append(productList, changeList...)
|
|
|
|
|
allData = append(allData, systemList...)
|
|
|
|
|
|
|
|
|
|
// 进行条件查询
|
|
|
|
|
var startTime time.Time
|
|
|
|
|
if m.StartTime != "" { // 出入库开始时间
|
|
|
|
|
startTime, err = time.Parse(QueryTimeFormat, m.StartTime)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Errorf("ReportByOtherDetailList err:", err)
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
var endTime time.Time
|
|
|
|
|
if m.EndTime != "" { // 出入库结束时间
|
|
|
|
|
endTime, err = time.Parse(QueryTimeFormat, m.EndTime)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Errorf("ReportByOtherDetailList err:", err)
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var totalPurchasePrice, totalEmployeePrice float64
|
|
|
|
|
filteredData := make([]ReportOtherDetailData, 0)
|
|
|
|
|
for i, data := range allData {
|
|
|
|
|
if allData[i].CategoryID == 0 {
|
|
|
|
|
// 添加分类信息
|
|
|
|
|
commodityInfo, err := GetCommodity(data.CommodityId)
|
|
|
|
|
if err != nil {
|
|
|
|
|
logger.Error("SetCategory err:", logger.Field("err", err))
|
|
|
|
|
}
|
|
|
|
|
allData[i].CategoryID = commodityInfo.ErpCategoryId
|
|
|
|
|
allData[i].CategoryName = commodityInfo.ErpCategoryName
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-27 03:08:39 +00:00
|
|
|
|
if m.IMEI != "" {
|
|
|
|
|
if data.IMEI == m.IMEI {
|
|
|
|
|
if data.Type == 3 || data.Type == 4 { // 系统出库、盘点出库
|
|
|
|
|
totalPurchasePrice -= allData[i].PurchasePrice
|
|
|
|
|
totalEmployeePrice -= allData[i].EmployeePrice
|
|
|
|
|
|
|
|
|
|
allData[i].PurchasePrice = -allData[i].PurchasePrice
|
|
|
|
|
allData[i].EmployeePrice = -allData[i].EmployeePrice
|
|
|
|
|
} else {
|
|
|
|
|
totalPurchasePrice += allData[i].PurchasePrice
|
|
|
|
|
totalEmployeePrice += allData[i].EmployeePrice
|
|
|
|
|
}
|
|
|
|
|
filteredData = append(filteredData, allData[i])
|
|
|
|
|
break
|
2024-04-24 08:53:14 +00:00
|
|
|
|
} else {
|
2024-05-27 03:08:39 +00:00
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (len(m.SerialNumber) == 0 || data.SerialNumber == m.SerialNumber) &&
|
|
|
|
|
(len(m.StoreId) == 0 || tools.Uint32SliceContains(m.StoreId, data.StoreId)) &&
|
|
|
|
|
(len(m.CommodityName) == 0 || tools.StringSliceContains(m.CommodityName, data.CommodityName)) &&
|
|
|
|
|
(len(m.CategoryID) == 0 || tools.Uint32SliceContains(m.CategoryID, allData[i].CategoryID)) &&
|
|
|
|
|
(m.Type == 0 || m.Type == data.Type) &&
|
|
|
|
|
((m.StartTime == "" && m.EndTime == "") || (data.StockTime.After(startTime) && data.StockTime.Before(endTime))) {
|
|
|
|
|
if data.Type == 3 || data.Type == 4 { // 系统出库、盘点出库
|
|
|
|
|
totalPurchasePrice -= allData[i].PurchasePrice
|
|
|
|
|
totalEmployeePrice -= allData[i].EmployeePrice
|
|
|
|
|
|
|
|
|
|
allData[i].PurchasePrice = -allData[i].PurchasePrice
|
|
|
|
|
allData[i].EmployeePrice = -allData[i].EmployeePrice
|
|
|
|
|
} else {
|
|
|
|
|
totalPurchasePrice += allData[i].PurchasePrice
|
|
|
|
|
totalEmployeePrice += allData[i].EmployeePrice
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
filteredData = append(filteredData, allData[i])
|
2024-04-24 08:53:14 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 进行排序
|
|
|
|
|
sort.Slice(filteredData, func(i, j int) bool {
|
|
|
|
|
return filteredData[i].StockTime.After(*filteredData[j].StockTime)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
resp.TotalPurchasePrice = tools.RoundToTwoDecimalPlaces(totalPurchasePrice)
|
|
|
|
|
resp.TotalEmployeePrice = tools.RoundToTwoDecimalPlaces(totalEmployeePrice)
|
|
|
|
|
|
|
|
|
|
if m.IsExport == 1 {
|
|
|
|
|
resp.List = filteredData
|
|
|
|
|
resp.Total = len(filteredData)
|
|
|
|
|
resp.ExportUrl, err = reportOtherDetailExport(resp)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
resp.List = []ReportOtherDetailData{}
|
|
|
|
|
resp.TotalPurchasePrice = 0
|
|
|
|
|
resp.TotalEmployeePrice = 0
|
|
|
|
|
} else {
|
|
|
|
|
// 进行分页处理
|
|
|
|
|
startIndex := page * m.PageSize
|
|
|
|
|
endIndex := startIndex + m.PageSize
|
|
|
|
|
if endIndex > len(filteredData) {
|
|
|
|
|
endIndex = len(filteredData)
|
|
|
|
|
}
|
|
|
|
|
resp.List = filteredData[startIndex:endIndex]
|
|
|
|
|
resp.Total = len(filteredData)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return resp, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 查询产品入库数据
|
|
|
|
|
func getProductOrderData() ([]ReportOtherDetailData, error) {
|
|
|
|
|
var productList []ReportOtherDetailData
|
|
|
|
|
err := orm.Eloquent.Debug().Table("erp_inventory_product_order").
|
|
|
|
|
Select("erp_inventory_product_order.serial_number, "+
|
|
|
|
|
"erp_inventory_product_order.store_id, "+
|
|
|
|
|
"erp_inventory_product_order.store_name, "+
|
|
|
|
|
"erp_inventory_product_order.audit_time as stock_time, "+
|
|
|
|
|
"CASE "+
|
|
|
|
|
"WHEN erp_inventory_product_order.state = 2 THEN 1 "+
|
|
|
|
|
"ELSE erp_inventory_product_order.state "+
|
|
|
|
|
"END AS type, "+
|
|
|
|
|
"erp_inventory_product_commodity.commodity_id, "+
|
|
|
|
|
"erp_inventory_product_commodity.commodity_name, "+
|
|
|
|
|
"erp_inventory_product_commodity.supplier_id, "+
|
|
|
|
|
"erp_inventory_product_commodity.supplier_name, "+
|
|
|
|
|
"erp_inventory_product_commodity.imei_type, "+
|
|
|
|
|
"erp_inventory_product_commodity.imei, "+
|
|
|
|
|
"erp_inventory_product_commodity.price as purchase_price, "+
|
|
|
|
|
"erp_inventory_product_commodity.employee_price as employee_price").
|
|
|
|
|
Joins("JOIN erp_inventory_product_commodity "+
|
|
|
|
|
"ON erp_inventory_product_commodity.product_order_id = erp_inventory_product_order.id").
|
|
|
|
|
Where("erp_inventory_product_order.state = ?", ErpInventoryProductOrderFinished).
|
|
|
|
|
Find(&productList).Error // 查询已审核的订单
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return productList, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 查询盘点出入库数据
|
|
|
|
|
func getChangeOrderData() ([]ReportOtherDetailData, error) {
|
|
|
|
|
var changeList []ReportOtherDetailData
|
|
|
|
|
err := orm.Eloquent.Debug().Table("erp_inventory_change_order").
|
|
|
|
|
Select("erp_inventory_change_order.serial_number, "+
|
|
|
|
|
"erp_inventory_change_order.store_id, "+
|
|
|
|
|
"erp_inventory_change_order.store_name, "+
|
|
|
|
|
"erp_inventory_change_order.audit_time as stock_time, "+
|
|
|
|
|
"CASE "+
|
|
|
|
|
"WHEN erp_inventory_change_order.change_type = 'add' THEN 2 "+
|
|
|
|
|
"WHEN erp_inventory_change_order.change_type = 'reduce' THEN 4 "+
|
|
|
|
|
"ELSE erp_inventory_change_order.state "+
|
|
|
|
|
"END AS type, "+
|
|
|
|
|
"erp_inventory_change_commodity.commodity_id, "+
|
|
|
|
|
"erp_inventory_change_commodity.commodity_name, "+
|
|
|
|
|
"erp_inventory_change_commodity.supplier_id, "+
|
|
|
|
|
"erp_inventory_change_commodity.supplier_name, "+
|
|
|
|
|
"erp_inventory_change_commodity.imei_type, "+
|
|
|
|
|
"erp_inventory_change_commodity.imei, "+
|
|
|
|
|
"erp_inventory_change_commodity.price as purchase_price, "+
|
|
|
|
|
"erp_inventory_change_commodity.employee_price as employee_price").
|
|
|
|
|
Joins("JOIN erp_inventory_change_commodity "+
|
|
|
|
|
"ON erp_inventory_change_commodity.change_order_id = erp_inventory_change_order.id").
|
|
|
|
|
Where("erp_inventory_change_order.state = ?", ErpInventoryChangeOrderFinished).
|
|
|
|
|
Find(&changeList).Error // 查询已审核的订单
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return changeList, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 查询系统出库数据
|
|
|
|
|
func getSystemOutData() ([]ReportOtherDetailData, error) {
|
|
|
|
|
var stockCommodities []ErpStockCommodity
|
|
|
|
|
err := orm.Eloquent.Table("erp_stock_commodity").
|
|
|
|
|
Where("state = ?", SystemOut).Find(&stockCommodities).Error
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var systemOutList []ReportOtherDetailData
|
|
|
|
|
for _, item := range stockCommodities {
|
|
|
|
|
var systemOutData ReportOtherDetailData
|
|
|
|
|
systemOutData.CommodityId = item.ErpCommodityId
|
|
|
|
|
systemOutData.CommodityName = item.ErpCommodityName
|
|
|
|
|
systemOutData.CategoryID = item.ErpCategoryId
|
|
|
|
|
systemOutData.CategoryName = item.ErpCategoryName
|
|
|
|
|
systemOutData.IMEIType = item.IMEIType
|
|
|
|
|
systemOutData.IMEI = item.IMEI
|
|
|
|
|
systemOutData.StoreId = item.StoreId
|
|
|
|
|
systemOutData.StoreName = item.StoreName
|
|
|
|
|
systemOutData.SupplierId = item.ErpSupplierId
|
|
|
|
|
systemOutData.SupplierName = item.ErpSupplierName
|
|
|
|
|
systemOutData.StockTime = &item.UpdatedAt
|
|
|
|
|
systemOutData.Type = 3
|
|
|
|
|
systemOutData.PurchasePrice = item.WholesalePrice
|
|
|
|
|
systemOutData.EmployeePrice = item.WholesalePrice + item.StaffCostPrice
|
|
|
|
|
|
|
|
|
|
systemOutList = append(systemOutList, systemOutData)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return systemOutList, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// reportOtherDetailExport 其他出入库明细导出excel
|
|
|
|
|
func reportOtherDetailExport(req *InventoryReportOtherDetailResp) (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 inventoryType string
|
|
|
|
|
switch reportData.Type {
|
|
|
|
|
case 1:
|
|
|
|
|
inventoryType = "产品入库"
|
|
|
|
|
case 2:
|
|
|
|
|
inventoryType = "盘点入库"
|
|
|
|
|
case 3:
|
|
|
|
|
inventoryType = "系统出库"
|
|
|
|
|
case 4:
|
|
|
|
|
inventoryType = "盘点出库"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var IMEIType string
|
|
|
|
|
switch reportData.IMEIType {
|
|
|
|
|
case 1:
|
|
|
|
|
IMEIType = "非串码"
|
|
|
|
|
case 2, 3:
|
|
|
|
|
IMEIType = "串码类"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var auditTime string
|
|
|
|
|
if reportData.StockTime != nil {
|
|
|
|
|
auditTime = reportData.StockTime.Format(TimeFormat)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
row1 = []interface{}{
|
|
|
|
|
reportData.CommodityName, // 商品名称
|
|
|
|
|
reportData.CategoryName, // 商品分类
|
|
|
|
|
IMEIType, // 是否串码
|
|
|
|
|
reportData.IMEI, // 商品串码
|
|
|
|
|
reportData.StoreName, // 所属门店
|
|
|
|
|
reportData.SupplierName, // 供应商
|
|
|
|
|
auditTime, // 出/入库时间
|
|
|
|
|
inventoryType, // 方式
|
|
|
|
|
reportData.SerialNumber, // 单据编号
|
|
|
|
|
reportData.PurchasePrice, // 入库采购价
|
|
|
|
|
reportData.EmployeePrice, // 入库员工成本价
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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.TotalPurchasePrice, req.TotalEmployeePrice}
|
|
|
|
|
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", 15)
|
|
|
|
|
file.SetColWidth("Sheet1", "D", "D", 18)
|
|
|
|
|
file.SetColWidth("Sheet1", "E", "E", 28)
|
|
|
|
|
file.SetColWidth("Sheet1", "G", "G", 18)
|
|
|
|
|
file.SetColWidth("Sheet1", "I", "I", 18)
|
|
|
|
|
|
|
|
|
|
endRow := fmt.Sprintf("K"+"%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
|
|
|
|
|
}
|