feat: 资产标识符标准化、资产历史订单查询及导入虚拟号强制验证
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m21s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m21s
主要变更: - 新增 AssetIdentifier 模型及 Store,统一管理资产标识符(ICCID/IMEI/SN 等) - 新增迁移:asset_identifier 表、order 表新增 asset_identifier 字段、iot_card.virtual_no NOT NULL 约束 - 资产 Handler/Service/Route 全面重构,支持标识符路由查询与解析 - 新增资产历史订单查询接口,支持跨设备/卡/钱包维度的订单聚合 - 设备与物联卡导入任务强制校验虚拟号,缺失时直接拒绝 - Excel 工具函数优化,前端导入指引文档同步更新 - 归档三个 OpenSpec 提案:asset-identifier-standardization、asset-historical-orders、import-mandatory-virtual-no - 更新 OpenAPI 文档及相关 DTO Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -6,6 +6,7 @@ import "time"
|
||||
type AssetResolveResponse struct {
|
||||
AssetType string `json:"asset_type" description:"资产类型:card 或 device"`
|
||||
AssetID uint `json:"asset_id" description:"资产数据库ID"`
|
||||
Identifier string `json:"identifier,omitempty" description:"解析时使用的标识符"`
|
||||
VirtualNo string `json:"virtual_no" description:"虚拟号"`
|
||||
Status int `json:"status" description:"资产状态"`
|
||||
BatchNo string `json:"batch_no" description:"批次号"`
|
||||
@@ -118,7 +119,12 @@ type AssetResolveRequest struct {
|
||||
Identifier string `path:"identifier" description:"资产标识符(虚拟号/ICCID/IMEI/SN/MSISDN)" required:"true"`
|
||||
}
|
||||
|
||||
// AssetTypeIDRequest 资产类型+ID请求(路径参数)
|
||||
// AssetIdentifierRequest 资产标识符路径参数请求
|
||||
type AssetIdentifierRequest struct {
|
||||
Identifier string `path:"identifier" description:"资产标识符(ICCID 或 VirtualNo)" required:"true"`
|
||||
}
|
||||
|
||||
// AssetTypeIDRequest 资产类型+ID请求(路径参数,保留用于钱包等向后兼容场景)
|
||||
type AssetTypeIDRequest struct {
|
||||
AssetType string `path:"asset_type" description:"资产类型:card 或 device" required:"true"`
|
||||
ID uint `path:"id" description:"资产ID" required:"true"`
|
||||
@@ -197,12 +203,69 @@ type DeviceGatewayInfo struct {
|
||||
IMSI *string `json:"imsi,omitempty" description:"IMSI用户标识码"`
|
||||
}
|
||||
|
||||
// AssetOrdersRequest 资产历史订单查询请求
|
||||
type AssetOrdersRequest struct {
|
||||
Identifier string `path:"identifier" description:"资产标识符(ICCID 或 VirtualNo)" required:"true"`
|
||||
Page int `query:"page" validate:"omitempty,min=1" minimum:"1" description:"页码(默认1)"`
|
||||
PageSize int `query:"page_size" validate:"omitempty,min=1,max=100" minimum:"1" maximum:"100" description:"每页条数(默认20,最大100)"`
|
||||
IncludePrevious bool `query:"include_previous" description:"是否包含前代订单,默认false"`
|
||||
}
|
||||
|
||||
// AssetOrderItemDetail 订单中的套餐明细
|
||||
type AssetOrderItemDetail struct {
|
||||
PackageName string `json:"package_name" description:"套餐名称快照"`
|
||||
Quantity int `json:"quantity" description:"数量"`
|
||||
UnitPrice int64 `json:"unit_price" description:"单价(分)"`
|
||||
Amount int64 `json:"amount" description:"小计金额(分)"`
|
||||
}
|
||||
|
||||
// AssetOrderItem 资产历史订单条目
|
||||
type AssetOrderItem struct {
|
||||
OrderNo string `json:"order_no" description:"订单号"`
|
||||
OrderType string `json:"order_type" description:"订单类型:single_card/device"`
|
||||
PaymentStatus int `json:"payment_status" description:"支付状态:1待支付 2已支付 3已取消 4已退款"`
|
||||
PaymentStatusText string `json:"payment_status_text" description:"支付状态文本"`
|
||||
TotalAmount int64 `json:"total_amount" description:"订单金额(分)"`
|
||||
PaymentMethod string `json:"payment_method" description:"支付方式:wallet/wechat/alipay/offline"`
|
||||
PaidAt *time.Time `json:"paid_at,omitempty" description:"支付时间"`
|
||||
Generation int `json:"generation" description:"订单所属资产世代编号"`
|
||||
Items []*AssetOrderItemDetail `json:"items" description:"套餐明细列表"`
|
||||
CreatedAt time.Time `json:"created_at" description:"订单创建时间"`
|
||||
}
|
||||
|
||||
// GenerationOrders 本代订单块(支持分页)
|
||||
type GenerationOrders struct {
|
||||
Generation int `json:"generation" description:"世代编号"`
|
||||
Identifier string `json:"identifier" description:"资产标识符"`
|
||||
AssetType string `json:"asset_type" description:"资产类型:card 或 device"`
|
||||
Total int64 `json:"total" description:"总订单数"`
|
||||
Page int `json:"page" description:"当前页码"`
|
||||
PageSize int `json:"page_size" description:"每页条数"`
|
||||
Items []*AssetOrderItem `json:"items" description:"订单列表"`
|
||||
}
|
||||
|
||||
// PreviousGenerationOrders 前代订单块(最多20条,不分页)
|
||||
type PreviousGenerationOrders struct {
|
||||
Generation int `json:"generation" description:"前代世代编号"`
|
||||
Identifier string `json:"identifier" description:"前代资产标识符"`
|
||||
AssetType string `json:"asset_type" description:"前代资产类型:card 或 device"`
|
||||
ExchangeNo string `json:"exchange_no" description:"换货单号"`
|
||||
ExchangedAt time.Time `json:"exchanged_at" description:"换货完成时间"`
|
||||
Total int64 `json:"total" description:"前代总订单数"`
|
||||
Items []*AssetOrderItem `json:"items" description:"前代订单列表(最多20条)"`
|
||||
}
|
||||
|
||||
// AssetOrdersResponse 资产历史订单完整响应
|
||||
type AssetOrdersResponse struct {
|
||||
CurrentGeneration *GenerationOrders `json:"current_generation" description:"本代订单(含分页)"`
|
||||
PreviousGenerations []*PreviousGenerationOrders `json:"previous_generations,omitempty" description:"前代订单列表(include_previous=true时返回)"`
|
||||
Truncated bool `json:"truncated" description:"是否已截断(换货链超过10代追溯上限时为true)"`
|
||||
}
|
||||
|
||||
// UpdateAssetPollingStatusRequest 更新资产轮询状态请求
|
||||
type UpdateAssetPollingStatusRequest struct {
|
||||
AssetType string `path:"asset_type" description:"资产类型 (iot_card:IoT卡, device:设备)" required:"true"`
|
||||
ID uint `path:"id" description:"资产ID" required:"true"`
|
||||
// EnablePolling 是否启用轮询
|
||||
EnablePolling bool `json:"enable_polling" description:"是否启用轮询 (true:启用, false:禁用)"`
|
||||
Identifier string `path:"identifier" description:"资产标识符(ICCID 或 VirtualNo)" required:"true"`
|
||||
EnablePolling bool `json:"enable_polling" description:"是否启用轮询 (true:启用, false:禁用)"`
|
||||
}
|
||||
|
||||
// UpdateAssetPollingStatusResponse 更新资产轮询状态响应
|
||||
|
||||
@@ -19,8 +19,7 @@ type AssetWalletResponse struct {
|
||||
|
||||
// AssetWalletTransactionListRequest 资产钱包流水列表请求(路径参数 + 查询参数)
|
||||
type AssetWalletTransactionListRequest struct {
|
||||
AssetType string `path:"asset_type" description:"资产类型:card 或 device" required:"true"`
|
||||
ID uint `path:"id" description:"资产ID" required:"true"`
|
||||
Identifier string `path:"identifier" description:"资产标识符(ICCID 或 VirtualNo)" required:"true"`
|
||||
Page int `json:"page" query:"page" description:"页码,默认1"`
|
||||
PageSize int `json:"page_size" query:"page_size" validate:"omitempty,min=1,max=100" description:"每页数量,默认20,最大100"`
|
||||
TransactionType *string `json:"transaction_type" query:"transaction_type" validate:"omitempty,oneof=recharge deduct refund" description:"交易类型过滤:recharge/deduct/refund"`
|
||||
|
||||
@@ -65,11 +65,11 @@ type GetDeviceByIdentifierRequest struct {
|
||||
}
|
||||
|
||||
type DeleteDeviceRequest struct {
|
||||
ID uint `path:"id" description:"设备ID" required:"true"`
|
||||
VirtualNo string `path:"virtual_no" description:"设备虚拟号" required:"true"`
|
||||
}
|
||||
|
||||
type ListDeviceCardsRequest struct {
|
||||
ID uint `path:"id" description:"设备ID" required:"true"`
|
||||
VirtualNo string `path:"virtual_no" description:"设备虚拟号" required:"true"`
|
||||
}
|
||||
|
||||
type DeviceCardBindingResponse struct {
|
||||
@@ -89,9 +89,10 @@ type ListDeviceCardsResponse struct {
|
||||
}
|
||||
|
||||
type BindCardToDeviceRequest struct {
|
||||
ID uint `path:"id" description:"设备ID" required:"true"`
|
||||
IotCardID uint `json:"iot_card_id" validate:"required,min=1" required:"true" minimum:"1" description:"IoT卡ID"`
|
||||
SlotPosition int `json:"slot_position" validate:"required,min=1,max=4" required:"true" minimum:"1" maximum:"4" description:"插槽位置 (1-4)"`
|
||||
VirtualNo string `path:"virtual_no" description:"设备虚拟号" required:"true"`
|
||||
ID uint `json:"-"`
|
||||
IotCardID uint `json:"iot_card_id" validate:"required,min=1" required:"true" minimum:"1" description:"IoT卡ID"`
|
||||
SlotPosition int `json:"slot_position" validate:"required,min=1,max=4" required:"true" minimum:"1" maximum:"4" description:"插槽位置 (1-4)"`
|
||||
}
|
||||
|
||||
type BindCardToDeviceResponse struct {
|
||||
@@ -100,8 +101,8 @@ type BindCardToDeviceResponse struct {
|
||||
}
|
||||
|
||||
type UnbindCardFromDeviceRequest struct {
|
||||
ID uint `path:"id" description:"设备ID" required:"true"`
|
||||
CardID uint `path:"cardId" description:"IoT卡ID" required:"true"`
|
||||
VirtualNo string `path:"virtual_no" description:"设备虚拟号" required:"true"`
|
||||
ICCID string `path:"iccid" description:"IoT卡ICCID" required:"true"`
|
||||
}
|
||||
|
||||
type UnbindCardFromDeviceResponse struct {
|
||||
|
||||
@@ -12,9 +12,7 @@ type CreateOrderRequest struct {
|
||||
|
||||
// CreateAdminOrderRequest 后台订单创建请求(仅允许 wallet/offline)
|
||||
type CreateAdminOrderRequest struct {
|
||||
OrderType string `json:"order_type" validate:"required,oneof=single_card device" required:"true" description:"订单类型 (single_card:单卡购买, device:设备购买)"`
|
||||
IotCardID *uint `json:"iot_card_id" validate:"required_if=OrderType single_card" description:"IoT卡ID(单卡购买时必填)"`
|
||||
DeviceID *uint `json:"device_id" validate:"required_if=OrderType device" description:"设备ID(设备购买时必填)"`
|
||||
Identifier string `json:"identifier" validate:"required,min=1,max=100" required:"true" minLength:"1" maxLength:"100" description:"资产标识符(ICCID 或 VirtualNo)"`
|
||||
PackageIDs []uint `json:"package_ids" validate:"required,min=1,max=10,dive,min=1" required:"true" minItems:"1" maxItems:"10" description:"套餐ID列表"`
|
||||
PaymentMethod string `json:"payment_method" validate:"required,oneof=wallet offline" required:"true" description:"支付方式 (wallet:钱包支付, offline:线下支付)"`
|
||||
}
|
||||
@@ -29,6 +27,7 @@ type OrderListRequest struct {
|
||||
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:未过期)"`
|
||||
Identifier string `json:"identifier" query:"identifier" validate:"omitempty,max=100" maxLength:"100" description:"资产标识符(ICCID 或 VirtualNo)精确查询"`
|
||||
}
|
||||
|
||||
type PayOrderRequest struct {
|
||||
@@ -79,6 +78,10 @@ type OrderResponse struct {
|
||||
// 订单超时信息
|
||||
ExpiresAt *time.Time `json:"expires_at,omitempty" description:"订单过期时间"`
|
||||
IsExpired bool `json:"is_expired" description:"是否已过期"`
|
||||
|
||||
// 资产标识符快照
|
||||
AssetIdentifier string `json:"asset_identifier,omitempty" description:"下单时资产的标识符快照(ICCID 或 VirtualNo)"`
|
||||
AssetType string `json:"asset_type,omitempty" description:"资产类型 (card:单卡, device:设备)"`
|
||||
}
|
||||
|
||||
type OrderListResponse struct {
|
||||
|
||||
Reference in New Issue
Block a user