完善商城订单模拟快照与空值展示
This commit is contained in:
@@ -312,14 +312,18 @@ func MockData(database *gorm.DB) error {
|
|||||||
|
|
||||||
ecOrder := models.EcOrder{
|
ecOrder := models.EcOrder{
|
||||||
Entity: entity(30, common.StatusEnable), OrderStatus: mockEcOrderPaidStatus(), OrderNo: "MOCK-ECORDER-001",
|
Entity: entity(30, common.StatusEnable), OrderStatus: mockEcOrderPaidStatus(), OrderNo: "MOCK-ECORDER-001",
|
||||||
UserAccountID: user.ID, GasStationID: gas.ID, DeliveryPointID: delivery.ID,
|
RequestNo: "MOCK-REQ-ECORDER-001", UserAccountID: user.ID,
|
||||||
|
GasStationID: gas.ID, DeliveryPointID: delivery.ID, UserAddressID: address.ID,
|
||||||
|
Address: address.Address, Longitude: address.Longitude, Latitude: address.Latitude,
|
||||||
|
ContactName: user.Name, ContactPhone: user.Phone, Remark: "模拟已支付商城订单",
|
||||||
ProductAmount: ecProduct.PriceAmount, PayableAmount: ecProduct.PriceAmount,
|
ProductAmount: ecProduct.PriceAmount, PayableAmount: ecProduct.PriceAmount,
|
||||||
TotalAmount: ecProduct.PriceAmount, PaidAt: &now,
|
TotalAmount: ecProduct.PriceAmount, PaidAt: &now,
|
||||||
}
|
}
|
||||||
|
desiredEcOrder := ecOrder
|
||||||
if err := put(tx, &ecOrder); err != nil {
|
if err := put(tx, &ecOrder); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := repairMockEcOrder(tx, ecOrder, mockEcOrderPaidStatus(), ecProduct.PriceAmount, &now); err != nil {
|
if err := repairMockEcOrder(tx, desiredEcOrder, mockEcOrderPaidStatus(), ecProduct.PriceAmount, &now); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -728,15 +732,19 @@ func seedAdditionalCoreScenarios(database *gorm.DB, passwordHash string, now tim
|
|||||||
|
|
||||||
ecOrder := models.EcOrder{
|
ecOrder := models.EcOrder{
|
||||||
Entity: entity(sequence+16, common.StatusEnable), OrderStatus: mockEcOrderPendingStatus(),
|
Entity: entity(sequence+16, common.StatusEnable), OrderStatus: mockEcOrderPendingStatus(),
|
||||||
OrderNo: "MOCK-ECORDER-" + suffix, UserAccountID: user.ID,
|
OrderNo: "MOCK-ECORDER-" + suffix, RequestNo: "MOCK-REQ-ECORDER-" + suffix,
|
||||||
GasStationID: gas.ID, DeliveryPointID: delivery.ID,
|
UserAccountID: user.ID, GasStationID: gas.ID, DeliveryPointID: delivery.ID,
|
||||||
|
UserAddressID: address.ID, Address: address.Address,
|
||||||
|
Longitude: address.Longitude, Latitude: address.Latitude,
|
||||||
|
ContactName: user.Name, ContactPhone: user.Phone, Remark: "模拟待支付商城订单",
|
||||||
ProductAmount: ecProduct.PriceAmount, PayableAmount: ecProduct.PriceAmount,
|
ProductAmount: ecProduct.PriceAmount, PayableAmount: ecProduct.PriceAmount,
|
||||||
TotalAmount: ecProduct.PriceAmount,
|
TotalAmount: ecProduct.PriceAmount,
|
||||||
}
|
}
|
||||||
|
desiredEcOrder := ecOrder
|
||||||
if err := put(database, &ecOrder); err != nil {
|
if err := put(database, &ecOrder); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := repairMockEcOrder(database, ecOrder, mockEcOrderPendingStatus(), ecProduct.PriceAmount, nil); err != nil {
|
if err := repairMockEcOrder(database, desiredEcOrder, mockEcOrderPendingStatus(), ecProduct.PriceAmount, nil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -786,7 +794,11 @@ func repairMockEcOrder(database *gorm.DB, order models.EcOrder, status int, amou
|
|||||||
Where("identity = ? AND order_no LIKE ?", order.Identity, "MOCK-ECORDER-%").
|
Where("identity = ? AND order_no LIKE ?", order.Identity, "MOCK-ECORDER-%").
|
||||||
Updates(map[string]any{
|
Updates(map[string]any{
|
||||||
"order_status": status, "product_amount": amount, "payable_amount": amount,
|
"order_status": status, "product_amount": amount, "payable_amount": amount,
|
||||||
"total_amount": amount, "paid_at": paidAt,
|
"total_amount": amount, "paid_at": paidAt, "request_no": order.RequestNo,
|
||||||
|
"user_address_id": order.UserAddressID, "address": order.Address,
|
||||||
|
"longitude": order.Longitude, "latitude": order.Latitude,
|
||||||
|
"contact_name": order.ContactName, "contact_phone": order.ContactPhone,
|
||||||
|
"remark": order.Remark,
|
||||||
})
|
})
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
return fmt.Errorf("repair mock ec order: %w", result.Error)
|
return fmt.Errorf("repair mock ec order: %w", result.Error)
|
||||||
@@ -797,9 +809,18 @@ func repairMockEcOrder(database *gorm.DB, order models.EcOrder, status int, amou
|
|||||||
type mockEcOrderRepairSpec struct {
|
type mockEcOrderRepairSpec struct {
|
||||||
identity string
|
identity string
|
||||||
orderNo string
|
orderNo string
|
||||||
|
requestNo string
|
||||||
|
userIdentity string
|
||||||
|
addressIdentity string
|
||||||
|
contactName string
|
||||||
|
contactPhone string
|
||||||
|
address string
|
||||||
|
longitude string
|
||||||
|
latitude string
|
||||||
status int
|
status int
|
||||||
amount int64
|
amount int64
|
||||||
paidAt *time.Time
|
paidAt *time.Time
|
||||||
|
remark string
|
||||||
}
|
}
|
||||||
|
|
||||||
// mockEcOrderRepairSpecs 返回固定 Mock 商城订单的文档化交易状态与金额。
|
// mockEcOrderRepairSpecs 返回固定 Mock 商城订单的文档化交易状态与金额。
|
||||||
@@ -808,17 +829,35 @@ func mockEcOrderRepairSpecs() []mockEcOrderRepairSpec {
|
|||||||
specs := []mockEcOrderRepairSpec{{
|
specs := []mockEcOrderRepairSpec{{
|
||||||
identity: entity(30, common.StatusEnable).Identity,
|
identity: entity(30, common.StatusEnable).Identity,
|
||||||
orderNo: "MOCK-ECORDER-001",
|
orderNo: "MOCK-ECORDER-001",
|
||||||
|
requestNo: "MOCK-REQ-ECORDER-001",
|
||||||
|
userIdentity: entity(7, common.StatusEnable).Identity,
|
||||||
|
addressIdentity: entity(8, common.StatusEnable).Identity,
|
||||||
|
contactName: "陈女士",
|
||||||
|
contactPhone: "13800000001",
|
||||||
|
address: "上海市浦东新区客户路 88 号",
|
||||||
|
longitude: "121.5500",
|
||||||
|
latitude: "31.2250",
|
||||||
status: mockEcOrderPaidStatus(),
|
status: mockEcOrderPaidStatus(),
|
||||||
amount: 10300,
|
amount: 10300,
|
||||||
paidAt: &paidAt,
|
paidAt: &paidAt,
|
||||||
|
remark: "模拟已支付商城订单",
|
||||||
}}
|
}}
|
||||||
for scenario := 2; scenario <= 10; scenario++ {
|
for scenario := 2; scenario <= 10; scenario++ {
|
||||||
sequence := 1000 + scenario*100
|
sequence := 1000 + scenario*100
|
||||||
specs = append(specs, mockEcOrderRepairSpec{
|
specs = append(specs, mockEcOrderRepairSpec{
|
||||||
identity: entity(sequence+16, common.StatusEnable).Identity,
|
identity: entity(sequence+16, common.StatusEnable).Identity,
|
||||||
orderNo: fmt.Sprintf("MOCK-ECORDER-%03d", scenario),
|
orderNo: fmt.Sprintf("MOCK-ECORDER-%03d", scenario),
|
||||||
|
requestNo: fmt.Sprintf("MOCK-REQ-ECORDER-%03d", scenario),
|
||||||
|
userIdentity: entity(sequence+4, common.StatusEnable).Identity,
|
||||||
|
addressIdentity: entity(sequence+5, common.StatusEnable).Identity,
|
||||||
|
contactName: fmt.Sprintf("示例客户%d", scenario),
|
||||||
|
contactPhone: "138" + fmt.Sprintf("%08d", scenario),
|
||||||
|
address: fmt.Sprintf("上海市客户路 %d 号", scenario),
|
||||||
|
longitude: fmt.Sprintf("121.5%03d", scenario),
|
||||||
|
latitude: fmt.Sprintf("31.2%03d", scenario),
|
||||||
status: mockEcOrderPendingStatus(),
|
status: mockEcOrderPendingStatus(),
|
||||||
amount: int64(9500 + scenario*100),
|
amount: int64(9500 + scenario*100),
|
||||||
|
remark: "模拟待支付商城订单",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return specs
|
return specs
|
||||||
@@ -829,12 +868,34 @@ func RepairMockEcOrders(database *gorm.DB) (int64, error) {
|
|||||||
var repaired int64
|
var repaired int64
|
||||||
err := database.Transaction(func(tx *gorm.DB) error {
|
err := database.Transaction(func(tx *gorm.DB) error {
|
||||||
for _, spec := range mockEcOrderRepairSpecs() {
|
for _, spec := range mockEcOrderRepairSpecs() {
|
||||||
|
var user models.UserAccount
|
||||||
|
if err := tx.Where("identity = ?", spec.userIdentity).First(&user).Error; err != nil {
|
||||||
|
return fmt.Errorf("load mock ec order user %s: %w", spec.orderNo, err)
|
||||||
|
}
|
||||||
|
if err := tx.Model(&user).Updates(map[string]any{
|
||||||
|
"name": spec.contactName, "phone": spec.contactPhone,
|
||||||
|
}).Error; err != nil {
|
||||||
|
return fmt.Errorf("repair mock ec order user %s: %w", spec.orderNo, err)
|
||||||
|
}
|
||||||
|
var address models.UserAddress
|
||||||
|
if err := tx.Where("identity = ?", spec.addressIdentity).First(&address).Error; err != nil {
|
||||||
|
return fmt.Errorf("load mock ec order address %s: %w", spec.orderNo, err)
|
||||||
|
}
|
||||||
|
if err := tx.Model(&address).Updates(map[string]any{
|
||||||
|
"address": spec.address, "longitude": spec.longitude, "latitude": spec.latitude,
|
||||||
|
}).Error; err != nil {
|
||||||
|
return fmt.Errorf("repair mock ec order address %s: %w", spec.orderNo, err)
|
||||||
|
}
|
||||||
result := tx.Model(&models.EcOrder{}).
|
result := tx.Model(&models.EcOrder{}).
|
||||||
Where("identity = ? AND order_no = ?", spec.identity, spec.orderNo).
|
Where("identity = ? AND order_no = ?", spec.identity, spec.orderNo).
|
||||||
Updates(map[string]any{
|
Updates(map[string]any{
|
||||||
"order_status": spec.status, "product_amount": spec.amount,
|
"order_status": spec.status, "product_amount": spec.amount,
|
||||||
"payable_amount": spec.amount, "total_amount": spec.amount,
|
"payable_amount": spec.amount, "total_amount": spec.amount,
|
||||||
"paid_at": spec.paidAt,
|
"paid_at": spec.paidAt, "request_no": spec.requestNo,
|
||||||
|
"user_address_id": address.ID, "address": spec.address,
|
||||||
|
"longitude": spec.longitude, "latitude": spec.latitude,
|
||||||
|
"contact_name": spec.contactName, "contact_phone": spec.contactPhone,
|
||||||
|
"remark": spec.remark,
|
||||||
})
|
})
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
return fmt.Errorf("repair mock ec order %s: %w", spec.orderNo, result.Error)
|
return fmt.Errorf("repair mock ec order %s: %w", spec.orderNo, result.Error)
|
||||||
|
|||||||
@@ -117,10 +117,17 @@ func TestMockEcOrderRepairSpecs(t *testing.T) {
|
|||||||
t.Fatalf("首条已支付 Mock 订单修复配置错误:%#v", specs[0])
|
t.Fatalf("首条已支付 Mock 订单修复配置错误:%#v", specs[0])
|
||||||
}
|
}
|
||||||
for _, spec := range specs[1:] {
|
for _, spec := range specs[1:] {
|
||||||
if spec.status != 16 || spec.paidAt != nil || spec.amount <= 0 {
|
if spec.status != 16 || spec.paidAt != nil || spec.amount <= 0 ||
|
||||||
|
spec.contactName == "" || spec.contactPhone == "" || spec.address == "" ||
|
||||||
|
spec.longitude == "" || spec.latitude == "" {
|
||||||
t.Fatalf("待支付 Mock 订单修复配置错误:%#v", spec)
|
t.Fatalf("待支付 Mock 订单修复配置错误:%#v", spec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
last := specs[len(specs)-1]
|
||||||
|
if last.contactName != "示例客户10" || last.address != "上海市客户路 10 号" ||
|
||||||
|
last.longitude != "121.5010" || last.latitude != "31.2010" {
|
||||||
|
t.Fatalf("第十组 Mock 快照格式错误:%#v", last)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestMockTrackPointSampleRequiredFields 验证演示轨迹点符合真实上报的必填字段和可读展示要求。
|
// TestMockTrackPointSampleRequiredFields 验证演示轨迹点符合真实上报的必填字段和可读展示要求。
|
||||||
|
|||||||
@@ -19,8 +19,11 @@
|
|||||||
3. 将 Mock 待支付订单从 `10` 修复为 `16`,已支付订单从 `35` 修复为 `18`。
|
3. 将 Mock 待支付订单从 `10` 修复为 `16`,已支付订单从 `35` 修复为 `18`。
|
||||||
4. 补齐 Mock 订单商品金额、应付金额及已支付订单的支付时间。
|
4. 补齐 Mock 订单商品金额、应付金额及已支付订单的支付时间。
|
||||||
5. 待支付订单的空支付时间明确显示为“未支付”,不再显示无语义短横线。
|
5. 待支付订单的空支付时间明确显示为“未支付”,不再显示无语义短横线。
|
||||||
6. 增加独立幂等修复命令,只更新固定十条商城 Mock 订单。
|
6. 补齐 Mock 订单的请求流水号、地址、经纬度、联系人、联系电话和备注快照。
|
||||||
7. 增加前端展示契约与后端种子测试,防止跨领域状态再次混入商城订单。
|
7. 修复第十组既有 Mock 用户名称、电话、地址及经纬度的错误值。
|
||||||
|
8. 待发货、未收货及无备注字段使用明确业务文案,不再统一显示短横线。
|
||||||
|
9. 增加独立幂等修复命令,只更新固定十条商城 Mock 订单及其用户、地址快照来源。
|
||||||
|
10. 增加前端展示契约与后端种子测试,防止跨领域状态再次混入商城订单。
|
||||||
|
|
||||||
## 行为变化
|
## 行为变化
|
||||||
|
|
||||||
|
|||||||
@@ -65,4 +65,4 @@ frontend/platform_admin/
|
|||||||
- v1.2:树形资源统一改为树形表格,明确展示名称、排序、状态、系统标识和操作,唯一标识降级为复制入口。
|
- v1.2:树形资源统一改为树形表格,明确展示名称、排序、状态、系统标识和操作,唯一标识降级为复制入口。
|
||||||
- v1.2.1:补齐 Arco 表格 `columns` 插槽,修复树形表格容器存在但列和数据不渲染的问题。
|
- v1.2.1:补齐 Arco 表格 `columns` 插槽,修复树形表格容器存在但列和数据不渲染的问题。
|
||||||
- v1.3:购物车列表的用户与商品关系列统一展示可读名称,UUID 降级为复制和排障信息。
|
- v1.3:购物车列表的用户与商品关系列统一展示可读名称,UUID 降级为复制和排障信息。
|
||||||
- v1.4:商城订单列表统一展示用户名称,未支付时间明确显示“未支付”;Mock 订单改用商城独立交易状态,并补齐金额与支付时间。
|
- v1.4:商城订单统一展示用户名称及空值业务文案;Mock 订单改用商城独立交易状态,并补齐金额、支付时间和下单快照。
|
||||||
|
|||||||
@@ -136,6 +136,20 @@ for (const invalidStatus of [10, 35]) {
|
|||||||
if (!orderDefinition.includes("f('paid_at', { emptyText: '未支付' })")) {
|
if (!orderDefinition.includes("f('paid_at', { emptyText: '未支付' })")) {
|
||||||
throw new Error('商城订单空支付时间必须明确显示为未支付');
|
throw new Error('商城订单空支付时间必须明确显示为未支付');
|
||||||
}
|
}
|
||||||
|
for (const displayContract of [
|
||||||
|
"f('request_no', { emptyText: '未记录' })",
|
||||||
|
"f('contact_name', { emptyText: '未记录' })",
|
||||||
|
"f('contact_phone', { emptyText: '未记录' })",
|
||||||
|
"f('logistics_no', { emptyText: '未发货' })",
|
||||||
|
"f('logistics_company', { emptyText: '未发货' })",
|
||||||
|
"f('shipped_at', { emptyText: '未发货' })",
|
||||||
|
"f('received_at', { emptyText: '未收货' })",
|
||||||
|
"f('remark', { emptyText: '无备注' })",
|
||||||
|
]) {
|
||||||
|
if (!orderDefinition.includes(displayContract)) {
|
||||||
|
throw new Error(`商城订单详情缺少空值业务文案:${displayContract}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (/title="ID"|data-index="id"/.test(listPage)) {
|
if (/title="ID"|data-index="id"/.test(listPage)) {
|
||||||
throw new Error('标准资源列表不得把数据库ID作为业务列展示');
|
throw new Error('标准资源列表不得把数据库ID作为业务列展示');
|
||||||
|
|||||||
@@ -706,7 +706,7 @@ export const resources: ResourceUiDefinition[] = [
|
|||||||
f('quantity'), f('selected'),
|
f('quantity'), f('selected'),
|
||||||
]),
|
]),
|
||||||
define('ec_order', '商城订单', 'readonly', [
|
define('ec_order', '商城订单', 'readonly', [
|
||||||
f('order_no'), f('request_no'), f('order_status', { type: 'select', options: [
|
f('order_no'), f('request_no', { emptyText: '未记录' }), f('order_status', { type: 'select', options: [
|
||||||
{ label: '待支付', value: 16 },
|
{ label: '待支付', value: 16 },
|
||||||
{ label: '已支付', value: 18 },
|
{ label: '已支付', value: 18 },
|
||||||
{ label: '已取消', value: 22 },
|
{ label: '已取消', value: 22 },
|
||||||
@@ -716,9 +716,12 @@ export const resources: ResourceUiDefinition[] = [
|
|||||||
displayRelationLabel: true, showIdentityCopy: true,
|
displayRelationLabel: true, showIdentityCopy: true,
|
||||||
}), relation('gas_basic_identity', '/gas_basic'),
|
}), relation('gas_basic_identity', '/gas_basic'),
|
||||||
relation('delivery_basic_identity', '/delivery_basic'), relation('user_address_identity', '/user_address'),
|
relation('delivery_basic_identity', '/delivery_basic'), relation('user_address_identity', '/user_address'),
|
||||||
f('contact_name'), f('contact_phone'), f('product_amount'), f('discount_amount'), f('payable_amount'),
|
f('contact_name', { emptyText: '未记录' }), f('contact_phone', { emptyText: '未记录' }),
|
||||||
f('total_amount'), f('paid_at', { emptyText: '未支付' }), f('logistics_no'), f('logistics_company'), f('logistics_status'),
|
f('product_amount'), f('discount_amount'), f('payable_amount'),
|
||||||
f('shipped_at'), f('received_at'), f('remark'),
|
f('total_amount'), f('paid_at', { emptyText: '未支付' }),
|
||||||
|
f('logistics_no', { emptyText: '未发货' }), f('logistics_company', { emptyText: '未发货' }),
|
||||||
|
f('logistics_status'), f('shipped_at', { emptyText: '未发货' }),
|
||||||
|
f('received_at', { emptyText: '未收货' }), f('remark', { emptyText: '无备注' }),
|
||||||
]),
|
]),
|
||||||
define('ec_order_item', '商城订单明细', 'readonly', [
|
define('ec_order_item', '商城订单明细', 'readonly', [
|
||||||
relation('ec_order_identity', '/ec_order'), relation('ec_product_identity', '/ec_product'),
|
relation('ec_order_identity', '/ec_order'), relation('ec_product_identity', '/ec_product'),
|
||||||
|
|||||||
Reference in New Issue
Block a user