新增完整换货生命周期管理:后台发起 → 客户端填收货信息 → 后台发货 → 确认完成(含可选全量迁移) → 旧资产转新再销售 后台接口(7个): - POST /api/admin/exchanges(发起换货) - GET /api/admin/exchanges(换货列表) - GET /api/admin/exchanges/:id(换货详情) - POST /api/admin/exchanges/:id/ship(发货) - POST /api/admin/exchanges/:id/complete(确认完成+可选迁移) - POST /api/admin/exchanges/:id/cancel(取消) - POST /api/admin/exchanges/:id/renew(旧资产转新) 客户端接口(2个): - GET /api/c/v1/exchange/pending(查询换货通知) - POST /api/c/v1/exchange/:id/shipping-info(填写收货信息) 核心能力: - ExchangeOrder 模型与状态机(1待填写→2待发货→3已发货→4已完成,1/2可取消→5) - 全量迁移事务(11张表:钱包、套餐、标签、客户绑定等) - 旧资产转新(generation+1、状态重置、新钱包、历史隔离) - 旧 CardReplacementRecord 表改名为 legacy,is_replaced 过滤改为查新表 - 数据库迁移:000085 新建 tb_exchange_order,000086 旧表改名
66 lines
3.6 KiB
Go
66 lines
3.6 KiB
Go
package model
|
||
|
||
import (
|
||
"fmt"
|
||
"math/rand"
|
||
"time"
|
||
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
// ExchangeOrder 换货单模型
|
||
// 承载客户端换货的完整生命周期:后台发起 → 客户端填写收货信息 → 后台发货 → 确认完成(含可选全量迁移) → 旧资产可转新
|
||
// 状态机:1-待填写信息 → 2-待发货 → 3-已发货待确认 → 4-已完成,1/2 时可取消 → 5-已取消
|
||
type ExchangeOrder struct {
|
||
gorm.Model
|
||
BaseModel `gorm:"embedded"`
|
||
|
||
// 单号
|
||
ExchangeNo string `gorm:"column:exchange_no;type:varchar(50);not null;uniqueIndex:idx_exchange_order_no,where:deleted_at IS NULL;comment:换货单号(EXC+日期+随机数)" json:"exchange_no"`
|
||
|
||
// 旧资产快照
|
||
OldAssetType string `gorm:"column:old_asset_type;type:varchar(20);not null;comment:旧资产类型(iot_card/device)" json:"old_asset_type"`
|
||
OldAssetID uint `gorm:"column:old_asset_id;not null;index:idx_exchange_order_old_asset;comment:旧资产ID" json:"old_asset_id"`
|
||
OldAssetIdentifier string `gorm:"column:old_asset_identifier;type:varchar(100);not null;comment:旧资产标识符(ICCID/虚拟号)" json:"old_asset_identifier"`
|
||
|
||
// 新资产快照(发货时填写)
|
||
NewAssetType string `gorm:"column:new_asset_type;type:varchar(20);comment:新资产类型(iot_card/device)" json:"new_asset_type"`
|
||
NewAssetID *uint `gorm:"column:new_asset_id;comment:新资产ID" json:"new_asset_id,omitempty"`
|
||
NewAssetIdentifier string `gorm:"column:new_asset_identifier;type:varchar(100);comment:新资产标识符(ICCID/虚拟号)" json:"new_asset_identifier"`
|
||
|
||
// 收货信息(客户端填写)
|
||
RecipientName string `gorm:"column:recipient_name;type:varchar(50);comment:收件人姓名" json:"recipient_name"`
|
||
RecipientPhone string `gorm:"column:recipient_phone;type:varchar(20);comment:收件人电话" json:"recipient_phone"`
|
||
RecipientAddress string `gorm:"column:recipient_address;type:text;comment:收货地址" json:"recipient_address"`
|
||
|
||
// 物流信息(后台发货时填写)
|
||
ExpressCompany string `gorm:"column:express_company;type:varchar(100);comment:快递公司" json:"express_company"`
|
||
ExpressNo string `gorm:"column:express_no;type:varchar(100);comment:快递单号" json:"express_no"`
|
||
|
||
// 迁移相关
|
||
MigrateData bool `gorm:"column:migrate_data;type:boolean;default:false;comment:是否执行全量迁移" json:"migrate_data"`
|
||
MigrationCompleted bool `gorm:"column:migration_completed;type:boolean;default:false;comment:迁移是否已完成" json:"migration_completed"`
|
||
MigrationBalance int64 `gorm:"column:migration_balance;type:bigint;default:0;comment:迁移转移金额(分)" json:"migration_balance"`
|
||
|
||
// 业务信息
|
||
ExchangeReason string `gorm:"column:exchange_reason;type:varchar(100);not null;comment:换货原因" json:"exchange_reason"`
|
||
Remark *string `gorm:"column:remark;type:text;comment:备注" json:"remark,omitempty"`
|
||
Status int `gorm:"column:status;type:int;not null;default:1;index:idx_exchange_order_status;comment:换货状态 1-待填写信息 2-待发货 3-已发货待确认 4-已完成 5-已取消" json:"status"`
|
||
|
||
// 多租户
|
||
ShopID *uint `gorm:"column:shop_id;index;comment:所属店铺ID" json:"shop_id,omitempty"`
|
||
}
|
||
|
||
// TableName 指定表名
|
||
func (ExchangeOrder) TableName() string {
|
||
return "tb_exchange_order"
|
||
}
|
||
|
||
// GenerateExchangeNo 生成换货单号
|
||
// 格式:EXC + 年月日时分秒 + 6位随机数,如 EXC20260319143052123456
|
||
func GenerateExchangeNo() string {
|
||
now := time.Now()
|
||
randomNum := rand.Intn(1000000)
|
||
return fmt.Sprintf("EXC%s%06d", now.Format("20060102150405"), randomNum)
|
||
}
|