优化
This commit is contained in:
@@ -39,7 +39,12 @@ public final class OrderSplitDtos {
|
||||
) {}
|
||||
|
||||
public record Child(Long orderId, String orderNo, Integer splitSequence,
|
||||
String splitRole, Integer packageCount) {}
|
||||
String splitRole, Integer packageCount, Long sourceOrderId,
|
||||
Long loadingPlanId, Long containerBookingId) {
|
||||
public Child(Long orderId, String orderNo, Integer splitSequence, String splitRole, Integer packageCount) {
|
||||
this(orderId, orderNo, splitSequence, splitRole, packageCount, null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
public record Tree(Long parentOrderId, String parentOrderNo, Integer parentVersion,
|
||||
List<Child> children, Integer allocatedPackageCount,
|
||||
|
||||
@@ -15,6 +15,7 @@ public class OrderFulfillmentSplitEntity {
|
||||
@TableId(type = IdType.ASSIGN_ID) private Long id;
|
||||
private Long tenantId;
|
||||
private Long parentOrderId;
|
||||
private Long sourceOrderId;
|
||||
private Long childOrderId;
|
||||
private Long loadingPlanId;
|
||||
private Long containerBookingId;
|
||||
|
||||
@@ -36,6 +36,8 @@ public class OrderFulfillmentSplitService {
|
||||
return response(req, splits.lockOrder(req.tenantId(), req.parentOrderId()), replay);
|
||||
}
|
||||
OrderEntity parent = splits.lockOrder(req.tenantId(), req.parentOrderId());
|
||||
replay = splits.findByIdempotency(req.tenantId(), req.parentOrderId(), req.idempotencyKey());
|
||||
if (!replay.isEmpty()) return response(req, parent, replay);
|
||||
if (parent == null) throw new BizException(ResultCode.NOT_FOUND, "父订单不存在或不属于该客户");
|
||||
if (!req.parentOrderId().equals(req.sourceOrderId()) && !isDirectChild(req.sourceOrderId(), parent))
|
||||
throw new BizException(ResultCode.CONFLICT, "来源订单必须是父订单或其直接子订单");
|
||||
@@ -67,7 +69,7 @@ public class OrderFulfillmentSplitService {
|
||||
List<OrderFulfillmentSplitEntity> rows = splits.findByParent(tenantId, parentId);
|
||||
Map<Long,OrderEntity> children = new HashMap<>();
|
||||
for (OrderFulfillmentSplitEntity row: rows) { OrderEntity child=orders.selectById(row.getChildOrderId()); if(child!=null&&tenantId==child.getTenantId()) children.put(child.getId(),child); }
|
||||
List<OrderSplitDtos.Child> result = rows.stream().map(r -> { OrderEntity c=children.get(r.getChildOrderId()); return new OrderSplitDtos.Child(r.getChildOrderId(), c==null?null:c.getOrderNo(), c==null?null:c.getSplitSequence(), r.getSplitRole(), "LOADED".equals(r.getSplitRole())?r.getLoadedPackageCount():r.getRemainingPackageCount()); }).toList();
|
||||
List<OrderSplitDtos.Child> result = rows.stream().map(r -> { OrderEntity c=children.get(r.getChildOrderId()); return new OrderSplitDtos.Child(r.getChildOrderId(), c==null?null:c.getOrderNo(), c==null?null:c.getSplitSequence(), r.getSplitRole(), "LOADED".equals(r.getSplitRole())?r.getLoadedPackageCount():r.getRemainingPackageCount(), r.getSourceOrderId(), r.getLoadingPlanId(), r.getContainerBookingId()); }).toList();
|
||||
int allocated = rows.stream().filter(r -> "LOADED".equals(r.getSplitRole())).mapToInt(OrderFulfillmentSplitEntity::getLoadedPackageCount).sum();
|
||||
return new OrderSplitDtos.Tree(parent.getId(), parent.getOrderNo(), parent.getVersion(), result, allocated, Math.max(0, rows.stream().mapToInt(OrderFulfillmentSplitEntity::getSourcePackageCount).findFirst().orElse(0)-allocated));
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ CREATE TABLE IF NOT EXISTS ord_order_fulfillment_split (
|
||||
id BIGINT UNSIGNED NOT NULL,
|
||||
tenant_id BIGINT UNSIGNED NOT NULL,
|
||||
parent_order_id BIGINT UNSIGNED NOT NULL,
|
||||
source_order_id BIGINT UNSIGNED NOT NULL,
|
||||
child_order_id BIGINT UNSIGNED NOT NULL,
|
||||
split_role VARCHAR(12) NOT NULL COMMENT 'LOADED或REMAINDER',
|
||||
loading_plan_id BIGINT UNSIGNED NULL,
|
||||
@@ -74,6 +75,7 @@ CREATE TABLE IF NOT EXISTS ord_order_fulfillment_split (
|
||||
UNIQUE KEY uk_order_split_idempotency (tenant_id,parent_order_id,idempotency_key,split_role),
|
||||
UNIQUE KEY uk_order_split_child (tenant_id,child_order_id),
|
||||
KEY idx_order_split_parent (tenant_id,parent_order_id,created_at,id),
|
||||
KEY idx_order_split_source (tenant_id,source_order_id,split_role),
|
||||
KEY idx_order_split_container (tenant_id,container_booking_id,created_at,id),
|
||||
CONSTRAINT fk_order_split_parent FOREIGN KEY(parent_order_id) REFERENCES ord_order(id),
|
||||
CONSTRAINT fk_order_split_child FOREIGN KEY(child_order_id) REFERENCES ord_order(id),
|
||||
@@ -114,6 +116,7 @@ END$$
|
||||
DELIMITER ;
|
||||
|
||||
CALL phase3_order_add_column('ord_order_fulfillment_split','split_role',"VARCHAR(12) NOT NULL DEFAULT 'LOADED' COMMENT 'LOADED或REMAINDER'");
|
||||
CALL phase3_order_add_column('ord_order_fulfillment_split','source_order_id','BIGINT UNSIGNED NULL COMMENT ''实际被消费的来源订单ID''');
|
||||
CALL phase3_order_add_column('ord_order_fulfillment_split','request_hash',"CHAR(64) NULL COMMENT '请求内容SHA-256;存量记录允许为空'");
|
||||
|
||||
DROP PROCEDURE IF EXISTS phase3_order_drop_split_index;
|
||||
|
||||
@@ -228,6 +228,46 @@ paths:
|
||||
responses:
|
||||
'200': {description: 成功或业务失败,按响应体 code 判断}
|
||||
'403': {description: 需要 platform:order:edit 权限}
|
||||
/internal/order/v1/fulfillment-splits:
|
||||
post:
|
||||
summary: 创建父订单装柜拆分(Firstleg 内部)
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/InternalToken'
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: '#/components/schemas/FulfillmentSplitCreateRequest' }
|
||||
responses:
|
||||
'200': { description: 成功, content: { application/json: { schema: { $ref: '#/components/schemas/FulfillmentSplitResponse' } } } }
|
||||
'409': { description: 数量或版本/幂等冲突 }
|
||||
|
||||
/internal/order/v1/fulfillment-splits/{tenantId}/{parentOrderId}:
|
||||
get:
|
||||
summary: 查询父子订单柜次树(Firstleg 内部)
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/InternalToken'
|
||||
- { name: tenantId, in: path, required: true, schema: { type: integer, format: int64 } }
|
||||
- { name: parentOrderId, in: path, required: true, schema: { type: integer, format: int64 } }
|
||||
responses:
|
||||
'200': { description: 成功 }
|
||||
'403': { description: 内部凭证无效 }
|
||||
|
||||
/api/platform/v1/orders/{orderId}/fulfillment-tree:
|
||||
get:
|
||||
summary: 查询父子订单与柜次数量摘要
|
||||
parameters:
|
||||
- { name: orderId, in: path, required: true, schema: { type: integer, format: int64 } }
|
||||
- { name: tenantId, in: query, required: true, schema: { type: integer, format: int64 } }
|
||||
responses: { '200': { description: 成功 }, '403': { description: 无权限 } }
|
||||
|
||||
/api/merchant/v1/orders/{orderId}/fulfillment-tree:
|
||||
get:
|
||||
summary: 查询我的父子订单与柜次数量摘要
|
||||
parameters:
|
||||
- { name: orderId, in: path, required: true, schema: { type: integer, format: int64 } }
|
||||
responses: { '200': { description: 成功 }, '403': { description: 无权限 } }
|
||||
|
||||
components:
|
||||
securitySchemes:
|
||||
bearerAuth:
|
||||
|
||||
Reference in New Issue
Block a user