暂存提交
This commit is contained in:
@@ -80,6 +80,7 @@ public class MerchantFirstLegOrderController {
|
||||
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "403", description = "Merchant scope required / 需要商户端权限")
|
||||
})
|
||||
@GetMapping
|
||||
@PreAuthorize("hasAuthority('merchant:order:list')")
|
||||
public ApiResponse<PageResult<OrderEntity>> page(@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@Valid OrderRequests.QueryRequest query) {
|
||||
return ApiResponse.success(service.page(OrderScopeGuard.merchant(user), query));
|
||||
@@ -92,6 +93,7 @@ public class MerchantFirstLegOrderController {
|
||||
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "404", description = "Order not found / 订单不存在")
|
||||
})
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("hasAuthority('merchant:order:view')")
|
||||
public ApiResponse<OrderDetailResponse> detail(
|
||||
@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@Parameter(description = "Order ID / 订单 ID", example = "190000000000000001", required = true) @PathVariable long id) {
|
||||
|
||||
@@ -47,6 +47,7 @@ public class PlatformFirstLegOrderController {
|
||||
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "403", description = "Platform scope required / 需要平台端权限")
|
||||
})
|
||||
@GetMapping
|
||||
@PreAuthorize("hasAuthority('platform:order:list')")
|
||||
public ApiResponse<PageResult<OrderEntity>> page(
|
||||
@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@Parameter(description = "Target tenant ID / 目标租户 ID", example = "10001", required = true) @RequestParam long tenantId,
|
||||
@@ -61,6 +62,7 @@ public class PlatformFirstLegOrderController {
|
||||
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "404", description = "Order not found in target tenant / 目标租户下订单不存在")
|
||||
})
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("hasAuthority('platform:order:list')")
|
||||
public ApiResponse<OrderDetailResponse> detail(
|
||||
@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@Parameter(description = "Target tenant ID / 目标租户 ID", example = "10001", required = true) @RequestParam long tenantId,
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.baiyue.order.dto.OrderDetailResponse;
|
||||
import com.baiyue.order.dto.OrderRequests;
|
||||
import com.baiyue.order.entity.*;
|
||||
import com.baiyue.order.repository.OrderRepository;
|
||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
@@ -14,10 +15,8 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@@ -33,7 +32,8 @@ public class OrderApplicationService {
|
||||
validatePrototypeFields(request);
|
||||
var snapshots = masterDataGuard.validate(tenantId, request);
|
||||
OrderEntity order = new OrderEntity();
|
||||
order.setTenantId(tenantId); order.setOrderNo(nextNo()); order.setStatus(OrderStatus.DRAFT);
|
||||
long orderId = IdWorker.getId();
|
||||
order.setId(orderId); order.setTenantId(tenantId); order.setOrderNo(nextNo(orderId)); order.setStatus(OrderStatus.DRAFT);
|
||||
apply(order, request, snapshots); order.setCreatedBy(userId); order.setUpdatedBy(userId);
|
||||
repository.insertOrder(order);
|
||||
saveChildren(tenantId, userId, order.getId(), request);
|
||||
@@ -182,8 +182,9 @@ public class OrderApplicationService {
|
||||
order.setShipmentId(request.shipmentId()); order.setReferenceId(request.referenceId());
|
||||
}
|
||||
private String formatAddress(com.baiyue.order.client.WarehouseClient.Detail detail) {
|
||||
if (detail.addresses() == null || detail.addresses().isEmpty()) return null;
|
||||
var a = detail.addresses().get(0);
|
||||
if (detail.addresses() == null) return null;
|
||||
var a = detail.addresses().stream().filter(java.util.Objects::nonNull).findFirst().orElse(null);
|
||||
if (a == null) return null;
|
||||
return java.util.stream.Stream.of(a.countryCode(), a.stateProvince(), a.city(), a.district(),
|
||||
a.addressLine1(), a.addressLine2(), a.postalCode())
|
||||
.filter(StringUtils::hasText).collect(Collectors.joining(" "));
|
||||
@@ -191,7 +192,7 @@ public class OrderApplicationService {
|
||||
private String formatReceivingTime(com.baiyue.order.client.WarehouseClient.Detail detail) {
|
||||
if (detail.capabilities() == null) return null;
|
||||
return detail.capabilities().stream()
|
||||
.filter(c -> "RECEIVING".equals(c.capabilityCode()) && Boolean.TRUE.equals(c.enabled()))
|
||||
.filter(c -> c != null && "RECEIVING".equals(c.capabilityCode()) && Boolean.TRUE.equals(c.enabled()))
|
||||
.map(c -> c.cutoffTime() == null ? "支持收货" : "每日 " + c.cutoffTime() + " 前收货")
|
||||
.findFirst().orElse(null);
|
||||
}
|
||||
@@ -241,8 +242,7 @@ public class OrderApplicationService {
|
||||
event.setPublishStatus("PENDING"); event.setRetryCount(0); event.setCreatedAt(LocalDateTime.now());
|
||||
repository.insertOutbox(event);
|
||||
}
|
||||
private String nextNo() {
|
||||
return "FL" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))
|
||||
+ ThreadLocalRandom.current().nextInt(100, 1000);
|
||||
private String nextNo(long orderId) {
|
||||
return "FL" + orderId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ import com.baiyue.order.dto.OrderRequests;
|
||||
import feign.FeignException;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
public class OrderMasterDataGuard {
|
||||
@@ -23,10 +26,10 @@ public class OrderMasterDataGuard {
|
||||
try {
|
||||
var partner=loadPartner(tenantId,request.customerId());
|
||||
var receiving=loadWarehouse(tenantId,request.receivingWarehouseId(),"收货仓库");
|
||||
if (receiving.addresses()==null || receiving.addresses().isEmpty())
|
||||
if (receiving.addresses()==null || receiving.addresses().stream().noneMatch(Objects::nonNull))
|
||||
throw new BizException(ResultCode.VALIDATION_FAILED,"收货仓库未配置地址");
|
||||
if (receiving.capabilities()==null || receiving.capabilities().stream().noneMatch(c ->
|
||||
"RECEIVING".equals(c.capabilityCode()) && Boolean.TRUE.equals(c.enabled())))
|
||||
c != null && "RECEIVING".equals(c.capabilityCode()) && Boolean.TRUE.equals(c.enabled())))
|
||||
throw new BizException(ResultCode.VALIDATION_FAILED,"仓库未启用收货能力");
|
||||
WarehouseClient.Detail destination=null;
|
||||
if (request.destinationWarehouseId()!=null) {
|
||||
@@ -57,6 +60,7 @@ public class OrderMasterDataGuard {
|
||||
var value=response.data();
|
||||
if (!Long.valueOf(tenantId).equals(value.tenantId()) || !"ACTIVE".equals(value.status()))
|
||||
throw new BizException(ResultCode.FORBIDDEN,"往来单位不属于当前企业或已停用");
|
||||
if (!StringUtils.hasText(value.partnerName())) throw unavailable("往来单位");
|
||||
return value;
|
||||
}
|
||||
private WarehouseClient.Detail loadWarehouse(long tenantId,long id,String name) {
|
||||
@@ -66,6 +70,9 @@ public class OrderMasterDataGuard {
|
||||
var value=response.data();
|
||||
if (!Long.valueOf(tenantId).equals(value.warehouse().tenantId()) || !"ACTIVE".equals(value.warehouse().status()))
|
||||
throw new BizException(ResultCode.FORBIDDEN,name+"不属于当前企业或已停用");
|
||||
if (!Long.valueOf(id).equals(value.warehouse().id()) || !StringUtils.hasText(value.warehouse().warehouseName())) {
|
||||
throw unavailable(name);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
private BizException unavailable(String name) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
SET NAMES utf8mb4;
|
||||
-- 订单服务独占数据库。其他服务只能通过 OpenAPI 或领域事件获取订单数据。
|
||||
|
||||
CREATE DATABASE IF NOT EXISTS baiyue_order
|
||||
DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
|
||||
USE baiyue_order;
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package com.baiyue.order.service;
|
||||
|
||||
import com.baiyue.common.core.api.ApiResponse;
|
||||
import com.baiyue.common.core.api.ResultCode;
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
import com.baiyue.order.client.PartnerClient;
|
||||
import com.baiyue.order.client.WarehouseClient;
|
||||
import com.baiyue.order.dto.OrderRequests;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
@@ -32,6 +34,31 @@ class OrderMasterDataGuardTest {
|
||||
assertThatThrownBy(() -> new OrderMasterDataGuard(warehouses,partners,"token").validate(10002,request(7L,8L)))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("服务暂时不可用");
|
||||
}
|
||||
@Test
|
||||
void 主数据响应含空元素时返回受控业务错误而不是空指针异常() {
|
||||
WarehouseClient warehouses=mock(WarehouseClient.class); PartnerClient partners=mock(PartnerClient.class);
|
||||
var partner=new PartnerClient.Partner(7L,10001L,"服务端客户名","ACTIVE");
|
||||
var wh=new WarehouseClient.Detail(new WarehouseClient.Warehouse(8L,10001L,"深圳仓","ACTIVE"),
|
||||
Collections.singletonList(null), Collections.singletonList(null));
|
||||
when(partners.active("token",10001,7)).thenReturn(ApiResponse.success(partner));
|
||||
when(warehouses.active("token",10001,8)).thenReturn(ApiResponse.success(wh));
|
||||
|
||||
assertThatThrownBy(() -> new OrderMasterDataGuard(warehouses,partners,"token").validate(10001,request(7L,8L)))
|
||||
.isInstanceOf(BizException.class)
|
||||
.extracting(exception -> ((BizException) exception).getResultCode())
|
||||
.isEqualTo(ResultCode.VALIDATION_FAILED);
|
||||
}
|
||||
@Test
|
||||
void 缺失快照名称的主数据响应按服务不可用处理() {
|
||||
WarehouseClient warehouses=mock(WarehouseClient.class); PartnerClient partners=mock(PartnerClient.class);
|
||||
when(partners.active("token",10001,7)).thenReturn(ApiResponse.success(new PartnerClient.Partner(7L,10001L,null,"ACTIVE")));
|
||||
|
||||
assertThatThrownBy(() -> new OrderMasterDataGuard(warehouses,partners,"token").validate(10001,request(7L,8L)))
|
||||
.isInstanceOf(BizException.class)
|
||||
.extracting(exception -> ((BizException) exception).getResultCode())
|
||||
.isEqualTo(ResultCode.SERVICE_UNAVAILABLE);
|
||||
verifyNoInteractions(warehouses);
|
||||
}
|
||||
private OrderRequests.SaveRequest request(Long partner,Long warehouse) {
|
||||
var party=new OrderRequests.Party("公司","联系人","13800138000",null,"CN",null,"深圳",null,"地址",null);
|
||||
var cargo=new OrderRequests.Cargo("货物",null,"CARTON",1,BigDecimal.ONE,BigDecimal.ONE,
|
||||
|
||||
Reference in New Issue
Block a user