This commit is contained in:
2026-08-26 14:48:43 +08:00
parent 0f4524c795
commit bf960f10d1
22 changed files with 237 additions and 40 deletions
@@ -71,6 +71,9 @@ public final class MasterDataQueries {
@NotBlank @Size(max = 128) String partnerName,
@Schema(description = "单值单位类型", allowableValues = {"CARRIER", "SHIPPER", "CONSIGNEE"})
@Pattern(regexp = "^(CARRIER|SHIPPER|CONSIGNEE)$") String partnerType,
@Schema(description = "船司标准编码;包含 CARRIER 类型时必填,其他类型必须为空",
allowableValues = {"MATSON", "SML", "ZIM", "COSCO", "EMC", "HEDE", "OTHER"})
@Pattern(regexp = "^(MATSON|SML|ZIM|COSCO|EMC|HEDE|OTHER)$") String carrierCode,
@Schema(description = "联系人", example = "张三")
@NotBlank @Size(max = 64) String contactName,
@Schema(description = "联系电话", example = "13800138000")
@@ -28,6 +28,9 @@ public class PartnerEntity extends BaseEntity {
private String partnerName;
@Schema(description = "类型", example = "CARRIER", allowableValues = {"CARRIER", "SHIPPER", "CONSIGNEE"})
private String partnerType;
@Schema(description = "船司标准编码;船公司必填,其他类型必须为空", example = "MATSON",
allowableValues = {"MATSON", "SML", "ZIM", "COSCO", "EMC", "HEDE", "OTHER"})
private String carrierCode;
@TableField(exist = false)
@Schema(description = "单位类型集合", allowableValues = {"CARRIER", "SHIPPER", "CONSIGNEE"})
private List<String> types;
@@ -35,10 +35,12 @@ public class PartnerImportService {
private static final String TEMPLATE_VERSION = "1";
private static final Set<String> ALLOWED_TYPES = Set.of(
"CARRIER", "SHIPPER", "CONSIGNEE");
private static final Set<String> ALLOWED_CARRIER_CODES = Set.of(
"MATSON", "SML", "ZIM", "COSCO", "EMC", "HEDE", "OTHER");
private static final Pattern EMAIL = Pattern.compile("^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$");
private static final String[] HEADERS = {
"单位编码*", "单位名称*", "单位类型*", "联系人*", "联系电话*", "联系邮箱",
"国家二字码*", "省/州", "城市*", "区/县", "详细地址*", "邮政编码", "状态*", "备注"
"船司标准编码", "国家二字码*", "省/州", "城市*", "区/县", "详细地址*", "邮政编码", "状态*", "备注"
};
@Resource
@@ -107,9 +109,9 @@ public class PartnerImportService {
ImportRow item = new ImportRow(index + 1,
value(row, 0, formatter), value(row, 1, formatter), parseTypes(value(row, 2, formatter)),
value(row, 3, formatter), value(row, 4, formatter), value(row, 5, formatter),
value(row, 6, formatter).toUpperCase(Locale.ROOT), value(row, 7, formatter),
value(row, 8, formatter), value(row, 9, formatter), value(row, 10, formatter),
value(row, 11, formatter), value(row, 12, formatter).toUpperCase(Locale.ROOT), value(row, 13, formatter));
value(row, 6, formatter).toUpperCase(Locale.ROOT), value(row, 7, formatter).toUpperCase(Locale.ROOT),
value(row, 8, formatter), value(row, 9, formatter), value(row, 10, formatter), value(row, 11, formatter),
value(row, 12, formatter), value(row, 13, formatter), value(row, 14, formatter).toUpperCase(Locale.ROOT), value(row, 15, formatter));
validate(tenantId, item, rows, errors);
rows.add(item);
}
@@ -134,6 +136,11 @@ public class PartnerImportService {
if (row.types.isEmpty()) errors.add(error(row, "单位类型", "至少填写一个类型"));
row.types.stream().filter(type -> !ALLOWED_TYPES.contains(type))
.forEach(type -> errors.add(error(row, "单位类型", "不支持类型 " + type)));
if (row.types.contains("CARRIER") && !ALLOWED_CARRIER_CODES.contains(row.carrierCode)) {
errors.add(error(row, "船司标准编码", "船公司必须选择 MATSON、SML、ZIM、COSCO、EMC、HEDE 或 OTHER"));
} else if (!row.types.contains("CARRIER") && !row.carrierCode.isBlank()) {
errors.add(error(row, "船司标准编码", "非船公司必须留空"));
}
required(row, errors, "联系人", row.contactName, 64);
required(row, errors, "联系电话", row.contactPhone, 32);
if (row.email.length() > 128 || (!row.email.isBlank() && !EMAIL.matcher(row.email).matches())) {
@@ -162,7 +169,8 @@ public class PartnerImportService {
entity.setPartnerCode(row.code);
entity.setPartnerName(row.name);
entity.setTypes(row.types);
entity.setPartnerType(row.types.get(0));
entity.setPartnerType(row.types.contains("CARRIER") ? "CARRIER" : row.types.get(0));
entity.setCarrierCode(nullable(row.carrierCode));
entity.setContactName(row.contactName);
entity.setContactPhone(row.contactPhone);
entity.setContactEmail(nullable(row.email));
@@ -216,6 +224,6 @@ public class PartnerImportService {
}
private record ImportRow(int row, String code, String name, List<String> types, String contactName,
String contactPhone, String email, String countryCode, String province, String city,
String contactPhone, String email, String carrierCode, String countryCode, String province, String city,
String district, String address, String postalCode, String status, String remark) { }
}
@@ -24,6 +24,8 @@ public class PlatformPartnerQueryService {
private static final long PUBLIC_TENANT_ID = 0L;
private static final Set<String> ALLOWED_QUERY_TYPES = Set.of(
"CARRIER", "SHIPPER", "CONSIGNEE");
private static final Set<String> ALLOWED_CARRIER_CODES = Set.of(
"MATSON", "SML", "ZIM", "COSCO", "EMC", "HEDE", "OTHER");
@Resource
private PartnerRepository repository;
@@ -121,10 +123,12 @@ public class PlatformPartnerQueryService {
private static void copy(PartnerEntity entity, PartnerSaveRequest request) {
List<String> types = normalizeTypes(request.types(), request.partnerType());
String carrierCode = normalizeCarrierCode(types, request.carrierCode());
entity.setPartnerCode(request.partnerCode());
entity.setPartnerName(request.partnerName());
entity.setTypes(types);
entity.setPartnerType(legacyType(types));
entity.setCarrierCode(carrierCode);
entity.setContactName(request.contactName());
entity.setContactPhone(request.contactPhone());
entity.setContactEmail(request.contactEmail());
@@ -154,6 +158,25 @@ public class PlatformPartnerQueryService {
}
private static String legacyType(List<String> types) {
return types.get(0);
return types.contains("CARRIER") ? "CARRIER" : types.get(0);
}
static String normalizeCarrierCode(List<String> types, String carrierCode) {
boolean carrier = types.contains("CARRIER");
if (!carrier) {
if (carrierCode != null && !carrierCode.isBlank()) {
throw new BizException(ResultCode.VALIDATION_FAILED, "非船公司不得设置船司标准编码");
}
return null;
}
if (carrierCode == null || carrierCode.isBlank()) {
throw new BizException(ResultCode.BAD_REQUEST, "船公司必须选择船司标准编码");
}
String normalized = carrierCode.trim().toUpperCase(Locale.ROOT);
if (!ALLOWED_CARRIER_CODES.contains(normalized)) {
throw new BizException(ResultCode.VALIDATION_FAILED,
"船司标准编码仅支持 MATSON、SML、ZIM、COSCO、EMC、HEDE 或 OTHER");
}
return normalized;
}
}
@@ -79,6 +79,7 @@ class PlatformMasterDataManagementServiceTest {
assertThat(entity.getValue().getPartnerCode()).isEqualTo("CUS-001");
assertThat(entity.getValue().getPartnerName()).isEqualTo("示例客户");
assertThat(entity.getValue().getTypes()).containsExactly("CARRIER", "SHIPPER");
assertThat(entity.getValue().getCarrierCode()).isEqualTo("OTHER");
assertThat(entity.getValue().getRemark()).isEqualTo("测试备注");
}
@@ -210,7 +211,7 @@ class PlatformMasterDataManagementServiceTest {
}
private static PartnerSaveRequest partnerRequest() {
return new PartnerSaveRequest("CUS-001", "示例客户", "CARRIER", "张三", "13800138000",
return new PartnerSaveRequest("CUS-001", "示例客户", "CARRIER", "OTHER", "张三", "13800138000",
"test@example.com", "CN", "广东省", "深圳市", "南山区", "示例地址", "518000", "ACTIVE",
java.util.List.of("CARRIER", "SHIPPER"), "测试备注");
}