实现换货资产快照与新旧独立搜索
This commit is contained in:
@@ -5,9 +5,9 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
customerBindingSvc "github.com/break/junhong_cmp_fiber/internal/service/customer_binding"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model/dto"
|
||||
customerBindingSvc "github.com/break/junhong_cmp_fiber/internal/service/customer_binding"
|
||||
"github.com/break/junhong_cmp_fiber/internal/store/postgres"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
@@ -112,47 +112,6 @@ func (s *Service) Create(ctx context.Context, req *dto.CreateExchangeRequest) (*
|
||||
return s.toExchangeOrderResponse(order), nil
|
||||
}
|
||||
|
||||
func (s *Service) List(ctx context.Context, req *dto.ExchangeListRequest) (*dto.ExchangeListResponse, error) {
|
||||
page := req.Page
|
||||
page = max(page, 1)
|
||||
pageSize := req.PageSize
|
||||
if pageSize < 1 {
|
||||
pageSize = constants.DefaultPageSize
|
||||
}
|
||||
if pageSize > constants.MaxPageSize {
|
||||
pageSize = constants.MaxPageSize
|
||||
}
|
||||
|
||||
filters := make(map[string]any)
|
||||
if req.Status != nil {
|
||||
filters["status"] = *req.Status
|
||||
}
|
||||
if req.FlowType != "" {
|
||||
filters["flow_type"] = normalizeExchangeFlowType(req.FlowType)
|
||||
}
|
||||
if req.Identifier != "" {
|
||||
filters["identifier"] = req.Identifier
|
||||
}
|
||||
if req.CreatedAtStart != nil {
|
||||
filters["created_at_start"] = *req.CreatedAtStart
|
||||
}
|
||||
if req.CreatedAtEnd != nil {
|
||||
filters["created_at_end"] = *req.CreatedAtEnd
|
||||
}
|
||||
|
||||
orders, total, err := s.exchangeStore.List(ctx, filters, page, pageSize)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询换货单列表失败")
|
||||
}
|
||||
|
||||
list := make([]*dto.ExchangeOrderResponse, 0, len(orders))
|
||||
for _, item := range orders {
|
||||
list = append(list, s.toExchangeOrderResponse(item))
|
||||
}
|
||||
|
||||
return &dto.ExchangeListResponse{List: list, Total: total, Page: page, PageSize: pageSize}, nil
|
||||
}
|
||||
|
||||
func (s *Service) Get(ctx context.Context, id uint) (*dto.ExchangeOrderResponse, error) {
|
||||
order, err := s.exchangeStore.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
@@ -433,7 +392,7 @@ func (s *Service) resolveAssetByIdentifier(ctx context.Context, expectedAssetTyp
|
||||
if expectedAssetType != "" && expectedAssetType != constants.ExchangeAssetTypeDevice {
|
||||
return nil, errors.New(errors.CodeExchangeAssetTypeMismatch)
|
||||
}
|
||||
return &resolvedExchangeAsset{AssetType: constants.ExchangeAssetTypeDevice, AssetID: device.ID, Identifier: identifier, VirtualNo: device.VirtualNo, AssetStatus: device.AssetStatus, ShopID: device.ShopID, Device: device}, nil
|
||||
return newResolvedDeviceAsset(device), nil
|
||||
}
|
||||
if err != gorm.ErrRecordNotFound {
|
||||
return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询设备失败")
|
||||
@@ -446,7 +405,7 @@ func (s *Service) resolveAssetByIdentifier(ctx context.Context, expectedAssetTyp
|
||||
if expectedAssetType != "" && expectedAssetType != constants.ExchangeAssetTypeIotCard {
|
||||
return nil, errors.New(errors.CodeExchangeAssetTypeMismatch)
|
||||
}
|
||||
return &resolvedExchangeAsset{AssetType: constants.ExchangeAssetTypeIotCard, AssetID: card.ID, Identifier: identifier, VirtualNo: card.VirtualNo, AssetStatus: card.AssetStatus, ShopID: card.ShopID, Card: card}, nil
|
||||
return newResolvedIotCardAsset(card), nil
|
||||
} else if err != gorm.ErrRecordNotFound {
|
||||
return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询IoT卡失败")
|
||||
}
|
||||
@@ -684,7 +643,7 @@ func (s *Service) resolveAssetByID(ctx context.Context, assetType string, assetI
|
||||
}
|
||||
return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询IoT卡失败")
|
||||
}
|
||||
return &resolvedExchangeAsset{AssetType: constants.ExchangeAssetTypeIotCard, AssetID: card.ID, Identifier: card.VirtualNo, VirtualNo: card.VirtualNo, AssetStatus: card.AssetStatus, ShopID: card.ShopID, Card: card}, nil
|
||||
return newResolvedIotCardAsset(card), nil
|
||||
}
|
||||
if assetType == constants.ExchangeAssetTypeDevice {
|
||||
device, err := s.deviceStore.GetByID(ctx, assetID)
|
||||
@@ -694,7 +653,7 @@ func (s *Service) resolveAssetByID(ctx context.Context, assetType string, assetI
|
||||
}
|
||||
return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询设备失败")
|
||||
}
|
||||
return &resolvedExchangeAsset{AssetType: constants.ExchangeAssetTypeDevice, AssetID: device.ID, Identifier: preferredDeviceIdentifier(device), VirtualNo: device.VirtualNo, AssetStatus: device.AssetStatus, ShopID: device.ShopID, Device: device}, nil
|
||||
return newResolvedDeviceAsset(device), nil
|
||||
}
|
||||
return nil, errors.New(errors.CodeInvalidParam, "资产类型不合法")
|
||||
}
|
||||
@@ -710,7 +669,7 @@ func (s *Service) resolveAssetByIDWithTx(ctx context.Context, tx *gorm.DB, asset
|
||||
}
|
||||
return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询IoT卡失败")
|
||||
}
|
||||
return &resolvedExchangeAsset{AssetType: constants.ExchangeAssetTypeIotCard, AssetID: card.ID, Identifier: card.VirtualNo, VirtualNo: card.VirtualNo, AssetStatus: card.AssetStatus, ShopID: card.ShopID, Card: &card}, nil
|
||||
return newResolvedIotCardAsset(&card), nil
|
||||
}
|
||||
if assetType == constants.ExchangeAssetTypeDevice {
|
||||
var device model.Device
|
||||
@@ -722,7 +681,7 @@ func (s *Service) resolveAssetByIDWithTx(ctx context.Context, tx *gorm.DB, asset
|
||||
}
|
||||
return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询设备失败")
|
||||
}
|
||||
return &resolvedExchangeAsset{AssetType: constants.ExchangeAssetTypeDevice, AssetID: device.ID, Identifier: preferredDeviceIdentifier(&device), VirtualNo: device.VirtualNo, AssetStatus: device.AssetStatus, ShopID: device.ShopID, Device: &device}, nil
|
||||
return newResolvedDeviceAsset(&device), nil
|
||||
}
|
||||
return nil, errors.New(errors.CodeInvalidParam, "资产类型不合法")
|
||||
}
|
||||
@@ -738,7 +697,7 @@ func (s *Service) resolveAssetByIdentifierWithTx(ctx context.Context, tx *gorm.D
|
||||
if expectedAssetType != "" && expectedAssetType != constants.ExchangeAssetTypeDevice {
|
||||
return nil, errors.New(errors.CodeExchangeAssetTypeMismatch)
|
||||
}
|
||||
return &resolvedExchangeAsset{AssetType: constants.ExchangeAssetTypeDevice, AssetID: device.ID, Identifier: identifier, VirtualNo: device.VirtualNo, AssetStatus: device.AssetStatus, ShopID: device.ShopID, Device: &device}, nil
|
||||
return newResolvedDeviceAsset(&device), nil
|
||||
} else if err != gorm.ErrRecordNotFound {
|
||||
return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询设备失败")
|
||||
}
|
||||
@@ -753,7 +712,7 @@ func (s *Service) resolveAssetByIdentifierWithTx(ctx context.Context, tx *gorm.D
|
||||
if expectedAssetType != "" && expectedAssetType != constants.ExchangeAssetTypeIotCard {
|
||||
return nil, errors.New(errors.CodeExchangeAssetTypeMismatch)
|
||||
}
|
||||
return &resolvedExchangeAsset{AssetType: constants.ExchangeAssetTypeIotCard, AssetID: card.ID, Identifier: identifier, VirtualNo: card.VirtualNo, AssetStatus: card.AssetStatus, ShopID: card.ShopID, Card: &card}, nil
|
||||
return newResolvedIotCardAsset(&card), nil
|
||||
} else if err != gorm.ErrRecordNotFound {
|
||||
return nil, errors.Wrap(errors.CodeDatabaseError, err, "查询IoT卡失败")
|
||||
}
|
||||
@@ -761,6 +720,16 @@ func (s *Service) resolveAssetByIdentifierWithTx(ctx context.Context, tx *gorm.D
|
||||
return nil, errors.New(errors.CodeAssetNotFound)
|
||||
}
|
||||
|
||||
// newResolvedIotCardAsset 将卡的权威 ICCID 固化为换货快照,避免请求标识污染历史记录。
|
||||
func newResolvedIotCardAsset(card *model.IotCard) *resolvedExchangeAsset {
|
||||
return &resolvedExchangeAsset{AssetType: constants.ExchangeAssetTypeIotCard, AssetID: card.ID, Identifier: card.ICCID, VirtualNo: card.VirtualNo, AssetStatus: card.AssetStatus, ShopID: card.ShopID, Card: card}
|
||||
}
|
||||
|
||||
// newResolvedDeviceAsset 按虚拟号、IMEI、SN 的稳定优先级生成设备换货快照。
|
||||
func newResolvedDeviceAsset(device *model.Device) *resolvedExchangeAsset {
|
||||
return &resolvedExchangeAsset{AssetType: constants.ExchangeAssetTypeDevice, AssetID: device.ID, Identifier: preferredDeviceIdentifier(device), VirtualNo: device.VirtualNo, AssetStatus: device.AssetStatus, ShopID: device.ShopID, Device: device}
|
||||
}
|
||||
|
||||
func (s *Service) ensureNoActiveExchangeWithTx(ctx context.Context, tx *gorm.DB, assetType string, assetID uint) error {
|
||||
var count int64
|
||||
query := tx.WithContext(ctx).Model(&model.ExchangeOrder{}).
|
||||
|
||||
Reference in New Issue
Block a user