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:
@@ -0,0 +1,54 @@
|
||||
## 1. 前置确认
|
||||
|
||||
- [x] 1.1 确认提案一(asset-identifier-standardization)已完成:`tb_order.asset_identifier` 字段存在,B 端资产路由已统一为 `:identifier`
|
||||
|
||||
## 2. 数据层:ExchangeOrder Store 扩展
|
||||
|
||||
- [x] 2.1 在 `internal/store/postgres/exchange_order_store.go` 新增 `FindByNewAssetID(ctx, assetType, assetID) (*model.ExchangeOrder, error)` 方法:查询 `WHERE new_asset_id = ? AND new_asset_type = ?`,返回该资产的换货来源记录(找不到则返回 nil,表示无前代)
|
||||
|
||||
## 3. DTO 层:新增响应结构
|
||||
|
||||
- [x] 3.1 在 `internal/model/dto/asset_dto.go` 新增以下结构体:
|
||||
- `AssetOrdersRequest`:路径参数 `identifier`,query 参数 `page`、`page_size`、`include_previous`
|
||||
- `AssetOrderItem`:单条订单项(order_no、order_type、payment_status、payment_status_text、total_amount、payment_method、paid_at、generation、items、created_at)
|
||||
- `GenerationOrders`:单代订单块(generation、identifier、asset_type、total、page、page_size、items)
|
||||
- `PreviousGenerationOrders`:前代订单块(generation、identifier、asset_type、exchange_no、exchanged_at、total、items)
|
||||
- `AssetOrdersResponse`:完整响应(current_generation、previous_generations、truncated)
|
||||
|
||||
## 4. 服务层:GetOrders 方法
|
||||
|
||||
- [x] 4.1 在 `internal/service/asset/service.go` 新增 `GetOrders(ctx, identifier, page, pageSize, includePrevious bool) (*dto.AssetOrdersResponse, error)` 方法:
|
||||
- 调用 `Resolve()` 得到 asset_type 和 asset_id
|
||||
- 查询本代订单:`orderStore.ListByAssetIdentifier(ctx, identifier, page, pageSize)`
|
||||
- 若 `includePrevious=true`:循环调用 `exchangeOrderStore.FindByNewAssetID()` 追溯换货链(最多 10 代);每代查询前代 `old_asset_identifier` 对应的订单(最多 20 条,无分页)
|
||||
- 组装 `AssetOrdersResponse` 返回
|
||||
- [x] 4.2 在 `internal/store/postgres/order_store.go` 新增 `ListByAssetIdentifier(ctx, identifier, page, pageSize) ([]*model.Order, int64, error)` 方法:查询 `WHERE asset_identifier = ?`,分页,倒序
|
||||
|
||||
## 5. Handler 层:新增 Orders Handler
|
||||
|
||||
- [x] 5.1 在 `internal/handler/admin/asset.go` 新增 `Orders(c *fiber.Ctx) error` handler:
|
||||
- 从路径参数读取 `identifier`;从 query 读取 `page`、`page_size`、`include_previous`
|
||||
- 调用 `assetService.GetOrders()`
|
||||
- 返回 `response.Success(c, result)`
|
||||
- 注释:`// Orders 查询资产历史订单(支持跨代追溯)` + `// GET /api/admin/assets/:identifier/orders`
|
||||
|
||||
## 6. 路由层:注册新路由
|
||||
|
||||
- [x] 6.1 在 `internal/routes/asset.go` 注册:`assets.Get("/:identifier/orders", h.Asset.Orders)`(注意路由顺序,避免与 `/resolve/:identifier` 冲突)
|
||||
|
||||
## 7. 文档生成器更新
|
||||
|
||||
- [x] 7.1 在 `cmd/api/docs.go` 和 `cmd/gendocs/main.go` 的 `handlers` 结构体中确认 `AssetHandler` 已包含新的 `Orders` 方法(检查是否需要更新 handler 注册)
|
||||
- [x] 7.2 执行 `go run cmd/gendocs/main.go` 重新生成 OpenAPI 文档,验证新接口体现
|
||||
|
||||
## 8. 验证
|
||||
|
||||
- [x] 8.1 构建验证:`go build ./...` 无编译错误
|
||||
- [x] 8.2 LSP 诊断:对所有修改文件运行 lsp_diagnostics,无错误/警告
|
||||
- [x] 8.3 接口验证(使用 PostgreSQL MCP + curl):
|
||||
- 查询有订单的资产:`GET /api/admin/assets/:identifier/orders` 返回正确订单列表,含 generation 字段
|
||||
- 查询无订单资产:返回 `items: [], total: 0`
|
||||
- 查询不存在的 identifier:返回 404
|
||||
- 查询换货资产(带 include_previous=true):`previous_generations` 包含前代订单,附带 exchange_no 和 exchanged_at
|
||||
- 查询无前代的资产(带 include_previous=true):`previous_generations` 为空数组
|
||||
- 代理查询无权限资产:返回 403
|
||||
Reference in New Issue
Block a user