优化
This commit is contained in:
+12
-16
@@ -41,55 +41,51 @@ public class PlatformFeeItemController {
|
||||
@Operation(summary = "查询费用项目")
|
||||
public ApiResponse<PageResult<FeeItemEntity>> list(
|
||||
@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@RequestParam long accountId,
|
||||
@RequestParam(required = false) String category,
|
||||
@RequestParam(required = false) String tradeScope,
|
||||
@RequestParam(required = false) String keyword,
|
||||
@RequestParam(required = false) String status,
|
||||
@RequestParam(defaultValue = "1") @Min(1) long page,
|
||||
@RequestParam(defaultValue = "20") @Min(1) @Max(200) long size) {
|
||||
return ApiResponse.success(service.list(FirstlegScopeGuard.platform(user, accountId),
|
||||
category, tradeScope, keyword, status, page, size));
|
||||
FirstlegScopeGuard.platform(user);
|
||||
return ApiResponse.success(service.list(category, tradeScope, keyword, status, page, size));
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("hasAuthority('firstleg:fee-item:view')")
|
||||
public ApiResponse<FeeItemEntity> detail(@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@RequestParam long accountId,
|
||||
@PathVariable long id) {
|
||||
return ApiResponse.success(service.detail(FirstlegScopeGuard.platform(user, accountId), id));
|
||||
FirstlegScopeGuard.platform(user);
|
||||
return ApiResponse.success(service.detail(id));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@BusinessAudit(event = "FEE_ITEM_CREATE", resourceType = "FEE_ITEM", description = "新增费用项目", captureBefore = false)
|
||||
@PreAuthorize("hasAuthority('firstleg:fee-item:create')")
|
||||
public ApiResponse<FeeItemEntity> create(@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@RequestParam long accountId,
|
||||
@Valid @RequestBody SaveRequest request) {
|
||||
long scope = FirstlegScopeGuard.platform(user, accountId);
|
||||
return ApiResponse.success(service.create(scope, user.userId(), user.username(), request));
|
||||
FirstlegScopeGuard.platform(user);
|
||||
return ApiResponse.success(service.create(user.userId(), user.username(), request));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
@BusinessAudit(event = "FEE_ITEM_UPDATE", resourceType = "FEE_ITEM", resourceId = "#id", description = "编辑费用项目")
|
||||
@PreAuthorize("hasAuthority('firstleg:fee-item:edit')")
|
||||
public ApiResponse<FeeItemEntity> update(@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@RequestParam long accountId,
|
||||
@PathVariable long id,
|
||||
@Valid @RequestBody SaveRequest request) {
|
||||
long scope = FirstlegScopeGuard.platform(user, accountId);
|
||||
return ApiResponse.success(service.update(scope, id, user.userId(), user.username(), request));
|
||||
FirstlegScopeGuard.platform(user);
|
||||
return ApiResponse.success(service.update(id, user.userId(), user.username(), request));
|
||||
}
|
||||
|
||||
@PatchMapping("/{id}/status")
|
||||
@BusinessAudit(event = "FEE_ITEM_STATUS_CHANGE", resourceType = "FEE_ITEM", resourceId = "#id", description = "启停费用项目")
|
||||
@PreAuthorize("hasAuthority('firstleg:fee-item:edit')")
|
||||
public ApiResponse<Void> changeStatus(@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@RequestParam long accountId,
|
||||
@PathVariable long id,
|
||||
@Valid @RequestBody StatusRequest request) {
|
||||
service.changeStatus(FirstlegScopeGuard.platform(user, accountId), id,
|
||||
user.userId(), user.username(), request.status());
|
||||
FirstlegScopeGuard.platform(user);
|
||||
service.changeStatus(id, user.userId(), user.username(), request.status());
|
||||
return ApiResponse.success(null);
|
||||
}
|
||||
|
||||
@@ -97,9 +93,9 @@ public class PlatformFeeItemController {
|
||||
@BusinessAudit(event = "FEE_ITEM_DELETE", resourceType = "FEE_ITEM", resourceId = "#id", description = "删除费用项目")
|
||||
@PreAuthorize("hasAuthority('firstleg:fee-item:delete')")
|
||||
public ApiResponse<Void> delete(@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@RequestParam long accountId,
|
||||
@PathVariable long id) {
|
||||
service.delete(FirstlegScopeGuard.platform(user, accountId), id);
|
||||
FirstlegScopeGuard.platform(user);
|
||||
service.delete(id);
|
||||
return ApiResponse.success(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ public final class FeeItemDtos {
|
||||
public record SaveRequest(
|
||||
@NotBlank @Size(max = 64) String category,
|
||||
@NotBlank @Pattern(regexp = "DOMESTIC|INTERNATIONAL") String tradeScope,
|
||||
@Size(max = 50) @Pattern(regexp = "[A-Za-z0-9_-]{1,50}") String feeCode,
|
||||
@NotBlank @Size(max = 128) String feeTypeName,
|
||||
@NotNull Boolean pickupPayable,
|
||||
@NotNull Boolean pickupReceivable,
|
||||
@@ -21,6 +22,14 @@ public final class FeeItemDtos {
|
||||
@NotNull Boolean allocationFee,
|
||||
@Size(max = 500) String description
|
||||
) {
|
||||
/** Backward-compatible constructor for callers predating the stable fee code. */
|
||||
public SaveRequest(String category, String tradeScope, String feeTypeName,
|
||||
Boolean pickupPayable, Boolean pickupReceivable,
|
||||
Boolean warehousePayable, Boolean warehouseReceivable,
|
||||
Boolean allocationFee, String description) {
|
||||
this(category, tradeScope, null, feeTypeName, pickupPayable, pickupReceivable,
|
||||
warehousePayable, warehouseReceivable, allocationFee, description);
|
||||
}
|
||||
}
|
||||
|
||||
public record StatusRequest(
|
||||
|
||||
+13
-4
@@ -27,7 +27,7 @@ public interface InboundSplitSettlementMapper {
|
||||
inbound_code AS inboundCode, inbound_role AS inboundRole,
|
||||
root_inbound_id AS rootInboundId,
|
||||
process_status AS processStatus, total_package_count AS totalPackageCount,
|
||||
package_count AS packageCount, version
|
||||
package_count AS packageCount, split_status AS splitStatus, version
|
||||
FROM fl_inbound_order
|
||||
WHERE id = #{inboundId} AND deleted = 0
|
||||
FOR UPDATE
|
||||
@@ -158,7 +158,8 @@ public interface InboundSplitSettlementMapper {
|
||||
@Param("expectedVersion") int expectedVersion);
|
||||
|
||||
@Update("UPDATE fl_inbound_order SET package_count=0,split_status='FULLY_SPLIT',updated_by=#{operatorId},version=version+1 "
|
||||
+ "WHERE id=#{parentInboundId} AND tenant_id=#{accountId} AND inbound_role='MASTER' AND deleted=0 AND version=#{expectedVersion}")
|
||||
+ "WHERE id=#{parentInboundId} AND tenant_id=#{accountId} AND inbound_role='MASTER' AND deleted=0 "
|
||||
+ "AND process_status IN ('INBOUNDED','LOADING') AND version=#{expectedVersion}")
|
||||
int markRootSplit(@Param("accountId") long accountId, @Param("parentInboundId") long parentInboundId,
|
||||
@Param("operatorId") long operatorId, @Param("expectedVersion") int expectedVersion);
|
||||
|
||||
@@ -269,11 +270,19 @@ public interface InboundSplitSettlementMapper {
|
||||
record ParentRow(Long id, Long tenantId, Long orderId, String orderNo,
|
||||
String inboundCode, String inboundRole, Long rootInboundId,
|
||||
String processStatus, Integer totalPackageCount, Integer packageCount,
|
||||
Integer version) {
|
||||
String splitStatus, Integer version) {
|
||||
public ParentRow(Long id, Long tenantId, String inboundCode, String inboundRole,
|
||||
String processStatus, Integer totalPackageCount, Integer packageCount, Integer version) {
|
||||
this(id, tenantId, 901L, "ORDER-001", inboundCode, inboundRole, id,
|
||||
processStatus, totalPackageCount, packageCount, version);
|
||||
processStatus, totalPackageCount, packageCount, "NOT_SPLIT", version);
|
||||
}
|
||||
|
||||
public ParentRow(Long id, Long tenantId, Long orderId, String orderNo,
|
||||
String inboundCode, String inboundRole, Long rootInboundId,
|
||||
String processStatus, Integer totalPackageCount, Integer packageCount,
|
||||
Integer version) {
|
||||
this(id, tenantId, orderId, orderNo, inboundCode, inboundRole, rootInboundId,
|
||||
processStatus, totalPackageCount, packageCount, "NOT_SPLIT", version);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.List;
|
||||
/** 费用项目与入库费用明细仓储。 */
|
||||
@Repository
|
||||
public class FeeItemRepository {
|
||||
private static final long PLATFORM_TENANT_ID = 0L;
|
||||
@Resource
|
||||
private FeeItemMapper feeItems;
|
||||
@Resource
|
||||
@@ -27,11 +28,11 @@ public class FeeItemRepository {
|
||||
@Resource
|
||||
private InboundOrderMapper inboundOrders;
|
||||
|
||||
public PageResult<FeeItemEntity> listItems(long tenantId, String category, String tradeScope,
|
||||
public PageResult<FeeItemEntity> listItems(String category, String tradeScope,
|
||||
String keyword, String status, long page, long size) {
|
||||
return PageResult.from(feeItems.selectPage(new Page<>(page, size),
|
||||
new LambdaQueryWrapper<FeeItemEntity>()
|
||||
.eq(FeeItemEntity::getTenantId, tenantId)
|
||||
.eq(FeeItemEntity::getTenantId, PLATFORM_TENANT_ID)
|
||||
.eq(StringUtils.hasText(category), FeeItemEntity::getCategory, category)
|
||||
.eq(StringUtils.hasText(tradeScope), FeeItemEntity::getTradeScope, tradeScope)
|
||||
.like(StringUtils.hasText(keyword), FeeItemEntity::getFeeTypeName, keyword)
|
||||
@@ -41,45 +42,53 @@ public class FeeItemRepository {
|
||||
.orderByDesc(FeeItemEntity::getId)));
|
||||
}
|
||||
|
||||
public FeeItemEntity findItem(long tenantId, long id) {
|
||||
public FeeItemEntity findItem(long id) {
|
||||
return feeItems.selectOne(new LambdaQueryWrapper<FeeItemEntity>()
|
||||
.eq(FeeItemEntity::getTenantId, tenantId)
|
||||
.eq(FeeItemEntity::getTenantId, PLATFORM_TENANT_ID)
|
||||
.eq(FeeItemEntity::getId, id));
|
||||
}
|
||||
|
||||
public FeeItemEntity findItemByCode(long tenantId, String feeCode) {
|
||||
public FeeItemEntity findItemByCode(String feeCode) {
|
||||
return feeItems.selectOne(new LambdaQueryWrapper<FeeItemEntity>()
|
||||
.eq(FeeItemEntity::getTenantId, tenantId)
|
||||
.eq(FeeItemEntity::getTenantId, PLATFORM_TENANT_ID)
|
||||
.eq(FeeItemEntity::getFeeCode, feeCode));
|
||||
}
|
||||
|
||||
public boolean itemNameExists(long tenantId, String tradeScope, String feeTypeName, Long excludedId) {
|
||||
public boolean itemNameExists(String tradeScope, String feeTypeName, Long excludedId) {
|
||||
return feeItems.selectCount(new LambdaQueryWrapper<FeeItemEntity>()
|
||||
.eq(FeeItemEntity::getTenantId, tenantId)
|
||||
.eq(FeeItemEntity::getTenantId, PLATFORM_TENANT_ID)
|
||||
.eq(FeeItemEntity::getTradeScope, tradeScope)
|
||||
.eq(FeeItemEntity::getFeeTypeName, feeTypeName)
|
||||
.ne(excludedId != null, FeeItemEntity::getId, excludedId)) > 0;
|
||||
}
|
||||
|
||||
public boolean itemCodeExists(String feeCode, Long excludedId) {
|
||||
return feeItems.selectCount(new LambdaQueryWrapper<FeeItemEntity>()
|
||||
.eq(FeeItemEntity::getTenantId, PLATFORM_TENANT_ID)
|
||||
.eq(FeeItemEntity::getFeeCode, feeCode)
|
||||
.ne(excludedId != null, FeeItemEntity::getId, excludedId)) > 0;
|
||||
}
|
||||
|
||||
public void insertItem(FeeItemEntity item) {
|
||||
item.setTenantId(PLATFORM_TENANT_ID);
|
||||
feeItems.insert(item);
|
||||
}
|
||||
|
||||
public int updateItem(FeeItemEntity item) {
|
||||
item.setTenantId(PLATFORM_TENANT_ID);
|
||||
return feeItems.update(item, new LambdaUpdateWrapper<FeeItemEntity>()
|
||||
.eq(FeeItemEntity::getTenantId, item.getTenantId())
|
||||
.eq(FeeItemEntity::getTenantId, PLATFORM_TENANT_ID)
|
||||
.eq(FeeItemEntity::getId, item.getId()));
|
||||
}
|
||||
|
||||
public int deleteItem(long tenantId, long id) {
|
||||
public int deleteItem(long id) {
|
||||
return feeItems.delete(new LambdaQueryWrapper<FeeItemEntity>()
|
||||
.eq(FeeItemEntity::getTenantId, tenantId)
|
||||
.eq(FeeItemEntity::getTenantId, PLATFORM_TENANT_ID)
|
||||
.eq(FeeItemEntity::getId, id));
|
||||
}
|
||||
|
||||
public long countBindings(long tenantId, long feeItemId) {
|
||||
public long countBindings(long feeItemId) {
|
||||
return feeDetails.selectCount(new LambdaQueryWrapper<InboundFeeDetailEntity>()
|
||||
.eq(InboundFeeDetailEntity::getTenantId, tenantId)
|
||||
.eq(InboundFeeDetailEntity::getFeeItemId, feeItemId));
|
||||
}
|
||||
|
||||
|
||||
@@ -7,54 +7,69 @@ import com.baiyue.firstleg.dto.FeeItemDtos.SaveRequest;
|
||||
import com.baiyue.firstleg.entity.FeeItemEntity;
|
||||
import com.baiyue.firstleg.repository.FeeItemRepository;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/** 费用项目主数据应用服务。 */
|
||||
@Service
|
||||
public class FeeItemService {
|
||||
private static final long PLATFORM_TENANT_ID = 0L;
|
||||
@Resource
|
||||
private FeeItemRepository repository;
|
||||
|
||||
public PageResult<FeeItemEntity> list(long tenantId, String category, String tradeScope,
|
||||
public PageResult<FeeItemEntity> list(String category, String tradeScope,
|
||||
String keyword, String status, long page, long size) {
|
||||
return repository.listItems(tenantId, category, tradeScope, keyword, status, page, size);
|
||||
return repository.listItems(category, tradeScope, keyword, status, page, size);
|
||||
}
|
||||
|
||||
public FeeItemEntity detail(long tenantId, long id) {
|
||||
return required(tenantId, id);
|
||||
public FeeItemEntity detail(long id) {
|
||||
return required(id);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public FeeItemEntity create(long tenantId, long operatorId, String operatorName, SaveRequest request) {
|
||||
ensureUnique(tenantId, request, null);
|
||||
public FeeItemEntity create(long operatorId, String operatorName, SaveRequest request) {
|
||||
ensureUnique(request, null);
|
||||
FeeItemEntity value = new FeeItemEntity();
|
||||
value.setTenantId(tenantId);
|
||||
value.setTenantId(PLATFORM_TENANT_ID);
|
||||
copy(value, request);
|
||||
if (value.getFeeCode() == null || value.getFeeCode().isBlank()) {
|
||||
value.setFeeCode("MANUAL_" + UUID.randomUUID().toString().replace("-", "").substring(0, 24));
|
||||
}
|
||||
value.setStatus("ACTIVE");
|
||||
value.setCreatedBy(operatorId);
|
||||
value.setUpdatedBy(operatorId);
|
||||
value.setCreatedByName(operatorName);
|
||||
value.setUpdatedByName(operatorName);
|
||||
repository.insertItem(value);
|
||||
try {
|
||||
repository.insertItem(value);
|
||||
} catch (DuplicateKeyException exception) {
|
||||
throw conflict("费用项目编码已存在");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public FeeItemEntity update(long tenantId, long id, long operatorId, String operatorName,
|
||||
public FeeItemEntity update(long id, long operatorId, String operatorName,
|
||||
SaveRequest request) {
|
||||
FeeItemEntity value = required(tenantId, id);
|
||||
ensureUnique(tenantId, request, id);
|
||||
FeeItemEntity value = required(id);
|
||||
ensureUnique(request, id);
|
||||
copy(value, request);
|
||||
value.setUpdatedBy(operatorId);
|
||||
value.setUpdatedByName(operatorName);
|
||||
if (repository.updateItem(value) != 1) throw conflict("费用项目已被其他人修改,请刷新后重试");
|
||||
return required(tenantId, id);
|
||||
try {
|
||||
if (repository.updateItem(value) != 1) throw conflict("费用项目已被其他人修改,请刷新后重试");
|
||||
} catch (DuplicateKeyException exception) {
|
||||
throw conflict("费用项目编码已存在");
|
||||
}
|
||||
return required(id);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void changeStatus(long tenantId, long id, long operatorId, String operatorName, String status) {
|
||||
FeeItemEntity value = required(tenantId, id);
|
||||
public void changeStatus(long id, long operatorId, String operatorName, String status) {
|
||||
FeeItemEntity value = required(id);
|
||||
value.setStatus(status);
|
||||
value.setUpdatedBy(operatorId);
|
||||
value.setUpdatedByName(operatorName);
|
||||
@@ -62,22 +77,26 @@ public class FeeItemService {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void delete(long tenantId, long id) {
|
||||
required(tenantId, id);
|
||||
if (repository.countBindings(tenantId, id) > 0) {
|
||||
public void delete(long id) {
|
||||
required(id);
|
||||
if (repository.countBindings(id) > 0) {
|
||||
throw conflict("费用项目已被入库费用明细使用,只能停用,不能删除");
|
||||
}
|
||||
if (repository.deleteItem(tenantId, id) != 1) throw conflict("费用项目删除冲突");
|
||||
if (repository.deleteItem(id) != 1) throw conflict("费用项目删除冲突");
|
||||
}
|
||||
|
||||
private FeeItemEntity required(long tenantId, long id) {
|
||||
FeeItemEntity value = repository.findItem(tenantId, id);
|
||||
private FeeItemEntity required(long id) {
|
||||
FeeItemEntity value = repository.findItem(id);
|
||||
if (value == null) throw new BizException(ResultCode.NOT_FOUND, "费用项目不存在");
|
||||
return value;
|
||||
}
|
||||
|
||||
private void ensureUnique(long tenantId, SaveRequest request, Long excludedId) {
|
||||
if (repository.itemNameExists(tenantId, request.tradeScope(), request.feeTypeName(), excludedId)) {
|
||||
private void ensureUnique(SaveRequest request, Long excludedId) {
|
||||
if (request.feeCode() != null && !request.feeCode().isBlank()
|
||||
&& repository.itemCodeExists(request.feeCode().trim().toUpperCase(), excludedId)) {
|
||||
throw conflict("费用项目编码已存在");
|
||||
}
|
||||
if (repository.itemNameExists(request.tradeScope(), request.feeTypeName(), excludedId)) {
|
||||
throw conflict("相同国内国际范围下的费用类型名称已存在");
|
||||
}
|
||||
}
|
||||
@@ -85,6 +104,8 @@ public class FeeItemService {
|
||||
private static void copy(FeeItemEntity value, SaveRequest request) {
|
||||
value.setCategory(request.category().trim());
|
||||
value.setTradeScope(request.tradeScope());
|
||||
value.setFeeCode(request.feeCode() == null || request.feeCode().isBlank()
|
||||
? value.getFeeCode() : request.feeCode().trim().toUpperCase());
|
||||
value.setFeeTypeName(request.feeTypeName().trim());
|
||||
value.setPickupPayable(request.pickupPayable());
|
||||
value.setPickupReceivable(request.pickupReceivable());
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.List;
|
||||
/** 入库单人工费用明细应用服务。 */
|
||||
@Service
|
||||
public class InboundFeeDetailService {
|
||||
private static final long PLATFORM_TENANT_ID = 0L;
|
||||
private static final String FREIGHT_FEE_CODE = "FBA_HEAD_FREIGHT";
|
||||
@Resource
|
||||
private FeeItemRepository repository;
|
||||
@@ -56,7 +57,7 @@ public class InboundFeeDetailService {
|
||||
throw conflict("只有已发送状态的计费快照才能生成客户运费明细");
|
||||
}
|
||||
LocalDateTime now = publishedAt == null ? LocalDateTime.now() : publishedAt;
|
||||
FeeItemEntity feeItem = requiredFreightItem(tenantId, operatorId, operatorName);
|
||||
FeeItemEntity feeItem = requiredFreightItem(operatorId, operatorName);
|
||||
InboundFeeItemEntity baseItem = pricingRepository.findBaseItem(tenantId, feeId);
|
||||
repository.supersedePublishedFreight(tenantId, inboundId, feeId, operatorId, now);
|
||||
|
||||
@@ -123,7 +124,7 @@ public class InboundFeeDetailService {
|
||||
public InboundFeeDetailEntity create(long tenantId, long inboundId, long operatorId,
|
||||
SaveRequest request) {
|
||||
InboundOrderEntity inbound = requiredInbound(tenantId, inboundId);
|
||||
FeeItemEntity item = requiredActiveItem(tenantId, request.feeItemId());
|
||||
FeeItemEntity item = requiredActiveItem(request.feeItemId());
|
||||
InboundFeeDetailEntity value = new InboundFeeDetailEntity();
|
||||
value.setTenantId(tenantId);
|
||||
value.setInboundId(inboundId);
|
||||
@@ -142,7 +143,7 @@ public class InboundFeeDetailService {
|
||||
long operatorId, SaveRequest request) {
|
||||
InboundFeeDetailEntity value = requiredEditable(tenantId, inboundId, detailId);
|
||||
InboundOrderEntity inbound = requiredInbound(tenantId, inboundId);
|
||||
FeeItemEntity item = requiredActiveItem(tenantId, request.feeItemId());
|
||||
FeeItemEntity item = requiredActiveItem(request.feeItemId());
|
||||
apply(value, inbound, item, request, operatorId);
|
||||
value.setReviewStatus("PENDING");
|
||||
value.setReviewerId(null);
|
||||
@@ -185,21 +186,21 @@ public class InboundFeeDetailService {
|
||||
return value;
|
||||
}
|
||||
|
||||
private FeeItemEntity requiredActiveItem(long tenantId, long itemId) {
|
||||
FeeItemEntity value = repository.findItem(tenantId, itemId);
|
||||
private FeeItemEntity requiredActiveItem(long itemId) {
|
||||
FeeItemEntity value = repository.findItem(itemId);
|
||||
if (value == null) throw new BizException(ResultCode.NOT_FOUND, "费用项目不存在");
|
||||
if (!"ACTIVE".equals(value.getStatus())) throw conflict("费用项目已停用,不能绑定");
|
||||
return value;
|
||||
}
|
||||
|
||||
private FeeItemEntity requiredFreightItem(long tenantId, long operatorId, String operatorName) {
|
||||
FeeItemEntity item = repository.findItemByCode(tenantId, FREIGHT_FEE_CODE);
|
||||
private FeeItemEntity requiredFreightItem(long operatorId, String operatorName) {
|
||||
FeeItemEntity item = repository.findItemByCode(FREIGHT_FEE_CODE);
|
||||
if (item != null) {
|
||||
if (!"ACTIVE".equals(item.getStatus())) throw conflict("系统费用项目FBA头程运费已停用");
|
||||
return item;
|
||||
}
|
||||
FeeItemEntity created = new FeeItemEntity();
|
||||
created.setTenantId(tenantId);
|
||||
created.setTenantId(PLATFORM_TENANT_ID);
|
||||
created.setCategory("头程运费");
|
||||
created.setTradeScope("INTERNATIONAL");
|
||||
created.setFeeCode(FREIGHT_FEE_CODE);
|
||||
@@ -219,8 +220,13 @@ public class InboundFeeDetailService {
|
||||
repository.insertItem(created);
|
||||
return created;
|
||||
} catch (DuplicateKeyException exception) {
|
||||
FeeItemEntity concurrent = repository.findItemByCode(tenantId, FREIGHT_FEE_CODE);
|
||||
if (concurrent != null) return concurrent;
|
||||
FeeItemEntity concurrent = repository.findItemByCode(FREIGHT_FEE_CODE);
|
||||
if (concurrent != null) {
|
||||
if (!"ACTIVE".equals(concurrent.getStatus())) {
|
||||
throw conflict("系统费用项目FBA头程运费已停用");
|
||||
}
|
||||
return concurrent;
|
||||
}
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,8 @@ public class PdaPickSettlementService {
|
||||
ParentRow parent = rootInboundId == parentInboundId ? root : splits.lockParent(parentInboundId);
|
||||
if (parent == null || parent.tenantId() == null || parent.tenantId() <= 0
|
||||
|| !("MASTER".equals(parent.inboundRole()) || "CHILD".equals(parent.inboundRole()))
|
||||
|| !"INBOUNDED".equals(parent.processStatus())) {
|
||||
|| !("INBOUNDED".equals(parent.processStatus()) || "LOADING".equals(parent.processStatus()))
|
||||
|| ("MASTER".equals(parent.inboundRole()) && "FULLY_SPLIT".equals(parent.splitStatus()))) {
|
||||
throw conflict("待拆分主入库单不在可拆分状态");
|
||||
}
|
||||
String operationId = "PDA-SPLIT-" + taskId + '-' + parentInboundId;
|
||||
@@ -109,7 +110,7 @@ public class PdaPickSettlementService {
|
||||
long loadingPlanId = task.getLoadingPlanId();
|
||||
Long containerBookingId = splits.containerBookingId(loadingPlanId);
|
||||
if (containerBookingId == null) throw conflict("PDA任务装柜计划缺少真实柜次");
|
||||
int parentAvailable = count(parent.packageCount(), "主入库单可用箱数");
|
||||
int parentAvailable = availablePackageCount(parent);
|
||||
if (pickedPackageCount <= 0 || pickedPackageCount > parentAvailable) {
|
||||
throw conflict("本次已拣箱数与主入库单可用箱数不一致");
|
||||
}
|
||||
@@ -457,6 +458,14 @@ public class PdaPickSettlementService {
|
||||
return value;
|
||||
}
|
||||
|
||||
private static int availablePackageCount(ParentRow parent) {
|
||||
if ("FULLY_SPLIT".equals(parent.splitStatus())) return 0;
|
||||
Integer available = parent.packageCount();
|
||||
if (available != null && available > 0) return available;
|
||||
if (available != null && available == 0 && !"NOT_SPLIT".equals(parent.splitStatus())) return 0;
|
||||
return count(parent.totalPackageCount(), "主入库单可用箱数");
|
||||
}
|
||||
|
||||
private static void requireAffected(int affected, String resource) {
|
||||
if (affected != 1) {
|
||||
throw conflict(resource + "已被并发修改,请刷新后重试");
|
||||
|
||||
Reference in New Issue
Block a user