mh_goadmin_server/app/admin/models/inventory_report.go

501 lines
22 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package models
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"
"strconv"
"time"
)
// 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 {
Total uint32 `json:"total"` // 总条数/记录数
PageIndex int `json:"pageIndex"` // 页码
PageSize int `json:"pageSize"` // 页面条数
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"` // 调入中金额
ExportUrl string `json:"export_url"` // 导出excel路径
List []ReportByProductData `json:"list"` //
}
// 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 {
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"` // 调拨金额
}
// InventoryReportAllotDetailReq 库存调拨明细入参
type InventoryReportAllotDetailReq struct {
SerialNumber string `json:"serial_number"` // 单据编号
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"` // 页面条数
}
// InventoryReportAllotDetailResp 库存调拨明细出参
type InventoryReportAllotDetailResp struct {
Total int `json:"total"` // 总条数/记录数
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"` // 审核时间
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"` // 商品串码
}
// InventoryReportByOtherReq 其他出入库汇总入参
type InventoryReportByOtherReq struct {
StoreId []uint32 `json:"store_id"` // 门店id
CommodityName []string `json:"commodity_name"` // 商品名称
CategoryID []uint32 `json:"category_id"` // 商品分类id
State uint32 `json:"state"` // 调拨状态1-产品入库 2-盘点入库 3-系统出库 4-盘点出库
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"` // 页面条数
TotalCount int32 `json:"total_count"` // 总数量
TotalAmount float64 `json:"total_amount"` // 总金额
ExportUrl string `json:"export_url"` // 导出excel路径
List []ReportByOtherData `json:"list"` //
}
// ReportByOtherData 其他出入库汇总数据
type ReportByOtherData struct {
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"` // 商品分类名称
State uint32 `json:"state"` // 调拨状态1-产品入库 2-盘点入库 3-系统出库 4-盘点出库
Count int32 `json:"count"` // 数量
Amount float64 `json:"amount"` // 金额
}
// 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
State uint32 `json:"state"` // 调拨状态1-产品入库 2-盘点入库 3-系统出库 4-盘点出库
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"` // 出入库时间
State uint32 `json:"state"` // 调拨状态1-产品入库 2-盘点入库 3-系统出库 4-盘点出库
SerialNumber string `json:"serial_number"` // 单据编号
PurchasePrice float64 `json:"purchase_price"` // 入库采购价
EmployeePrice float64 `json:"employee_price"` // 入库员工成本价
}
// 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)
}
qs = qs.Where("category_id IN (?)", categoryIDs)
}
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)
}
qs = qs.Where("commodity_name IN (?)", commodityNames)
}
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
err = qs.Find(&commodities).Error
} else {
err = qs.Offset(page * m.PageSize).Limit(m.PageSize).Find(&commodities).Error
}
if err != nil && err != RecordNotFound {
logger.Error("查询无库存列表失败", logger.Field("err", err))
return nil, err
}
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)
}
resp.TotalEffectiveCount = nTotalEffectiveCount
resp.TotalTransferCount = nTotalTransferCount
resp.TotalCount = resp.TotalTransferCount + resp.TotalEffectiveCount
resp.TotalEffectiveAmount = nTotalEffectiveAmount
resp.TotalTransferAmount = nTotalTransferAmount
resp.Total = resp.TotalCount
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
}
// 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
}