- 数据库: 重命名 series_allocation_id → series_id - Model: IotCard 和 Device 字段重命名 - DTO: 所有请求/响应字段统一为 series_id - Store: 方法重命名,新增 GetByShopAndSeries 查询 - Service: 业务逻辑优化,系列验证和权限验证分离 - 测试: 更新所有测试用例,新增 shop_series_allocation_store_test.go - 文档: 更新 API 文档说明参数变更 BREAKING CHANGE: API 参数从 series_allocation_id 改为 series_id
1089 lines
36 KiB
Go
1089 lines
36 KiB
Go
package order
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/break/junhong_cmp_fiber/internal/model"
|
|
"github.com/break/junhong_cmp_fiber/internal/model/dto"
|
|
"github.com/break/junhong_cmp_fiber/internal/service/purchase_validation"
|
|
"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"
|
|
"github.com/break/junhong_cmp_fiber/pkg/middleware"
|
|
"github.com/break/junhong_cmp_fiber/tests/testutils"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
type testEnv struct {
|
|
ctx context.Context
|
|
svc *Service
|
|
card *model.IotCard
|
|
device *model.Device
|
|
pkg *model.Package
|
|
shop *model.Shop
|
|
wallet *model.Wallet
|
|
allocation *model.ShopSeriesAllocation
|
|
}
|
|
|
|
func setupOrderTestEnv(t *testing.T) *testEnv {
|
|
tx := testutils.NewTestTransaction(t)
|
|
rdb := testutils.GetTestRedis(t)
|
|
testutils.CleanTestRedisKeys(t, rdb)
|
|
|
|
iotCardStore := postgres.NewIotCardStore(tx, rdb)
|
|
deviceStore := postgres.NewDeviceStore(tx, rdb)
|
|
packageStore := postgres.NewPackageStore(tx)
|
|
seriesAllocationStore := postgres.NewShopSeriesAllocationStore(tx)
|
|
packageSeriesStore := postgres.NewPackageSeriesStore(tx)
|
|
carrierStore := postgres.NewCarrierStore(tx)
|
|
shopStore := postgres.NewShopStore(tx, rdb)
|
|
orderStore := postgres.NewOrderStore(tx, rdb)
|
|
orderItemStore := postgres.NewOrderItemStore(tx, rdb)
|
|
walletStore := postgres.NewWalletStore(tx, rdb)
|
|
|
|
ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{
|
|
UserID: 1,
|
|
UserType: constants.UserTypePlatform,
|
|
})
|
|
|
|
carrier := &model.Carrier{
|
|
CarrierCode: "TEST_CARRIER_ORDER",
|
|
CarrierName: "测试运营商",
|
|
CarrierType: constants.CarrierTypeCMCC,
|
|
Status: constants.StatusEnabled,
|
|
}
|
|
require.NoError(t, carrierStore.Create(ctx, carrier))
|
|
|
|
shop := &model.Shop{
|
|
ShopName: "测试店铺ORDER",
|
|
ShopCode: "TEST_SHOP_ORDER",
|
|
Level: 1,
|
|
Status: constants.StatusEnabled,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, shopStore.Create(ctx, shop))
|
|
|
|
series := &model.PackageSeries{
|
|
SeriesCode: "TEST_SERIES_ORDER",
|
|
SeriesName: "测试套餐系列",
|
|
Description: "测试用",
|
|
Status: constants.StatusEnabled,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, packageSeriesStore.Create(ctx, series))
|
|
|
|
allocation := &model.ShopSeriesAllocation{
|
|
ShopID: shop.ID,
|
|
SeriesID: series.ID,
|
|
Status: constants.StatusEnabled,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, seriesAllocationStore.Create(ctx, allocation))
|
|
|
|
pkg := &model.Package{
|
|
PackageCode: "TEST_PKG_ORDER",
|
|
PackageName: "测试套餐",
|
|
SeriesID: series.ID,
|
|
PackageType: "formal",
|
|
DurationMonths: 1,
|
|
DataAmountMB: 1024,
|
|
SuggestedRetailPrice: 9900,
|
|
Status: constants.StatusEnabled,
|
|
ShelfStatus: constants.ShelfStatusOn,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, packageStore.Create(ctx, pkg))
|
|
|
|
shopIDPtr := &shop.ID
|
|
card := &model.IotCard{
|
|
ICCID: "89860000000000000002",
|
|
ShopID: shopIDPtr,
|
|
CarrierID: carrier.ID,
|
|
SeriesID: &allocation.SeriesID,
|
|
Status: constants.StatusEnabled,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, iotCardStore.Create(ctx, card))
|
|
|
|
device := &model.Device{
|
|
DeviceNo: "DEV_TEST_ORDER_001",
|
|
ShopID: shopIDPtr,
|
|
SeriesID: &allocation.SeriesID,
|
|
Status: constants.StatusEnabled,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, deviceStore.Create(ctx, device))
|
|
|
|
wallet := &model.Wallet{
|
|
ResourceType: "shop",
|
|
ResourceID: shop.ID,
|
|
WalletType: "main",
|
|
Balance: 100000,
|
|
Version: 1,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, tx.Create(wallet).Error)
|
|
|
|
purchaseValidationSvc := purchase_validation.New(tx, iotCardStore, deviceStore, packageStore, seriesAllocationStore)
|
|
logger := zap.NewNop()
|
|
orderSvc := New(tx, orderStore, orderItemStore, walletStore, purchaseValidationSvc, nil, seriesAllocationStore, iotCardStore, deviceStore, nil, nil, logger)
|
|
|
|
userCtx := middleware.SetUserContext(ctx, &middleware.UserContextInfo{
|
|
UserID: 1,
|
|
UserType: constants.UserTypeAgent,
|
|
ShopID: shop.ID,
|
|
})
|
|
|
|
return &testEnv{
|
|
ctx: userCtx,
|
|
svc: orderSvc,
|
|
card: card,
|
|
device: device,
|
|
pkg: pkg,
|
|
shop: shop,
|
|
wallet: wallet,
|
|
allocation: allocation,
|
|
}
|
|
}
|
|
|
|
func TestOrderService_Create(t *testing.T) {
|
|
env := setupOrderTestEnv(t)
|
|
|
|
t.Run("创建单卡订单成功", func(t *testing.T) {
|
|
req := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
IotCardID: &env.card.ID,
|
|
PackageIDs: []uint{env.pkg.ID},
|
|
PaymentMethod: model.PaymentMethodWallet,
|
|
}
|
|
|
|
resp, err := env.svc.Create(env.ctx, req, model.BuyerTypeAgent, env.shop.ID)
|
|
require.NoError(t, err)
|
|
assert.NotZero(t, resp.ID)
|
|
assert.Contains(t, resp.OrderNo, "ORD")
|
|
assert.Equal(t, model.OrderTypeSingleCard, resp.OrderType)
|
|
assert.Equal(t, model.BuyerTypeAgent, resp.BuyerType)
|
|
assert.Equal(t, env.shop.ID, resp.BuyerID)
|
|
assert.Equal(t, env.pkg.SuggestedRetailPrice, resp.TotalAmount)
|
|
assert.Equal(t, model.PaymentStatusPending, resp.PaymentStatus)
|
|
assert.Len(t, resp.Items, 1)
|
|
})
|
|
|
|
t.Run("创建设备订单成功", func(t *testing.T) {
|
|
req := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeDevice,
|
|
DeviceID: &env.device.ID,
|
|
PackageIDs: []uint{env.pkg.ID},
|
|
PaymentMethod: model.PaymentMethodWallet,
|
|
}
|
|
|
|
resp, err := env.svc.Create(env.ctx, req, model.BuyerTypeAgent, env.shop.ID)
|
|
require.NoError(t, err)
|
|
assert.NotZero(t, resp.ID)
|
|
assert.Equal(t, model.OrderTypeDevice, resp.OrderType)
|
|
})
|
|
|
|
t.Run("单卡订单缺少卡ID", func(t *testing.T) {
|
|
req := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
PackageIDs: []uint{env.pkg.ID},
|
|
PaymentMethod: model.PaymentMethodWallet,
|
|
}
|
|
|
|
_, err := env.svc.Create(env.ctx, req, model.BuyerTypeAgent, env.shop.ID)
|
|
require.Error(t, err)
|
|
appErr, ok := err.(*errors.AppError)
|
|
require.True(t, ok)
|
|
assert.Equal(t, errors.CodeInvalidParam, appErr.Code)
|
|
})
|
|
|
|
t.Run("设备订单缺少设备ID", func(t *testing.T) {
|
|
req := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeDevice,
|
|
PackageIDs: []uint{env.pkg.ID},
|
|
PaymentMethod: model.PaymentMethodWallet,
|
|
}
|
|
|
|
_, err := env.svc.Create(env.ctx, req, model.BuyerTypeAgent, env.shop.ID)
|
|
require.Error(t, err)
|
|
appErr, ok := err.(*errors.AppError)
|
|
require.True(t, ok)
|
|
assert.Equal(t, errors.CodeInvalidParam, appErr.Code)
|
|
})
|
|
|
|
t.Run("钱包支付创建订单", func(t *testing.T) {
|
|
req := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
IotCardID: &env.card.ID,
|
|
PackageIDs: []uint{env.pkg.ID},
|
|
PaymentMethod: model.PaymentMethodWallet,
|
|
}
|
|
|
|
resp, err := env.svc.Create(env.ctx, req, model.BuyerTypeAgent, env.shop.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, model.PaymentStatusPending, resp.PaymentStatus)
|
|
assert.False(t, resp.IsPurchaseOnBehalf)
|
|
})
|
|
|
|
t.Run("线下支付创建订单", func(t *testing.T) {
|
|
req := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
IotCardID: &env.card.ID,
|
|
PackageIDs: []uint{env.pkg.ID},
|
|
PaymentMethod: model.PaymentMethodOffline,
|
|
}
|
|
|
|
platformCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{
|
|
UserID: 1,
|
|
UserType: constants.UserTypePlatform,
|
|
})
|
|
|
|
resp, err := env.svc.Create(platformCtx, req, "", 0)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, model.PaymentStatusPaid, resp.PaymentStatus)
|
|
assert.True(t, resp.IsPurchaseOnBehalf)
|
|
assert.NotNil(t, resp.PaidAt)
|
|
})
|
|
}
|
|
|
|
func TestOrderService_Get(t *testing.T) {
|
|
env := setupOrderTestEnv(t)
|
|
|
|
req := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
IotCardID: &env.card.ID,
|
|
PackageIDs: []uint{env.pkg.ID},
|
|
PaymentMethod: model.PaymentMethodWallet,
|
|
}
|
|
created, err := env.svc.Create(env.ctx, req, model.BuyerTypeAgent, env.shop.ID)
|
|
require.NoError(t, err)
|
|
|
|
t.Run("获取订单成功", func(t *testing.T) {
|
|
resp, err := env.svc.Get(env.ctx, created.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, created.OrderNo, resp.OrderNo)
|
|
assert.Len(t, resp.Items, 1)
|
|
})
|
|
|
|
t.Run("订单不存在", func(t *testing.T) {
|
|
_, err := env.svc.Get(env.ctx, 99999)
|
|
require.Error(t, err)
|
|
appErr, ok := err.(*errors.AppError)
|
|
require.True(t, ok)
|
|
assert.Equal(t, errors.CodeNotFound, appErr.Code)
|
|
})
|
|
}
|
|
|
|
func TestOrderService_List(t *testing.T) {
|
|
env := setupOrderTestEnv(t)
|
|
|
|
for i := 0; i < 3; i++ {
|
|
req := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
IotCardID: &env.card.ID,
|
|
PackageIDs: []uint{env.pkg.ID},
|
|
PaymentMethod: model.PaymentMethodWallet,
|
|
}
|
|
_, err := env.svc.Create(env.ctx, req, model.BuyerTypeAgent, env.shop.ID)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
t.Run("列表查询", func(t *testing.T) {
|
|
listReq := &dto.OrderListRequest{
|
|
Page: 1,
|
|
PageSize: 10,
|
|
}
|
|
resp, err := env.svc.List(env.ctx, listReq, model.BuyerTypeAgent, env.shop.ID)
|
|
require.NoError(t, err)
|
|
assert.GreaterOrEqual(t, resp.Total, int64(3))
|
|
assert.GreaterOrEqual(t, len(resp.List), 3)
|
|
})
|
|
|
|
t.Run("按支付状态过滤", func(t *testing.T) {
|
|
status := model.PaymentStatusPending
|
|
listReq := &dto.OrderListRequest{
|
|
Page: 1,
|
|
PageSize: 10,
|
|
PaymentStatus: &status,
|
|
}
|
|
resp, err := env.svc.List(env.ctx, listReq, model.BuyerTypeAgent, env.shop.ID)
|
|
require.NoError(t, err)
|
|
for _, o := range resp.List {
|
|
assert.Equal(t, model.PaymentStatusPending, o.PaymentStatus)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestOrderService_Cancel(t *testing.T) {
|
|
env := setupOrderTestEnv(t)
|
|
|
|
req := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
IotCardID: &env.card.ID,
|
|
PackageIDs: []uint{env.pkg.ID},
|
|
PaymentMethod: model.PaymentMethodWallet,
|
|
}
|
|
created, err := env.svc.Create(env.ctx, req, model.BuyerTypeAgent, env.shop.ID)
|
|
require.NoError(t, err)
|
|
|
|
t.Run("取消订单成功", func(t *testing.T) {
|
|
err := env.svc.Cancel(env.ctx, created.ID, model.BuyerTypeAgent, env.shop.ID)
|
|
require.NoError(t, err)
|
|
|
|
order, err := env.svc.Get(env.ctx, created.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, model.PaymentStatusCancelled, order.PaymentStatus)
|
|
})
|
|
|
|
t.Run("订单不存在", func(t *testing.T) {
|
|
err := env.svc.Cancel(env.ctx, 99999, model.BuyerTypeAgent, env.shop.ID)
|
|
require.Error(t, err)
|
|
appErr, ok := err.(*errors.AppError)
|
|
require.True(t, ok)
|
|
assert.Equal(t, errors.CodeNotFound, appErr.Code)
|
|
})
|
|
|
|
t.Run("无权操作", func(t *testing.T) {
|
|
newReq := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
IotCardID: &env.card.ID,
|
|
PackageIDs: []uint{env.pkg.ID},
|
|
PaymentMethod: model.PaymentMethodWallet,
|
|
}
|
|
newOrder, err := env.svc.Create(env.ctx, newReq, model.BuyerTypeAgent, env.shop.ID)
|
|
require.NoError(t, err)
|
|
|
|
err = env.svc.Cancel(env.ctx, newOrder.ID, model.BuyerTypeAgent, 99999)
|
|
require.Error(t, err)
|
|
appErr, ok := err.(*errors.AppError)
|
|
require.True(t, ok)
|
|
assert.Equal(t, errors.CodeForbidden, appErr.Code)
|
|
})
|
|
}
|
|
|
|
func TestOrderService_WalletPay(t *testing.T) {
|
|
env := setupOrderTestEnv(t)
|
|
|
|
t.Run("钱包支付成功", func(t *testing.T) {
|
|
req := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
IotCardID: &env.card.ID,
|
|
PackageIDs: []uint{env.pkg.ID},
|
|
PaymentMethod: model.PaymentMethodWallet,
|
|
}
|
|
created, err := env.svc.Create(env.ctx, req, model.BuyerTypeAgent, env.shop.ID)
|
|
require.NoError(t, err)
|
|
|
|
err = env.svc.WalletPay(env.ctx, created.ID, model.BuyerTypeAgent, env.shop.ID)
|
|
require.NoError(t, err)
|
|
|
|
order, err := env.svc.Get(env.ctx, created.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, model.PaymentStatusPaid, order.PaymentStatus)
|
|
assert.Equal(t, model.PaymentMethodWallet, order.PaymentMethod)
|
|
assert.NotNil(t, order.PaidAt)
|
|
})
|
|
|
|
t.Run("订单不存在", func(t *testing.T) {
|
|
err := env.svc.WalletPay(env.ctx, 99999, model.BuyerTypeAgent, env.shop.ID)
|
|
require.Error(t, err)
|
|
appErr, ok := err.(*errors.AppError)
|
|
require.True(t, ok)
|
|
assert.Equal(t, errors.CodeNotFound, appErr.Code)
|
|
})
|
|
|
|
t.Run("无权操作", func(t *testing.T) {
|
|
req := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
IotCardID: &env.card.ID,
|
|
PackageIDs: []uint{env.pkg.ID},
|
|
PaymentMethod: model.PaymentMethodWallet,
|
|
}
|
|
created, err := env.svc.Create(env.ctx, req, model.BuyerTypeAgent, env.shop.ID)
|
|
require.NoError(t, err)
|
|
|
|
err = env.svc.WalletPay(env.ctx, created.ID, model.BuyerTypeAgent, 99999)
|
|
require.Error(t, err)
|
|
appErr, ok := err.(*errors.AppError)
|
|
require.True(t, ok)
|
|
assert.Equal(t, errors.CodeForbidden, appErr.Code)
|
|
})
|
|
|
|
t.Run("重复支付-幂等成功", func(t *testing.T) {
|
|
req := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
IotCardID: &env.card.ID,
|
|
PackageIDs: []uint{env.pkg.ID},
|
|
PaymentMethod: model.PaymentMethodWallet,
|
|
}
|
|
created, err := env.svc.Create(env.ctx, req, model.BuyerTypeAgent, env.shop.ID)
|
|
require.NoError(t, err)
|
|
|
|
err = env.svc.WalletPay(env.ctx, created.ID, model.BuyerTypeAgent, env.shop.ID)
|
|
require.NoError(t, err)
|
|
|
|
err = env.svc.WalletPay(env.ctx, created.ID, model.BuyerTypeAgent, env.shop.ID)
|
|
require.NoError(t, err)
|
|
})
|
|
|
|
t.Run("已取消订单无法支付", func(t *testing.T) {
|
|
req := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
IotCardID: &env.card.ID,
|
|
PackageIDs: []uint{env.pkg.ID},
|
|
PaymentMethod: model.PaymentMethodWallet,
|
|
}
|
|
created, err := env.svc.Create(env.ctx, req, model.BuyerTypeAgent, env.shop.ID)
|
|
require.NoError(t, err)
|
|
|
|
err = env.svc.Cancel(env.ctx, created.ID, model.BuyerTypeAgent, env.shop.ID)
|
|
require.NoError(t, err)
|
|
|
|
err = env.svc.WalletPay(env.ctx, created.ID, model.BuyerTypeAgent, env.shop.ID)
|
|
require.Error(t, err)
|
|
appErr, ok := err.(*errors.AppError)
|
|
require.True(t, ok)
|
|
assert.Equal(t, errors.CodeInvalidStatus, appErr.Code)
|
|
})
|
|
}
|
|
|
|
func TestOrderService_HandlePaymentCallback(t *testing.T) {
|
|
env := setupOrderTestEnv(t)
|
|
|
|
t.Run("支付回调成功", func(t *testing.T) {
|
|
req := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
IotCardID: &env.card.ID,
|
|
PackageIDs: []uint{env.pkg.ID},
|
|
PaymentMethod: model.PaymentMethodWallet,
|
|
}
|
|
created, err := env.svc.Create(env.ctx, req, model.BuyerTypeAgent, env.shop.ID)
|
|
require.NoError(t, err)
|
|
|
|
err = env.svc.HandlePaymentCallback(env.ctx, created.OrderNo, model.PaymentMethodWechat)
|
|
require.NoError(t, err)
|
|
|
|
order, err := env.svc.Get(env.ctx, created.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, model.PaymentStatusPaid, order.PaymentStatus)
|
|
assert.Equal(t, model.PaymentMethodWechat, order.PaymentMethod)
|
|
})
|
|
|
|
t.Run("幂等处理-已支付订单", func(t *testing.T) {
|
|
req := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
IotCardID: &env.card.ID,
|
|
PackageIDs: []uint{env.pkg.ID},
|
|
PaymentMethod: model.PaymentMethodWallet,
|
|
}
|
|
created, err := env.svc.Create(env.ctx, req, model.BuyerTypeAgent, env.shop.ID)
|
|
require.NoError(t, err)
|
|
|
|
err = env.svc.HandlePaymentCallback(env.ctx, created.OrderNo, model.PaymentMethodAlipay)
|
|
require.NoError(t, err)
|
|
|
|
err = env.svc.HandlePaymentCallback(env.ctx, created.OrderNo, model.PaymentMethodAlipay)
|
|
require.NoError(t, err)
|
|
})
|
|
|
|
t.Run("订单不存在", func(t *testing.T) {
|
|
err := env.svc.HandlePaymentCallback(env.ctx, "NOT_EXISTS_ORDER_NO", model.PaymentMethodWechat)
|
|
require.Error(t, err)
|
|
appErr, ok := err.(*errors.AppError)
|
|
require.True(t, ok)
|
|
assert.Equal(t, errors.CodeNotFound, appErr.Code)
|
|
})
|
|
}
|
|
|
|
func TestOrderService_IdempotencyAndConcurrency(t *testing.T) {
|
|
tx := testutils.NewTestTransaction(t)
|
|
rdb := testutils.GetTestRedis(t)
|
|
testutils.CleanTestRedisKeys(t, rdb)
|
|
|
|
iotCardStore := postgres.NewIotCardStore(tx, rdb)
|
|
deviceStore := postgres.NewDeviceStore(tx, rdb)
|
|
packageStore := postgres.NewPackageStore(tx)
|
|
seriesAllocationStore := postgres.NewShopSeriesAllocationStore(tx)
|
|
packageSeriesStore := postgres.NewPackageSeriesStore(tx)
|
|
carrierStore := postgres.NewCarrierStore(tx)
|
|
shopStore := postgres.NewShopStore(tx, rdb)
|
|
orderStore := postgres.NewOrderStore(tx, rdb)
|
|
orderItemStore := postgres.NewOrderItemStore(tx, rdb)
|
|
walletStore := postgres.NewWalletStore(tx, rdb)
|
|
|
|
ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{
|
|
UserID: 1,
|
|
UserType: constants.UserTypePlatform,
|
|
})
|
|
|
|
carrier := &model.Carrier{
|
|
CarrierCode: "TEST_CARRIER_IDEM",
|
|
CarrierName: "测试运营商幂等",
|
|
CarrierType: constants.CarrierTypeCMCC,
|
|
Status: constants.StatusEnabled,
|
|
}
|
|
require.NoError(t, carrierStore.Create(ctx, carrier))
|
|
|
|
shop := &model.Shop{
|
|
ShopName: "测试店铺IDEM",
|
|
ShopCode: "TEST_SHOP_IDEM",
|
|
Level: 1,
|
|
Status: constants.StatusEnabled,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, shopStore.Create(ctx, shop))
|
|
|
|
series := &model.PackageSeries{
|
|
SeriesCode: "TEST_SERIES_IDEM",
|
|
SeriesName: "测试套餐系列幂等",
|
|
Description: "测试用",
|
|
Status: constants.StatusEnabled,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, packageSeriesStore.Create(ctx, series))
|
|
|
|
allocation := &model.ShopSeriesAllocation{
|
|
ShopID: shop.ID,
|
|
SeriesID: series.ID,
|
|
Status: constants.StatusEnabled,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, seriesAllocationStore.Create(ctx, allocation))
|
|
|
|
pkg := &model.Package{
|
|
PackageCode: "TEST_PKG_IDEM",
|
|
PackageName: "测试套餐幂等",
|
|
SeriesID: series.ID,
|
|
PackageType: "formal",
|
|
DurationMonths: 1,
|
|
DataAmountMB: 1024,
|
|
SuggestedRetailPrice: 9900,
|
|
Status: constants.StatusEnabled,
|
|
ShelfStatus: constants.ShelfStatusOn,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, packageStore.Create(ctx, pkg))
|
|
|
|
shopIDPtr := &shop.ID
|
|
card := &model.IotCard{
|
|
ICCID: "89860000000000000099",
|
|
ShopID: shopIDPtr,
|
|
CarrierID: carrier.ID,
|
|
SeriesID: &allocation.SeriesID,
|
|
Status: constants.StatusEnabled,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, iotCardStore.Create(ctx, card))
|
|
|
|
wallet := &model.Wallet{
|
|
ResourceType: "shop",
|
|
ResourceID: shop.ID,
|
|
WalletType: "main",
|
|
Balance: 1000000,
|
|
Version: 1,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, tx.Create(wallet).Error)
|
|
|
|
purchaseValidationSvc := purchase_validation.New(tx, iotCardStore, deviceStore, packageStore, seriesAllocationStore)
|
|
logger := zap.NewNop()
|
|
orderSvc := New(tx, orderStore, orderItemStore, walletStore, purchaseValidationSvc, nil, seriesAllocationStore, iotCardStore, deviceStore, nil, nil, logger)
|
|
|
|
userCtx := middleware.SetUserContext(ctx, &middleware.UserContextInfo{
|
|
UserID: 1,
|
|
UserType: constants.UserTypeAgent,
|
|
ShopID: shop.ID,
|
|
})
|
|
|
|
t.Run("串行幂等支付测试", func(t *testing.T) {
|
|
req := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
IotCardID: &card.ID,
|
|
PackageIDs: []uint{pkg.ID},
|
|
PaymentMethod: model.PaymentMethodWallet,
|
|
}
|
|
created, err := orderSvc.Create(userCtx, req, model.BuyerTypeAgent, shop.ID)
|
|
require.NoError(t, err)
|
|
|
|
err = orderSvc.WalletPay(userCtx, created.ID, model.BuyerTypeAgent, shop.ID)
|
|
require.NoError(t, err)
|
|
|
|
err = orderSvc.WalletPay(userCtx, created.ID, model.BuyerTypeAgent, shop.ID)
|
|
require.NoError(t, err)
|
|
|
|
err = orderSvc.WalletPay(userCtx, created.ID, model.BuyerTypeAgent, shop.ID)
|
|
require.NoError(t, err)
|
|
|
|
var usageCount int64
|
|
err = tx.Model(&model.PackageUsage{}).Where("order_id = ?", created.ID).Count(&usageCount).Error
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(1), usageCount)
|
|
|
|
order, err := orderSvc.Get(userCtx, created.ID)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, model.PaymentStatusPaid, order.PaymentStatus)
|
|
})
|
|
|
|
t.Run("串行回调幂等测试", func(t *testing.T) {
|
|
req := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
IotCardID: &card.ID,
|
|
PackageIDs: []uint{pkg.ID},
|
|
PaymentMethod: model.PaymentMethodWallet,
|
|
}
|
|
created, err := orderSvc.Create(userCtx, req, model.BuyerTypeAgent, shop.ID)
|
|
require.NoError(t, err)
|
|
|
|
err = orderSvc.HandlePaymentCallback(userCtx, created.OrderNo, model.PaymentMethodWechat)
|
|
require.NoError(t, err)
|
|
|
|
err = orderSvc.HandlePaymentCallback(userCtx, created.OrderNo, model.PaymentMethodWechat)
|
|
require.NoError(t, err)
|
|
|
|
err = orderSvc.HandlePaymentCallback(userCtx, created.OrderNo, model.PaymentMethodWechat)
|
|
require.NoError(t, err)
|
|
|
|
var usageCount int64
|
|
err = tx.Model(&model.PackageUsage{}).Where("order_id = ?", created.ID).Count(&usageCount).Error
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(1), usageCount)
|
|
})
|
|
|
|
t.Run("已取消订单回调测试", func(t *testing.T) {
|
|
req := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
IotCardID: &card.ID,
|
|
PackageIDs: []uint{pkg.ID},
|
|
PaymentMethod: model.PaymentMethodWallet,
|
|
}
|
|
created, err := orderSvc.Create(userCtx, req, model.BuyerTypeAgent, shop.ID)
|
|
require.NoError(t, err)
|
|
|
|
err = orderSvc.Cancel(userCtx, created.ID, model.BuyerTypeAgent, shop.ID)
|
|
require.NoError(t, err)
|
|
|
|
err = orderSvc.HandlePaymentCallback(userCtx, created.OrderNo, model.PaymentMethodWechat)
|
|
require.Error(t, err)
|
|
appErr, ok := err.(*errors.AppError)
|
|
require.True(t, ok)
|
|
assert.Equal(t, errors.CodeInvalidStatus, appErr.Code)
|
|
|
|
var usageCount int64
|
|
err = tx.Model(&model.PackageUsage{}).Where("order_id = ?", created.ID).Count(&usageCount).Error
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(0), usageCount)
|
|
})
|
|
}
|
|
|
|
func TestOrderService_ForceRechargeValidation(t *testing.T) {
|
|
tx := testutils.NewTestTransaction(t)
|
|
rdb := testutils.GetTestRedis(t)
|
|
testutils.CleanTestRedisKeys(t, rdb)
|
|
|
|
iotCardStore := postgres.NewIotCardStore(tx, rdb)
|
|
deviceStore := postgres.NewDeviceStore(tx, rdb)
|
|
packageStore := postgres.NewPackageStore(tx)
|
|
seriesAllocationStore := postgres.NewShopSeriesAllocationStore(tx)
|
|
packageSeriesStore := postgres.NewPackageSeriesStore(tx)
|
|
carrierStore := postgres.NewCarrierStore(tx)
|
|
shopStore := postgres.NewShopStore(tx, rdb)
|
|
orderStore := postgres.NewOrderStore(tx, rdb)
|
|
orderItemStore := postgres.NewOrderItemStore(tx, rdb)
|
|
walletStore := postgres.NewWalletStore(tx, rdb)
|
|
|
|
ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{
|
|
UserID: 1,
|
|
UserType: constants.UserTypePlatform,
|
|
})
|
|
|
|
carrier := &model.Carrier{
|
|
CarrierCode: "TEST_CARRIER_FR",
|
|
CarrierName: "测试运营商强充",
|
|
CarrierType: constants.CarrierTypeCMCC,
|
|
Status: constants.StatusEnabled,
|
|
}
|
|
require.NoError(t, carrierStore.Create(ctx, carrier))
|
|
|
|
shop := &model.Shop{
|
|
ShopName: "测试店铺FR",
|
|
ShopCode: "TEST_SHOP_FR",
|
|
Level: 1,
|
|
Status: constants.StatusEnabled,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, shopStore.Create(ctx, shop))
|
|
|
|
series := &model.PackageSeries{
|
|
SeriesCode: "TEST_SERIES_FR",
|
|
SeriesName: "测试套餐系列强充",
|
|
Description: "测试用",
|
|
Status: constants.StatusEnabled,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, packageSeriesStore.Create(ctx, series))
|
|
|
|
allocation := &model.ShopSeriesAllocation{
|
|
ShopID: shop.ID,
|
|
SeriesID: series.ID,
|
|
Status: constants.StatusEnabled,
|
|
EnableOneTimeCommission: true,
|
|
OneTimeCommissionTrigger: model.OneTimeCommissionTriggerSingleRecharge,
|
|
OneTimeCommissionThreshold: 20000,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, seriesAllocationStore.Create(ctx, allocation))
|
|
|
|
cheapPkg := &model.Package{
|
|
PackageCode: "TEST_PKG_CHEAP",
|
|
PackageName: "便宜套餐",
|
|
SeriesID: series.ID,
|
|
PackageType: "formal",
|
|
DurationMonths: 1,
|
|
DataAmountMB: 512,
|
|
SuggestedRetailPrice: 5000,
|
|
Status: constants.StatusEnabled,
|
|
ShelfStatus: constants.ShelfStatusOn,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, packageStore.Create(ctx, cheapPkg))
|
|
|
|
expensivePkg := &model.Package{
|
|
PackageCode: "TEST_PKG_EXP",
|
|
PackageName: "高价套餐",
|
|
SeriesID: series.ID,
|
|
PackageType: "formal",
|
|
DurationMonths: 12,
|
|
DataAmountMB: 10240,
|
|
SuggestedRetailPrice: 25000,
|
|
Status: constants.StatusEnabled,
|
|
ShelfStatus: constants.ShelfStatusOn,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, packageStore.Create(ctx, expensivePkg))
|
|
|
|
shopIDPtr := &shop.ID
|
|
card := &model.IotCard{
|
|
ICCID: "89860000000000000FR1",
|
|
ShopID: shopIDPtr,
|
|
CarrierID: carrier.ID,
|
|
SeriesID: &allocation.SeriesID,
|
|
Status: constants.StatusEnabled,
|
|
FirstCommissionPaid: false,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, iotCardStore.Create(ctx, card))
|
|
|
|
purchaseValidationSvc := purchase_validation.New(tx, iotCardStore, deviceStore, packageStore, seriesAllocationStore)
|
|
logger := zap.NewNop()
|
|
orderSvc := New(tx, orderStore, orderItemStore, walletStore, purchaseValidationSvc, nil, seriesAllocationStore, iotCardStore, deviceStore, nil, nil, logger)
|
|
|
|
userCtx := middleware.SetUserContext(ctx, &middleware.UserContextInfo{
|
|
UserID: 1,
|
|
UserType: constants.UserTypeAgent,
|
|
ShopID: shop.ID,
|
|
})
|
|
|
|
t.Run("强充验证-金额不足拒绝", func(t *testing.T) {
|
|
req := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
IotCardID: &card.ID,
|
|
PackageIDs: []uint{cheapPkg.ID},
|
|
PaymentMethod: model.PaymentMethodWallet,
|
|
}
|
|
|
|
_, err := orderSvc.Create(userCtx, req, model.BuyerTypeAgent, shop.ID)
|
|
require.Error(t, err)
|
|
appErr, ok := err.(*errors.AppError)
|
|
require.True(t, ok)
|
|
assert.Equal(t, errors.CodeForceRechargeRequired, appErr.Code)
|
|
})
|
|
|
|
t.Run("强充验证-金额足够通过", func(t *testing.T) {
|
|
req := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
IotCardID: &card.ID,
|
|
PackageIDs: []uint{expensivePkg.ID},
|
|
PaymentMethod: model.PaymentMethodWallet,
|
|
}
|
|
|
|
resp, err := orderSvc.Create(userCtx, req, model.BuyerTypeAgent, shop.ID)
|
|
require.NoError(t, err)
|
|
assert.NotZero(t, resp.ID)
|
|
assert.Equal(t, expensivePkg.SuggestedRetailPrice, resp.TotalAmount)
|
|
})
|
|
|
|
t.Run("已付佣金-跳过强充验证", func(t *testing.T) {
|
|
card2 := &model.IotCard{
|
|
ICCID: "89860000000000000FR2",
|
|
ShopID: shopIDPtr,
|
|
CarrierID: carrier.ID,
|
|
SeriesID: &allocation.SeriesID,
|
|
Status: constants.StatusEnabled,
|
|
FirstCommissionPaid: true,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, iotCardStore.Create(ctx, card2))
|
|
|
|
req := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
IotCardID: &card2.ID,
|
|
PackageIDs: []uint{cheapPkg.ID},
|
|
PaymentMethod: model.PaymentMethodWallet,
|
|
}
|
|
|
|
resp, err := orderSvc.Create(userCtx, req, model.BuyerTypeAgent, shop.ID)
|
|
require.NoError(t, err)
|
|
assert.NotZero(t, resp.ID)
|
|
})
|
|
}
|
|
|
|
func TestOrderService_GetPurchaseCheck(t *testing.T) {
|
|
tx := testutils.NewTestTransaction(t)
|
|
rdb := testutils.GetTestRedis(t)
|
|
testutils.CleanTestRedisKeys(t, rdb)
|
|
|
|
iotCardStore := postgres.NewIotCardStore(tx, rdb)
|
|
deviceStore := postgres.NewDeviceStore(tx, rdb)
|
|
packageStore := postgres.NewPackageStore(tx)
|
|
seriesAllocationStore := postgres.NewShopSeriesAllocationStore(tx)
|
|
packageSeriesStore := postgres.NewPackageSeriesStore(tx)
|
|
carrierStore := postgres.NewCarrierStore(tx)
|
|
shopStore := postgres.NewShopStore(tx, rdb)
|
|
orderStore := postgres.NewOrderStore(tx, rdb)
|
|
orderItemStore := postgres.NewOrderItemStore(tx, rdb)
|
|
walletStore := postgres.NewWalletStore(tx, rdb)
|
|
|
|
ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{
|
|
UserID: 1,
|
|
UserType: constants.UserTypePlatform,
|
|
})
|
|
|
|
carrier := &model.Carrier{
|
|
CarrierCode: "TEST_CARRIER_PC",
|
|
CarrierName: "测试运营商预检",
|
|
CarrierType: constants.CarrierTypeCMCC,
|
|
Status: constants.StatusEnabled,
|
|
}
|
|
require.NoError(t, carrierStore.Create(ctx, carrier))
|
|
|
|
shop := &model.Shop{
|
|
ShopName: "测试店铺PC",
|
|
ShopCode: "TEST_SHOP_PC",
|
|
Level: 1,
|
|
Status: constants.StatusEnabled,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, shopStore.Create(ctx, shop))
|
|
|
|
series := &model.PackageSeries{
|
|
SeriesCode: "TEST_SERIES_PC",
|
|
SeriesName: "测试套餐系列预检",
|
|
Description: "测试用",
|
|
Status: constants.StatusEnabled,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, packageSeriesStore.Create(ctx, series))
|
|
|
|
allocation := &model.ShopSeriesAllocation{
|
|
ShopID: shop.ID,
|
|
SeriesID: series.ID,
|
|
Status: constants.StatusEnabled,
|
|
EnableOneTimeCommission: true,
|
|
OneTimeCommissionTrigger: model.OneTimeCommissionTriggerSingleRecharge,
|
|
OneTimeCommissionThreshold: 10000,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, seriesAllocationStore.Create(ctx, allocation))
|
|
|
|
pkg := &model.Package{
|
|
PackageCode: "TEST_PKG_PC",
|
|
PackageName: "测试套餐预检",
|
|
SeriesID: series.ID,
|
|
PackageType: "formal",
|
|
DurationMonths: 1,
|
|
DataAmountMB: 1024,
|
|
SuggestedRetailPrice: 5000,
|
|
Status: constants.StatusEnabled,
|
|
ShelfStatus: constants.ShelfStatusOn,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, packageStore.Create(ctx, pkg))
|
|
|
|
shopIDPtr := &shop.ID
|
|
card := &model.IotCard{
|
|
ICCID: "89860000000000000PC1",
|
|
ShopID: shopIDPtr,
|
|
CarrierID: carrier.ID,
|
|
SeriesID: &allocation.SeriesID,
|
|
Status: constants.StatusEnabled,
|
|
FirstCommissionPaid: false,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, iotCardStore.Create(ctx, card))
|
|
|
|
purchaseValidationSvc := purchase_validation.New(tx, iotCardStore, deviceStore, packageStore, seriesAllocationStore)
|
|
logger := zap.NewNop()
|
|
orderSvc := New(tx, orderStore, orderItemStore, walletStore, purchaseValidationSvc, nil, seriesAllocationStore, iotCardStore, deviceStore, nil, nil, logger)
|
|
|
|
t.Run("预检-需要强充", func(t *testing.T) {
|
|
req := &dto.PurchaseCheckRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
ResourceID: card.ID,
|
|
PackageIDs: []uint{pkg.ID},
|
|
}
|
|
|
|
resp, err := orderSvc.GetPurchaseCheck(ctx, req)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, pkg.SuggestedRetailPrice, resp.TotalPackageAmount)
|
|
assert.True(t, resp.NeedForceRecharge)
|
|
assert.Equal(t, allocation.OneTimeCommissionThreshold, resp.ForceRechargeAmount)
|
|
assert.Equal(t, allocation.OneTimeCommissionThreshold, resp.ActualPayment)
|
|
assert.NotEmpty(t, resp.Message)
|
|
})
|
|
|
|
t.Run("预检-无需强充", func(t *testing.T) {
|
|
card2 := &model.IotCard{
|
|
ICCID: "89860000000000000PC2",
|
|
ShopID: shopIDPtr,
|
|
CarrierID: carrier.ID,
|
|
SeriesID: &allocation.SeriesID,
|
|
Status: constants.StatusEnabled,
|
|
FirstCommissionPaid: true,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, iotCardStore.Create(ctx, card2))
|
|
|
|
req := &dto.PurchaseCheckRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
ResourceID: card2.ID,
|
|
PackageIDs: []uint{pkg.ID},
|
|
}
|
|
|
|
resp, err := orderSvc.GetPurchaseCheck(ctx, req)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, pkg.SuggestedRetailPrice, resp.TotalPackageAmount)
|
|
assert.False(t, resp.NeedForceRecharge)
|
|
assert.Equal(t, pkg.SuggestedRetailPrice, resp.ActualPayment)
|
|
assert.Empty(t, resp.Message)
|
|
})
|
|
}
|
|
|
|
func TestOrderService_WalletPay_PurchaseOnBehalf(t *testing.T) {
|
|
tx := testutils.NewTestTransaction(t)
|
|
rdb := testutils.GetTestRedis(t)
|
|
testutils.CleanTestRedisKeys(t, rdb)
|
|
|
|
iotCardStore := postgres.NewIotCardStore(tx, rdb)
|
|
deviceStore := postgres.NewDeviceStore(tx, rdb)
|
|
packageStore := postgres.NewPackageStore(tx)
|
|
seriesAllocationStore := postgres.NewShopSeriesAllocationStore(tx)
|
|
packageSeriesStore := postgres.NewPackageSeriesStore(tx)
|
|
carrierStore := postgres.NewCarrierStore(tx)
|
|
shopStore := postgres.NewShopStore(tx, rdb)
|
|
orderStore := postgres.NewOrderStore(tx, rdb)
|
|
orderItemStore := postgres.NewOrderItemStore(tx, rdb)
|
|
walletStore := postgres.NewWalletStore(tx, rdb)
|
|
|
|
ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{
|
|
UserID: 1,
|
|
UserType: constants.UserTypePlatform,
|
|
})
|
|
|
|
carrier := &model.Carrier{
|
|
CarrierCode: "TEST_CARRIER_WP",
|
|
CarrierName: "测试运营商WP",
|
|
CarrierType: constants.CarrierTypeCMCC,
|
|
Status: constants.StatusEnabled,
|
|
}
|
|
require.NoError(t, carrierStore.Create(ctx, carrier))
|
|
|
|
shop := &model.Shop{
|
|
ShopName: "测试店铺WP",
|
|
ShopCode: "TEST_SHOP_WP",
|
|
Level: 1,
|
|
Status: constants.StatusEnabled,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, shopStore.Create(ctx, shop))
|
|
|
|
series := &model.PackageSeries{
|
|
SeriesCode: "TEST_SERIES_WP",
|
|
SeriesName: "测试套餐系列WP",
|
|
Description: "测试用",
|
|
Status: constants.StatusEnabled,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, packageSeriesStore.Create(ctx, series))
|
|
|
|
allocation := &model.ShopSeriesAllocation{
|
|
ShopID: shop.ID,
|
|
SeriesID: series.ID,
|
|
AllocatorShopID: 0,
|
|
BaseCommissionMode: model.CommissionModePercent,
|
|
BaseCommissionValue: 100,
|
|
Status: constants.StatusEnabled,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, seriesAllocationStore.Create(ctx, allocation))
|
|
|
|
pkg := &model.Package{
|
|
PackageCode: "TEST_PKG_WP",
|
|
PackageName: "测试套餐WP",
|
|
SeriesID: series.ID,
|
|
PackageType: "formal",
|
|
DurationMonths: 1,
|
|
DataAmountMB: 1024,
|
|
SuggestedRetailPrice: 10000,
|
|
Status: constants.StatusEnabled,
|
|
ShelfStatus: constants.ShelfStatusOn,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, packageStore.Create(ctx, pkg))
|
|
|
|
wallet := &model.Wallet{
|
|
ResourceType: "shop",
|
|
ResourceID: shop.ID,
|
|
WalletType: "main",
|
|
Balance: 100000,
|
|
Version: 1,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, tx.Create(wallet).Error)
|
|
|
|
shopIDPtr := &shop.ID
|
|
card := &model.IotCard{
|
|
ICCID: "89860000000000000WP1",
|
|
ShopID: shopIDPtr,
|
|
CarrierID: carrier.ID,
|
|
SeriesID: &allocation.SeriesID,
|
|
Status: constants.StatusEnabled,
|
|
BaseModel: model.BaseModel{Creator: 1, Updater: 1},
|
|
}
|
|
require.NoError(t, iotCardStore.Create(ctx, card))
|
|
|
|
purchaseValidationSvc := purchase_validation.New(tx, iotCardStore, deviceStore, packageStore, seriesAllocationStore)
|
|
logger := zap.NewNop()
|
|
orderSvc := New(tx, orderStore, orderItemStore, walletStore, purchaseValidationSvc, nil, seriesAllocationStore, iotCardStore, deviceStore, nil, nil, logger)
|
|
|
|
t.Run("代购订单无法进行钱包支付", func(t *testing.T) {
|
|
req := &dto.CreateOrderRequest{
|
|
OrderType: model.OrderTypeSingleCard,
|
|
IotCardID: &card.ID,
|
|
PackageIDs: []uint{pkg.ID},
|
|
PaymentMethod: model.PaymentMethodOffline,
|
|
}
|
|
|
|
created, err := orderSvc.Create(ctx, req, model.BuyerTypeAgent, shop.ID)
|
|
require.NoError(t, err)
|
|
|
|
err = orderSvc.WalletPay(ctx, created.ID, model.BuyerTypeAgent, shop.ID)
|
|
require.Error(t, err)
|
|
appErr, ok := err.(*errors.AppError)
|
|
require.True(t, ok)
|
|
assert.Equal(t, errors.CodeInvalidStatus, appErr.Code)
|
|
})
|
|
}
|