256 lines
10 KiB
Go
256 lines
10 KiB
Go
package service
|
|
|
|
import (
|
|
"fmt"
|
|
"psi/database"
|
|
"psi/models"
|
|
systemReq "psi/models/request"
|
|
systemRes "psi/models/response"
|
|
"psi/utils"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type OutboundService struct{}
|
|
|
|
// GetOutboundOrderList 获取出库单列表
|
|
func (s *OutboundService) GetOutboundOrderList(req systemReq.GetOutboundOrderListRequest, creatorID int64, role int64, db ...*gorm.DB) (*systemRes.OutboundOrderListResponse, error) {
|
|
databaseConn := database.OptionalDB(db...)
|
|
|
|
if req.Page < 1 {
|
|
req.Page = 1
|
|
}
|
|
if req.PageSize < 1 || req.PageSize > 100 {
|
|
req.PageSize = 20
|
|
}
|
|
|
|
query := databaseConn.Model(&models.OutboundOrder{}).Where("outbound_order.is_del = ?", 0)
|
|
|
|
if req.Status > 0 {
|
|
query = query.Where("outbound_order.status = ?", req.Status)
|
|
}
|
|
if req.CustomerID > 0 {
|
|
query = query.Where("outbound_order.customer_id = ?", req.CustomerID)
|
|
}
|
|
if req.WarehouseID > 0 {
|
|
query = query.Where("outbound_order.warehouse_id = ?", req.WarehouseID)
|
|
}
|
|
if req.LocationID > 0 {
|
|
subQuery := databaseConn.Table("outbound_order_item").
|
|
Select("outbound_order_item.out_order_id").
|
|
Where("outbound_order_item.is_del = 0 AND outbound_order_item.location_id = ?", req.LocationID)
|
|
query = query.Where("outbound_order.id IN (?)", subQuery)
|
|
}
|
|
if req.OutNo != "" {
|
|
query = query.Where("outbound_order.out_no LIKE ?", "%"+req.OutNo+"%")
|
|
}
|
|
if req.StartDate > 0 {
|
|
query = query.Where("outbound_order.created_at >= ?", req.StartDate)
|
|
}
|
|
if req.EndDate > 0 {
|
|
query = query.Where("outbound_order.created_at <= ?", req.EndDate)
|
|
}
|
|
|
|
if req.AssociationOrderNo != "" {
|
|
subQuery := databaseConn.Table("outbound_order_item").
|
|
Select("outbound_order_item.out_order_id").
|
|
Joins("INNER JOIN sales_order ON outbound_order_item.sales_order_id = sales_order.id AND sales_order.is_del = 0").
|
|
Where("outbound_order_item.is_del = 0 AND sales_order.association_order_no LIKE ?", "%"+req.AssociationOrderNo+"%")
|
|
query = query.Where("outbound_order.id IN (?)", subQuery)
|
|
}
|
|
if req.LogisticsNo != "" {
|
|
subQuery := databaseConn.Table("outbound_order_item").
|
|
Select("outbound_order_item.out_order_id").
|
|
Joins("INNER JOIN sales_order_item ON outbound_order_item.sales_order_id = sales_order_item.sales_order_id AND sales_order_item.is_del = 0").
|
|
Where("outbound_order_item.is_del = 0 AND sales_order_item.logistics_no LIKE ?", "%"+req.LogisticsNo+"%")
|
|
query = query.Where("outbound_order.id IN (?)", subQuery)
|
|
}
|
|
if req.ShopType > 0 {
|
|
subQuery := databaseConn.Table("outbound_order_item").
|
|
Select("outbound_order_item.out_order_id").
|
|
Joins("INNER JOIN sales_order ON outbound_order_item.sales_order_id = sales_order.id AND sales_order.is_del = 0").
|
|
Where("outbound_order_item.is_del = 0 AND sales_order.shop_type = ?", req.ShopType)
|
|
query = query.Where("outbound_order.id IN (?)", subQuery)
|
|
}
|
|
|
|
var total int64
|
|
if err := query.Count(&total).Error; err != nil {
|
|
return nil, utils.NewError("查询总数失败")
|
|
}
|
|
|
|
if total == 0 {
|
|
return &systemRes.OutboundOrderListResponse{
|
|
List: []systemRes.OutboundOrderItem{},
|
|
Total: 0,
|
|
Page: req.Page,
|
|
PageSize: req.PageSize,
|
|
}, nil
|
|
}
|
|
|
|
var orders []systemRes.OutboundOrderWithInfo
|
|
offset := (req.Page - 1) * req.PageSize
|
|
if err := query.Select("outbound_order.*, c.name as customer_name, w.name as warehouse_name").
|
|
Joins("LEFT JOIN customer c ON outbound_order.customer_id = c.id AND c.is_del = 0").
|
|
Joins("LEFT JOIN warehouse w ON outbound_order.warehouse_id = w.id AND w.is_del = 0").
|
|
Order("outbound_order.created_at DESC").
|
|
Offset(offset).
|
|
Limit(req.PageSize).
|
|
Find(&orders).Error; err != nil {
|
|
return nil, utils.NewError("查询出库单列表失败")
|
|
}
|
|
|
|
// 收集订单ID用于批量查询
|
|
orderIDs := make([]int64, len(orders))
|
|
for i, order := range orders {
|
|
orderIDs[i] = order.ID
|
|
}
|
|
|
|
// 批量查询店铺信息:按 out_order_id 分组
|
|
type shopRow struct {
|
|
OutOrderID int64 `gorm:"column:out_order_id"`
|
|
ShopName string `gorm:"column:shop_name"`
|
|
ShopType int8 `gorm:"column:shop_type"`
|
|
}
|
|
var shopRows []shopRow
|
|
databaseConn.Table("outbound_order_item").
|
|
Select("DISTINCT outbound_order_item.out_order_id, so.sales_person as shop_name, so.shop_type as shop_type").
|
|
Joins("INNER JOIN sales_order so ON outbound_order_item.sales_order_id = so.id AND so.is_del = 0").
|
|
Where("outbound_order_item.out_order_id IN ? AND outbound_order_item.is_del = ?", orderIDs, 0).
|
|
Scan(&shopRows)
|
|
|
|
shopsByOrderID := make(map[int64][]systemRes.OutboundShopInfo, len(orderIDs))
|
|
for _, row := range shopRows {
|
|
shopsByOrderID[row.OutOrderID] = append(shopsByOrderID[row.OutOrderID], systemRes.OutboundShopInfo{
|
|
ShopName: row.ShopName,
|
|
ShopType: row.ShopType,
|
|
ShopTypeText: systemRes.GetShopTypeText(row.ShopType),
|
|
})
|
|
}
|
|
|
|
// 批量查询关联订单号:按 out_order_id 分组
|
|
type assocRow struct {
|
|
OutOrderID int64 `gorm:"column:out_order_id"`
|
|
AssociationOrderNo string `gorm:"column:association_order_no"`
|
|
}
|
|
var assocRows []assocRow
|
|
databaseConn.Table("outbound_order_item").
|
|
Select("outbound_order_item.out_order_id, GROUP_CONCAT(DISTINCT so.association_order_no SEPARATOR ', ') as association_order_no").
|
|
Joins("INNER JOIN sales_order so ON outbound_order_item.sales_order_id = so.id AND so.is_del = 0").
|
|
Where("outbound_order_item.out_order_id IN ? AND outbound_order_item.is_del = ? AND so.association_order_no != ''", orderIDs, 0).
|
|
Group("outbound_order_item.out_order_id").
|
|
Scan(&assocRows)
|
|
|
|
assocByOrderID := make(map[int64]string, len(assocRows))
|
|
for _, row := range assocRows {
|
|
assocByOrderID[row.OutOrderID] = row.AssociationOrderNo
|
|
}
|
|
|
|
// 批量查询物流单号:按 out_order_id 分组
|
|
type logRow struct {
|
|
OutOrderID int64 `gorm:"column:out_order_id"`
|
|
LogisticsNos string `gorm:"column:logistics_nos"`
|
|
}
|
|
var logRows []logRow
|
|
databaseConn.Table("outbound_order_item").
|
|
Select("outbound_order_item.out_order_id, COALESCE(GROUP_CONCAT(DISTINCT soi.logistics_no SEPARATOR ', '), '') as logistics_nos").
|
|
Joins("INNER JOIN sales_order_item soi ON outbound_order_item.sales_order_id = soi.sales_order_id AND outbound_order_item.product_id = soi.product_id AND soi.is_del = 0").
|
|
Where("outbound_order_item.out_order_id IN ? AND outbound_order_item.is_del = ? AND soi.logistics_no != ''", orderIDs, 0).
|
|
Group("outbound_order_item.out_order_id").
|
|
Scan(&logRows)
|
|
|
|
logByOrderID := make(map[int64]string, len(logRows))
|
|
for _, row := range logRows {
|
|
logByOrderID[row.OutOrderID] = row.LogisticsNos
|
|
}
|
|
|
|
// 组装结果:每个订单从 map 中查找
|
|
orderItems := make([]systemRes.OutboundOrderItem, 0, len(orders))
|
|
for _, order := range orders {
|
|
shopList := shopsByOrderID[order.ID]
|
|
if shopList == nil {
|
|
shopList = []systemRes.OutboundShopInfo{}
|
|
}
|
|
|
|
orderItems = append(orderItems, systemRes.ConvertOutboundOrderToItem(
|
|
order.OutboundOrder,
|
|
order.CustomerName,
|
|
order.WarehouseName,
|
|
shopList,
|
|
assocByOrderID[order.ID],
|
|
logByOrderID[order.ID],
|
|
))
|
|
}
|
|
|
|
return &systemRes.OutboundOrderListResponse{
|
|
List: orderItems,
|
|
Total: total,
|
|
Page: req.Page,
|
|
PageSize: req.PageSize,
|
|
}, nil
|
|
}
|
|
|
|
// GetOutboundOrderDetail 获取出库单详情
|
|
func (s *OutboundService) GetOutboundOrderDetail(id int64, creatorID int64, role int64, db ...*gorm.DB) (*systemRes.OutboundOrderDetailResponse, error) {
|
|
databaseConn := database.OptionalDB(db...)
|
|
|
|
query := databaseConn.Model(&models.OutboundOrder{}).
|
|
Select("outbound_order.*, c.name as customer_name, w.name as warehouse_name").
|
|
Joins("LEFT JOIN customer c ON outbound_order.customer_id = c.id AND c.is_del = 0").
|
|
Joins("LEFT JOIN warehouse w ON outbound_order.warehouse_id = w.id AND w.is_del = 0").
|
|
Where("outbound_order.id = ? AND outbound_order.is_del = ?", id, 0)
|
|
|
|
// 打印SQL调试
|
|
sqlStmt := query.Session(&gorm.Session{DryRun: true}).First(&systemRes.OutboundOrderWithInfo{}).Statement
|
|
fmt.Println("Generated SQL:", sqlStmt.SQL.String(), "Vars:", sqlStmt.Vars)
|
|
|
|
var order systemRes.OutboundOrderWithInfo
|
|
result := query.First(&order)
|
|
|
|
if result.Error != nil {
|
|
return nil, utils.NewError("出库单不存在")
|
|
}
|
|
|
|
var items []systemRes.OutboundOrderItemWithProduct
|
|
itemQuery := databaseConn.Model(&models.OutboundOrderItem{}).
|
|
Select("outbound_order_item.*, p.name as product_name, p.barcode as product_code, p.category_id, c.name as category_name, l.code as location_name, w.name as warehouse_name, w.code as warehouse_code, so.so_no as sales_order_no").
|
|
Joins("LEFT JOIN product p ON outbound_order_item.product_id = p.id AND p.is_del = 0").
|
|
Joins("LEFT JOIN product_category c ON p.category_id = c.id AND c.is_del = 0").
|
|
Joins("LEFT JOIN location l ON outbound_order_item.location_id = l.id AND l.is_del = 0").
|
|
Joins("LEFT JOIN warehouse w ON l.warehouse_id = w.id AND w.is_del = 0").
|
|
Joins("LEFT JOIN sales_order so ON outbound_order_item.sales_order_id = so.id AND so.is_del = 0").
|
|
Where("outbound_order_item.out_order_id = ? AND outbound_order_item.is_del = ?", order.ID, 0)
|
|
|
|
// 打印SQL调试
|
|
itemSqlStmt := itemQuery.Session(&gorm.Session{DryRun: true}).Find(&[]systemRes.OutboundOrderItemWithProduct{}).Statement
|
|
fmt.Println("Generated SQL:", itemSqlStmt.SQL.String(), "Vars:", itemSqlStmt.Vars)
|
|
|
|
itemQuery.Find(&items)
|
|
|
|
detailItems := make([]systemRes.OutboundOrderDetailItem, 0, len(items))
|
|
for _, item := range items {
|
|
detailItems = append(detailItems, systemRes.OutboundOrderDetailItem{
|
|
ID: item.ID,
|
|
OutboundOrderID: item.OutOrderID,
|
|
SalesOrderNo: item.SalesOrderNo,
|
|
ProductID: item.ProductID,
|
|
ProductName: item.ProductName,
|
|
ProductCode: item.ProductCode,
|
|
CategoryID: item.CategoryID,
|
|
CategoryName: item.CategoryName,
|
|
LocationID: item.LocationID,
|
|
LocationName: item.LocationName,
|
|
WarehouseName: item.WarehouseName,
|
|
WarehouseCode: item.WarehouseCode,
|
|
BatchNo: item.BatchNo,
|
|
ProductionDate: item.ProductionDate,
|
|
ExpiryDate: item.ExpiryDate,
|
|
Quantity: item.Quantity,
|
|
CreatedAt: item.CreatedAt,
|
|
UpdatedAt: item.UpdatedAt,
|
|
})
|
|
}
|
|
|
|
detail := systemRes.ConvertOutboundOrderToDetail(order.OutboundOrder, order.CustomerName, order.WarehouseName, detailItems)
|
|
return &detail, nil
|
|
}
|