统一财务费用来源入池链路
This commit is contained in:
+2
-2
@@ -20,8 +20,8 @@ public final class OverseasFeeSourceDtos {
|
||||
public record SaveRequest(
|
||||
@NotBlank @Size(max = 128) String customerId,
|
||||
@Size(max = 200) String customerName,
|
||||
@NotBlank @Pattern(regexp = "OVERSEAS_INBOUND_FEE|OVERSEAS_PROCUREMENT_FEE|OVERSEAS_TRUCK_FEE|OVERSEAS_LOOSEBOARD_FEE|OVERSEAS_WAREHOUSE_FEE|OVERSEAS_CONTAINER_FEE") String sourceType,
|
||||
@NotBlank @Pattern(regexp = "OVERSEAS_INBOUND|OVERSEAS_PROCUREMENT|US_TRUCK|LOCAL_LOOSEBOARD|WAREHOUSE_SERVICE|OVERSEAS_CONTAINER") String businessType,
|
||||
@NotBlank @Pattern(regexp = "OVERSEAS_INBOUND_FEE|OVERSEAS_PROCUREMENT_FEE|OVERSEAS_TRUCK_FEE|OVERSEAS_LOOSEBOARD_FEE|OVERSEAS_WAREHOUSE_FEE|OVERSEAS_CONTAINER_FEE|OVERSEAS_ORDER_FEE|OVERSEAS_DELIVERY_FEE|OVERSEAS_RELABEL_FEE") String sourceType,
|
||||
@NotBlank @Pattern(regexp = "OVERSEAS_INBOUND|OVERSEAS_PROCUREMENT|PROCUREMENT_FEE|US_TRUCK|LOCAL_LOOSEBOARD|WAREHOUSE_SERVICE|OVERSEAS_CONTAINER|LASTLEG_ORDER|DELIVERY_ORDER|RELABEL_ORDER") String businessType,
|
||||
@Min(1) Long businessId,
|
||||
@NotBlank @Size(max = 128) String businessNo,
|
||||
@Min(1) Long orderId,
|
||||
|
||||
+26
@@ -2,7 +2,11 @@ package com.baiyue.lastleg.financefee.service;
|
||||
|
||||
import com.baiyue.lastleg.financefee.dto.OverseasFeeSourceDtos.SaveRequest;
|
||||
import com.baiyue.lastleg.financefee.dto.OverseasFeeSourceDtos.ContainerCustomerOption;
|
||||
import com.baiyue.lastleg.client.DomesticWarehouseDirectoryClient;
|
||||
import feign.FeignException;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -14,6 +18,8 @@ import java.util.List;
|
||||
@RequiredArgsConstructor
|
||||
public class OverseasFeeBusinessGuard {
|
||||
private final JdbcTemplate jdbc;
|
||||
@Resource private DomesticWarehouseDirectoryClient warehouses;
|
||||
@Value("${baiyue.security.internal-service-token}") private String internalToken;
|
||||
|
||||
public List<ContainerCustomerOption> listContainerCustomers(long containerBookingId) {
|
||||
List<ContainerCustomerOption> customers = jdbc.query(
|
||||
@@ -37,13 +43,18 @@ public class OverseasFeeBusinessGuard {
|
||||
throw bad("业务记录ID不能为空");
|
||||
if (fee.warehouseId() == null)
|
||||
throw bad("海外仓服务费必须关联海外仓;入仓记录和入仓码按实际业务选填");
|
||||
requireActiveOverseasWarehouse(fee.warehouseId());
|
||||
return;
|
||||
}
|
||||
Table table = switch (fee.businessType()) {
|
||||
case "OVERSEAS_INBOUND" -> new Table("ll_inbound_plan", "plan_no");
|
||||
case "OVERSEAS_PROCUREMENT" -> new Table("ll_overseas_procurement_order", "order_no");
|
||||
case "PROCUREMENT_FEE" -> new Table("ll_overseas_procurement_fee", "fee_no");
|
||||
case "US_TRUCK" -> new Table("ll_us_truck_order", "order_no");
|
||||
case "LOCAL_LOOSEBOARD" -> new Table("ll_local_looseboard_order", "order_no");
|
||||
case "LASTLEG_ORDER" -> new Table("ll_order", "order_no");
|
||||
case "DELIVERY_ORDER" -> new Table("ll_delivery_order", "delivery_no");
|
||||
case "RELABEL_ORDER" -> new Table("ll_relabel_application", "relabel_no");
|
||||
default -> throw bad("业务类型与业务记录ID不匹配");
|
||||
};
|
||||
Integer count = jdbc.queryForObject("SELECT COUNT(*) FROM " + table.name
|
||||
@@ -83,6 +94,21 @@ public class OverseasFeeBusinessGuard {
|
||||
if (owned == null || owned < 1) throw bad("该客户不属于费用关联的真实货柜");
|
||||
}
|
||||
|
||||
private void requireActiveOverseasWarehouse(long warehouseId) {
|
||||
try {
|
||||
var response = warehouses.activeWarehouse(warehouseId, internalToken);
|
||||
var warehouse = response == null || response.data() == null ? null : response.data().warehouse();
|
||||
if (warehouse == null || !response.successful() || !Long.valueOf(warehouseId).equals(warehouse.id())
|
||||
|| !Long.valueOf(0L).equals(warehouse.tenantId()) || !"ACTIVE".equals(warehouse.status())
|
||||
|| !List.of("OVERSEAS", "OVERSEAS_PARTNER").contains(warehouse.warehouseType())) {
|
||||
throw bad("海外仓不存在、已停用或类型不正确");
|
||||
}
|
||||
} catch (FeignException exception) {
|
||||
if (exception.status() >= 400 && exception.status() < 500) throw bad("海外仓不存在、已停用或类型不正确");
|
||||
throw new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE, "仓库主数据暂不可用", exception);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean blank(String value) { return value == null || value.isBlank(); }
|
||||
private static ResponseStatusException bad(String message) {
|
||||
return new ResponseStatusException(HttpStatus.BAD_REQUEST, message);
|
||||
|
||||
+35
@@ -53,6 +53,15 @@ public class OverseasFeeSourceService {
|
||||
.orderByDesc(OverseasFeeSource::getCreatedAt).orderByDesc(OverseasFeeSource::getId));
|
||||
}
|
||||
|
||||
public List<OverseasFeeSource> listForBusiness(String customerId, String businessType, long businessId) {
|
||||
return mapper.selectList(new LambdaQueryWrapper<OverseasFeeSource>()
|
||||
.eq(OverseasFeeSource::getCustomerId, customerId)
|
||||
.eq(OverseasFeeSource::getBusinessType, businessType)
|
||||
.eq(OverseasFeeSource::getBusinessId, businessId)
|
||||
.inSql(OverseasFeeSource::getId, "SELECT MAX(v.id) FROM ll_finance_fee_source v GROUP BY v.source_fee_id")
|
||||
.orderByAsc(OverseasFeeSource::getCreatedAt).orderByAsc(OverseasFeeSource::getId));
|
||||
}
|
||||
|
||||
public List<ContainerCustomerOption> listContainerCustomers(long containerBookingId) {
|
||||
return businessGuard.listContainerCustomers(containerBookingId);
|
||||
}
|
||||
@@ -70,6 +79,22 @@ public class OverseasFeeSourceService {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public OverseasFeeSource publishApproved(String operatorId, String key, SaveRequest request) {
|
||||
OverseasFeeSource value = create(operatorId, key, request);
|
||||
if ("DRAFT".equals(value.getReviewStatus()) || "REJECTED".equals(value.getReviewStatus())) {
|
||||
value = submit(value.getSourceFeeId(), operatorId, childKey(key, "submit"));
|
||||
}
|
||||
if ("PENDING".equals(value.getReviewStatus())) {
|
||||
value = review(value.getSourceFeeId(), operatorId,
|
||||
new ReviewRequest("APPROVE", "业务完成自动确认费用", childKey(key, "approve")));
|
||||
}
|
||||
if (!"APPROVED".equals(value.getReviewStatus()) || !"PUBLISHED".equals(value.getPublicationStatus())) {
|
||||
throw conflict("业务费用未能审核发布");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public OverseasFeeSource submit(long sourceFeeId, String operatorId, String key) {
|
||||
OverseasFeeCommand replay = replay(operatorId, "SUBMIT", key, sourceFeeId);
|
||||
@@ -168,10 +193,14 @@ public class OverseasFeeSourceService {
|
||||
String expected = switch (value.businessType()) {
|
||||
case "OVERSEAS_INBOUND" -> "OVERSEAS_INBOUND_FEE";
|
||||
case "OVERSEAS_PROCUREMENT" -> "OVERSEAS_PROCUREMENT_FEE";
|
||||
case "PROCUREMENT_FEE" -> "OVERSEAS_PROCUREMENT_FEE";
|
||||
case "US_TRUCK" -> "OVERSEAS_TRUCK_FEE";
|
||||
case "LOCAL_LOOSEBOARD" -> "OVERSEAS_LOOSEBOARD_FEE";
|
||||
case "WAREHOUSE_SERVICE" -> "OVERSEAS_WAREHOUSE_FEE";
|
||||
case "OVERSEAS_CONTAINER" -> "OVERSEAS_CONTAINER_FEE";
|
||||
case "LASTLEG_ORDER" -> "OVERSEAS_ORDER_FEE";
|
||||
case "DELIVERY_ORDER" -> "OVERSEAS_DELIVERY_FEE";
|
||||
case "RELABEL_ORDER" -> "OVERSEAS_RELABEL_FEE";
|
||||
default -> "";
|
||||
};
|
||||
if (!expected.equals(value.sourceType())) throw bad("来源类型与业务类型不匹配");
|
||||
@@ -212,6 +241,12 @@ public class OverseasFeeSourceService {
|
||||
if (existing != null && !existing.getRequestHash().equals(hash(request))) throw conflict("幂等键已被不同请求使用");
|
||||
return existing;
|
||||
}
|
||||
|
||||
private static String childKey(String key, String suffix) {
|
||||
String prefix = key == null ? "" : key.trim();
|
||||
int maxPrefix = Math.max(0, 128 - suffix.length() - 1);
|
||||
return prefix.substring(0, Math.min(prefix.length(), maxPrefix)) + ':' + suffix;
|
||||
}
|
||||
private void command(String operator, String action, String key, Object request, long sourceFeeId, int version) {
|
||||
OverseasFeeCommand value = new OverseasFeeCommand(); value.setId(IdWorker.getId()); value.setOperatorId(operator);
|
||||
value.setAction(action); value.setIdempotencyKey(key.trim()); value.setRequestHash(hash(request)); value.setSourceFeeId(sourceFeeId);
|
||||
|
||||
Reference in New Issue
Block a user