Merge remote-tracking branch 'origin/dev' into test

# Conflicts:
#	warehouse/src/main/java/com/baiyue/warehouse/dto/WarehouseRequests.java
#	warehouse/src/main/java/com/baiyue/warehouse/service/WarehouseImportService.java
#	warehouse/src/main/java/com/baiyue/warehouse/service/WarehouseSaveNormalizer.java
#	warehouse/src/main/resources/db/warehouse.sql
This commit is contained in:
2026-08-26 20:51:27 +08:00
1157 changed files with 78457 additions and 2736 deletions
@@ -4,6 +4,8 @@ import com.baiyue.common.core.api.ApiResponse;
import com.baiyue.common.core.api.ResultCode;
import com.baiyue.common.core.exception.BizException;
import com.baiyue.warehouse.dto.WarehouseDetailResponse;
import com.baiyue.warehouse.dto.OverseasPartnerWarehouseResponse;
import com.baiyue.warehouse.dto.SharedOverseasWarehouseResponse;
import com.baiyue.warehouse.service.WarehouseApplicationService;
import jakarta.annotation.Resource;
import jakarta.annotation.PostConstruct;
@@ -11,6 +13,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.List;
@RestController
@RequestMapping("/internal/warehouses")
@@ -39,6 +42,28 @@ public class InternalWarehouseController {
return ApiResponse.success(service.activeDetail(PLATFORM_TENANT_ID, id));
}
@GetMapping("/overseas-partners")
public ApiResponse<List<OverseasPartnerWarehouseResponse>> overseasPartners(
@RequestHeader(value="X-Internal-Service-Token", required=false) String token) {
verifyToken(token);
return ApiResponse.success(service.activeOverseasPartners());
}
@GetMapping("/shared-overseas")
public ApiResponse<List<SharedOverseasWarehouseResponse>> sharedOverseasWarehouses(
@RequestHeader(value="X-Internal-Service-Token", required=false) String token) {
verifyToken(token);
return ApiResponse.success(service.activeSharedOverseasWarehouses());
}
@GetMapping("/shared-overseas/{warehouseId}")
public ApiResponse<SharedOverseasWarehouseResponse> sharedOverseasWarehouse(
@RequestHeader(value="X-Internal-Service-Token", required=false) String token,
@PathVariable long warehouseId) {
verifyToken(token);
return ApiResponse.success(service.activeSharedOverseasWarehouse(warehouseId));
}
private void verifyToken(String token) {
byte[] supplied = token == null ? new byte[0] : token.getBytes(StandardCharsets.UTF_8);
if (!MessageDigest.isEqual(expected, supplied)) {
@@ -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")
@@ -0,0 +1,17 @@
package com.baiyue.warehouse.dto;
import com.baiyue.warehouse.entity.WarehouseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
@Schema(name = "OverseasPartnerWarehouseResponse", description = "Active overseas partner warehouse option / 启用的海外合作仓候选")
public record OverseasPartnerWarehouseResponse(
@Schema(description = "Platform public warehouse ID / 平台公共仓库 ID") Long id,
@Schema(description = "Warehouse code / 仓库编码") String warehouseCode,
@Schema(description = "Warehouse name / 仓库名称") String warehouseName,
@Schema(description = "ISO two-letter country code / 国家二字码") String countryCode
) {
public static OverseasPartnerWarehouseResponse of(WarehouseEntity warehouse) {
return new OverseasPartnerWarehouseResponse(warehouse.getId(), warehouse.getWarehouseCode(),
warehouse.getWarehouseName(), warehouse.getCountryCode());
}
}
@@ -0,0 +1,19 @@
package com.baiyue.warehouse.dto;
import com.baiyue.warehouse.entity.WarehouseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
@Schema(name = "SharedOverseasWarehouseResponse",
description = "Domestic-authoritative active shared overseas receiving warehouse")
public record SharedOverseasWarehouseResponse(
Long warehouseId,
String warehouseCode,
String warehouseName,
String countryCode,
String status
) {
public static SharedOverseasWarehouseResponse of(WarehouseEntity warehouse) {
return new SharedOverseasWarehouseResponse(warehouse.getId(), warehouse.getWarehouseCode(),
warehouse.getWarehouseName(), warehouse.getCountryCode(), warehouse.getStatus());
}
}
@@ -29,7 +29,7 @@ public final class WarehouseRequests {
@NotBlank @Size(max = 50) String warehouseCode,
@Schema(description = "Warehouse name / 仓库名称", example = "Los Angeles Main Warehouse / 洛杉矶主仓", maxLength = 120, requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank @Size(max = 120) String warehouseName,
@Schema(description = "Warehouse type; defaults to DOMESTIC / 仓库类型,默认 DOMESTIC", example = "FBA", allowableValues = {"DOMESTIC", "FBA", "OVERSEAS", "OVERSEAS_PARTNER"}, defaultValue = "DOMESTIC")
@Schema(description = "Warehouse type; defaults to DOMESTIC / 仓库类型,默认 DOMESTIC", example = "OVERSEAS_PARTNER", allowableValues = {"DOMESTIC", "FBA", "OVERSEAS", "OVERSEAS_PARTNER"}, defaultValue = "DOMESTIC")
@Pattern(regexp = "DOMESTIC|FBA|OVERSEAS|OVERSEAS_PARTNER") String warehouseType,
@Schema(description = "ISO 3166-1 alpha-2 country code; DOMESTIC defaults to CN / ISO 两位国家代码,DOMESTIC 默认 CN", example = "US", pattern = "[A-Z]{2}")
@Pattern(regexp = "[A-Z]{2}") String countryCode,
@@ -104,7 +104,7 @@ public final class WarehouseRequests {
String countryCode,
@Schema(description = "Enabled capability code filter / 已启用能力编码筛选", example = "STORAGE")
String capabilityCode,
@Schema(description = "Warehouse type filter / 仓库类型筛选", example = "DOMESTIC", allowableValues = {"DOMESTIC", "FBA", "OVERSEAS", "OVERSEAS_PARTNER"})
@Schema(description = "Warehouse type filter / 仓库类型筛选", example = "OVERSEAS_PARTNER", allowableValues = {"DOMESTIC", "FBA", "OVERSEAS", "OVERSEAS_PARTNER"})
@Pattern(regexp = "DOMESTIC|FBA|OVERSEAS|OVERSEAS_PARTNER") String warehouseType,
@Schema(description = "Status filter / 状态筛选", example = "ACTIVE", allowableValues = {"ACTIVE", "INACTIVE"})
@Pattern(regexp = "ACTIVE|INACTIVE") String status
@@ -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;
@@ -27,7 +27,8 @@ public class WarehouseEntity extends BaseEntity {
private String warehouseCode;
@Schema(description = "Warehouse name / 仓库名称", example = "Los Angeles Main Warehouse / 洛杉矶主仓")
private String warehouseName;
@Schema(description = "Warehouse type / 仓库类型", example = "OVERSEAS")
@Schema(description = "Warehouse type / 仓库类型", example = "OVERSEAS_PARTNER",
allowableValues = {"DOMESTIC", "FBA", "OVERSEAS", "OVERSEAS_PARTNER"})
private String warehouseType;
@Schema(description = "ISO two-letter country code / ISO 两位国家代码", example = "US")
private String countryCode;
@@ -59,6 +59,15 @@ public class WarehouseRepository {
.eq(WarehouseEntity::getStatus, "ACTIVE"));
}
public List<WarehouseEntity> findActiveByType(long tenantId, String warehouseType) {
return warehouses.selectList(new LambdaQueryWrapper<WarehouseEntity>()
.eq(WarehouseEntity::getTenantId, tenantId)
.eq(WarehouseEntity::getWarehouseType, warehouseType)
.eq(WarehouseEntity::getStatus, "ACTIVE")
.orderByAsc(WarehouseEntity::getWarehouseName)
.orderByAsc(WarehouseEntity::getId));
}
public boolean existsCode(long tenantId, String code, Long excludedId) {
return warehouses.selectCount(new LambdaQueryWrapper<WarehouseEntity>()
.eq(WarehouseEntity::getTenantId, tenantId)
@@ -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).toUpperCase(Locale.ROOT), value(row, 14, 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;
}
}
@@ -7,7 +7,9 @@ import com.baiyue.common.core.api.ResultCode;
import com.baiyue.common.core.exception.BizException;
import com.baiyue.warehouse.dto.WarehouseDetailResponse;
import com.baiyue.warehouse.dto.WarehouseRequests;
import com.baiyue.warehouse.dto.OverseasPartnerWarehouseResponse;
import com.baiyue.warehouse.dto.WarehouseSummaryResponse;
import com.baiyue.warehouse.dto.SharedOverseasWarehouseResponse;
import com.baiyue.warehouse.entity.ServiceCapabilityEntity;
import com.baiyue.warehouse.entity.WarehouseAddressEntity;
import com.baiyue.warehouse.entity.WarehouseEntity;
@@ -86,6 +88,40 @@ public class WarehouseApplicationService {
return repository.activePage(tenantId, query);
}
public List<OverseasPartnerWarehouseResponse> activeOverseasPartners() {
return repository.findActiveByType(WarehouseSaveNormalizer.PUBLIC_TENANT_ID,
WarehouseSaveNormalizer.TYPE_OVERSEAS_PARTNER)
.stream()
.map(OverseasPartnerWarehouseResponse::of)
.toList();
}
public List<SharedOverseasWarehouseResponse> activeSharedOverseasWarehouses() {
return repository.findActiveByType(WarehouseSaveNormalizer.PUBLIC_TENANT_ID,
WarehouseSaveNormalizer.TYPE_OVERSEAS)
.stream()
.filter(warehouse -> hasReceivingCapability(warehouse.getId()))
.map(SharedOverseasWarehouseResponse::of)
.toList();
}
public SharedOverseasWarehouseResponse activeSharedOverseasWarehouse(long warehouseId) {
WarehouseEntity warehouse = repository.findOwned(WarehouseSaveNormalizer.PUBLIC_TENANT_ID, warehouseId);
if (warehouse == null || !"ACTIVE".equals(warehouse.getStatus())
|| !WarehouseSaveNormalizer.TYPE_OVERSEAS.equals(warehouse.getWarehouseType())
|| !hasReceivingCapability(warehouseId)) {
throw new BizException(ResultCode.NOT_FOUND,
"启用的公共海外收货仓不存在");
}
return SharedOverseasWarehouseResponse.of(warehouse);
}
private boolean hasReceivingCapability(long warehouseId) {
return repository.findCapabilities(WarehouseSaveNormalizer.PUBLIC_TENANT_ID, warehouseId).stream()
.anyMatch(capability -> "RECEIVING".equals(capability.getCapabilityCode())
&& Boolean.TRUE.equals(capability.getEnabled()));
}
public WarehouseDetailResponse activeDetail(long tenantId, long id) {
WarehouseEntity warehouse = repository.findOwned(tenantId, id);
if (warehouse == null) {
@@ -56,7 +56,7 @@ public class WarehouseImportService {
Row instruction = sheet.createRow(1);
instruction.createCell(0).setCellValue("说明");
instruction.createCell(1).setCellValue(
"默认仅新增;仓库类型默认 DOMESTIC,状态默认 ACTIVE;DOMESTIC 默认 CN/UTC+8;FBA 名称可不填并默认使用编码,多时区州必须显式填写时区;更新不覆盖联系人和备注");
"默认仅新增;仓库类型默认 DOMESTIC,可填 OVERSEAS_PARTNER 表示海外合作仓;状态默认 ACTIVE;DOMESTIC 默认 CN/UTC+8;FBA 名称可不填并默认使用编码,多时区州必须显式填写时区;更新不覆盖联系人和备注");
Row header = sheet.createRow(2);
for (int i = 0; i < HEADERS.length; i++) {
header.createCell(i).setCellValue(HEADERS[i]);
@@ -203,7 +203,7 @@ public class WarehouseImportService {
optionalLength(row, errors, "仓库名称", row.name(), 120);
}
if (!row.type().isBlank() && !row.type().matches("(?i)DOMESTIC|FBA|OVERSEAS|OVERSEAS_PARTNER")) {
errors.add(new WarehouseImportError(row.row(), "仓库类型", "只能填写 DOMESTIC、FBA 或 OVERSEAS"));
errors.add(new WarehouseImportError(row.row(), "仓库类型", "只能填写 DOMESTIC、FBA、OVERSEAS 或 OVERSEAS_PARTNER"));
}
if (!row.countryCode().isBlank() && !row.countryCode().matches("(?i)[A-Z]{2}")) {
errors.add(new WarehouseImportError(row.row(), "国家二字码", "必须是两个英文字母"));
@@ -71,7 +71,8 @@ final class WarehouseSaveNormalizer {
static NormalizedSaveRequest normalize(WarehouseRequests.SaveRequest request, long tenantId) {
String warehouseType = upperOrDefault(request.warehouseType(), TYPE_DOMESTIC);
if (!Set.of(TYPE_DOMESTIC, TYPE_FBA, TYPE_OVERSEAS, TYPE_OVERSEAS_PARTNER).contains(warehouseType)) {
throw new BizException(ResultCode.VALIDATION_FAILED, "Warehouse type must be DOMESTIC, FBA, OVERSEAS or OVERSEAS_PARTNER / 仓库类型只能为 DOMESTIC、FBA、OVERSEAS 或 OVERSEAS_PARTNER");
throw new BizException(ResultCode.VALIDATION_FAILED,
"Warehouse type must be DOMESTIC, FBA, OVERSEAS or OVERSEAS_PARTNER / 仓库类型只能为 DOMESTIC、FBA、OVERSEAS 或 OVERSEAS_PARTNER");
}
String status = upperOrDefault(request.status(), STATUS_ACTIVE);
if (!STATUS_ACTIVE.equals(status) && !"INACTIVE".equals(status)) {
@@ -102,7 +102,8 @@ CALL add_column_if_missing('wh_partner', 'tenant_id', 'BIGINT UNSIGNED NOT NULL
CALL add_column_if_missing('wh_partner', 'partner_code', 'VARCHAR(50) NOT NULL DEFAULT '''' AFTER tenant_id');
CALL add_column_if_missing('wh_partner', 'partner_name', 'VARCHAR(128) NOT NULL DEFAULT '''' AFTER partner_code');
CALL add_column_if_missing('wh_partner', 'partner_type', 'VARCHAR(20) NOT NULL DEFAULT ''CUSTOMER'' AFTER partner_name');
CALL add_column_if_missing('wh_partner', 'contact_name', 'VARCHAR(64) NOT NULL DEFAULT '''' AFTER partner_type');
CALL add_column_if_missing('wh_partner', 'carrier_code', 'VARCHAR(16) NULL COMMENT ''船司标准编码:MATSON、SML、ZIM、COSCO、EMC、HEDE或OTHER;仅CARRIER必填'' AFTER partner_type');
CALL add_column_if_missing('wh_partner', 'contact_name', 'VARCHAR(64) NOT NULL DEFAULT '''' AFTER carrier_code');
CALL add_column_if_missing('wh_partner', 'contact_phone', 'VARCHAR(32) NOT NULL DEFAULT '''' AFTER contact_name');
CALL add_column_if_missing('wh_partner', 'contact_email', 'VARCHAR(128) NULL');
CALL add_column_if_missing('wh_partner', 'country_code', 'CHAR(2) NOT NULL DEFAULT ''CN'' AFTER contact_email');
@@ -118,6 +119,8 @@ CALL add_column_if_missing('wh_partner', 'updated_by', 'BIGINT UNSIGNED NULL');
CALL add_column_if_missing('wh_partner', 'updated_at', 'DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)');
CALL add_column_if_missing('wh_partner', 'deleted', 'TINYINT(1) NOT NULL DEFAULT 0');
CALL add_column_if_missing('wh_partner', 'version', 'INT NOT NULL DEFAULT 0');
UPDATE wh_partner SET carrier_code = 'OTHER'
WHERE id = 191000000000000001 AND partner_type = 'CARRIER' AND carrier_code IS NULL;
-- 该表在旧库中不存在时先由 warehouse-express-company.sql 建表;此段补齐早期部署缺列。
CALL add_column_if_missing('wh_express_company', 'tenant_id', 'BIGINT UNSIGNED NOT NULL DEFAULT 0 AFTER id');
@@ -5,6 +5,7 @@ CREATE TABLE IF NOT EXISTS wh_partner (
data_scope_id BIGINT UNSIGNED NOT NULL COMMENT '所属业务数据范围',
partner_code VARCHAR(50) NOT NULL COMMENT '平台内唯一往来单位编码', partner_name VARCHAR(128) NOT NULL COMMENT '往来单位名称',
partner_type VARCHAR(20) NOT NULL COMMENT '往来单位类型:CARRIER、SHIPPER或CONSIGNEE',
carrier_code VARCHAR(16) NULL COMMENT '船司标准编码:MATSON、SML、ZIM、COSCO、EMC、HEDE或OTHER;仅CARRIER必填',
contact_name VARCHAR(64) NOT NULL COMMENT '联系人姓名', contact_phone VARCHAR(32) NOT NULL COMMENT '联系电话',
contact_email VARCHAR(128) NULL COMMENT '联系邮箱', country_code CHAR(2) NOT NULL COMMENT '国家二字码',
province VARCHAR(64) NULL COMMENT '省或州', city VARCHAR(64) NOT NULL COMMENT '城市', district VARCHAR(64) NULL COMMENT '区县',
@@ -16,7 +17,8 @@ CREATE TABLE IF NOT EXISTS wh_partner (
deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除标记:0未删除、1已删除', version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
PRIMARY KEY(id), UNIQUE KEY uk_wh_partner_tenant_code(tenant_id,partner_code,deleted),
KEY idx_wh_partner_tenant_status(tenant_id,status,deleted),
CONSTRAINT chk_wh_partner_type CHECK (partner_type IN ('CARRIER','SHIPPER','CONSIGNEE'))
CONSTRAINT chk_wh_partner_type CHECK (partner_type IN ('CARRIER','SHIPPER','CONSIGNEE')),
CONSTRAINT chk_wh_partner_carrier_code CHECK (carrier_code IS NULL OR carrier_code IN ('MATSON','SML','ZIM','COSCO','EMC','HEDE','OTHER'))
) ENGINE=InnoDB COMMENT='平台统一维护、供全部客户共享的往来单位主数据';
CREATE TABLE IF NOT EXISTS wh_partner_type (
partner_id BIGINT UNSIGNED NOT NULL COMMENT '往来单位ID', tenant_id BIGINT UNSIGNED NOT NULL COMMENT '平台公共往来单位固定使用 tenant_id=0',
@@ -162,7 +162,7 @@ JOIN wh_warehouse warehouse
ON DUPLICATE KEY UPDATE
tenant_id = VALUES(tenant_id);
-- 国内固定作业仓必须启用收货能力,FBA 目的地址仍不得创建作业能力。
-- 四个固定平台作业仓必须启用收货能力,FBA 目的地址仍不得创建作业能力。
INSERT INTO wh_service_capability (
id, tenant_id, warehouse_id, capability_code, capability_name, enabled, cutoff_time,
description, created_by, created_at, updated_by, updated_at, deleted, version
@@ -171,7 +171,11 @@ VALUES
(193000000000400001,0,193000000000200001,'RECEIVING','头程收货',1,'16:00:00',
'义乌仓头程订单收货能力',NULL,CURRENT_TIMESTAMP(3),NULL,CURRENT_TIMESTAMP(3),0,0),
(193000000000400002,0,193000000000200002,'RECEIVING','头程收货',1,'16:00:00',
'东莞仓头程订单收货能力',NULL,CURRENT_TIMESTAMP(3),NULL,CURRENT_TIMESTAMP(3),0,0)
'东莞仓头程订单收货能力',NULL,CURRENT_TIMESTAMP(3),NULL,CURRENT_TIMESTAMP(3),0,0),
(193000000000400003,0,193000000000200003,'RECEIVING','海外收货',1,'16:00:00',
'洛杉矶仓海外接柜入仓收货能力',NULL,CURRENT_TIMESTAMP(3),NULL,CURRENT_TIMESTAMP(3),0,0),
(193000000000400004,0,193000000000200004,'RECEIVING','海外收货',1,'16:00:00',
'纽约仓海外接柜入仓收货能力',NULL,CURRENT_TIMESTAMP(3),NULL,CURRENT_TIMESTAMP(3),0,0)
ON DUPLICATE KEY UPDATE
capability_name = VALUES(capability_name),
enabled = VALUES(enabled),
@@ -677,11 +681,11 @@ BEGIN
IF (SELECT COUNT(*)
FROM wh_service_capability capability
WHERE capability.tenant_id = 0
AND capability.warehouse_id IN (193000000000200001,193000000000200002)
AND capability.warehouse_id IN (193000000000200001,193000000000200002,193000000000200003,193000000000200004)
AND capability.capability_code = 'RECEIVING'
AND capability.enabled = 1
AND capability.deleted = 0) <> 2 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '国内固定作业仓收货能力写入校验失败';
AND capability.deleted = 0) <> 4 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '固定平台作业仓收货能力写入校验失败';
END IF;
END//
DELIMITER ;
@@ -8,7 +8,7 @@ CREATE TABLE IF NOT EXISTS wh_warehouse (
tenant_id BIGINT UNSIGNED NOT NULL COMMENT '平台公共仓库固定使用 tenant_id=0',
warehouse_code VARCHAR(50) NOT NULL COMMENT '平台内唯一仓库编码',
warehouse_name VARCHAR(120) NOT NULL COMMENT '仓库名称',
warehouse_type VARCHAR(32) NOT NULL DEFAULT 'DOMESTIC' COMMENT '公共仓库类型:DOMESTIC、FBA、OVERSEAS、OVERSEAS_PARTNER',
warehouse_type VARCHAR(32) NOT NULL DEFAULT 'DOMESTIC' COMMENT '公共仓库类型:DOMESTIC国内仓、FBA亚马逊仓、OVERSEAS普通海外仓、OVERSEAS_PARTNER海外合作仓',
country_code CHAR(2) NOT NULL COMMENT '所在国家二字码',
timezone VARCHAR(64) NOT NULL COMMENT '仓库所在地UTC偏移量',
contact_name VARCHAR(64) DEFAULT NULL COMMENT '仓库联系人',