优化
This commit is contained in:
+9
-3
@@ -2,13 +2,13 @@ package com.baiyue.firstleg.loading.coload;
|
||||
|
||||
import com.baiyue.common.security.AuthenticatedUser;
|
||||
import com.baiyue.firstleg.loading.coload.controller.PlatformColoadGroupController;
|
||||
import com.baiyue.firstleg.loading.coload.model.ColoadGroupModels.BatchQueryRequest;
|
||||
import com.baiyue.firstleg.loading.coload.model.ColoadGroupModels.CancelRequest;
|
||||
import com.baiyue.firstleg.loading.coload.model.ColoadGroupModels.CreateRequest;
|
||||
import com.baiyue.firstleg.loading.coload.port.ColoadGroupAssignmentPort;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
@@ -25,9 +25,15 @@ class ColoadGroupContractTest {
|
||||
assertEndpoint("create", "", AuthenticatedUser.class, String.class, CreateRequest.class);
|
||||
assertEndpoint("cancel", "/{groupId}/cancel", AuthenticatedUser.class, long.class,
|
||||
String.class, CancelRequest.class);
|
||||
assertEndpoint("batchQuery", "/batch-query", AuthenticatedUser.class, BatchQueryRequest.class);
|
||||
Method read = PlatformColoadGroupController.class.getDeclaredMethod(
|
||||
"byInboundCode", AuthenticatedUser.class, String.class);
|
||||
assertThat(read.getAnnotation(GetMapping.class).value())
|
||||
.containsExactly("/by-inbound-code/{inboundCode}");
|
||||
assertThat(read.getAnnotation(PreAuthorize.class).value())
|
||||
.isEqualTo("hasAuthority('platform:firstleg:smart-loading:list')");
|
||||
assertThat(Arrays.stream(PlatformColoadGroupController.class.getDeclaredMethods())
|
||||
.map(Method::getName)).doesNotContain("addMember", "removeMember", "updateMember");
|
||||
.map(Method::getName)).doesNotContain(
|
||||
"batchQuery", "addMember", "removeMember", "updateMember");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+10
-6
@@ -12,23 +12,25 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class ColoadGroupOpenApiContractTest {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
void publishesBoundedLongIdGroupContractWithoutNewPermission() throws Exception {
|
||||
void publishesInboundCodeBusinessSummaryWithoutExposingInternalGroupIdentity() throws Exception {
|
||||
String source = Files.readString(Path.of("src/main/resources/openapi/coload-groups-v1.yaml"));
|
||||
Map<String, Object> yaml = new Yaml().load(source);
|
||||
Map<String, Object> paths = (Map<String, Object>) yaml.get("paths");
|
||||
Map<String, Object> components = (Map<String, Object>) yaml.get("components");
|
||||
Map<String, Object> schemas = (Map<String, Object>) components.get("schemas");
|
||||
Map<String, Object> orderInfo = (Map<String, Object>) schemas.get("OrderColoadGroupInfo");
|
||||
Map<String, Object> orderInfoProperties = (Map<String, Object>) orderInfo.get("properties");
|
||||
Map<String, Object> summary = (Map<String, Object>) schemas.get("ColoadGroupBusinessSummary");
|
||||
Map<String, Object> summaryProperties = (Map<String, Object>) summary.get("properties");
|
||||
Map<String, Object> member = (Map<String, Object>) schemas.get("ColoadGroupBusinessMember");
|
||||
Map<String, Object> memberProperties = (Map<String, Object>) member.get("properties");
|
||||
|
||||
assertThat(paths).containsKeys(
|
||||
"/api/platform/v1/first-leg/coload-groups",
|
||||
"/api/platform/v1/first-leg/coload-groups/{groupId}/cancel",
|
||||
"/api/platform/v1/first-leg/coload-groups/batch-query");
|
||||
"/api/platform/v1/first-leg/coload-groups/by-inbound-code/{inboundCode}");
|
||||
assertThat(paths).doesNotContainKey("/api/platform/v1/first-leg/coload-groups/batch-query");
|
||||
assertThat(source)
|
||||
.contains("minItems: 2")
|
||||
.contains("maxItems: 100")
|
||||
.contains("maxItems: 200")
|
||||
.contains("uniqueItems: true")
|
||||
.contains("pattern: '^[1-9][0-9]*$'")
|
||||
.contains("enum: [ACTIVE, LOCKED, CONSUMED, CANCELLED]")
|
||||
@@ -36,12 +38,14 @@ class ColoadGroupOpenApiContractTest {
|
||||
.contains("expectedVersion")
|
||||
.contains("fullPackageCount")
|
||||
.contains("platform:firstleg:smart-loading:assign")
|
||||
.contains("platform:firstleg:smart-loading:list")
|
||||
.contains("全部 WAIT_SPLIT")
|
||||
.contains("国内仓和渠道一致")
|
||||
.doesNotContain("destinationType")
|
||||
.doesNotContain("destinationWarehouseId")
|
||||
.doesNotContain("destinationCode")
|
||||
.doesNotContain("platform:firstleg:coload");
|
||||
assertThat(orderInfoProperties).containsOnlyKeys("orderId", "group");
|
||||
assertThat(summaryProperties).containsOnlyKeys("status", "memberCount", "members");
|
||||
assertThat(memberProperties).containsOnlyKeys("inboundCode");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import com.baiyue.firstleg.loading.coload.persistence.ColoadGroupMapper;
|
||||
import com.baiyue.firstleg.loading.coload.persistence.ColoadPersistenceRows.GroupRow;
|
||||
import com.baiyue.firstleg.loading.coload.persistence.ColoadPersistenceRows.InboundCandidateRow;
|
||||
import com.baiyue.firstleg.loading.coload.persistence.ColoadPersistenceRows.MemberRow;
|
||||
import com.baiyue.firstleg.loading.coload.persistence.ColoadPersistenceRows.InboundGroupLookupRow;
|
||||
import com.baiyue.firstleg.loading.coload.persistence.ColoadPersistenceRows.MemberCodeRow;
|
||||
import com.baiyue.firstleg.loading.coload.service.ColoadGroupService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -33,6 +35,54 @@ class ColoadGroupServiceTest {
|
||||
@Resource
|
||||
private ColoadGroupService service;
|
||||
|
||||
@Test
|
||||
void readsCrossCustomerTwoMemberGroupByEitherInboundCodeWithoutInternalIdentifiers() {
|
||||
when(mapper.groupsByInboundCode("IN-A")).thenReturn(List.of(lookup(500L, "ACTIVE")));
|
||||
when(mapper.effectiveMemberCodes(500L)).thenReturn(List.of(code("IN-A"), code("IN-B")));
|
||||
|
||||
var result = service.queryByInboundCode(" IN-A ");
|
||||
|
||||
assertThat(result.status()).isEqualTo("ACTIVE");
|
||||
assertThat(result.memberCount()).isEqualTo(2);
|
||||
assertThat(result.members()).extracting("inboundCode").containsExactly("IN-A", "IN-B");
|
||||
verify(mapper).groupsByInboundCode("IN-A");
|
||||
}
|
||||
|
||||
@Test
|
||||
void returnsEveryEffectiveSplitFragmentAndEliminatesDuplicateInboundCodes() {
|
||||
when(mapper.groupsByInboundCode("MASTER-A-2")).thenReturn(List.of(lookup(500L, "LOCKED")));
|
||||
when(mapper.effectiveMemberCodes(500L)).thenReturn(List.of(
|
||||
code("MASTER-A-3"), code("MASTER-A-2"), code("MASTER-A-2"), code("ORDER-B")));
|
||||
|
||||
var result = service.queryByInboundCode("MASTER-A-2");
|
||||
|
||||
assertThat(result.status()).isEqualTo("LOCKED");
|
||||
assertThat(result.memberCount()).isEqualTo(3);
|
||||
assertThat(result.members()).extracting("inboundCode")
|
||||
.containsExactly("MASTER-A-2", "MASTER-A-3", "ORDER-B");
|
||||
}
|
||||
|
||||
@Test
|
||||
void preservesConsumedStatusWhileReadingClosedFrozenMemberships() {
|
||||
when(mapper.groupsByInboundCode("IN-A")).thenReturn(List.of(lookup(500L, "CONSUMED")));
|
||||
when(mapper.effectiveMemberCodes(500L)).thenReturn(List.of(code("IN-A"), code("IN-B")));
|
||||
|
||||
assertThat(service.queryByInboundCode("IN-A").status()).isEqualTo("CONSUMED");
|
||||
}
|
||||
|
||||
@Test
|
||||
void failsClosedWhenGroupHasNoEffectiveMemberOrLookupIsAmbiguous() {
|
||||
when(mapper.groupsByInboundCode("EMPTY")).thenReturn(List.of(lookup(500L, "ACTIVE")));
|
||||
when(mapper.effectiveMemberCodes(500L)).thenReturn(List.of());
|
||||
when(mapper.groupsByInboundCode("AMBIGUOUS")).thenReturn(List.of(
|
||||
lookup(500L, "ACTIVE"), lookup(501L, "LOCKED")));
|
||||
|
||||
assertThatThrownBy(() -> service.queryByInboundCode("EMPTY"))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("不存在有效入仓片段");
|
||||
assertThatThrownBy(() -> service.queryByInboundCode("AMBIGUOUS"))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("多个有效");
|
||||
}
|
||||
|
||||
@Test
|
||||
void createsCrossCustomerGroupAndFreezesAllAvailableFragmentsForEveryOrder() {
|
||||
when(mapper.lockCandidates(List.of(11L, 12L))).thenReturn(List.of(
|
||||
@@ -209,6 +259,19 @@ class ColoadGroupServiceTest {
|
||||
return value;
|
||||
}
|
||||
|
||||
private static InboundGroupLookupRow lookup(long groupId, String status) {
|
||||
InboundGroupLookupRow value = new InboundGroupLookupRow();
|
||||
value.setGroupId(groupId);
|
||||
value.setGroupStatus(status);
|
||||
return value;
|
||||
}
|
||||
|
||||
private static MemberCodeRow code(String inboundCode) {
|
||||
MemberCodeRow value = new MemberCodeRow();
|
||||
value.setInboundCode(inboundCode);
|
||||
return value;
|
||||
}
|
||||
|
||||
private static org.assertj.core.groups.Tuple tuple(Object... values) {
|
||||
return org.assertj.core.groups.Tuple.tuple(values);
|
||||
}
|
||||
|
||||
+19
@@ -56,6 +56,25 @@ class ColoadGroupSqlContractTest {
|
||||
.doesNotContain("destination_code");
|
||||
}
|
||||
|
||||
@Test
|
||||
void inboundCodeReadKeepsConsumedGroupsAndAllFrozenEffectiveFragments() throws Exception {
|
||||
Method lookup = ColoadGroupMapper.class.getDeclaredMethod("groupsByInboundCode", String.class);
|
||||
String lookupSql = String.join(" ", lookup.getAnnotation(Select.class).value());
|
||||
Method members = ColoadGroupMapper.class.getDeclaredMethod("effectiveMemberCodes", long.class);
|
||||
String memberSql = String.join(" ", members.getAnnotation(Select.class).value());
|
||||
|
||||
assertThat(lookupSql)
|
||||
.contains("requested.inbound_code=#{inboundCode}")
|
||||
.contains("requested.deleted=0")
|
||||
.contains("'ACTIVE','LOCKED','CONSUMED'")
|
||||
.doesNotContain("group_no", "order_id=#{");
|
||||
assertThat(memberSql)
|
||||
.contains("SELECT DISTINCT inbound.inbound_code inboundCode")
|
||||
.contains("member.group_id=#{groupId}")
|
||||
.contains("inbound.deleted=0")
|
||||
.doesNotContain("member.active_flag=1", "inbound_role", "split_status", "split_purpose");
|
||||
}
|
||||
|
||||
private static String tableDefinition(String source, String tableName) {
|
||||
int start = source.indexOf("CREATE TABLE IF NOT EXISTS " + tableName + " (");
|
||||
int end = source.indexOf(';', start);
|
||||
|
||||
Reference in New Issue
Block a user