daShangDao_psiServer/service/shipping.go
Administrator a2ea0c3a40 1.在这个接口里 /api/product/updateNameAndImages,添加多张图片时,并未覆盖原来的多张图片。(Y)
2.从系统导出的excel数据,在外部对excel某一列进行更改时,新增的要回传到原来的地方;并对改动的地方进行覆盖。
3.销售单管理、出库管理、发货单三个接口里面展示第三方订单编号和快递单号
4.选择多个仓库时,只要选择发货单子就会报错
5.在这个/api/split-account-deduction-log/create接口里,当传参时,如果参数 total_amount 是0,则会报错 {"code":204,"data":{},"msg":"TotalAmount不能为空"} 0是金额数字,不能当空值进行判断(T)
传递参数created_by,没有往数据表里写入
6.商品销毁的同时写入日志,也能通过读取这个日志,还原销毁的商品。传出这个新增的接口
7.新增一个不需要签名认证的分帐扣钱日志列表接口,新增一个返回字段buniness_no,并对这个字段进行模糊查询。
测试接口:/open/split-account-deduction-log/list
8.增加个新接口:首先 调用 /api/sales-order/create 创建销售订单的时候会锁定库存,
现在我需要一个解锁库存的接口,传递参数是订单编号
POST /api/sales-order/unlock-inventory // 解锁销售订单库存
/api/split-account-deduction-log/update /api/sales-order/unlock-inventory 在这两个接口里不需要签名认证
/api/sales-order/unlock-inventory 在这个接口里面返回解锁的所有商品信息
/api/split-account-deduction-log/update  在这个接口里面的status也需要更改,status没有变化
2026-06-24 09:41:12 +08:00

460 lines
18 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 (
"psi/database"
"psi/models"
systemReq "psi/models/request"
systemRes "psi/models/response"
"psi/utils"
"gorm.io/gorm"
)
type ShippingService struct{}
// GetShippingOrderList 获取发货单列表
func (s *ShippingService) GetShippingOrderList(req systemReq.GetShippingOrderListRequest, creatorID int64, role int64, db ...*gorm.DB) (*systemRes.ShippingOrderListResponse, 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.ShippingOrder{}).Where("shipping_order.is_del = ?", 0)
if req.Status > 0 {
query = query.Where("shipping_order.status = ?", req.Status)
}
if req.CustomerID > 0 {
query = query.Where("shipping_order.customer_id = ?", req.CustomerID)
}
if req.ShippingNo != "" {
query = query.Where("shipping_order.shipping_no LIKE ?", "%"+req.ShippingNo+"%")
}
if req.StartDate > 0 {
query = query.Where("shipping_order.created_at >= ?", req.StartDate)
}
if req.EndDate > 0 {
query = query.Where("shipping_order.created_at <= ?", req.EndDate)
}
if req.AssociationOrderNo != "" {
subQuery := databaseConn.Table("shipping_order_item").
Select("shipping_order_item.shipping_order_id").
Joins("INNER JOIN outbound_order_item ON shipping_order_item.outbound_order_item_id = outbound_order_item.id AND outbound_order_item.is_del = 0").
Joins("INNER JOIN sales_order ON outbound_order_item.sales_order_id = sales_order.id AND sales_order.is_del = 0").
Where("shipping_order_item.is_del = 0 AND sales_order.association_order_no LIKE ?", "%"+req.AssociationOrderNo+"%")
query = query.Where("shipping_order.id IN (?)", subQuery)
}
if req.LogisticsNo != "" {
subQuery := databaseConn.Table("shipping_order_item").
Select("shipping_order_item.shipping_order_id").
Joins("INNER JOIN outbound_order_item ON shipping_order_item.outbound_order_item_id = outbound_order_item.id AND outbound_order_item.is_del = 0").
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("shipping_order_item.is_del = 0 AND sales_order_item.logistics_no LIKE ?", "%"+req.LogisticsNo+"%")
query = query.Where("shipping_order.id IN (?)", subQuery)
}
var total int64
if err := query.Count(&total).Error; err != nil {
return nil, utils.NewError("查询总数失败")
}
if total == 0 {
return &systemRes.ShippingOrderListResponse{
List: []systemRes.ShippingOrderItem{},
Total: 0,
Page: req.Page,
PageSize: req.PageSize,
}, nil
}
var orders []systemRes.ShippingOrderWithInfo
offset := (req.Page - 1) * req.PageSize
if err := query.Select("shipping_order.*, c.name as customer_name").
Joins("LEFT JOIN customer c ON shipping_order.customer_id = c.id AND c.is_del = 0").
Order("shipping_order.created_at DESC").
Offset(offset).
Limit(req.PageSize).
Find(&orders).Error; err != nil {
return nil, utils.NewError("查询发货单列表失败")
}
orderItems := make([]systemRes.ShippingOrderItem, 0, len(orders))
for _, order := range orders {
var shopList []systemRes.OutboundShopInfo
var shops []struct {
ShopName string `gorm:"column:shop_name"`
ShopType int8 `gorm:"column:shop_type"`
}
databaseConn.Table("shipping_order_item").
Select("DISTINCT so.sales_person as shop_name, so.shop_type as shop_type").
Joins("INNER JOIN outbound_order_item ooi ON shipping_order_item.outbound_order_item_id = ooi.id AND ooi.is_del = 0").
Joins("INNER JOIN sales_order so ON ooi.sales_order_id = so.id AND so.is_del = 0").
Where("shipping_order_item.shipping_order_id = ? AND shipping_order_item.is_del = ?", order.ID, 0).
Scan(&shops)
for _, shop := range shops {
shopList = append(shopList, systemRes.OutboundShopInfo{
ShopName: shop.ShopName,
ShopType: shop.ShopType,
ShopTypeText: systemRes.GetShopTypeText(shop.ShopType),
})
}
var associationOrderNos string
databaseConn.Table("shipping_order_item").
Select("GROUP_CONCAT(DISTINCT so.association_order_no SEPARATOR ', ')").
Joins("INNER JOIN outbound_order_item ooi ON shipping_order_item.outbound_order_item_id = ooi.id AND ooi.is_del = 0").
Joins("INNER JOIN sales_order so ON ooi.sales_order_id = so.id AND so.is_del = 0").
Where("shipping_order_item.shipping_order_id = ? AND shipping_order_item.is_del = ? AND so.association_order_no != ''", order.ID, 0).
Scan(&associationOrderNos)
var logisticsNos string
databaseConn.Table("shipping_order_item").
Select("GROUP_CONCAT(DISTINCT soi.logistics_no SEPARATOR ', ')").
Joins("INNER JOIN outbound_order_item ooi ON shipping_order_item.outbound_order_item_id = ooi.id AND ooi.is_del = 0").
Joins("INNER JOIN sales_order_item soi ON ooi.sales_order_id = soi.sales_order_id AND ooi.product_id = soi.product_id AND soi.is_del = 0").
Where("shipping_order_item.shipping_order_id = ? AND shipping_order_item.is_del = ? AND soi.logistics_no != ''", order.ID, 0).
Scan(&logisticsNos)
orderItems = append(orderItems, systemRes.ConvertShippingOrderToItem(
order.ShippingOrder,
order.CustomerName,
shopList,
associationOrderNos,
logisticsNos,
))
}
return &systemRes.ShippingOrderListResponse{
List: orderItems,
Total: total,
Page: req.Page,
PageSize: req.PageSize,
}, nil
}
// GetShippingOrderDetail 获取发货单详情
func (s *ShippingService) GetShippingOrderDetail(id int64, creatorID int64, role int64, db ...*gorm.DB) (*systemRes.ShippingOrderDetailResponse, error) {
databaseConn := database.OptionalDB(db...)
query := databaseConn.Model(&models.ShippingOrder{}).
Select("shipping_order.*, c.name as customer_name").
Joins("LEFT JOIN customer c ON shipping_order.customer_id = c.id AND c.is_del = 0").
Where("shipping_order.id = ? AND shipping_order.is_del = ?", id, 0)
var order systemRes.ShippingOrderWithInfo
result := query.First(&order)
if result.Error != nil {
return nil, utils.NewError("发货单不存在")
}
var items []systemRes.ShippingOrderItemWithProduct
databaseConn.Model(&models.ShippingOrderItem{}).
Select(`shipping_order_item.*,
p.id as product_id,
p.name as product_name,
p.barcode as product_code,
p.category_id,
c.name as category_name,
l.id as location_id,
l.code as location_name,
w.name as warehouse_name,
w.code as warehouse_code,
w.contact_person as warehouse_contact_person,
w.contact_phone as warehouse_contact_phone,
w.province as warehouse_province,
w.city as warehouse_city,
w.district as warehouse_district,
w.address as warehouse_address,
so.so_no as sales_order_no,
oo.out_no as outbound_order_no,
ooi.unit_price,
so.created_at as sales_order_created_at,
so.sales_person_id,
so.association_order_id,
so.association_order_no,
soi.id as sales_order_item_id,
soi.created_at as so_item_created_at,
soi.receiver_name,
soi.receiver_phone,
soi.receiver_address,
soi.logistics_company,
soi.logistics_no`).
Joins("LEFT JOIN outbound_order_item ooi ON shipping_order_item.outbound_order_item_id = ooi.id AND ooi.is_del = 0").
Joins("LEFT JOIN product p ON ooi.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 ooi.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 ooi.sales_order_id = so.id AND so.is_del = 0").
Joins("LEFT JOIN sales_order_item soi ON ooi.sales_order_id = soi.sales_order_id AND ooi.product_id = soi.product_id AND soi.is_del = 0").
Joins("LEFT JOIN outbound_order oo ON ooi.out_order_id = oo.id AND oo.is_del = 0").
Where("shipping_order_item.shipping_order_id = ? AND shipping_order_item.is_del = ?", order.ID, 0).
Order("l.sort ASC, l.id ASC").
Find(&items)
detailItems := make([]systemRes.ShippingOrderDetailItem, 0, len(items))
for _, item := range items {
detailItems = append(detailItems, systemRes.ShippingOrderDetailItem{
ID: item.ID,
ShippingOrderID: item.ShippingOrderID,
OutboundOrderItemID: item.OutboundOrderItemID,
SalesOrderItemID: item.SalesOrderItemID,
SalesOrderNo: item.SalesOrderNo,
OutboundOrderNo: item.OutboundOrderNo,
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,
WarehouseContactPerson: item.WarehouseContactPerson,
WarehouseContactPhone: item.WarehouseContactPhone,
WarehouseProvince: item.WarehouseProvince,
WarehouseCity: item.WarehouseCity,
WarehouseDistrict: item.WarehouseDistrict,
WarehouseAddress: item.WarehouseAddress,
Quantity: item.Quantity,
UnitPrice: item.UnitPrice,
SalesOrderCreatedAt: item.SalesOrderCreatedAt,
SalesPersonID: item.SalesPersonID,
AssociationOrderID: item.AssociationOrderID,
AssociationOrderNo: item.AssociationOrderNo,
SoItemCreatedAt: item.SoItemCreatedAt,
ReceiverName: item.ReceiverName,
ReceiverPhone: item.ReceiverPhone,
ReceiverAddress: item.ReceiverAddress,
LogisticsCompany: item.LogisticsCompany,
LogisticsNo: item.LogisticsNo,
})
}
detail := systemRes.ConvertShippingOrderToDetail(order.ShippingOrder, order.CustomerName, detailItems)
return &detail, nil
}
// GetShippingOrderDetailList 获取发货单详情列表(按状态筛选,含全部明细字段)
func (s *ShippingService) GetShippingOrderDetailList(req systemReq.GetShippingOrderDetailListRequest, creatorID int64, role int64, db ...*gorm.DB) (*systemRes.ShippingOrderDetailListResponse, 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.ShippingOrder{}).Where("shipping_order.is_del = ?", 0)
if req.Status > 0 {
query = query.Where("shipping_order.status = ?", req.Status)
}
if req.CustomerID > 0 {
query = query.Where("shipping_order.customer_id = ?", req.CustomerID)
}
if req.ShippingNo != "" {
query = query.Where("shipping_order.shipping_no LIKE ?", "%"+req.ShippingNo+"%")
}
if req.StartDate > 0 {
query = query.Where("shipping_order.created_at >= ?", req.StartDate)
}
if req.EndDate > 0 {
query = query.Where("shipping_order.created_at <= ?", req.EndDate)
}
if req.AssociationOrderNo != "" {
subQuery := databaseConn.Table("shipping_order_item").
Select("shipping_order_item.shipping_order_id").
Joins("INNER JOIN outbound_order_item ON shipping_order_item.outbound_order_item_id = outbound_order_item.id AND outbound_order_item.is_del = 0").
Joins("INNER JOIN sales_order ON outbound_order_item.sales_order_id = sales_order.id AND sales_order.is_del = 0").
Where("shipping_order_item.is_del = 0 AND sales_order.association_order_no LIKE ?", "%"+req.AssociationOrderNo+"%")
query = query.Where("shipping_order.id IN (?)", subQuery)
}
if req.LogisticsNo != "" {
subQuery := databaseConn.Table("shipping_order_item").
Select("shipping_order_item.shipping_order_id").
Joins("INNER JOIN outbound_order_item ON shipping_order_item.outbound_order_item_id = outbound_order_item.id AND outbound_order_item.is_del = 0").
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("shipping_order_item.is_del = 0 AND sales_order_item.logistics_no LIKE ?", "%"+req.LogisticsNo+"%")
query = query.Where("shipping_order.id IN (?)", subQuery)
}
var total int64
if err := query.Count(&total).Error; err != nil {
return nil, utils.NewError("查询总数失败")
}
if total == 0 {
return &systemRes.ShippingOrderDetailListResponse{
List: []systemRes.ShippingOrderDetailListItem{},
Total: 0,
Page: req.Page,
PageSize: req.PageSize,
}, nil
}
var orders []systemRes.ShippingOrderWithInfo
offset := (req.Page - 1) * req.PageSize
if err := query.Select("shipping_order.*, c.name as customer_name").
Joins("LEFT JOIN customer c ON shipping_order.customer_id = c.id AND c.is_del = 0").
Order("shipping_order.created_at DESC").
Offset(offset).
Limit(req.PageSize).
Find(&orders).Error; err != nil {
return nil, utils.NewError("查询发货单列表失败")
}
// 收集所有订单ID
orderIDs := make([]int64, 0, len(orders))
for _, order := range orders {
orderIDs = append(orderIDs, order.ID)
}
// 批量按订单分组查询店铺信息
type shopRow struct {
ShippingOrderID int64
ShopName string `gorm:"column:shop_name"`
ShopType int8 `gorm:"column:shop_type"`
}
var shopRows []shopRow
databaseConn.Table("shipping_order_item").
Select("DISTINCT shipping_order_item.shipping_order_id, so.sales_person as shop_name, so.shop_type as shop_type").
Joins("INNER JOIN outbound_order_item ooi ON shipping_order_item.outbound_order_item_id = ooi.id AND ooi.is_del = 0").
Joins("INNER JOIN sales_order so ON ooi.sales_order_id = so.id AND so.is_del = 0").
Where("shipping_order_item.shipping_order_id IN ? AND shipping_order_item.is_del = ?", orderIDs, 0).
Scan(&shopRows)
shopsByOrderID := make(map[int64][]systemRes.OutboundShopInfo, len(orderIDs))
for _, row := range shopRows {
shopsByOrderID[row.ShippingOrderID] = append(shopsByOrderID[row.ShippingOrderID], systemRes.OutboundShopInfo{
ShopName: row.ShopName,
ShopType: row.ShopType,
ShopTypeText: systemRes.GetShopTypeText(row.ShopType),
})
}
// 批量查询所有订单的明细一次查询全部JOIN
var allItems []systemRes.ShippingOrderItemWithProduct
databaseConn.Model(&models.ShippingOrderItem{}).
Select(`shipping_order_item.*,
p.id as product_id,
p.name as product_name,
p.barcode as product_code,
p.category_id,
c.name as category_name,
l.id as location_id,
l.code as location_name,
w.name as warehouse_name,
w.code as warehouse_code,
w.contact_person as warehouse_contact_person,
w.contact_phone as warehouse_contact_phone,
w.province as warehouse_province,
w.city as warehouse_city,
w.district as warehouse_district,
w.address as warehouse_address,
so.so_no as sales_order_no,
oo.out_no as outbound_order_no,
ooi.unit_price,
so.created_at as sales_order_created_at,
so.sales_person_id,
so.association_order_id,
so.association_order_no,
soi.id as sales_order_item_id,
soi.created_at as so_item_created_at,
soi.receiver_name,
soi.receiver_phone,
soi.receiver_address,
soi.logistics_company,
soi.logistics_no`).
Joins("LEFT JOIN outbound_order_item ooi ON shipping_order_item.outbound_order_item_id = ooi.id AND ooi.is_del = 0").
Joins("LEFT JOIN product p ON ooi.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 ooi.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 ooi.sales_order_id = so.id AND so.is_del = 0").
Joins("LEFT JOIN sales_order_item soi ON ooi.sales_order_id = soi.sales_order_id AND ooi.product_id = soi.product_id AND soi.is_del = 0").
Joins("LEFT JOIN outbound_order oo ON ooi.out_order_id = oo.id AND oo.is_del = 0").
Where("shipping_order_item.shipping_order_id IN ? AND shipping_order_item.is_del = ?", orderIDs, 0).
Order("l.sort ASC, l.id ASC").
Find(&allItems)
// 按订单ID分组明细
itemsByOrderID := make(map[int64][]systemRes.ShippingOrderItemWithProduct, len(orderIDs))
for _, item := range allItems {
itemsByOrderID[item.ShippingOrderID] = append(itemsByOrderID[item.ShippingOrderID], item)
}
// 组装最终结果
detailListItems := make([]systemRes.ShippingOrderDetailListItem, 0, len(orders))
for _, order := range orders {
orderItems := itemsByOrderID[order.ID]
detailItems := make([]systemRes.ShippingOrderDetailItem, 0, len(orderItems))
for _, item := range orderItems {
detailItems = append(detailItems, systemRes.ShippingOrderDetailItem{
ID: item.ID,
ShippingOrderID: item.ShippingOrderID,
OutboundOrderItemID: item.OutboundOrderItemID,
SalesOrderItemID: item.SalesOrderItemID,
SalesOrderNo: item.SalesOrderNo,
OutboundOrderNo: item.OutboundOrderNo,
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,
WarehouseContactPerson: item.WarehouseContactPerson,
WarehouseContactPhone: item.WarehouseContactPhone,
WarehouseProvince: item.WarehouseProvince,
WarehouseCity: item.WarehouseCity,
WarehouseDistrict: item.WarehouseDistrict,
WarehouseAddress: item.WarehouseAddress,
Quantity: item.Quantity,
UnitPrice: item.UnitPrice,
SalesOrderCreatedAt: item.SalesOrderCreatedAt,
SalesPersonID: item.SalesPersonID,
AssociationOrderID: item.AssociationOrderID,
AssociationOrderNo: item.AssociationOrderNo,
SoItemCreatedAt: item.SoItemCreatedAt,
ReceiverName: item.ReceiverName,
ReceiverPhone: item.ReceiverPhone,
ReceiverAddress: item.ReceiverAddress,
LogisticsCompany: item.LogisticsCompany,
LogisticsNo: item.LogisticsNo,
})
}
shopList := shopsByOrderID[order.ID]
if shopList == nil {
shopList = []systemRes.OutboundShopInfo{}
}
detailListItems = append(detailListItems, systemRes.ConvertShippingOrderToDetailListItem(
order.ShippingOrder,
order.CustomerName,
shopList,
detailItems,
))
}
return &systemRes.ShippingOrderDetailListResponse{
List: detailListItems,
Total: total,
Page: req.Page,
PageSize: req.PageSize,
}, nil
}