优化
This commit is contained in:
+6
-6
@@ -3,7 +3,7 @@ package com.baiyue.firstleg.controller;
|
||||
import com.baiyue.common.audit.BusinessAudit;
|
||||
import com.baiyue.common.core.api.ApiResponse;
|
||||
import com.baiyue.common.security.AuthenticatedUser;
|
||||
import com.baiyue.firstleg.dto.CustomerDimensionConfigDtos.Response;
|
||||
import com.baiyue.firstleg.dto.CustomerDimensionConfigDtos.GroupResponse;
|
||||
import com.baiyue.firstleg.dto.CustomerDimensionConfigDtos.UpdateRequest;
|
||||
import com.baiyue.firstleg.service.CustomerDimensionConfigService;
|
||||
import com.baiyue.firstleg.service.FirstlegScopeGuard;
|
||||
@@ -30,8 +30,8 @@ public class PlatformCustomerDimensionConfigController {
|
||||
@GetMapping
|
||||
@PreAuthorize("hasAuthority('firstleg:dimension-config:view')")
|
||||
@Operation(summary = "查询客户尺寸计算配置")
|
||||
public ApiResponse<Response> get(@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@RequestParam long tenantId) {
|
||||
public ApiResponse<GroupResponse> get(@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@RequestParam long tenantId) {
|
||||
return ApiResponse.success(service.get(FirstlegScopeGuard.platform(user, tenantId)));
|
||||
}
|
||||
|
||||
@@ -41,9 +41,9 @@ public class PlatformCustomerDimensionConfigController {
|
||||
resourceType = "DIMENSION_CONFIG", resourceId = "#tenantId",
|
||||
description = "平台编辑客户尺寸计算配置")
|
||||
@Operation(summary = "编辑客户尺寸计算配置")
|
||||
public ApiResponse<Response> update(@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@RequestParam long tenantId,
|
||||
@Valid @RequestBody UpdateRequest request) {
|
||||
public ApiResponse<GroupResponse> update(@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@RequestParam long tenantId,
|
||||
@Valid @RequestBody UpdateRequest request) {
|
||||
long scope = FirstlegScopeGuard.platform(user, tenantId);
|
||||
return ApiResponse.success(service.update(scope, user.userId(), request));
|
||||
}
|
||||
|
||||
+17
@@ -21,6 +21,7 @@ import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
@@ -167,6 +168,22 @@ public class PlatformInboundMeasurementController {
|
||||
tenantId, inboundId, resultId, user.userId(), user.username(), request));
|
||||
}
|
||||
|
||||
@BusinessAudit(event = "INBOUND_WEIGHT_IMAGE_DELETE", resourceType = "INBOUND_WEIGHT_RESULT",
|
||||
resourceId = "#resultId", description = "删除称重图片及重量结果")
|
||||
@Operation(summary = "删除称重图片", description = "删除重量结果和文件;已确认图片删除后重新汇总实际总毛重。")
|
||||
@DeleteMapping("/weight-results/{resultId}")
|
||||
@PreAuthorize("hasAuthority('platform:firstleg:inbound:weight:edit')")
|
||||
public ApiResponse<Void> deleteWeightResult(
|
||||
@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@RequestParam long tenantId,
|
||||
@RequestParam int version,
|
||||
@PathVariable long inboundId,
|
||||
@PathVariable long resultId) {
|
||||
requirePlatformTenant(user, tenantId);
|
||||
service.deleteWeightResult(tenantId, inboundId, resultId, version, user.userId());
|
||||
return ApiResponse.success(null);
|
||||
}
|
||||
|
||||
private static void requirePlatformTenant(AuthenticatedUser user, long tenantId) {
|
||||
FirstlegScopeGuard.platform(user, tenantId);
|
||||
if (user.userId() == null || user.userId() <= 0) {
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.baiyue.firstleg.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/** 平台固定维护的四种客户箱规,不允许扩展或改名。 */
|
||||
public enum CustomerDimensionBoxType {
|
||||
SMALL("小箱", "30.000", "20.000", "20.000", "标准小箱"),
|
||||
MEDIUM("中箱", "40.000", "30.000", "30.000", "标准中箱"),
|
||||
LARGE("大箱", "50.000", "40.000", "40.000", "标准大箱"),
|
||||
EXTRA_LARGE("特大箱", "60.000", "50.000", "50.000", "特大箱");
|
||||
|
||||
private final String displayName;
|
||||
private final BigDecimal defaultLengthCm;
|
||||
private final BigDecimal defaultWidthCm;
|
||||
private final BigDecimal defaultHeightCm;
|
||||
private final String defaultRemark;
|
||||
|
||||
CustomerDimensionBoxType(String displayName, String defaultLengthCm, String defaultWidthCm,
|
||||
String defaultHeightCm, String defaultRemark) {
|
||||
this.displayName = displayName;
|
||||
this.defaultLengthCm = new BigDecimal(defaultLengthCm);
|
||||
this.defaultWidthCm = new BigDecimal(defaultWidthCm);
|
||||
this.defaultHeightCm = new BigDecimal(defaultHeightCm);
|
||||
this.defaultRemark = defaultRemark;
|
||||
}
|
||||
|
||||
public String displayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public BigDecimal defaultLengthCm() {
|
||||
return defaultLengthCm;
|
||||
}
|
||||
|
||||
public BigDecimal defaultWidthCm() {
|
||||
return defaultWidthCm;
|
||||
}
|
||||
|
||||
public BigDecimal defaultHeightCm() {
|
||||
return defaultHeightCm;
|
||||
}
|
||||
|
||||
public String defaultRemark() {
|
||||
return defaultRemark;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.baiyue.firstleg.dto;
|
||||
|
||||
import com.baiyue.firstleg.domain.CustomerDimensionBoxType;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.DecimalMax;
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import jakarta.validation.constraints.Digits;
|
||||
@@ -10,21 +12,40 @@ import jakarta.validation.constraints.Size;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
public final class CustomerDimensionConfigDtos {
|
||||
private CustomerDimensionConfigDtos() { }
|
||||
|
||||
public record UpdateRequest(
|
||||
@NotNull @Size(min = 4, max = 4) List<@Valid RuleUpdateRequest> rules
|
||||
) { }
|
||||
|
||||
public record RuleUpdateRequest(
|
||||
@NotNull CustomerDimensionBoxType boxType,
|
||||
@NotNull @DecimalMin("0.001") @Digits(integer = 6, fraction = 3) BigDecimal innerLengthCm,
|
||||
@NotNull @DecimalMin("0.001") @Digits(integer = 6, fraction = 3) BigDecimal innerWidthCm,
|
||||
@NotNull @DecimalMin("0.001") @Digits(integer = 6, fraction = 3) BigDecimal innerHeightCm,
|
||||
@NotNull @DecimalMin("0.001") @DecimalMax("100.000") @Digits(integer = 3, fraction = 3)
|
||||
BigDecimal edgeAdditionCm,
|
||||
@Size(max = 500) String remark,
|
||||
@NotNull @Min(0) Integer version
|
||||
) { }
|
||||
|
||||
public record Response(
|
||||
public record GroupResponse(Long tenantId, List<RuleResponse> rules) { }
|
||||
|
||||
public record RuleResponse(
|
||||
Long id,
|
||||
Long tenantId,
|
||||
CustomerDimensionBoxType boxType,
|
||||
String boxTypeName,
|
||||
BigDecimal innerLengthCm,
|
||||
BigDecimal innerWidthCm,
|
||||
BigDecimal innerHeightCm,
|
||||
BigDecimal edgeAdditionCm,
|
||||
BigDecimal outerLengthCm,
|
||||
BigDecimal outerWidthCm,
|
||||
BigDecimal outerHeightCm,
|
||||
BigDecimal volumeCbm,
|
||||
String remark,
|
||||
Integer version,
|
||||
LocalDateTime createdAt,
|
||||
|
||||
+6
-1
@@ -4,12 +4,13 @@ import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baiyue.common.core.model.BaseEntity;
|
||||
import com.baiyue.firstleg.domain.CustomerDimensionBoxType;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/** 客户填写真实尺寸后使用的每侧加宽配置。 */
|
||||
/** 客户固定箱规的内径和每侧加宽配置。 */
|
||||
@Getter
|
||||
@Setter
|
||||
@TableName("fl_customer_dimension_config")
|
||||
@@ -17,6 +18,10 @@ public class CustomerDimensionConfigEntity extends BaseEntity {
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
private Long tenantId;
|
||||
private CustomerDimensionBoxType boxType;
|
||||
private BigDecimal innerLengthCm;
|
||||
private BigDecimal innerWidthCm;
|
||||
private BigDecimal innerHeightCm;
|
||||
private BigDecimal edgeAdditionCm;
|
||||
private String remark;
|
||||
private String initializationKey;
|
||||
|
||||
+43
-14
@@ -5,33 +5,62 @@ import com.baiyue.firstleg.entity.CustomerDimensionConfigEntity;
|
||||
import org.apache.ibatis.annotations.Delete;
|
||||
import org.apache.ibatis.annotations.Insert;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
public interface CustomerDimensionConfigMapper extends BaseMapper<CustomerDimensionConfigEntity> {
|
||||
@Insert("""
|
||||
<script>
|
||||
INSERT IGNORE INTO fl_customer_dimension_config
|
||||
(id, tenant_id, edge_addition_cm, remark, initialization_key, created_by, created_at,
|
||||
(id, tenant_id, box_type, inner_length_cm, inner_width_cm, inner_height_cm,
|
||||
edge_addition_cm, remark, initialization_key, created_by, created_at,
|
||||
updated_by, updated_at, deleted, version)
|
||||
VALUES
|
||||
(#{id}, #{tenantId}, #{edgeAdditionCm}, #{remark}, #{initializationKey}, #{operatorId}, CURRENT_TIMESTAMP(3),
|
||||
#{operatorId}, CURRENT_TIMESTAMP(3), 0, 0)
|
||||
<foreach collection="rows" item="row" separator=",">
|
||||
(#{row.id}, #{row.tenantId}, #{row.boxType}, #{row.innerLengthCm}, #{row.innerWidthCm},
|
||||
#{row.innerHeightCm}, #{row.edgeAdditionCm}, #{row.remark}, #{row.initializationKey},
|
||||
#{operatorId}, CURRENT_TIMESTAMP(3), #{operatorId}, CURRENT_TIMESTAMP(3), 0, 0)
|
||||
</foreach>
|
||||
</script>
|
||||
""")
|
||||
int insertDefault(@Param("id") long id, @Param("tenantId") long tenantId,
|
||||
@Param("edgeAdditionCm") BigDecimal edgeAdditionCm,
|
||||
@Param("remark") String remark, @Param("initializationKey") String initializationKey,
|
||||
@Param("operatorId") long operatorId);
|
||||
int insertDefaults(@Param("rows") List<CustomerDimensionConfigEntity> rows,
|
||||
@Param("operatorId") long operatorId);
|
||||
|
||||
@Select("""
|
||||
SELECT id, tenant_id, box_type, inner_length_cm, inner_width_cm, inner_height_cm,
|
||||
edge_addition_cm, remark, initialization_key, created_by, created_at,
|
||||
updated_by, updated_at, deleted, version
|
||||
FROM fl_customer_dimension_config
|
||||
WHERE tenant_id = #{tenantId}
|
||||
AND initialization_key = #{initializationKey}
|
||||
AND deleted = 0
|
||||
FOR UPDATE
|
||||
""")
|
||||
List<CustomerDimensionConfigEntity> selectDefaultsForCompensation(
|
||||
@Param("tenantId") long tenantId, @Param("initializationKey") String initializationKey);
|
||||
|
||||
@Delete("""
|
||||
DELETE FROM fl_customer_dimension_config
|
||||
WHERE id = #{id}
|
||||
AND tenant_id = #{tenantId}
|
||||
WHERE tenant_id = #{tenantId}
|
||||
AND initialization_key = #{initializationKey}
|
||||
AND edge_addition_cm = #{edgeAdditionCm}
|
||||
AND version = 0
|
||||
AND deleted = 0
|
||||
AND box_type IN ('SMALL', 'MEDIUM', 'LARGE', 'EXTRA_LARGE')
|
||||
AND inner_length_cm = CASE box_type
|
||||
WHEN 'SMALL' THEN 30.000 WHEN 'MEDIUM' THEN 40.000
|
||||
WHEN 'LARGE' THEN 50.000 WHEN 'EXTRA_LARGE' THEN 60.000 END
|
||||
AND inner_width_cm = CASE box_type
|
||||
WHEN 'SMALL' THEN 20.000 WHEN 'MEDIUM' THEN 30.000
|
||||
WHEN 'LARGE' THEN 40.000 WHEN 'EXTRA_LARGE' THEN 50.000 END
|
||||
AND inner_height_cm = CASE box_type
|
||||
WHEN 'SMALL' THEN 20.000 WHEN 'MEDIUM' THEN 30.000
|
||||
WHEN 'LARGE' THEN 40.000 WHEN 'EXTRA_LARGE' THEN 50.000 END
|
||||
AND edge_addition_cm = 2.000
|
||||
AND remark = CASE box_type
|
||||
WHEN 'SMALL' THEN '标准小箱' WHEN 'MEDIUM' THEN '标准中箱'
|
||||
WHEN 'LARGE' THEN '标准大箱' WHEN 'EXTRA_LARGE' THEN '特大箱' END
|
||||
""")
|
||||
int deleteUnchangedDefault(@Param("tenantId") long tenantId, @Param("id") long id,
|
||||
@Param("initializationKey") String initializationKey,
|
||||
@Param("edgeAdditionCm") BigDecimal edgeAdditionCm);
|
||||
int deleteUnchangedDefaults(@Param("tenantId") long tenantId,
|
||||
@Param("initializationKey") String initializationKey);
|
||||
}
|
||||
|
||||
+12
-9
@@ -6,29 +6,32 @@ import com.baiyue.firstleg.mapper.CustomerDimensionConfigMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public class CustomerDimensionConfigRepository {
|
||||
@Resource
|
||||
private CustomerDimensionConfigMapper mapper;
|
||||
|
||||
public CustomerDimensionConfigEntity find(long tenantId) {
|
||||
return mapper.selectOne(new LambdaQueryWrapper<CustomerDimensionConfigEntity>()
|
||||
public List<CustomerDimensionConfigEntity> findAll(long tenantId) {
|
||||
return mapper.selectList(new LambdaQueryWrapper<CustomerDimensionConfigEntity>()
|
||||
.eq(CustomerDimensionConfigEntity::getTenantId, tenantId));
|
||||
}
|
||||
|
||||
public boolean insertDefault(long id, long tenantId, BigDecimal edgeAdditionCm,
|
||||
String remark, String initializationKey, long operatorId) {
|
||||
return mapper.insertDefault(id, tenantId, edgeAdditionCm, remark, initializationKey, operatorId) == 1;
|
||||
public int insertDefaults(List<CustomerDimensionConfigEntity> rows, long operatorId) {
|
||||
return mapper.insertDefaults(rows, operatorId);
|
||||
}
|
||||
|
||||
public int update(CustomerDimensionConfigEntity value) {
|
||||
return mapper.updateById(value);
|
||||
}
|
||||
|
||||
public int deleteUnchangedDefault(long tenantId, long id, String initializationKey,
|
||||
BigDecimal edgeAdditionCm) {
|
||||
return mapper.deleteUnchangedDefault(tenantId, id, initializationKey, edgeAdditionCm);
|
||||
public List<CustomerDimensionConfigEntity> findDefaultsForCompensation(long tenantId,
|
||||
String initializationKey) {
|
||||
return mapper.selectDefaultsForCompensation(tenantId, initializationKey);
|
||||
}
|
||||
|
||||
public int deleteUnchangedDefaults(long tenantId, String initializationKey) {
|
||||
return mapper.deleteUnchangedDefaults(tenantId, initializationKey);
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -157,6 +157,14 @@ public class InboundMeasurementRepository {
|
||||
.eq(InboundWeightResultEntity::getId, weight.getId())) == 1;
|
||||
}
|
||||
|
||||
public boolean deleteWeight(long tenantId, long inboundId, long resultId, int expectedVersion) {
|
||||
return weights.delete(new LambdaQueryWrapper<InboundWeightResultEntity>()
|
||||
.eq(InboundWeightResultEntity::getTenantId, tenantId)
|
||||
.eq(InboundWeightResultEntity::getInboundId, inboundId)
|
||||
.eq(InboundWeightResultEntity::getId, resultId)
|
||||
.eq(InboundWeightResultEntity::getVersion, expectedVersion)) == 1;
|
||||
}
|
||||
|
||||
|
||||
public void insertRevision(InboundWeightRevisionEntity revision) {
|
||||
revisions.insert(revision);
|
||||
|
||||
+184
-41
@@ -3,8 +3,11 @@ package com.baiyue.firstleg.service;
|
||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import com.baiyue.common.core.api.ResultCode;
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
import com.baiyue.firstleg.domain.CustomerDimensionBoxType;
|
||||
import com.baiyue.firstleg.dto.CustomerDimensionConfigDtos.GroupResponse;
|
||||
import com.baiyue.firstleg.dto.CustomerDimensionConfigDtos.InitializeResponse;
|
||||
import com.baiyue.firstleg.dto.CustomerDimensionConfigDtos.Response;
|
||||
import com.baiyue.firstleg.dto.CustomerDimensionConfigDtos.RuleResponse;
|
||||
import com.baiyue.firstleg.dto.CustomerDimensionConfigDtos.RuleUpdateRequest;
|
||||
import com.baiyue.firstleg.dto.CustomerDimensionConfigDtos.UpdateRequest;
|
||||
import com.baiyue.firstleg.entity.CustomerDimensionConfigEntity;
|
||||
import com.baiyue.firstleg.repository.CustomerDimensionConfigRepository;
|
||||
@@ -13,75 +16,215 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/** 管理每个客户唯一的尺寸加边配置,不参与当前订单或计费计算。 */
|
||||
/** 管理每个客户固定四种箱规的尺寸配置,不参与当前订单或计费计算。 */
|
||||
@Service
|
||||
public class CustomerDimensionConfigService {
|
||||
public static final BigDecimal DEFAULT_EDGE_ADDITION_CM = new BigDecimal("2.000");
|
||||
private static final String DEFAULT_REMARK = "默认每侧加宽 2cm";
|
||||
private static final BigDecimal TWO = new BigDecimal("2");
|
||||
private static final BigDecimal CUBIC_CENTIMETERS_PER_CBM = new BigDecimal("1000000");
|
||||
|
||||
@Resource
|
||||
private CustomerDimensionConfigRepository repository;
|
||||
|
||||
public Response get(long tenantId) {
|
||||
CustomerDimensionConfigEntity value = repository.find(tenantId);
|
||||
if (value == null) {
|
||||
throw new BizException(ResultCode.NOT_FOUND, "客户尺寸计算配置不存在");
|
||||
}
|
||||
return response(value);
|
||||
public GroupResponse get(long tenantId) {
|
||||
return response(tenantId, requireCompleteRules(repository.findAll(tenantId)));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Response update(long tenantId, long operatorId, UpdateRequest request) {
|
||||
CustomerDimensionConfigEntity value = repository.find(tenantId);
|
||||
if (value == null) {
|
||||
throw new BizException(ResultCode.NOT_FOUND, "客户尺寸计算配置不存在");
|
||||
public GroupResponse update(long tenantId, long operatorId, UpdateRequest request) {
|
||||
Map<CustomerDimensionBoxType, RuleUpdateRequest> requested = requireFixedRuleSet(request);
|
||||
List<CustomerDimensionConfigEntity> existing = requireCompleteRules(repository.findAll(tenantId));
|
||||
Map<CustomerDimensionBoxType, CustomerDimensionConfigEntity> persisted = index(existing);
|
||||
|
||||
for (CustomerDimensionBoxType type : CustomerDimensionBoxType.values()) {
|
||||
CustomerDimensionConfigEntity value = persisted.get(type);
|
||||
if (!value.getVersion().equals(requested.get(type).version())) {
|
||||
throw staleConfiguration();
|
||||
}
|
||||
}
|
||||
if (!value.getVersion().equals(request.version())) {
|
||||
throw new BizException(ResultCode.CONFLICT, "尺寸计算配置已被修改,请刷新后重试");
|
||||
|
||||
for (CustomerDimensionBoxType type : CustomerDimensionBoxType.values()) {
|
||||
CustomerDimensionConfigEntity value = persisted.get(type);
|
||||
RuleUpdateRequest update = requested.get(type);
|
||||
value.setInnerLengthCm(update.innerLengthCm());
|
||||
value.setInnerWidthCm(update.innerWidthCm());
|
||||
value.setInnerHeightCm(update.innerHeightCm());
|
||||
value.setEdgeAdditionCm(update.edgeAdditionCm());
|
||||
value.setRemark(normalizeRemark(update.remark()));
|
||||
value.setUpdatedBy(operatorId);
|
||||
if (repository.update(value) != 1) {
|
||||
throw staleConfiguration();
|
||||
}
|
||||
}
|
||||
value.setEdgeAdditionCm(request.edgeAdditionCm());
|
||||
value.setRemark(normalizeRemark(request.remark()));
|
||||
value.setUpdatedBy(operatorId);
|
||||
if (repository.update(value) != 1) {
|
||||
throw new BizException(ResultCode.CONFLICT, "尺寸计算配置已被修改,请刷新后重试");
|
||||
}
|
||||
return response(value);
|
||||
return response(tenantId, existing);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public InitializeResponse initializeDefault(long tenantId, long operatorId, String initializationKey) {
|
||||
requireTenant(tenantId);
|
||||
String normalizedKey = requireInitializationKey(initializationKey);
|
||||
CustomerDimensionConfigEntity existing = repository.find(tenantId);
|
||||
if (existing != null) {
|
||||
return new InitializeResponse(existing.getId(),
|
||||
normalizedKey.equals(existing.getInitializationKey()));
|
||||
List<CustomerDimensionConfigEntity> existing = repository.findAll(tenantId);
|
||||
if (!existing.isEmpty()) {
|
||||
List<CustomerDimensionConfigEntity> complete = requireCompleteRules(existing);
|
||||
return initializationResponse(complete, normalizedKey);
|
||||
}
|
||||
|
||||
long id = IdWorker.getId();
|
||||
boolean created = repository.insertDefault(id, tenantId, DEFAULT_EDGE_ADDITION_CM,
|
||||
DEFAULT_REMARK, normalizedKey, operatorId);
|
||||
CustomerDimensionConfigEntity persisted = repository.find(tenantId);
|
||||
if (persisted == null) {
|
||||
throw new BizException(ResultCode.INTERNAL_ERROR, "客户尺寸计算配置初始化失败");
|
||||
}
|
||||
boolean ownedByKey = normalizedKey.equals(persisted.getInitializationKey());
|
||||
return new InitializeResponse(persisted.getId(), created || ownedByKey);
|
||||
repository.insertDefaults(defaultRows(tenantId, normalizedKey), operatorId);
|
||||
List<CustomerDimensionConfigEntity> persisted = requireCompleteRules(repository.findAll(tenantId));
|
||||
return initializationResponse(persisted, normalizedKey);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void compensateDefault(long tenantId, String initializationKey) {
|
||||
requireTenant(tenantId);
|
||||
String normalizedKey = requireInitializationKey(initializationKey);
|
||||
CustomerDimensionConfigEntity existing = repository.find(tenantId);
|
||||
if (existing == null || !normalizedKey.equals(existing.getInitializationKey())) return;
|
||||
repository.deleteUnchangedDefault(tenantId, existing.getId(), normalizedKey, DEFAULT_EDGE_ADDITION_CM);
|
||||
List<CustomerDimensionConfigEntity> locked =
|
||||
repository.findDefaultsForCompensation(tenantId, normalizedKey);
|
||||
if (!isUnchangedDefaultGroup(locked, normalizedKey)) return;
|
||||
if (repository.deleteUnchangedDefaults(tenantId, normalizedKey) != CustomerDimensionBoxType.values().length) {
|
||||
throw new BizException(ResultCode.INTERNAL_ERROR, "客户箱规默认配置补偿删除失败");
|
||||
}
|
||||
}
|
||||
|
||||
private static Response response(CustomerDimensionConfigEntity value) {
|
||||
return new Response(value.getId(), value.getTenantId(), value.getEdgeAdditionCm(), value.getRemark(),
|
||||
value.getVersion(), value.getCreatedAt(), value.getUpdatedAt());
|
||||
private static Map<CustomerDimensionBoxType, RuleUpdateRequest> requireFixedRuleSet(UpdateRequest request) {
|
||||
if (request == null || request.rules() == null || request.rules().size() != CustomerDimensionBoxType.values().length) {
|
||||
throw new BizException(ResultCode.BAD_REQUEST, "必须完整提交固定四种箱规");
|
||||
}
|
||||
Map<CustomerDimensionBoxType, RuleUpdateRequest> values = new EnumMap<>(CustomerDimensionBoxType.class);
|
||||
for (RuleUpdateRequest rule : request.rules()) {
|
||||
if (rule == null || rule.boxType() == null || values.put(rule.boxType(), rule) != null) {
|
||||
throw new BizException(ResultCode.BAD_REQUEST, "箱规类型重复或无效");
|
||||
}
|
||||
requirePositive(rule.innerLengthCm(), "箱规内长");
|
||||
requirePositive(rule.innerWidthCm(), "箱规内宽");
|
||||
requirePositive(rule.innerHeightCm(), "箱规内高");
|
||||
requirePositive(rule.edgeAdditionCm(), "箱规单侧加宽");
|
||||
if (rule.version() == null || rule.version() < 0) {
|
||||
throw new BizException(ResultCode.BAD_REQUEST, "箱规版本号无效");
|
||||
}
|
||||
}
|
||||
if (values.size() != CustomerDimensionBoxType.values().length) {
|
||||
throw new BizException(ResultCode.BAD_REQUEST, "必须完整提交固定四种箱规");
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
private static List<CustomerDimensionConfigEntity> requireCompleteRules(
|
||||
List<CustomerDimensionConfigEntity> values) {
|
||||
if (values == null || values.isEmpty()) {
|
||||
throw new BizException(ResultCode.NOT_FOUND, "客户箱规尺寸配置不存在");
|
||||
}
|
||||
Map<CustomerDimensionBoxType, CustomerDimensionConfigEntity> indexed = index(values);
|
||||
if (values.size() != CustomerDimensionBoxType.values().length
|
||||
|| indexed.size() != CustomerDimensionBoxType.values().length) {
|
||||
throw new BizException(ResultCode.INTERNAL_ERROR, "客户箱规尺寸配置不完整");
|
||||
}
|
||||
List<CustomerDimensionConfigEntity> ordered = new ArrayList<>(CustomerDimensionBoxType.values().length);
|
||||
for (CustomerDimensionBoxType type : CustomerDimensionBoxType.values()) {
|
||||
CustomerDimensionConfigEntity value = indexed.get(type);
|
||||
if (value == null) {
|
||||
throw new BizException(ResultCode.INTERNAL_ERROR, "客户箱规尺寸配置不完整");
|
||||
}
|
||||
ordered.add(value);
|
||||
}
|
||||
return ordered;
|
||||
}
|
||||
|
||||
private static Map<CustomerDimensionBoxType, CustomerDimensionConfigEntity> index(
|
||||
List<CustomerDimensionConfigEntity> values) {
|
||||
Map<CustomerDimensionBoxType, CustomerDimensionConfigEntity> indexed =
|
||||
new EnumMap<>(CustomerDimensionBoxType.class);
|
||||
for (CustomerDimensionConfigEntity value : values) {
|
||||
if (value == null || value.getBoxType() == null || indexed.put(value.getBoxType(), value) != null) {
|
||||
throw new BizException(ResultCode.INTERNAL_ERROR, "客户箱规尺寸配置不完整");
|
||||
}
|
||||
}
|
||||
return indexed;
|
||||
}
|
||||
|
||||
private static List<CustomerDimensionConfigEntity> defaultRows(long tenantId, String initializationKey) {
|
||||
List<CustomerDimensionConfigEntity> rows = new ArrayList<>(CustomerDimensionBoxType.values().length);
|
||||
for (CustomerDimensionBoxType type : CustomerDimensionBoxType.values()) {
|
||||
CustomerDimensionConfigEntity value = new CustomerDimensionConfigEntity();
|
||||
value.setId(IdWorker.getId());
|
||||
value.setTenantId(tenantId);
|
||||
value.setBoxType(type);
|
||||
value.setInnerLengthCm(type.defaultLengthCm());
|
||||
value.setInnerWidthCm(type.defaultWidthCm());
|
||||
value.setInnerHeightCm(type.defaultHeightCm());
|
||||
value.setEdgeAdditionCm(DEFAULT_EDGE_ADDITION_CM);
|
||||
value.setRemark(type.defaultRemark());
|
||||
value.setInitializationKey(initializationKey);
|
||||
rows.add(value);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
private static boolean isUnchangedDefaultGroup(List<CustomerDimensionConfigEntity> values,
|
||||
String initializationKey) {
|
||||
if (values == null || values.size() != CustomerDimensionBoxType.values().length) return false;
|
||||
Map<CustomerDimensionBoxType, CustomerDimensionConfigEntity> indexed;
|
||||
try {
|
||||
indexed = index(values);
|
||||
} catch (BizException ignored) {
|
||||
return false;
|
||||
}
|
||||
for (CustomerDimensionBoxType type : CustomerDimensionBoxType.values()) {
|
||||
CustomerDimensionConfigEntity value = indexed.get(type);
|
||||
if (value == null || !initializationKey.equals(value.getInitializationKey())
|
||||
|| value.getVersion() == null || value.getVersion() != 0
|
||||
|| value.getInnerLengthCm() == null || value.getInnerWidthCm() == null
|
||||
|| value.getInnerHeightCm() == null || value.getEdgeAdditionCm() == null
|
||||
|| value.getInnerLengthCm().compareTo(type.defaultLengthCm()) != 0
|
||||
|| value.getInnerWidthCm().compareTo(type.defaultWidthCm()) != 0
|
||||
|| value.getInnerHeightCm().compareTo(type.defaultHeightCm()) != 0
|
||||
|| value.getEdgeAdditionCm().compareTo(DEFAULT_EDGE_ADDITION_CM) != 0
|
||||
|| !type.defaultRemark().equals(value.getRemark())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static InitializeResponse initializationResponse(List<CustomerDimensionConfigEntity> values,
|
||||
String initializationKey) {
|
||||
boolean ownedByKey = values.stream()
|
||||
.allMatch(value -> initializationKey.equals(value.getInitializationKey()));
|
||||
return new InitializeResponse(values.get(0).getId(), ownedByKey);
|
||||
}
|
||||
|
||||
private static GroupResponse response(long tenantId, List<CustomerDimensionConfigEntity> values) {
|
||||
return new GroupResponse(tenantId, values.stream().map(CustomerDimensionConfigService::ruleResponse).toList());
|
||||
}
|
||||
|
||||
private static RuleResponse ruleResponse(CustomerDimensionConfigEntity value) {
|
||||
BigDecimal edgePair = value.getEdgeAdditionCm().multiply(TWO);
|
||||
BigDecimal outerLength = value.getInnerLengthCm().add(edgePair);
|
||||
BigDecimal outerWidth = value.getInnerWidthCm().add(edgePair);
|
||||
BigDecimal outerHeight = value.getInnerHeightCm().add(edgePair);
|
||||
BigDecimal volume = outerLength.multiply(outerWidth).multiply(outerHeight)
|
||||
.divide(CUBIC_CENTIMETERS_PER_CBM)
|
||||
.setScale(3, RoundingMode.HALF_UP);
|
||||
return new RuleResponse(value.getId(), value.getBoxType(), value.getBoxType().displayName(),
|
||||
value.getInnerLengthCm(), value.getInnerWidthCm(), value.getInnerHeightCm(),
|
||||
value.getEdgeAdditionCm(), outerLength, outerWidth, outerHeight, volume,
|
||||
value.getRemark(), value.getVersion(), value.getCreatedAt(), value.getUpdatedAt());
|
||||
}
|
||||
|
||||
private static void requirePositive(BigDecimal value, String fieldName) {
|
||||
if (value == null || value.compareTo(new BigDecimal("0.001")) < 0) {
|
||||
throw new BizException(ResultCode.BAD_REQUEST, fieldName + "必须大于0");
|
||||
}
|
||||
}
|
||||
|
||||
private static BizException staleConfiguration() {
|
||||
return new BizException(ResultCode.CONFLICT, "箱规尺寸配置已被修改,请刷新后重试");
|
||||
}
|
||||
|
||||
private static String normalizeRemark(String value) {
|
||||
|
||||
@@ -3,7 +3,9 @@ package com.baiyue.firstleg.service;
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import com.baiyue.common.core.api.ResultCode;
|
||||
import com.baiyue.common.core.api.ApiResponse;
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
import com.baiyue.firstleg.client.MeasurementImageClient;
|
||||
import com.baiyue.firstleg.dto.InboundMeasurementRequests;
|
||||
import com.baiyue.firstleg.dto.InboundMeasurementResponses;
|
||||
import com.baiyue.firstleg.dto.MeasurementBatchCommand;
|
||||
@@ -17,6 +19,8 @@ import com.baiyue.firstleg.repository.InboundMeasurementRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import feign.FeignException;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
@@ -32,6 +36,8 @@ public class InboundMeasurementService {
|
||||
private static final String WEIGHT_CONFIRMED = "CONFIRMED";
|
||||
private static final String WEIGHT_PENDING_CONFIRM = "PENDING_CONFIRM";
|
||||
private static final String WEIGHT_NEEDS_MANUAL = "NEEDS_MANUAL";
|
||||
private static final Set<String> WEIGHT_EDITABLE_STATUSES = Set.of(
|
||||
"WAIT_MEASURE", "MEASURING", "MEASURE_REJECTED");
|
||||
/** 测量完成后的默认普通托盘类型;实际拆托和库位占用由提交编排服务执行。 */
|
||||
private static final String RECOMMENDED_PALLET_TYPE = "STANDARD";
|
||||
private static final BigDecimal LB_TO_KG = new BigDecimal("0.45359237");
|
||||
@@ -40,6 +46,10 @@ public class InboundMeasurementService {
|
||||
private InboundMeasurementRepository repository;
|
||||
@Resource
|
||||
private MeasurementBatchService batchService;
|
||||
@Resource
|
||||
private MeasurementImageClient imageClient;
|
||||
@Value("${baiyue.security.internal-service-token}")
|
||||
private String internalToken;
|
||||
|
||||
public InboundMeasurementResponses.Detail detail(long tenantId, long inboundId) {
|
||||
InboundOrderEntity inbound = requireInbound(tenantId, inboundId);
|
||||
@@ -231,13 +241,45 @@ public class InboundMeasurementService {
|
||||
return toWeight(weight);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteWeightResult(long tenantId, long inboundId, long resultId,
|
||||
int version, long operatorId) {
|
||||
InboundOrderEntity inbound = requireInbound(tenantId, inboundId);
|
||||
if (!WEIGHT_EDITABLE_STATUSES.contains(inbound.getProcessStatus())) {
|
||||
throw new BizException(ResultCode.CONFLICT, "当前入库状态不允许删除称重图片");
|
||||
}
|
||||
InboundWeightResultEntity weight = requireWeight(tenantId, inboundId, resultId);
|
||||
requireVersion(version, weight.getVersion());
|
||||
if (!repository.deleteWeight(tenantId, inboundId, resultId, version)) {
|
||||
throw concurrentModification();
|
||||
}
|
||||
if (WEIGHT_CONFIRMED.equals(weight.getRecognitionStatus())) {
|
||||
recalculateConfirmedWeight(inbound, operatorId);
|
||||
}
|
||||
try {
|
||||
ApiResponse<Void> response = imageClient.delete(
|
||||
internalToken, operatorId, tenantId, inboundId, weight.getFileId());
|
||||
if (response == null || !response.successful()) {
|
||||
String message = response == null || !StringUtils.hasText(response.message())
|
||||
? "称重图片删除失败" : response.message();
|
||||
throw new BizException(response == null ? ResultCode.SERVICE_UNAVAILABLE
|
||||
: ResultCode.of(response.code()), message);
|
||||
}
|
||||
} catch (FeignException exception) {
|
||||
throw new BizException(ResultCode.SERVICE_UNAVAILABLE, "文件服务暂不可用,称重图片未删除");
|
||||
}
|
||||
}
|
||||
|
||||
private void recalculateConfirmedWeight(InboundOrderEntity inbound, long operatorId) {
|
||||
BigDecimal total = repository.listWeights(inbound.getTenantId(), inbound.getId()).stream()
|
||||
List<InboundWeightResultEntity> confirmedWeights = repository
|
||||
.listWeights(inbound.getTenantId(), inbound.getId()).stream()
|
||||
.filter(weight -> WEIGHT_CONFIRMED.equals(weight.getRecognitionStatus()))
|
||||
.toList();
|
||||
BigDecimal total = confirmedWeights.stream()
|
||||
.map(InboundWeightResultEntity::getFinalWeightKg)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add)
|
||||
.setScale(3, RoundingMode.HALF_UP);
|
||||
inbound.setActualGrossWeightKg(total);
|
||||
inbound.setActualGrossWeightKg(confirmedWeights.isEmpty() ? null : total);
|
||||
if ("WAIT_MEASURE".equals(inbound.getProcessStatus())) {
|
||||
inbound.setProcessStatus("MEASURING");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user