88 lines
4.8 KiB
Java
88 lines
4.8 KiB
Java
package com.baiyue.firstleg.controller;
|
|
|
|
import com.baiyue.common.security.AuthenticatedUser;
|
|
import com.baiyue.firstleg.dto.MeasurementApprovalResponse;
|
|
import com.baiyue.firstleg.dto.MeasurementReviewRequest;
|
|
import com.baiyue.firstleg.service.InitialInboundPricingService;
|
|
import com.baiyue.firstleg.service.MeasurementReviewService;
|
|
import org.junit.jupiter.api.DisplayName;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.springframework.core.io.ClassPathResource;
|
|
import org.springframework.security.access.prepost.PreAuthorize;
|
|
import org.springframework.test.util.ReflectionTestUtils;
|
|
|
|
import java.lang.reflect.Method;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.Set;
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
import static org.mockito.Mockito.inOrder;
|
|
import static org.mockito.Mockito.mock;
|
|
import static org.mockito.Mockito.when;
|
|
|
|
@DisplayName("入库测量审核控制器契约")
|
|
class InboundMeasurementReviewContractTest {
|
|
@Test
|
|
@DisplayName("审核和历史接口声明独立按钮权限")
|
|
void shouldDeclareButtonPermissions() throws Exception {
|
|
assertAuthority("approve", "hasAuthority('firstleg:inbound:measurement-review')",
|
|
AuthenticatedUser.class, long.class, long.class, String.class, MeasurementReviewRequest.class);
|
|
assertAuthority("history", "hasAuthority('firstleg:inbound:measurement-review-history')",
|
|
AuthenticatedUser.class, long.class, long.class, long.class, long.class);
|
|
}
|
|
|
|
@Test
|
|
@DisplayName("测量审核不进入待客户确认,并声明幂等和字符串长ID")
|
|
void shouldDocumentReviewContract() throws Exception {
|
|
String openapi = new ClassPathResource("openapi/firstleg-v1.yaml")
|
|
.getContentAsString(StandardCharsets.UTF_8);
|
|
assertThat(openapi)
|
|
.contains("/api/platform/v1/inbounds/{inboundId}/measurements/approve:")
|
|
.contains("Idempotency-Key")
|
|
.contains("初算异常只返回非阻断提示")
|
|
.contains("标准头程审核通过后进入 WAIT_SPLIT")
|
|
.contains("一件代发进入 WAIT_PALLETIZE")
|
|
.contains("feeStatus=UNPRICED 且主流程仍成功")
|
|
.contains("name: inboundId")
|
|
.contains("schema: {type: string, pattern:")
|
|
.doesNotContain("/api/platform/v1/inbounds/{inboundId}/measurements/reject:")
|
|
.doesNotContain("/api/platform/v1/inbounds/{inboundId}/measurements/exception-release:");
|
|
// 约束仅针对测量审核;客户费用确认属于另一业务,允许独立存在。
|
|
int start = openapi.indexOf(" /api/platform/v1/inbounds/{inboundId}/measurements/approve:");
|
|
int end = openapi.indexOf("\n /", start + 1);
|
|
assertThat(openapi.substring(start, end < 0 ? openapi.length() : end)).doesNotContain("待客户确认");
|
|
}
|
|
|
|
@Test
|
|
@DisplayName("审核先提交待分柜,再执行不阻塞的初算")
|
|
void shouldApproveBeforeBestEffortInitialPricing() {
|
|
MeasurementReviewService review = mock(MeasurementReviewService.class);
|
|
InitialInboundPricingService initialPricing = mock(InitialInboundPricingService.class);
|
|
PlatformInboundMeasurementReviewController controller = new PlatformInboundMeasurementReviewController();
|
|
ReflectionTestUtils.setField(controller, "service", review);
|
|
ReflectionTestUtils.setField(controller, "initialPricing", initialPricing);
|
|
AuthenticatedUser user = new AuthenticatedUser(9L, 0L, 0L, null,
|
|
"客服", "PLATFORM", "WEB", Set.of("firstleg:inbound:measurement-review"));
|
|
MeasurementReviewRequest request = new MeasurementReviewRequest(30L, 4, "通过");
|
|
var result = new MeasurementApprovalResponse(88L, 30L, "WAIT_SPLIT", "UNPRICED",
|
|
false, "待人工维护费用", null);
|
|
when(initialPricing.tryCalculate(10001L, 9L, 88L, 30L, 5)).thenReturn(result);
|
|
|
|
var first = controller.approve(user, 10001L, 88L, "approve-1", request);
|
|
var replay = controller.approve(user, 10001L, 88L, "approve-1", request);
|
|
|
|
assertThat(first.data()).isSameAs(result);
|
|
assertThat(replay.data()).isSameAs(result);
|
|
var ordered = inOrder(review, initialPricing);
|
|
ordered.verify(review).approve(10001L, 9L, "客服", 88L, "approve-1", request);
|
|
ordered.verify(initialPricing).tryCalculate(10001L, 9L, 88L, 30L, 5);
|
|
ordered.verify(review).approve(10001L, 9L, "客服", 88L, "approve-1", request);
|
|
ordered.verify(initialPricing).tryCalculate(10001L, 9L, 88L, 30L, 5);
|
|
}
|
|
|
|
private void assertAuthority(String name, String expression, Class<?>... types) throws Exception {
|
|
Method method = PlatformInboundMeasurementReviewController.class.getDeclaredMethod(name, types);
|
|
assertThat(method.getAnnotation(PreAuthorize.class).value()).isEqualTo(expression);
|
|
}
|
|
}
|