daShangDao_psiServer/service/inventory.go

736 lines
24 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 service
import (
"fmt"
"psi/constant"
"psi/database"
"psi/models"
systemReq "psi/models/request"
systemRes "psi/models/response"
"psi/utils"
"gorm.io/gorm"
)
type InventoryService struct{}
// GetInventoryList 获取库存汇总列表
func (s *InventoryService) GetInventoryList(req systemReq.GetInventoryListRequest, db ...*gorm.DB) (*systemRes.InventoryListResponse, error) {
databaseConn := database.OptionalDB(db...)
if req.Page < 1 {
req.Page = 1
}
if req.PageSize < 1 || req.PageSize > 100 {
req.PageSize = 20
}
query := databaseConn.Table("inventory").
Select(`
inventory.product_id,
p.name as product_name,
p.barcode,
p.appearance,
p.price,
inventory.warehouse_id,
w.name as warehouse_name,
w.code as warehouse_code,
l.code as location_code,
i.quantity as total_quantity,
i.locked_quantity as locked_quantity
`).
Joins("LEFT JOIN inventory_detail i ON i.product_id = inventory.product_id").
Joins("LEFT JOIN location l ON l.id = i.location_id").
Joins("LEFT JOIN product p ON inventory.product_id = p.id AND p.is_del = 0").
Joins("LEFT JOIN warehouse w ON inventory.warehouse_id = w.id AND w.is_del = 0").
Where("inventory.is_del = ?", 0)
if req.ProductId > 0 {
query = query.Where("inventory.product_id = ?", req.ProductId)
}
if req.WarehouseID > 0 {
query = query.Where("inventory.warehouse_id = ?", req.WarehouseID)
}
if req.LocationID > 0 {
query = query.Where("i.location_id = ?", req.LocationID)
}
if req.ISBN != "" {
query = query.Where("p.barcode LIKE ?", "%"+req.ISBN+"%")
}
if req.Name != "" {
query = query.Where("p.name LIKE ?", "%"+req.Name+"%")
}
var total int64
if err := query.Count(&total).Error; err != nil {
return nil, utils.NewError("查询总数失败")
}
if total == 0 {
return &systemRes.InventoryListResponse{
List: []systemRes.InventoryItem{},
Total: 0,
Page: req.Page,
PageSize: req.PageSize,
}, nil
}
type InventorySummary struct {
ProductID int64 `gorm:"column:product_id"`
ProductName string `gorm:"column:product_name"`
Appearance int64 `gorm:"column:appearance"`
Barcode string `gorm:"column:barcode"`
Price int64 `gorm:"column:price"`
WarehouseID int64 `gorm:"column:warehouse_id"`
WarehouseName string `gorm:"column:warehouse_name"`
WarehouseCode string `gorm:"column:warehouse_code"`
LocationCode string `gorm:"column:location_code"`
TotalQuantity int64 `gorm:"column:total_quantity"`
LockedQuantity int64 `gorm:"column:locked_quantity"`
}
var summaries []InventorySummary
offset := (req.Page - 1) * req.PageSize
if err := query.Order("i.updated_at DESC").Offset(offset).Limit(req.PageSize).Find(&summaries).Error; err != nil {
return nil, utils.NewError("查询库存汇总列表失败")
}
items := make([]systemRes.InventoryItem, 0, len(summaries))
for _, summary := range summaries {
items = append(items, systemRes.ConvertInventoryToItem(
summary.ProductID,
summary.ProductName,
summary.Appearance,
summary.Barcode,
summary.Price,
summary.WarehouseID,
summary.WarehouseName,
summary.WarehouseCode,
summary.LocationCode,
summary.TotalQuantity,
summary.LockedQuantity,
))
}
return &systemRes.InventoryListResponse{
List: items,
Total: total,
Page: req.Page,
PageSize: req.PageSize,
}, nil
}
// GetInventoryGroupedList 获取按仓库库位分组的库存列表
func (s *InventoryService) GetInventoryGroupedList(req systemReq.GetInventoryGroupedListRequest, db ...*gorm.DB) (*systemRes.InventoryGroupedListResponse, error) {
databaseConn := database.OptionalDB(db...)
if req.Page < 1 {
req.Page = 1
}
if req.PageSize < 1 || req.PageSize > 100 {
req.PageSize = 20
}
// 第一步:查询仓库库位分组统计信息
groupQuery := databaseConn.Table("inventory_detail").
Select(`
inventory_detail.warehouse_id,
w.name as warehouse_name,
w.code as warehouse_code,
inventory_detail.location_id,
l.code as location_code,
COALESCE(SUM(inventory_detail.quantity), 0) as total_quantity,
COALESCE(SUM(inventory_detail.locked_quantity), 0) as locked_quantity,
COUNT(DISTINCT inventory_detail.product_id) as item_count
`).
Joins("LEFT JOIN warehouse w ON inventory_detail.warehouse_id = w.id AND w.is_del = 0").
Joins("LEFT JOIN location l ON inventory_detail.location_id = l.id AND l.is_del = 0").
Where("inventory_detail.is_del = ?", 0).
Group("inventory_detail.warehouse_id, w.name, w.code, inventory_detail.location_id, l.code")
if req.WarehouseID > 0 {
groupQuery = groupQuery.Where("inventory_detail.warehouse_id = ?", req.WarehouseID)
}
if req.LocationID > 0 {
groupQuery = groupQuery.Where("inventory_detail.location_id = ?", req.LocationID)
}
var total int64
if err := groupQuery.Count(&total).Error; err != nil {
return nil, utils.NewError("查询总数失败")
}
if total == 0 {
return &systemRes.InventoryGroupedListResponse{
List: []systemRes.InventoryGroupItem{},
Total: 0,
Page: req.Page,
PageSize: req.PageSize,
}, nil
}
type GroupSummary struct {
WarehouseID int64 `gorm:"column:warehouse_id"`
WarehouseName string `gorm:"column:warehouse_name"`
WarehouseCode string `gorm:"column:warehouse_code"`
LocationID int64 `gorm:"column:location_id"`
LocationCode string `gorm:"column:location_code"`
TotalQuantity int64 `gorm:"column:total_quantity"`
LockedQuantity int64 `gorm:"column:locked_quantity"`
ItemCount int `gorm:"column:item_count"`
}
var groupSummaries []GroupSummary
offset := (req.Page - 1) * req.PageSize
if err := groupQuery.Order("inventory_detail.warehouse_id ASC, inventory_detail.location_id ASC").Offset(offset).Limit(req.PageSize).Find(&groupSummaries).Error; err != nil {
return nil, utils.NewError("查询库存分组列表失败")
}
// 第二步:为每个分组查询详细的库存记录
groupList := make([]systemRes.InventoryGroupItem, 0, len(groupSummaries))
for _, group := range groupSummaries {
// 查询该仓库库位下的所有库存明细
detailQuery := databaseConn.Table("inventory_detail").
Select(`
inventory_detail.*,
p.name as product_name,
p.barcode,
p.appearance,
p.sale_price
`).
Joins("LEFT JOIN product p ON inventory_detail.product_id = p.id AND p.is_del = 0").
Where("inventory_detail.warehouse_id = ? AND inventory_detail.location_id = ? AND inventory_detail.is_del = ?",
group.WarehouseID, group.LocationID, 0)
if req.ProductId > 0 {
detailQuery = detailQuery.Where("inventory_detail.product_id = ?", req.ProductId)
}
var details []struct {
models.InventoryDetail
ProductName string `gorm:"column:product_name"`
Barcode string `gorm:"column:barcode"`
Appearance int64 `gorm:"column:appearance"`
SalePrice int64 `gorm:"column:sale_price"`
}
if err := detailQuery.Order("inventory_detail.updated_at DESC").Find(&details).Error; err != nil {
utils.ErrorLog(constant.LoggerChannelWork, map[string]interface{}{
"source": "查询库存明细",
"warehouse_id": group.WarehouseID,
"location_id": group.LocationID,
"error": fmt.Sprintf("查询失败: %v", err),
})
continue
}
detailItems := make([]systemRes.InventoryDetailItem, 0, len(details))
for _, detail := range details {
detailItems = append(detailItems, systemRes.InventoryDetailItem{
ID: detail.ID,
WarehouseID: detail.WarehouseID,
WarehouseName: group.WarehouseName,
LocationID: detail.LocationID,
LocationCode: group.LocationCode,
BatchNo: detail.BatchNo,
ProductionDate: detail.ProductionDate,
ExpiryDate: detail.ExpiryDate,
Quantity: detail.Quantity,
LockedQuantity: detail.LockedQuantity,
CreatedAt: detail.CreatedAt,
UpdatedAt: detail.UpdatedAt,
ProductID: detail.ProductID,
ProductName: detail.ProductName,
Barcode: detail.Barcode,
Appearance: detail.Appearance,
SalePrice: detail.SalePrice,
})
}
groupList = append(groupList, systemRes.InventoryGroupItem{
WarehouseID: group.WarehouseID,
WarehouseName: group.WarehouseName,
WarehouseCode: group.WarehouseCode,
LocationID: group.LocationID,
LocationCode: group.LocationCode,
TotalQuantity: group.TotalQuantity,
LockedQuantity: group.LockedQuantity,
ItemCount: group.ItemCount,
Details: detailItems,
})
}
return &systemRes.InventoryGroupedListResponse{
List: groupList,
Total: total,
Page: req.Page,
PageSize: req.PageSize,
}, nil
}
// GetInventorySummary 获取库存统计信息
func (s *InventoryService) GetInventorySummary(db ...*gorm.DB) (*systemRes.InventorySummaryResponse, error) {
databaseConn := database.OptionalDB(db...)
response := &systemRes.InventorySummaryResponse{}
// 1. 查询商品总种类数同一个barcode算一个
productTypeQuery := databaseConn.Table("inventory_detail").
Joins("LEFT JOIN product p ON inventory_detail.product_id = p.id AND p.is_del = ?", 0).
Where("inventory_detail.is_del = ?", 0)
var productTypeCount int64
if err := productTypeQuery.Distinct("p.barcode").Count(&productTypeCount).Error; err != nil {
utils.ErrorLog(constant.LoggerChannelWork, map[string]interface{}{
"source": "查询商品种类数",
"error": fmt.Sprintf("查询失败: %v", err),
})
return nil, utils.NewError("查询商品种类数失败")
}
response.ProductTypeCount = productTypeCount
// 2. 查询商品总数(不去重,按库存明细记录数)
productCountQuery := databaseConn.Table("inventory_detail").
Where("inventory_detail.is_del = ?", 0)
var productCount int64
if err := productCountQuery.Count(&productCount).Error; err != nil {
utils.ErrorLog(constant.LoggerChannelWork, map[string]interface{}{
"source": "查询商品总数",
"error": fmt.Sprintf("查询失败: %v", err),
})
return nil, utils.NewError("查询商品总数失败")
}
response.ProductCount = productCount
// 3. 查询库存总量
totalQuantityQuery := databaseConn.Table("inventory_detail").
Select("COALESCE(SUM(quantity), 0)").
Where("inventory_detail.is_del = ?", 0)
var totalQuantity int64
if err := totalQuantityQuery.Scan(&totalQuantity).Error; err != nil {
utils.ErrorLog(constant.LoggerChannelWork, map[string]interface{}{
"source": "查询库存总量",
"error": fmt.Sprintf("查询失败: %v", err),
})
return nil, utils.NewError("查询库存总量失败")
}
response.TotalQuantity = totalQuantity
// 4. 查询有货商品数量库存大于0的商品种类按barcode去重
availableProductQuery := databaseConn.Table("inventory_detail").
Joins("LEFT JOIN product p ON inventory_detail.product_id = p.id AND p.is_del = ?", 0).
Where("inventory_detail.is_del = ?", 0).
Where("inventory_detail.quantity > 0")
var availableProductCount int64
if err := availableProductQuery.Distinct("p.barcode").Count(&availableProductCount).Error; err != nil {
utils.ErrorLog(constant.LoggerChannelWork, map[string]interface{}{
"source": "查询有货商品数量",
"error": fmt.Sprintf("查询失败: %v", err),
})
return nil, utils.NewError("查询有货商品数量失败")
}
response.AvailableProductCount = availableProductCount
// 5. 查询库位数(使用过的库位数量)
locationQuery := databaseConn.Table("inventory_detail").
Select("COUNT(DISTINCT location_id)").
Where("inventory_detail.is_del = ?", 0)
var locationCount int64
if err := locationQuery.Scan(&locationCount).Error; err != nil {
utils.ErrorLog(constant.LoggerChannelWork, map[string]interface{}{
"source": "查询库位数",
"error": fmt.Sprintf("查询失败: %v", err),
})
return nil, utils.NewError("查询库位数失败")
}
response.LocationCount = locationCount
return response, nil
}
// GetInventoryDetail 获取库存明细
func (s *InventoryService) GetInventoryDetail(productID int64, db ...*gorm.DB) (*systemRes.InventoryDetailResponse, error) {
databaseConn := database.OptionalDB(db...)
var product models.Product
if err := databaseConn.Where("id = ? AND is_del = ?", productID, 0).First(&product).Error; err != nil {
return nil, utils.NewError("商品不存在")
}
query := databaseConn.Model(&models.InventoryDetail{}).
Select("inventory_detail.*, w.name as warehouse_name, l.code as location_code").
Joins("LEFT JOIN warehouse w ON inventory_detail.warehouse_id = w.id AND w.is_del = 0").
Joins("LEFT JOIN location l ON inventory_detail.location_id = l.id AND l.is_del = 0").
Where("inventory_detail.product_id = ? AND inventory_detail.is_del = ?", productID, 0)
var total int64
if err := query.Count(&total).Error; err != nil {
return nil, utils.NewError("查询总数失败")
}
var details []struct {
models.InventoryDetail
WarehouseName string `gorm:"column:warehouse_name"`
LocationCode string `gorm:"column:location_code"`
}
if err := query.Order("inventory_detail.updated_at DESC").Find(&details).Error; err != nil {
return nil, utils.NewError("查询库存明细失败")
}
// 查询该商品关联的任务信息
type TaskInfo struct {
WaveNo string `gorm:"column:wave_no"`
WaveTaskNo string `gorm:"column:wave_task_no"`
OutTaskNo int64 `gorm:"column:out_task_no"`
SalesOrderNo string `gorm:"column:sales_order_no"`
ShippingNo string `gorm:"column:shipping_no"`
}
var taskInfo TaskInfo
databaseConn.Table("wave_task_detail wtd").
Select(`COALESCE(wh.wave_no, '') as wave_no,
COALESCE(wt.task_no, '') as wave_task_no,
COALESCE(ot.out_task_id, 0) as out_task_no,
COALESCE(so.so_no, '') as sales_order_no,
COALESCE(sh.shipping_no, '') as shipping_no`).
Joins("JOIN wave_task wt ON wt.id = wtd.wave_task_id AND wt.is_del = 0").
Joins("JOIN wave_header wh ON wh.id = wt.wave_id AND wh.is_del = 0").
Joins("LEFT JOIN out_task ot ON ot.wave_task_id = wt.id AND ot.is_del = 0").
Joins("LEFT JOIN sales_order so ON so.id = wh.related_order_id AND so.is_del = 0").
Joins("LEFT JOIN outbound_order obo ON obo.wave_task_id = wt.id AND obo.is_del = 0").
Joins("LEFT JOIN outbound_order_item oboi ON oboi.out_order_id = obo.id AND oboi.product_id = ? AND oboi.is_del = 0", productID).
Joins("LEFT JOIN shipping_order_item soi ON soi.outbound_order_item_id = oboi.id AND soi.is_del = 0").
Joins("LEFT JOIN shipping_order sh ON sh.id = soi.shipping_order_id AND sh.is_del = 0").
Where("wtd.product_id = ? AND wtd.is_del = 0", productID).
Order("wt.id DESC").
Limit(1).
Scan(&taskInfo)
items := make([]systemRes.InventoryDetailItem, 0, len(details))
for _, detail := range details {
items = append(items, systemRes.ConvertInventoryDetailToItem(
detail.InventoryDetail,
detail.WarehouseName,
detail.LocationCode,
taskInfo.WaveNo,
taskInfo.WaveTaskNo,
taskInfo.OutTaskNo,
taskInfo.SalesOrderNo,
taskInfo.ShippingNo,
))
}
return &systemRes.InventoryDetailResponse{
ProductID: productID,
ProductName: product.Name,
List: items,
Total: total,
}, nil
}
// GetInventoryLogList 获取库存流水列表
func (s *InventoryService) GetInventoryLogList(req systemReq.GetInventoryLogListRequest, db ...*gorm.DB) (*systemRes.InventoryLogListResponse, error) {
databaseConn := database.OptionalDB(db...)
if req.Page < 1 {
req.Page = 1
}
if req.PageSize < 1 || req.PageSize > 100 {
req.PageSize = 20
}
query := databaseConn.Table("inventory_log").
Select(`
inventory_log.*,
w.name as warehouse_name,
l.code as location_code,
p.name as product_name,
p.barcode
`).
Joins("LEFT JOIN warehouse w ON inventory_log.warehouse_id = w.id AND w.is_del = 0").
Joins("LEFT JOIN location l ON inventory_log.location_id = l.id AND l.is_del = 0").
Joins("LEFT JOIN product p ON inventory_log.product_id = p.id AND p.is_del = 0").
Where("inventory_log.is_del = ?", 0)
if req.ISBN != "" {
query = query.Where("p.barcode LIKE ?", "%"+req.ISBN+"%")
}
if req.BookName != "" {
query = query.Where("p.name LIKE ?", "%"+req.BookName+"%")
}
if req.WarehouseID > 0 {
query = query.Where("inventory_log.warehouse_id = ?", req.WarehouseID)
}
if req.LocationID > 0 {
query = query.Where("inventory_log.location_id = ?", req.LocationID)
}
if req.ChangeType > 0 {
query = query.Where("inventory_log.change_type = ?", req.ChangeType)
}
if req.RelatedOrderNo != "" {
query = query.Where("inventory_log.related_order_no LIKE ?", "%"+req.RelatedOrderNo+"%")
}
if req.StartDate > 0 {
query = query.Where("inventory_log.created_at >= ?", req.StartDate)
}
if req.EndDate > 0 {
query = query.Where("inventory_log.created_at <= ?", req.EndDate)
}
var total int64
if err := query.Count(&total).Error; err != nil {
return nil, utils.NewError("查询总数失败")
}
if total == 0 {
return &systemRes.InventoryLogListResponse{
List: []systemRes.InventoryLogItem{},
Total: 0,
Page: req.Page,
PageSize: req.PageSize,
}, nil
}
var logs []struct {
models.InventoryLog
WarehouseName string `gorm:"column:warehouse_name"`
LocationCode string `gorm:"column:location_code"`
ProductName string `gorm:"column:product_name"`
Barcode string `gorm:"column:barcode"`
}
offset := (req.Page - 1) * req.PageSize
if err := query.Order("inventory_log.created_at DESC").Offset(offset).Limit(req.PageSize).Find(&logs).Error; err != nil {
return nil, utils.NewError("查询库存流水列表失败")
}
items := make([]systemRes.InventoryLogItem, 0, len(logs))
for _, log := range logs {
items = append(items, systemRes.ConvertInventoryLogToItem(
log.InventoryLog,
log.WarehouseName,
log.LocationCode,
log.ProductName,
log.Barcode,
))
}
return &systemRes.InventoryLogListResponse{
List: items,
Total: total,
Page: req.Page,
PageSize: req.PageSize,
}, nil
}
// InventoryStatist 获取ISBN/品相的库存总数(跨所有商品和仓库)
func (s *InventoryService) InventoryStatist(req systemReq.InventoryStatistRequest, db ...*gorm.DB) (*systemRes.InventoryStatistResponse, error) {
databaseConn := database.OptionalDB(db...)
if req.Barcode == "" && req.Appearance <= 0 {
return nil, utils.NewError("条码和品相至少提供一个")
}
type InventoryTotal struct {
Barcode string `gorm:"column:barcode"`
Appearance int64 `gorm:"column:appearance"`
TotalQuantity int64 `gorm:"column:total_quantity"`
ProductCount int `gorm:"column:product_count"`
}
query := databaseConn.Table("inventory").
Select(`
p.barcode,
p.appearance,
SUM(inventory.quantity) as total_quantity,
COUNT(DISTINCT inventory.product_id) as product_count
`).
Joins("LEFT JOIN product p ON inventory.product_id = p.id AND p.is_del = 0").
Where("inventory.is_del = ?", 0)
if req.Barcode != "" {
query = query.Where("p.barcode = ?", req.Barcode)
}
if req.Appearance > 0 {
query = query.Where("p.Appearance = ?", req.Appearance)
}
var total InventoryTotal
if err := query.Group("p.barcode, p.appearance").Limit(1).Scan(&total).Error; err != nil {
return nil, utils.NewError("查询库存总数失败")
}
return &systemRes.InventoryStatistResponse{
Barcode: total.Barcode,
Appearance: total.Appearance,
TotalQuantity: total.TotalQuantity,
ProductCount: total.ProductCount,
}, nil
}
// GetStockCheckList 获取盘库列表(不包含明细)
func (s *InventoryService) GetStockCheckList(req systemReq.GetStockCheckListRequest, db ...*gorm.DB) (*systemRes.StockCheckListResponse, error) {
databaseConn := database.OptionalDB(db...)
if req.Page < 1 {
req.Page = 1
}
if req.PageSize < 1 || req.PageSize > 100 {
req.PageSize = 20
}
query := databaseConn.Table("stock_check").
Select(`
stock_check.*,
w.name as warehouse_name
`).
Joins("LEFT JOIN warehouse w ON stock_check.warehouse_id = w.id AND w.is_del = 0").
Where("stock_check.is_del = ?", 0)
if req.WarehouseID > 0 {
query = query.Where("stock_check.warehouse_id = ?", req.WarehouseID)
}
if req.Status > 0 {
query = query.Where("stock_check.status = ?", req.Status)
}
if req.CheckNo != "" {
query = query.Where("stock_check.check_no LIKE ?", "%"+req.CheckNo+"%")
}
if req.StartDate > 0 {
query = query.Where("stock_check.created_at >= ?", req.StartDate)
}
if req.EndDate > 0 {
query = query.Where("stock_check.created_at <= ?", req.EndDate)
}
var total int64
if err := query.Count(&total).Error; err != nil {
return nil, utils.NewError("查询总数失败")
}
if total == 0 {
return &systemRes.StockCheckListResponse{
List: []systemRes.StockCheckItem{},
Total: 0,
Page: req.Page,
PageSize: req.PageSize,
}, nil
}
type StockCheckWithWarehouse struct {
models.StockCheck
WarehouseName string `gorm:"column:warehouse_name"`
}
var checks []StockCheckWithWarehouse
offset := (req.Page - 1) * req.PageSize
if err := query.Order("stock_check.created_at DESC").Offset(offset).Limit(req.PageSize).Find(&checks).Error; err != nil {
return nil, utils.NewError("查询盘库列表失败")
}
items := make([]systemRes.StockCheckItem, 0, len(checks))
for _, check := range checks {
item := systemRes.ConvertStockCheckToItem(check.StockCheck, check.WarehouseName)
items = append(items, item)
}
return &systemRes.StockCheckListResponse{
List: items,
Total: total,
Page: req.Page,
PageSize: req.PageSize,
}, nil
}
// GetStockCheckDetail 获取盘库明细列表
func (s *InventoryService) GetStockCheckDetail(req systemReq.GetStockCheckDetailRequest, db ...*gorm.DB) (*systemRes.StockCheckDetailResponse, error) {
databaseConn := database.OptionalDB(db...)
if req.Page < 1 {
req.Page = 1
}
if req.PageSize < 1 || req.PageSize > 100 {
req.PageSize = 20
}
if req.StockCheckID == 0 {
return nil, utils.NewError("盘库单ID不能为空")
}
query := databaseConn.Table("stock_check_item").
Select(`
stock_check_item.*,
p.name as product_name,
p.barcode,
l.code as location_code
`).
Joins("LEFT JOIN product p ON stock_check_item.product_id = p.id AND p.is_del = 0").
Joins("LEFT JOIN location l ON stock_check_item.location_id = l.id AND l.is_del = 0").
Where("stock_check_item.stock_check_id = ? AND stock_check_item.is_del = ?", req.StockCheckID, 0)
var total int64
if err := query.Count(&total).Error; err != nil {
return nil, utils.NewError("查询总数失败")
}
if total == 0 {
return &systemRes.StockCheckDetailResponse{
List: []systemRes.StockCheckDetailItem{},
Total: 0,
Page: req.Page,
PageSize: req.PageSize,
}, nil
}
type StockCheckItemWithInfo struct {
models.StockCheckItem
ProductName string `gorm:"column:product_name"`
Barcode string `gorm:"column:barcode"`
LocationCode string `gorm:"column:location_code"`
}
var items []StockCheckItemWithInfo
offset := (req.Page - 1) * req.PageSize
if err := query.Order("stock_check_item.created_at ASC").Offset(offset).Limit(req.PageSize).Find(&items).Error; err != nil {
return nil, utils.NewError("查询盘库明细失败")
}
details := make([]systemRes.StockCheckDetailItem, 0, len(items))
for _, item := range items {
detail := systemRes.StockCheckDetailItem{
ID: item.ID,
ProductID: item.ProductID,
ProductName: item.ProductName,
Barcode: item.Barcode,
LocationID: item.LocationID,
LocationCode: item.LocationCode,
BatchNo: item.BatchNo,
ProductionDate: item.ProductionDate,
ExpiryDate: item.ExpiryDate,
SystemQuantity: item.SystemQuantity,
ActualQuantity: item.ActualQuantity,
DifferenceQuantity: item.DifferenceQuantity,
Status: item.Status,
StatusText: systemRes.GetStockCheckItemStatusText(item.Status),
CheckOperator: item.CheckOperator,
CheckOperatorID: item.CheckOperatorID,
CheckTime: item.CheckTime,
Remark: item.Remark,
CreatedAt: item.CreatedAt,
UpdatedAt: item.UpdatedAt,
}
details = append(details, detail)
}
return &systemRes.StockCheckDetailResponse{
List: details,
Total: total,
Page: req.Page,
PageSize: req.PageSize,
}, nil
}