feat: 实现订单超时自动取消功能,支持钱包余额解冻和 Asynq Scheduler 统一调度
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m58s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m58s
- 新增 expires_at 字段和复合索引,待支付订单 30 分钟超时自动取消 - 实现 cancelOrder/unfreezeWalletForCancel 钱包余额解冻逻辑 - 创建 Asynq 定时任务(order_expire/alert_check/data_cleanup) - 将原有 time.Ticker 轮询迁移至 Asynq Scheduler 统一调度 - 同步 delta specs 到 main specs 并归档变更
This commit is contained in:
@@ -37,27 +37,27 @@ func (w *AgentWallet) GetAvailableBalance() int64 {
|
||||
// AgentWalletTransaction 代理钱包交易记录模型
|
||||
// 记录所有代理钱包余额变动
|
||||
type AgentWalletTransaction struct {
|
||||
ID uint `gorm:"column:id;primaryKey" json:"id"`
|
||||
AgentWalletID uint `gorm:"column:agent_wallet_id;not null;index;comment:代理钱包ID" json:"agent_wallet_id"`
|
||||
ShopID uint `gorm:"column:shop_id;not null;index;comment:店铺ID(冗余字段,便于查询)" json:"shop_id"`
|
||||
UserID uint `gorm:"column:user_id;not null;comment:操作人用户ID" json:"user_id"`
|
||||
TransactionType string `gorm:"column:transaction_type;type:varchar(20);not null;comment:交易类型(recharge-充值 | deduct-扣款 | refund-退款 | commission-分佣 | withdrawal-提现)" json:"transaction_type"`
|
||||
TransactionSubtype *string `gorm:"column:transaction_subtype;type:varchar(50);comment:交易子类型(细分 order_payment 场景)" json:"transaction_subtype,omitempty"`
|
||||
Amount int64 `gorm:"column:amount;type:bigint;not null;comment:变动金额(单位:分,正数为增加,负数为减少)" json:"amount"`
|
||||
BalanceBefore int64 `gorm:"column:balance_before;type:bigint;not null;comment:变动前余额(单位:分)" json:"balance_before"`
|
||||
BalanceAfter int64 `gorm:"column:balance_after;type:bigint;not null;comment:变动后余额(单位:分)" json:"balance_after"`
|
||||
Status int `gorm:"column:status;type:int;not null;default:1;comment:交易状态(1-成功 2-失败 3-处理中)" json:"status"`
|
||||
ReferenceType *string `gorm:"column:reference_type;type:varchar(50);comment:关联业务类型(order | commission | withdrawal | topup)" json:"reference_type,omitempty"`
|
||||
ReferenceID *uint `gorm:"column:reference_id;comment:关联业务ID" json:"reference_id,omitempty"`
|
||||
RelatedShopID *uint `gorm:"column:related_shop_id;comment:关联店铺ID(代购时记录下级店铺)" json:"related_shop_id,omitempty"`
|
||||
Remark *string `gorm:"column:remark;type:text;comment:备注" json:"remark,omitempty"`
|
||||
Metadata *string `gorm:"column:metadata;type:jsonb;comment:扩展信息(如手续费、支付方式等)" json:"metadata,omitempty"`
|
||||
Creator uint `gorm:"column:creator;not null;comment:创建人ID" json:"creator"`
|
||||
ShopIDTag uint `gorm:"column:shop_id_tag;not null;index;comment:店铺ID标签(多租户过滤)" json:"shop_id_tag"`
|
||||
EnterpriseIDTag *uint `gorm:"column:enterprise_id_tag;index;comment:企业ID标签(多租户过滤)" json:"enterprise_id_tag,omitempty"`
|
||||
CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP" json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;index" json:"deleted_at,omitempty"`
|
||||
ID uint `gorm:"column:id;primaryKey" json:"id"`
|
||||
AgentWalletID uint `gorm:"column:agent_wallet_id;not null;index;comment:代理钱包ID" json:"agent_wallet_id"`
|
||||
ShopID uint `gorm:"column:shop_id;not null;index;comment:店铺ID(冗余字段,便于查询)" json:"shop_id"`
|
||||
UserID uint `gorm:"column:user_id;not null;comment:操作人用户ID" json:"user_id"`
|
||||
TransactionType string `gorm:"column:transaction_type;type:varchar(20);not null;comment:交易类型(recharge-充值 | deduct-扣款 | refund-退款 | commission-分佣 | withdrawal-提现)" json:"transaction_type"`
|
||||
TransactionSubtype *string `gorm:"column:transaction_subtype;type:varchar(50);comment:交易子类型(细分 order_payment 场景)" json:"transaction_subtype,omitempty"`
|
||||
Amount int64 `gorm:"column:amount;type:bigint;not null;comment:变动金额(单位:分,正数为增加,负数为减少)" json:"amount"`
|
||||
BalanceBefore int64 `gorm:"column:balance_before;type:bigint;not null;comment:变动前余额(单位:分)" json:"balance_before"`
|
||||
BalanceAfter int64 `gorm:"column:balance_after;type:bigint;not null;comment:变动后余额(单位:分)" json:"balance_after"`
|
||||
Status int `gorm:"column:status;type:int;not null;default:1;comment:交易状态(1-成功 2-失败 3-处理中)" json:"status"`
|
||||
ReferenceType *string `gorm:"column:reference_type;type:varchar(50);comment:关联业务类型(order | commission | withdrawal | topup)" json:"reference_type,omitempty"`
|
||||
ReferenceID *uint `gorm:"column:reference_id;comment:关联业务ID" json:"reference_id,omitempty"`
|
||||
RelatedShopID *uint `gorm:"column:related_shop_id;comment:关联店铺ID(代购时记录下级店铺)" json:"related_shop_id,omitempty"`
|
||||
Remark *string `gorm:"column:remark;type:text;comment:备注" json:"remark,omitempty"`
|
||||
Metadata *string `gorm:"column:metadata;type:jsonb;comment:扩展信息(如手续费、支付方式等)" json:"metadata,omitempty"`
|
||||
Creator uint `gorm:"column:creator;not null;comment:创建人ID" json:"creator"`
|
||||
ShopIDTag uint `gorm:"column:shop_id_tag;not null;index;comment:店铺ID标签(多租户过滤)" json:"shop_id_tag"`
|
||||
EnterpriseIDTag *uint `gorm:"column:enterprise_id_tag;index;comment:企业ID标签(多租户过滤)" json:"enterprise_id_tag,omitempty"`
|
||||
CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP" json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;index" json:"deleted_at,omitempty"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
|
||||
@@ -29,8 +29,8 @@ type StandaloneIotCardResponse struct {
|
||||
IMSI string `json:"imsi,omitempty" description:"IMSI"`
|
||||
MSISDN string `json:"msisdn,omitempty" description:"卡接入号"`
|
||||
BatchNo string `json:"batch_no,omitempty" description:"批次号"`
|
||||
Supplier string `json:"supplier,omitempty" description:"供应商"`
|
||||
Status int `json:"status" description:"状态 (1:在库, 2:已分销, 3:已激活, 4:已停用)"`
|
||||
Supplier string `json:"supplier,omitempty" description:"供应商"`
|
||||
Status int `json:"status" description:"状态 (1:在库, 2:已分销, 3:已激活, 4:已停用)"`
|
||||
ShopID *uint `json:"shop_id,omitempty" description:"店铺ID"`
|
||||
ShopName string `json:"shop_name,omitempty" description:"店铺名称"`
|
||||
ActivatedAt *time.Time `json:"activated_at,omitempty" description:"激活时间"`
|
||||
|
||||
@@ -28,6 +28,7 @@ type OrderListRequest struct {
|
||||
PurchaseRole string `json:"purchase_role" query:"purchase_role" validate:"omitempty,oneof=self_purchase purchased_by_parent purchased_by_platform purchase_for_subordinate" description:"订单角色 (self_purchase:自己购买, purchased_by_parent:上级代理购买, purchased_by_platform:平台代购, purchase_for_subordinate:给下级购买)"`
|
||||
StartTime *time.Time `json:"start_time" query:"start_time" description:"创建时间起始"`
|
||||
EndTime *time.Time `json:"end_time" query:"end_time" description:"创建时间结束"`
|
||||
IsExpired *bool `json:"is_expired" query:"is_expired" description:"是否已过期 (true:已过期, false:未过期)"`
|
||||
}
|
||||
|
||||
type PayOrderRequest struct {
|
||||
@@ -44,21 +45,21 @@ type OrderItemResponse struct {
|
||||
}
|
||||
|
||||
type OrderResponse struct {
|
||||
ID uint `json:"id" description:"订单ID"`
|
||||
OrderNo string `json:"order_no" description:"订单号"`
|
||||
OrderType string `json:"order_type" description:"订单类型 (single_card:单卡购买, device:设备购买)"`
|
||||
BuyerType string `json:"buyer_type" description:"买家类型 (personal:个人客户, agent:代理商)"`
|
||||
BuyerID uint `json:"buyer_id" description:"买家ID"`
|
||||
IotCardID *uint `json:"iot_card_id,omitempty" description:"IoT卡ID"`
|
||||
DeviceID *uint `json:"device_id,omitempty" description:"设备ID"`
|
||||
TotalAmount int64 `json:"total_amount" description:"订单总金额(分)"`
|
||||
PaymentMethod string `json:"payment_method,omitempty" description:"支付方式 (wallet:钱包支付, wechat:微信支付, alipay:支付宝支付)"`
|
||||
PaymentStatus int `json:"payment_status" description:"支付状态 (1:待支付, 2:已支付, 3:已取消, 4:已退款)"`
|
||||
PaymentStatusText string `json:"payment_status_text" description:"支付状态文本"`
|
||||
PaidAt *time.Time `json:"paid_at,omitempty" description:"支付时间"`
|
||||
IsPurchaseOnBehalf bool `json:"is_purchase_on_behalf" description:"是否为代购订单"`
|
||||
CommissionStatus int `json:"commission_status" description:"佣金状态 (1:待计算, 2:已计算)"`
|
||||
CommissionConfigVersion int `json:"commission_config_version" description:"佣金配置版本"`
|
||||
ID uint `json:"id" description:"订单ID"`
|
||||
OrderNo string `json:"order_no" description:"订单号"`
|
||||
OrderType string `json:"order_type" description:"订单类型 (single_card:单卡购买, device:设备购买)"`
|
||||
BuyerType string `json:"buyer_type" description:"买家类型 (personal:个人客户, agent:代理商)"`
|
||||
BuyerID uint `json:"buyer_id" description:"买家ID"`
|
||||
IotCardID *uint `json:"iot_card_id,omitempty" description:"IoT卡ID"`
|
||||
DeviceID *uint `json:"device_id,omitempty" description:"设备ID"`
|
||||
TotalAmount int64 `json:"total_amount" description:"订单总金额(分)"`
|
||||
PaymentMethod string `json:"payment_method,omitempty" description:"支付方式 (wallet:钱包支付, wechat:微信支付, alipay:支付宝支付)"`
|
||||
PaymentStatus int `json:"payment_status" description:"支付状态 (1:待支付, 2:已支付, 3:已取消, 4:已退款)"`
|
||||
PaymentStatusText string `json:"payment_status_text" description:"支付状态文本"`
|
||||
PaidAt *time.Time `json:"paid_at,omitempty" description:"支付时间"`
|
||||
IsPurchaseOnBehalf bool `json:"is_purchase_on_behalf" description:"是否为代购订单"`
|
||||
CommissionStatus int `json:"commission_status" description:"佣金状态 (1:待计算, 2:已计算)"`
|
||||
CommissionConfigVersion int `json:"commission_config_version" description:"佣金配置版本"`
|
||||
|
||||
// 操作者信息
|
||||
OperatorID *uint `json:"operator_id,omitempty" description:"操作者ID"`
|
||||
@@ -74,6 +75,10 @@ type OrderResponse struct {
|
||||
Items []*OrderItemResponse `json:"items" description:"订单明细列表"`
|
||||
CreatedAt time.Time `json:"created_at" description:"创建时间"`
|
||||
UpdatedAt time.Time `json:"updated_at" description:"更新时间"`
|
||||
|
||||
// 订单超时信息
|
||||
ExpiresAt *time.Time `json:"expires_at,omitempty" description:"订单过期时间"`
|
||||
IsExpired bool `json:"is_expired" description:"是否已过期"`
|
||||
}
|
||||
|
||||
type OrderListResponse struct {
|
||||
|
||||
@@ -22,8 +22,8 @@ type IotCard struct {
|
||||
IMSI string `gorm:"column:imsi;type:varchar(50);comment:IMSI" json:"imsi"`
|
||||
MSISDN string `gorm:"column:msisdn;type:varchar(20);comment:MSISDN(手机号码)" json:"msisdn"`
|
||||
BatchNo string `gorm:"column:batch_no;type:varchar(100);comment:批次号" json:"batch_no"`
|
||||
Supplier string `gorm:"column:supplier;type:varchar(255);comment:供应商" json:"supplier"`
|
||||
Status int `gorm:"column:status;type:int;default:1;not null;comment:状态 1-在库 2-已分销 3-已激活 4-已停用" json:"status"`
|
||||
Supplier string `gorm:"column:supplier;type:varchar(255);comment:供应商" json:"supplier"`
|
||||
Status int `gorm:"column:status;type:int;default:1;not null;comment:状态 1-在库 2-已分销 3-已激活 4-已停用" json:"status"`
|
||||
ShopID *uint `gorm:"column:shop_id;index;comment:店铺ID(NULL=平台所有,有值=店铺所有)" json:"shop_id,omitempty"`
|
||||
ActivatedAt *time.Time `gorm:"column:activated_at;comment:激活时间" json:"activated_at"`
|
||||
ActivationStatus int `gorm:"column:activation_status;type:int;default:0;not null;comment:激活状态 0-未激活 1-已激活" json:"activation_status"`
|
||||
|
||||
@@ -52,6 +52,9 @@ type Order struct {
|
||||
|
||||
// 订单角色(标识订单中的买卖关系)
|
||||
PurchaseRole string `gorm:"column:purchase_role;type:varchar(50);index:idx_orders_purchase_role;comment:订单角色(self_purchase/purchased_by_parent/purchased_by_platform/purchase_for_subordinate)" json:"purchase_role,omitempty"`
|
||||
|
||||
// 订单超时信息
|
||||
ExpiresAt *time.Time `gorm:"column:expires_at;comment:订单过期时间(NULL表示不过期)" json:"expires_at,omitempty"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
|
||||
Reference in New Issue
Block a user