fix: complete order measurement downstream flow
This commit is contained in:
@@ -5,6 +5,8 @@ import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
@@ -36,10 +38,21 @@ public interface OrderCargoClient {
|
||||
@RequestHeader("X-Internal-Service-Token") String token,
|
||||
@PathVariable long tenantId, @PathVariable long orderId);
|
||||
|
||||
@PutMapping("/{tenantId}/{orderId}/remarks")
|
||||
ApiResponse<RemarksUpdateResponse> updateRemarks(
|
||||
@RequestHeader("X-Internal-Service-Token") String token,
|
||||
@PathVariable long tenantId, @PathVariable long orderId,
|
||||
@RequestBody RemarksUpdateRequest request);
|
||||
|
||||
record MeasurementDeclarationSnapshot(
|
||||
String referenceId, BigDecimal originalGrossWeightKg,
|
||||
BigDecimal originalVolumeCbm, String defaultActualGoodsName) {}
|
||||
|
||||
record RemarksUpdateRequest(String internalRemark, String warehouseRemark,
|
||||
String customerServiceRemark, long operatorId) {}
|
||||
record RemarksUpdateResponse(int version, String customerRemark, String internalRemark,
|
||||
String warehouseRemark, String customerServiceRemark) {}
|
||||
|
||||
record CargoBinding(Long cargoId, Long orderId, Integer itemNo, String cargoName,
|
||||
Integer originalPackageCount, BigDecimal originalGrossWeightKg,
|
||||
BigDecimal originalVolumeCbm, String skuNo, String cargoNameEn,
|
||||
|
||||
+12
@@ -12,7 +12,9 @@ import com.baiyue.firstleg.service.InboundOrderCreationService;
|
||||
import com.baiyue.firstleg.service.InboundCartonLabelService;
|
||||
import com.baiyue.firstleg.service.UnifiedInboundQueryService;
|
||||
import com.baiyue.firstleg.service.OrderDeclarationSyncService;
|
||||
import com.baiyue.firstleg.service.OrderRemarksSyncService;
|
||||
import com.baiyue.firstleg.dto.OrderDeclarationSync;
|
||||
import com.baiyue.firstleg.dto.OrderRemarksSync;
|
||||
import com.baiyue.firstleg.dto.UnifiedInboundDetail;
|
||||
import com.baiyue.firstleg.dto.UnifiedInboundQuery;
|
||||
import com.baiyue.firstleg.dto.UnifiedInboundRequest;
|
||||
@@ -43,6 +45,8 @@ public class InternalInboundOrderController {
|
||||
private UnifiedInboundQueryService unifiedQueryService;
|
||||
@Resource
|
||||
private OrderDeclarationSyncService declarationSync;
|
||||
@Resource
|
||||
private OrderRemarksSyncService remarksSync;
|
||||
@Value("${baiyue.security.internal-service-token}")
|
||||
private String internalToken;
|
||||
private byte[] expectedToken;
|
||||
@@ -127,6 +131,14 @@ public class InternalInboundOrderController {
|
||||
return ApiResponse.success(null);
|
||||
}
|
||||
|
||||
@PostMapping("/order-remarks-updated")
|
||||
public ApiResponse<Integer> updateOrderRemarks(
|
||||
@RequestHeader(value = "X-Internal-Service-Token", required = false) String token,
|
||||
@Valid @RequestBody OrderRemarksSync.Command command) {
|
||||
requireToken(token);
|
||||
return ApiResponse.success(remarksSync.sync(command));
|
||||
}
|
||||
|
||||
@PostMapping("/unified-orders/query")
|
||||
public ApiResponse<PageResult<UnifiedInboundSummary>> unifiedPage(
|
||||
@RequestHeader(value = "X-Internal-Service-Token", required = false) String token,
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.baiyue.firstleg.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Positive;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
public final class OrderRemarksSync {
|
||||
private OrderRemarksSync() {
|
||||
}
|
||||
|
||||
public record Command(
|
||||
@Positive long tenantId,
|
||||
@Positive long orderId,
|
||||
@Size(max = 1000) String customerRemark,
|
||||
@Size(max = 1000) String internalRemark,
|
||||
@Size(max = 1000) String warehouseRemark,
|
||||
@Size(max = 1000) String customerServiceRemark,
|
||||
@NotNull @Positive Long operatorId,
|
||||
@Size(max = 128) String operatorName
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
package com.baiyue.firstleg.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baiyue.firstleg.entity.LoadingPlanItemEntity; import org.apache.ibatis.annotations.*;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baiyue.firstleg.entity.LoadingPlanItemEntity; import org.apache.ibatis.annotations.*; import java.util.List;
|
||||
@Mapper public interface LoadingPlanItemMapper extends BaseMapper<LoadingPlanItemEntity> {
|
||||
@Update("""
|
||||
UPDATE fl_loading_plan_item SET deleted=1,removed_by=#{operatorId},removed_by_name=#{operatorName},
|
||||
@@ -30,4 +30,69 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baiyue.firstl
|
||||
@Param("customerServiceRemark") String customerServiceRemark,
|
||||
@Param("operatorId") long operatorId,
|
||||
@Param("operatorName") String operatorName);
|
||||
|
||||
@Select("""
|
||||
SELECT DISTINCT i.loading_plan_id
|
||||
FROM fl_loading_plan_item i
|
||||
JOIN fl_loading_plan p ON p.id=i.loading_plan_id AND p.plan_status IN ('EDITING','LOADING')
|
||||
WHERE i.account_id=#{tenantId} AND i.order_id=#{orderId} AND i.deleted=0 AND i.frozen_at IS NULL
|
||||
AND (#{excludedItemId} IS NULL OR i.id<>#{excludedItemId})
|
||||
AND NOT (i.customer_remark <=> #{customerRemark}
|
||||
AND i.internal_remark <=> #{internalRemark}
|
||||
AND i.warehouse_remark <=> #{warehouseRemark}
|
||||
AND i.customer_service_remark <=> #{customerServiceRemark})
|
||||
""")
|
||||
List<Long> findMutablePlanIdsWithDifferentRemarks(@Param("tenantId") long tenantId,
|
||||
@Param("orderId") long orderId,
|
||||
@Param("customerRemark") String customerRemark,
|
||||
@Param("internalRemark") String internalRemark,
|
||||
@Param("warehouseRemark") String warehouseRemark,
|
||||
@Param("customerServiceRemark") String customerServiceRemark,
|
||||
@Param("excludedItemId") Long excludedItemId);
|
||||
|
||||
@Update("""
|
||||
UPDATE fl_loading_plan_item i
|
||||
JOIN fl_loading_plan p ON p.id=i.loading_plan_id AND p.plan_status IN ('EDITING','LOADING')
|
||||
SET i.customer_remark=#{customerRemark}, i.internal_remark=#{internalRemark}, i.warehouse_remark=#{warehouseRemark},
|
||||
i.customer_service_remark=#{customerServiceRemark}, i.updated_by=#{operatorId},
|
||||
i.updated_by_name=#{operatorName}, i.updated_at=CURRENT_TIMESTAMP(3), i.version=i.version+1
|
||||
WHERE i.account_id=#{tenantId} AND i.order_id=#{orderId} AND i.deleted=0 AND i.frozen_at IS NULL
|
||||
AND (#{excludedItemId} IS NULL OR i.id<>#{excludedItemId})
|
||||
AND NOT (i.customer_remark <=> #{customerRemark}
|
||||
AND i.internal_remark <=> #{internalRemark}
|
||||
AND i.warehouse_remark <=> #{warehouseRemark}
|
||||
AND i.customer_service_remark <=> #{customerServiceRemark})
|
||||
""")
|
||||
int syncMutableOrderRemarks(@Param("tenantId") long tenantId, @Param("orderId") long orderId,
|
||||
@Param("customerRemark") String customerRemark,
|
||||
@Param("internalRemark") String internalRemark,
|
||||
@Param("warehouseRemark") String warehouseRemark,
|
||||
@Param("customerServiceRemark") String customerServiceRemark,
|
||||
@Param("operatorId") long operatorId,
|
||||
@Param("operatorName") String operatorName,
|
||||
@Param("excludedItemId") Long excludedItemId);
|
||||
|
||||
@Select("""
|
||||
SELECT DISTINCT i.loading_plan_id
|
||||
FROM fl_loading_plan_item i
|
||||
JOIN fl_loading_plan p ON p.id=i.loading_plan_id AND p.plan_status IN ('EDITING','LOADING')
|
||||
WHERE i.account_id=#{tenantId} AND i.order_id=#{orderId} AND i.deleted=0 AND i.frozen_at IS NULL
|
||||
AND NOT (i.customer_remark <=> #{customerRemark})
|
||||
""")
|
||||
List<Long> findMutablePlanIdsWithDifferentCustomerRemark(@Param("tenantId") long tenantId,
|
||||
@Param("orderId") long orderId,
|
||||
@Param("customerRemark") String customerRemark);
|
||||
|
||||
@Update("""
|
||||
UPDATE fl_loading_plan_item i
|
||||
JOIN fl_loading_plan p ON p.id=i.loading_plan_id AND p.plan_status IN ('EDITING','LOADING')
|
||||
SET i.customer_remark=#{customerRemark}, i.updated_by=#{operatorId}, i.updated_by_name=#{operatorName},
|
||||
i.updated_at=CURRENT_TIMESTAMP(3), i.version=i.version+1
|
||||
WHERE i.account_id=#{tenantId} AND i.order_id=#{orderId} AND i.deleted=0 AND i.frozen_at IS NULL
|
||||
AND NOT (i.customer_remark <=> #{customerRemark})
|
||||
""")
|
||||
int syncMutableOrderCustomerRemark(@Param("tenantId") long tenantId, @Param("orderId") long orderId,
|
||||
@Param("customerRemark") String customerRemark,
|
||||
@Param("operatorId") long operatorId,
|
||||
@Param("operatorName") String operatorName);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package com.baiyue.firstleg.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baiyue.firstleg.entity.LoadingPlanEntity; import org.apache.ibatis.annotations.*;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baiyue.firstleg.entity.LoadingPlanEntity; import org.apache.ibatis.annotations.*; import java.util.List;
|
||||
@Mapper public interface LoadingPlanMapper extends BaseMapper<LoadingPlanEntity> {
|
||||
@Update("""
|
||||
UPDATE fl_loading_plan SET updated_by=#{operatorId},updated_by_name=#{operatorName},
|
||||
@@ -13,4 +13,16 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baiyue.firstl
|
||||
WHERE id=#{planId} AND plan_status='EDITING'
|
||||
""")
|
||||
int startPicking(@Param("planId") long planId,@Param("operatorId") long operatorId,@Param("operatorName") String operatorName);
|
||||
|
||||
@Update("""
|
||||
<script>
|
||||
UPDATE fl_loading_plan SET updated_by=#{operatorId},updated_by_name=#{operatorName},
|
||||
updated_at=CURRENT_TIMESTAMP(3),version=version+1
|
||||
WHERE plan_status IN ('EDITING','LOADING') AND id IN
|
||||
<foreach collection="planIds" item="planId" open="(" separator="," close=")">#{planId}</foreach>
|
||||
</script>
|
||||
""")
|
||||
int touchForOrderRemarks(@Param("planIds") List<Long> planIds,
|
||||
@Param("operatorId") long operatorId,
|
||||
@Param("operatorName") String operatorName);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.Objects;
|
||||
public class OrderDeclarationSyncService {
|
||||
@Resource private OrderDeclarationSyncMapper mapper;
|
||||
@Resource private ObjectMapper json;
|
||||
@Resource private OrderRemarksSyncService remarksSync;
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public ChannelChangeValidationResponse validateChannelChange(ChannelChangeValidationRequest request) {
|
||||
@@ -86,6 +87,8 @@ public class OrderDeclarationSyncService {
|
||||
normalizeChannel(event.channelCode()), event.channelName(), event.operatorId()) != 1) {
|
||||
throw conflict("Firstleg 入库申报快照已发生变化");
|
||||
}
|
||||
remarksSync.syncCustomerRemark(event.tenantId(), event.orderId(), event.customerRemark(),
|
||||
event.operatorId(), "order-declaration");
|
||||
}
|
||||
|
||||
private void recordEvent(UpdatedEvent event, String hash) {
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.baiyue.firstleg.service;
|
||||
|
||||
import com.baiyue.firstleg.dto.OrderRemarksSync;
|
||||
import com.baiyue.firstleg.mapper.LoadingPlanItemMapper;
|
||||
import com.baiyue.firstleg.mapper.LoadingPlanMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class OrderRemarksSyncService {
|
||||
@Resource private LoadingPlanItemMapper items;
|
||||
@Resource private LoadingPlanMapper plans;
|
||||
|
||||
@Transactional
|
||||
public int sync(OrderRemarksSync.Command command) {
|
||||
return sync(command, null, null);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public int sync(OrderRemarksSync.Command command, Long alreadyTouchedPlanId) {
|
||||
return sync(command, alreadyTouchedPlanId, null);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public int sync(OrderRemarksSync.Command command, Long alreadyTouchedPlanId, Long excludedItemId) {
|
||||
List<Long> affectedPlanIds = items.findMutablePlanIdsWithDifferentRemarks(
|
||||
command.tenantId(), command.orderId(), command.customerRemark(), command.internalRemark(), command.warehouseRemark(),
|
||||
command.customerServiceRemark(), excludedItemId);
|
||||
if (affectedPlanIds.isEmpty()) return 0;
|
||||
int updated = items.syncMutableOrderRemarks(command.tenantId(), command.orderId(),
|
||||
command.customerRemark(), command.internalRemark(), command.warehouseRemark(), command.customerServiceRemark(),
|
||||
command.operatorId(), command.operatorName(), excludedItemId);
|
||||
if (updated > 0) {
|
||||
List<Long> plansToTouch = affectedPlanIds.stream()
|
||||
.filter(planId -> !planId.equals(alreadyTouchedPlanId)).toList();
|
||||
if (!plansToTouch.isEmpty()) {
|
||||
plans.touchForOrderRemarks(plansToTouch, command.operatorId(), command.operatorName());
|
||||
}
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public int syncCustomerRemark(long tenantId, long orderId, String customerRemark,
|
||||
long operatorId, String operatorName) {
|
||||
List<Long> affectedPlanIds = items.findMutablePlanIdsWithDifferentCustomerRemark(
|
||||
tenantId, orderId, customerRemark);
|
||||
if (affectedPlanIds.isEmpty()) return 0;
|
||||
int updated = items.syncMutableOrderCustomerRemark(
|
||||
tenantId, orderId, customerRemark, operatorId, operatorName);
|
||||
if (updated > 0) plans.touchForOrderRemarks(affectedPlanIds, operatorId, operatorName);
|
||||
return updated;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import com.baiyue.common.core.api.PageResult;
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
import com.baiyue.common.audit.BusinessAudit;
|
||||
import com.baiyue.firstleg.dto.SmartLoadingDtos.*;
|
||||
import com.baiyue.firstleg.dto.OrderRemarksSync;
|
||||
import com.baiyue.firstleg.domain.SmartLoadingChannelGroupCatalog;
|
||||
import com.baiyue.firstleg.client.OrderCargoClient;
|
||||
import com.baiyue.firstleg.client.PendingReviewOrderClient;
|
||||
@@ -56,6 +57,7 @@ public class SmartLoadingService {
|
||||
@Resource private FbaPricingService fbaPricingService;
|
||||
@Resource private PriceBookQueryUseCase priceBooks;
|
||||
@Resource private FirstlegDocumentNumberGenerator documentNumbers;
|
||||
@Resource private OrderRemarksSyncService orderRemarksSync;
|
||||
@Resource private ObjectMapper objectMapper;
|
||||
@Value("${baiyue.security.internal-service-token:}") private String internalToken;
|
||||
public SmartLoadingService() { }
|
||||
@@ -1099,6 +1101,9 @@ public class SmartLoadingService {
|
||||
LoadingPlanEntity plan = editing(planId, request.expectedPlanVersion(), operatorId, operatorName);
|
||||
LoadingPlanItemEntity item = repository.item(planId, itemId);
|
||||
if (item == null) throw new BizException(ResultCode.NOT_FOUND, "装柜明细不存在");
|
||||
if (item.getVersion() != request.expectedItemVersion()) {
|
||||
throw conflict("装柜计划或明细已被其他人修改,请刷新后重试");
|
||||
}
|
||||
if (Objects.equals(item.getInternalRemark(), internalRemark)
|
||||
&& Objects.equals(item.getWarehouseRemark(), warehouseRemark)
|
||||
&& Objects.equals(item.getCustomerServiceRemark(), customerServiceRemark)) {
|
||||
@@ -1109,16 +1114,30 @@ public class SmartLoadingService {
|
||||
"version", item.getVersion()));
|
||||
try {
|
||||
touch(plan, operatorId, operatorName);
|
||||
ApiResponse<OrderCargoClient.RemarksUpdateResponse> response = orderCargoClient.updateRemarks(
|
||||
internalToken, item.getAccountId(), item.getOrderId(),
|
||||
new OrderCargoClient.RemarksUpdateRequest(internalRemark, warehouseRemark,
|
||||
customerServiceRemark, operatorId));
|
||||
if (response == null || !response.successful() || response.data() == null) {
|
||||
throw new BizException(ResultCode.SERVICE_UNAVAILABLE,
|
||||
response == null ? "订单备注服务暂不可用" : response.message());
|
||||
}
|
||||
if (repository.updateRemarks(planId, itemId, request.expectedPlanVersion() + 1,
|
||||
request.expectedItemVersion(), internalRemark, warehouseRemark, customerServiceRemark,
|
||||
operatorId, operatorName) != 1) {
|
||||
request.expectedItemVersion(), response.data().internalRemark(), response.data().warehouseRemark(),
|
||||
response.data().customerServiceRemark(), operatorId, operatorName) != 1) {
|
||||
throw conflict("装柜计划或明细已被其他人修改,请刷新后重试");
|
||||
}
|
||||
orderRemarksSync.sync(new OrderRemarksSync.Command(item.getAccountId(), item.getOrderId(),
|
||||
response.data().customerRemark(),
|
||||
response.data().internalRemark(), response.data().warehouseRemark(),
|
||||
response.data().customerServiceRemark(), operatorId, operatorName), planId, itemId);
|
||||
} catch (DataAccessException exception) {
|
||||
if (hasSqlState(exception, "45000")) {
|
||||
throw conflict("装柜计划或明细状态已变化,备注未保存,请刷新后重试");
|
||||
}
|
||||
throw exception;
|
||||
} catch (FeignException exception) {
|
||||
throw unavailable();
|
||||
}
|
||||
history(planId, itemId, "REMARKS", plan.getPlanStatus(), plan.getPlanStatus(), operation,
|
||||
before, json(values("internalRemark", internalRemark, "warehouseRemark", warehouseRemark,
|
||||
|
||||
Reference in New Issue
Block a user