优化
This commit is contained in:
+1
-1
@@ -41,7 +41,7 @@ public class InternalCustomerDimensionConfigController {
|
||||
@Valid @RequestBody InitializeRequest request) {
|
||||
requireToken(token);
|
||||
return ApiResponse.success(service.initializeDefault(
|
||||
request.tenantId(), request.operatorId(), request.initializationKey()));
|
||||
request.tenantId(), request.operatorId(), request.initializationKey(), request.customerName()));
|
||||
}
|
||||
|
||||
@DeleteMapping("/defaults")
|
||||
|
||||
@@ -60,8 +60,10 @@ public final class CustomerDimensionConfigDtos {
|
||||
public record InitializeRequest(
|
||||
@NotNull @Min(1) Long tenantId,
|
||||
@NotNull @Min(0) Long operatorId,
|
||||
@NotBlank @Size(max = 128) String initializationKey
|
||||
@NotBlank @Size(max = 128) String initializationKey,
|
||||
@NotBlank @Size(max = 128) String customerName
|
||||
) { }
|
||||
|
||||
public record InitializeResponse(Long configId, boolean createdByThisInitialization) { }
|
||||
public record InitializeResponse(Long configId, Long chargeRuleId,
|
||||
boolean createdByThisInitialization) { }
|
||||
}
|
||||
|
||||
@@ -38,4 +38,6 @@ public class CustomerChargeRuleEntity extends BaseEntity {
|
||||
private LocalDateTime effectiveTo;
|
||||
private String status;
|
||||
private String remark;
|
||||
/** 客户创建执行器的幂等键;人工创建的规则为空。 */
|
||||
private String initializationKey;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,50 @@
|
||||
package com.baiyue.firstleg.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Delete;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baiyue.firstleg.entity.CustomerChargeRuleEntity;
|
||||
@Mapper
|
||||
public interface CustomerChargeRuleMapper extends BaseMapper<CustomerChargeRuleEntity> {}
|
||||
public interface CustomerChargeRuleMapper extends BaseMapper<CustomerChargeRuleEntity> {
|
||||
@Select("""
|
||||
SELECT id, tenant_id, rule_code, rule_version, customer_id, customer_name, business_type,
|
||||
charge_mode, tax_mode, conversion_factor, length_factor, width_factor, height_factor,
|
||||
default_rule, rounding_scale, rounding_mode, currency, effective_from, effective_to,
|
||||
status, remark, initialization_key, created_by, created_at, updated_by, updated_at,
|
||||
deleted, version
|
||||
FROM fl_customer_charge_rule
|
||||
WHERE tenant_id = #{tenantId} AND initialization_key = #{initializationKey} AND deleted = 0
|
||||
LIMIT 1
|
||||
""")
|
||||
CustomerChargeRuleEntity selectByInitializationKey(
|
||||
@Param("tenantId") long tenantId, @Param("initializationKey") String initializationKey);
|
||||
|
||||
@Select("""
|
||||
SELECT id, tenant_id, rule_code, rule_version, customer_id, customer_name, business_type,
|
||||
charge_mode, tax_mode, conversion_factor, length_factor, width_factor, height_factor,
|
||||
default_rule, rounding_scale, rounding_mode, currency, effective_from, effective_to,
|
||||
status, remark, initialization_key, created_by, created_at, updated_by, updated_at,
|
||||
deleted, version
|
||||
FROM fl_customer_charge_rule
|
||||
WHERE tenant_id = #{tenantId} AND initialization_key = #{initializationKey} AND deleted = 0
|
||||
LIMIT 1 FOR UPDATE
|
||||
""")
|
||||
CustomerChargeRuleEntity selectByInitializationKeyForUpdate(
|
||||
@Param("tenantId") long tenantId, @Param("initializationKey") String initializationKey);
|
||||
|
||||
@Delete("""
|
||||
DELETE FROM fl_customer_charge_rule
|
||||
WHERE tenant_id = #{tenantId} AND initialization_key = #{initializationKey}
|
||||
AND rule_code = 'DEFAULT-DIMENSION-WEIGHT' AND rule_version = 1
|
||||
AND customer_id = #{tenantId} AND business_type = 'FBA' AND charge_mode = 'CBM'
|
||||
AND tax_mode = 'TAX_INCLUDED' AND conversion_factor = 167.000000
|
||||
AND length_factor = 1.100000 AND width_factor = 1.100000 AND height_factor = 1.100000
|
||||
AND default_rule = 1 AND rounding_scale = 2 AND rounding_mode = 'HALF_UP'
|
||||
AND currency = 'CNY' AND effective_to IS NULL AND status = 'ACTIVE'
|
||||
AND deleted = 0 AND version = 0
|
||||
""")
|
||||
int deleteUnchangedInitializedRule(
|
||||
@Param("tenantId") long tenantId, @Param("initializationKey") String initializationKey);
|
||||
}
|
||||
|
||||
@@ -55,6 +55,19 @@ public class FbaPricingRepository {
|
||||
|
||||
public void insertRule(CustomerChargeRuleEntity rule) { rules.insert(rule); }
|
||||
|
||||
public CustomerChargeRuleEntity findRuleByInitializationKey(long tenantId, String initializationKey) {
|
||||
return rules.selectByInitializationKey(tenantId, initializationKey);
|
||||
}
|
||||
|
||||
public CustomerChargeRuleEntity findRuleByInitializationKeyForUpdate(
|
||||
long tenantId, String initializationKey) {
|
||||
return rules.selectByInitializationKeyForUpdate(tenantId, initializationKey);
|
||||
}
|
||||
|
||||
public int deleteUnchangedInitializedRule(long tenantId, String initializationKey) {
|
||||
return rules.deleteUnchangedInitializedRule(tenantId, initializationKey);
|
||||
}
|
||||
|
||||
public int clearDefaultRule(long tenantId, long customerId, long operatorId) {
|
||||
return rules.update(null, new LambdaUpdateWrapper<CustomerChargeRuleEntity>()
|
||||
.eq(CustomerChargeRuleEntity::getTenantId, tenantId)
|
||||
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
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.entity.CustomerChargeRuleEntity;
|
||||
import com.baiyue.firstleg.repository.FbaPricingRepository;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/** 在客户创建执行器中幂等生成“箱规按权重系数计算”的默认规则。 */
|
||||
@Service
|
||||
public class CustomerChargeRuleInitializationService {
|
||||
static final String DEFAULT_RULE_CODE = "DEFAULT-DIMENSION-WEIGHT";
|
||||
static final BigDecimal DEFAULT_COEFFICIENT = new BigDecimal("1.100000");
|
||||
static final BigDecimal DEFAULT_CONVERSION_FACTOR = new BigDecimal("167.000000");
|
||||
static final String DEFAULT_REMARK = "SMALL:30,20,20;系数:1.1;重量:5;小箱:标准小箱;"
|
||||
+ "MEDIUM:40,30,30;系数:1.1;重量:8;中箱:标准中箱;"
|
||||
+ "LARGE:50,40,40;系数:1.1;重量:12;大箱:标准大箱;"
|
||||
+ "EXTRA_LARGE:60,50,50;系数:1.1;重量:15;特大箱:特大箱";
|
||||
|
||||
@Resource private FbaPricingRepository repository;
|
||||
|
||||
public CustomerChargeRuleEntity initializeDefault(long tenantId, long operatorId,
|
||||
String initializationKey, String customerName) {
|
||||
CustomerChargeRuleEntity existing = repository.findRuleByInitializationKey(
|
||||
tenantId, initializationKey);
|
||||
if (existing != null) return existing;
|
||||
|
||||
CustomerChargeRuleEntity value = new CustomerChargeRuleEntity();
|
||||
value.setId(IdWorker.getId());
|
||||
value.setTenantId(tenantId);
|
||||
value.setRuleCode(DEFAULT_RULE_CODE);
|
||||
value.setRuleVersion(1);
|
||||
value.setCustomerId(tenantId);
|
||||
value.setCustomerName(requireCustomerName(customerName));
|
||||
value.setBusinessType("FBA");
|
||||
value.setChargeMode("CBM");
|
||||
value.setTaxMode("TAX_INCLUDED");
|
||||
value.setConversionFactor(DEFAULT_CONVERSION_FACTOR);
|
||||
value.setLengthFactor(DEFAULT_COEFFICIENT);
|
||||
value.setWidthFactor(DEFAULT_COEFFICIENT);
|
||||
value.setHeightFactor(DEFAULT_COEFFICIENT);
|
||||
value.setDefaultRule(true);
|
||||
value.setRoundingScale(2);
|
||||
value.setRoundingMode("HALF_UP");
|
||||
value.setCurrency("CNY");
|
||||
value.setEffectiveFrom(LocalDateTime.now());
|
||||
value.setEffectiveTo(null);
|
||||
value.setStatus("ACTIVE");
|
||||
value.setRemark(DEFAULT_REMARK);
|
||||
value.setInitializationKey(initializationKey);
|
||||
value.setCreatedBy(operatorId);
|
||||
value.setUpdatedBy(operatorId);
|
||||
repository.insertRule(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
CustomerChargeRuleEntity lockForCompensation(long tenantId, String initializationKey) {
|
||||
return repository.findRuleByInitializationKeyForUpdate(tenantId, initializationKey);
|
||||
}
|
||||
|
||||
boolean isUnchangedDefault(CustomerChargeRuleEntity value) {
|
||||
return value != null
|
||||
&& value.getVersion() != null && value.getVersion() == 0
|
||||
&& DEFAULT_RULE_CODE.equals(value.getRuleCode()) && Integer.valueOf(1).equals(value.getRuleVersion())
|
||||
&& value.getTenantId().equals(value.getCustomerId())
|
||||
&& "FBA".equals(value.getBusinessType()) && "CBM".equals(value.getChargeMode())
|
||||
&& "TAX_INCLUDED".equals(value.getTaxMode())
|
||||
&& DEFAULT_CONVERSION_FACTOR.compareTo(value.getConversionFactor()) == 0
|
||||
&& DEFAULT_COEFFICIENT.compareTo(value.getLengthFactor()) == 0
|
||||
&& DEFAULT_COEFFICIENT.compareTo(value.getWidthFactor()) == 0
|
||||
&& DEFAULT_COEFFICIENT.compareTo(value.getHeightFactor()) == 0
|
||||
&& Boolean.TRUE.equals(value.getDefaultRule()) && Integer.valueOf(2).equals(value.getRoundingScale())
|
||||
&& "HALF_UP".equals(value.getRoundingMode()) && "CNY".equals(value.getCurrency())
|
||||
&& value.getEffectiveTo() == null && "ACTIVE".equals(value.getStatus())
|
||||
&& DEFAULT_REMARK.equals(value.getRemark());
|
||||
}
|
||||
|
||||
void deleteUnchangedDefault(long tenantId, String initializationKey) {
|
||||
if (repository.deleteUnchangedInitializedRule(tenantId, initializationKey) != 1) {
|
||||
throw new BizException(ResultCode.INTERNAL_ERROR, "客户权重系数默认规则补偿删除失败");
|
||||
}
|
||||
}
|
||||
|
||||
private static String requireCustomerName(String value) {
|
||||
if (value == null || value.isBlank() || value.trim().length() > 128) {
|
||||
throw new BizException(ResultCode.BAD_REQUEST, "客户名称无效");
|
||||
}
|
||||
return value.trim();
|
||||
}
|
||||
}
|
||||
+29
-7
@@ -10,6 +10,7 @@ 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.entity.CustomerChargeRuleEntity;
|
||||
import com.baiyue.firstleg.repository.CustomerDimensionConfigRepository;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -32,6 +33,8 @@ public class CustomerDimensionConfigService {
|
||||
|
||||
@Resource
|
||||
private CustomerDimensionConfigRepository repository;
|
||||
@Resource
|
||||
private CustomerChargeRuleInitializationService chargeRuleInitialization;
|
||||
|
||||
public GroupResponse get(long tenantId) {
|
||||
return response(tenantId, requireCompleteRules(repository.findAll(tenantId)));
|
||||
@@ -78,18 +81,26 @@ public class CustomerDimensionConfigService {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public InitializeResponse initializeDefault(long tenantId, long operatorId, String initializationKey) {
|
||||
public InitializeResponse initializeDefault(long tenantId, long operatorId, String initializationKey,
|
||||
String customerName) {
|
||||
requireTenant(tenantId);
|
||||
String normalizedKey = requireInitializationKey(initializationKey);
|
||||
List<CustomerDimensionConfigEntity> existing = repository.findAll(tenantId);
|
||||
if (!existing.isEmpty()) {
|
||||
List<CustomerDimensionConfigEntity> complete = requireCompleteRules(existing);
|
||||
return initializationResponse(complete, normalizedKey);
|
||||
boolean ownedByKey = ownedByInitialization(complete, normalizedKey);
|
||||
CustomerChargeRuleEntity chargeRule = ownedByKey
|
||||
? chargeRuleInitialization.initializeDefault(
|
||||
tenantId, operatorId, normalizedKey, customerName)
|
||||
: null;
|
||||
return initializationResponse(complete, chargeRule, ownedByKey);
|
||||
}
|
||||
|
||||
repository.insertDefaults(defaultRows(tenantId, normalizedKey), operatorId);
|
||||
List<CustomerDimensionConfigEntity> persisted = requireCompleteRules(repository.findAll(tenantId));
|
||||
return initializationResponse(persisted, normalizedKey);
|
||||
CustomerChargeRuleEntity chargeRule = chargeRuleInitialization.initializeDefault(
|
||||
tenantId, operatorId, normalizedKey, customerName);
|
||||
return initializationResponse(persisted, chargeRule, true);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -99,6 +110,12 @@ public class CustomerDimensionConfigService {
|
||||
List<CustomerDimensionConfigEntity> locked =
|
||||
repository.findDefaultsForCompensation(tenantId, normalizedKey);
|
||||
if (!isUnchangedDefaultGroup(locked, normalizedKey)) return;
|
||||
CustomerChargeRuleEntity chargeRule = chargeRuleInitialization.lockForCompensation(
|
||||
tenantId, normalizedKey);
|
||||
if (chargeRule != null && !chargeRuleInitialization.isUnchangedDefault(chargeRule)) return;
|
||||
if (chargeRule != null) {
|
||||
chargeRuleInitialization.deleteUnchangedDefault(tenantId, normalizedKey);
|
||||
}
|
||||
if (repository.deleteUnchangedDefaults(tenantId, normalizedKey) != CustomerDimensionBoxType.values().length) {
|
||||
throw new BizException(ResultCode.INTERNAL_ERROR, "客户箱规默认配置补偿删除失败");
|
||||
}
|
||||
@@ -206,11 +223,16 @@ public class CustomerDimensionConfigService {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean ownedByInitialization(List<CustomerDimensionConfigEntity> values,
|
||||
String initializationKey) {
|
||||
return values.stream().allMatch(value -> initializationKey.equals(value.getInitializationKey()));
|
||||
}
|
||||
|
||||
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);
|
||||
CustomerChargeRuleEntity chargeRule,
|
||||
boolean ownedByKey) {
|
||||
return new InitializeResponse(values.get(0).getId(),
|
||||
chargeRule == null ? null : chargeRule.getId(), ownedByKey);
|
||||
}
|
||||
|
||||
private static GroupResponse response(long tenantId, List<CustomerDimensionConfigEntity> values) {
|
||||
|
||||
@@ -24,6 +24,7 @@ CALL phase2_fba_add_column('fl_customer_charge_rule', 'length_factor', "DECIMAL(
|
||||
CALL phase2_fba_add_column('fl_customer_charge_rule', 'width_factor', "DECIMAL(18,6) NOT NULL DEFAULT 1 COMMENT '宽度计算系数' AFTER length_factor");
|
||||
CALL phase2_fba_add_column('fl_customer_charge_rule', 'height_factor', "DECIMAL(18,6) NOT NULL DEFAULT 1 COMMENT '高度计算系数' AFTER width_factor");
|
||||
CALL phase2_fba_add_column('fl_customer_charge_rule', 'default_rule', "TINYINT(1) NOT NULL DEFAULT 0 COMMENT '客户默认生效规则' AFTER status");
|
||||
CALL phase2_fba_add_column('fl_customer_charge_rule', 'initialization_key', "VARCHAR(128) NULL COMMENT '客户创建执行器幂等键及补偿归属' AFTER remark");
|
||||
CALL phase2_fba_add_column('fl_carrier_fba_rate', 'version', "INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号' AFTER deleted");
|
||||
CALL phase2_fba_add_column('fl_inbound_fee', 'rule_code', "VARCHAR(50) NOT NULL DEFAULT '' COMMENT '客户规则编码快照' AFTER carrier_rate_version");
|
||||
CALL phase2_fba_add_column('fl_inbound_fee', 'measurement_id', "BIGINT UNSIGNED NULL COMMENT '费用绑定的测量批次ID快照' AFTER inbound_id");
|
||||
@@ -67,6 +68,14 @@ PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
DROP PROCEDURE IF EXISTS phase2_fba_add_column;
|
||||
|
||||
SET @idx_exists = (SELECT COUNT(*) FROM information_schema.STATISTICS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'fl_customer_charge_rule'
|
||||
AND INDEX_NAME = 'idx_charge_rule_initialization');
|
||||
SET @sql = IF(@idx_exists = 0,
|
||||
'ALTER TABLE fl_customer_charge_rule ADD INDEX idx_charge_rule_initialization (tenant_id, initialization_key)',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 旧索引可能缺少业务类型、船司和结束时间;用新索引名并存,避免破坏线上依赖。
|
||||
SET @idx_exists = (SELECT COUNT(*) FROM information_schema.STATISTICS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'fl_carrier_fba_rate' AND INDEX_NAME = 'idx_fba_rate_unique_match');
|
||||
|
||||
@@ -430,6 +430,7 @@ CREATE TABLE IF NOT EXISTS fl_customer_charge_rule (
|
||||
effective_to DATETIME(3) NULL COMMENT '生效结束时间',
|
||||
status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE' COMMENT '规则状态:ACTIVE启用、DISABLED停用',
|
||||
remark VARCHAR(500) NULL COMMENT '规则备注',
|
||||
initialization_key VARCHAR(128) NULL COMMENT '客户创建执行器幂等键及补偿归属',
|
||||
created_by BIGINT UNSIGNED NOT NULL COMMENT '创建人ID',
|
||||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||||
updated_by BIGINT UNSIGNED NOT NULL COMMENT '最后修改人ID',
|
||||
@@ -438,6 +439,7 @@ CREATE TABLE IF NOT EXISTS fl_customer_charge_rule (
|
||||
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uk_charge_rule_version (tenant_id, rule_code, rule_version),
|
||||
KEY idx_charge_rule_initialization (tenant_id, initialization_key),
|
||||
KEY idx_charge_rule_match (tenant_id, customer_id, business_type, status, effective_from, effective_to)
|
||||
) ENGINE=InnoDB COMMENT='客户头程计费规则版本';
|
||||
|
||||
|
||||
@@ -1750,16 +1750,18 @@ components:
|
||||
updatedAt: {type: string, format: date-time, nullable: true}
|
||||
CustomerDimensionConfigInitializeRequest:
|
||||
type: object
|
||||
required: [tenantId, operatorId, initializationKey]
|
||||
required: [tenantId, operatorId, initializationKey, customerName]
|
||||
properties:
|
||||
tenantId: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||
operatorId: {type: string, pattern: '^[0-9]+$'}
|
||||
initializationKey: {type: string, minLength: 1, maxLength: 128}
|
||||
customerName: {type: string, minLength: 1, maxLength: 128}
|
||||
CustomerDimensionConfigInitializeResponse:
|
||||
type: object
|
||||
required: [configId, createdByThisInitialization]
|
||||
required: [configId, chargeRuleId, createdByThisInitialization]
|
||||
properties:
|
||||
configId: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||
chargeRuleId: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||
createdByThisInitialization: {type: boolean}
|
||||
WeightPalletSnapshot:
|
||||
type: object
|
||||
|
||||
+5
-5
@@ -33,15 +33,15 @@ class CustomerDimensionConfigControllerContractTest {
|
||||
|
||||
@Test
|
||||
void internalInitializationRequiresTokenAndReturnsCreationIdentity() {
|
||||
InitializeRequest request = new InitializeRequest(8L, 100L, "registration-1");
|
||||
when(service.initializeDefault(8L, 100L, "registration-1"))
|
||||
.thenReturn(new InitializeResponse(91L, true));
|
||||
InitializeRequest request = new InitializeRequest(8L, 100L, "registration-1", "柏悦物流");
|
||||
when(service.initializeDefault(8L, 100L, "registration-1", "柏悦物流"))
|
||||
.thenReturn(new InitializeResponse(91L, 191L, true));
|
||||
|
||||
assertThatThrownBy(() -> internalController.initializeDefault("wrong", request))
|
||||
.isInstanceOf(BizException.class);
|
||||
assertThat(internalController.initializeDefault("test-token", request).data())
|
||||
.isEqualTo(new InitializeResponse(91L, true));
|
||||
verify(service).initializeDefault(8L, 100L, "registration-1");
|
||||
.isEqualTo(new InitializeResponse(91L, 191L, true));
|
||||
verify(service).initializeDefault(8L, 100L, "registration-1", "柏悦物流");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
package com.baiyue.firstleg.service;
|
||||
|
||||
import com.baiyue.firstleg.entity.CustomerChargeRuleEntity;
|
||||
import com.baiyue.firstleg.repository.FbaPricingRepository;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@SpringJUnitConfig(CustomerChargeRuleInitializationService.class)
|
||||
class CustomerChargeRuleInitializationServiceTest {
|
||||
@MockBean private FbaPricingRepository repository;
|
||||
@Resource private CustomerChargeRuleInitializationService service;
|
||||
|
||||
@Test
|
||||
void initializesDefaultWeightCoefficientRuleForNewCustomer() {
|
||||
CustomerChargeRuleEntity result = service.initializeDefault(
|
||||
8L, 100L, "iam-customer-create:8", "柏悦物流");
|
||||
|
||||
ArgumentCaptor<CustomerChargeRuleEntity> captor =
|
||||
ArgumentCaptor.forClass(CustomerChargeRuleEntity.class);
|
||||
verify(repository).insertRule(captor.capture());
|
||||
CustomerChargeRuleEntity saved = captor.getValue();
|
||||
assertThat(result).isSameAs(saved);
|
||||
assertThat(saved.getTenantId()).isEqualTo(8L);
|
||||
assertThat(saved.getCustomerId()).isEqualTo(8L);
|
||||
assertThat(saved.getCustomerName()).isEqualTo("柏悦物流");
|
||||
assertThat(saved.getRuleCode()).isEqualTo("DEFAULT-DIMENSION-WEIGHT");
|
||||
assertThat(saved.getRuleVersion()).isEqualTo(1);
|
||||
assertThat(saved.getDefaultRule()).isTrue();
|
||||
assertThat(saved.getLengthFactor()).isEqualByComparingTo("1.100000");
|
||||
assertThat(saved.getWidthFactor()).isEqualByComparingTo("1.100000");
|
||||
assertThat(saved.getHeightFactor()).isEqualByComparingTo("1.100000");
|
||||
assertThat(saved.getConversionFactor()).isEqualByComparingTo("167.000000");
|
||||
assertThat(saved.getRemark()).contains(
|
||||
"SMALL:30,20,20;系数:1.1;重量:5",
|
||||
"EXTRA_LARGE:60,50,50;系数:1.1;重量:15");
|
||||
assertThat(saved.getInitializationKey()).isEqualTo("iam-customer-create:8");
|
||||
}
|
||||
|
||||
@Test
|
||||
void retryReturnsRuleOwnedBySameInitializationWithoutDuplicating() {
|
||||
CustomerChargeRuleEntity existing = new CustomerChargeRuleEntity();
|
||||
existing.setId(191L);
|
||||
when(repository.findRuleByInitializationKey(8L, "iam-customer-create:8"))
|
||||
.thenReturn(existing);
|
||||
|
||||
assertThat(service.initializeDefault(8L, 100L, "iam-customer-create:8", "柏悦物流"))
|
||||
.isSameAs(existing);
|
||||
verify(repository, never()).insertRule(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void compensationDeletesOnlyAnUnchangedInitializedRule() {
|
||||
CustomerChargeRuleEntity value = service.initializeDefault(
|
||||
8L, 100L, "iam-customer-create:8", "柏悦物流");
|
||||
value.setVersion(0);
|
||||
when(repository.findRuleByInitializationKeyForUpdate(8L, "iam-customer-create:8"))
|
||||
.thenReturn(value);
|
||||
when(repository.deleteUnchangedInitializedRule(8L, "iam-customer-create:8"))
|
||||
.thenReturn(1);
|
||||
|
||||
CustomerChargeRuleEntity locked = service.lockForCompensation(8L, "iam-customer-create:8");
|
||||
assertThat(service.isUnchangedDefault(locked)).isTrue();
|
||||
service.deleteUnchangedDefault(8L, "iam-customer-create:8");
|
||||
|
||||
verify(repository).deleteUnchangedInitializedRule(8L, "iam-customer-create:8");
|
||||
}
|
||||
}
|
||||
+25
-6
@@ -22,6 +22,7 @@ import java.util.List;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
@@ -32,6 +33,8 @@ import static org.mockito.Mockito.when;
|
||||
class CustomerDimensionConfigServiceTest {
|
||||
@MockBean
|
||||
private CustomerDimensionConfigRepository repository;
|
||||
@MockBean
|
||||
private CustomerChargeRuleInitializationService chargeRuleInitialization;
|
||||
@Resource
|
||||
private CustomerDimensionConfigService service;
|
||||
|
||||
@@ -40,10 +43,12 @@ class CustomerDimensionConfigServiceTest {
|
||||
List<CustomerDimensionConfigEntity> persisted = defaultConfigs("registration-1");
|
||||
when(repository.findAll(8L)).thenReturn(List.of(), persisted);
|
||||
when(repository.insertDefaults(any(), eq(100L))).thenReturn(4);
|
||||
when(chargeRuleInitialization.initializeDefault(8L, 100L, "registration-1", "柏悦物流"))
|
||||
.thenReturn(defaultChargeRule());
|
||||
|
||||
InitializeResponse result = service.initializeDefault(8L, 100L, "registration-1");
|
||||
InitializeResponse result = service.initializeDefault(8L, 100L, "registration-1", "柏悦物流");
|
||||
|
||||
assertThat(result).isEqualTo(new InitializeResponse(91L, true));
|
||||
assertThat(result).isEqualTo(new InitializeResponse(91L, 191L, true));
|
||||
@SuppressWarnings("unchecked")
|
||||
ArgumentCaptor<List<CustomerDimensionConfigEntity>> captor = ArgumentCaptor.forClass(List.class);
|
||||
verify(repository).insertDefaults(captor.capture(), eq(100L));
|
||||
@@ -67,10 +72,12 @@ class CustomerDimensionConfigServiceTest {
|
||||
@Test
|
||||
void retryAfterLostResponseKeepsCreationOwnershipForSameKey() {
|
||||
when(repository.findAll(8L)).thenReturn(defaultConfigs("registration-1"));
|
||||
when(chargeRuleInitialization.initializeDefault(8L, 100L, "registration-1", "柏悦物流"))
|
||||
.thenReturn(defaultChargeRule());
|
||||
|
||||
InitializeResponse result = service.initializeDefault(8L, 100L, "registration-1");
|
||||
InitializeResponse result = service.initializeDefault(8L, 100L, "registration-1", "柏悦物流");
|
||||
|
||||
assertThat(result).isEqualTo(new InitializeResponse(91L, true));
|
||||
assertThat(result).isEqualTo(new InitializeResponse(91L, 191L, true));
|
||||
verify(repository, never()).insertDefaults(any(), eq(100L));
|
||||
}
|
||||
|
||||
@@ -78,10 +85,11 @@ class CustomerDimensionConfigServiceTest {
|
||||
void differentInitializationKeyDoesNotTakeOwnershipOrOverwrite() {
|
||||
when(repository.findAll(8L)).thenReturn(defaultConfigs("registration-1"));
|
||||
|
||||
InitializeResponse result = service.initializeDefault(8L, 100L, "registration-2");
|
||||
InitializeResponse result = service.initializeDefault(8L, 100L, "registration-2", "柏悦物流");
|
||||
|
||||
assertThat(result).isEqualTo(new InitializeResponse(91L, false));
|
||||
assertThat(result).isEqualTo(new InitializeResponse(91L, null, false));
|
||||
verify(repository, never()).insertDefaults(any(), eq(100L));
|
||||
verify(chargeRuleInitialization, never()).initializeDefault(anyLong(), anyLong(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -173,10 +181,14 @@ class CustomerDimensionConfigServiceTest {
|
||||
when(repository.findDefaultsForCompensation(8L, "registration-1"))
|
||||
.thenReturn(defaultConfigs("registration-1"));
|
||||
when(repository.deleteUnchangedDefaults(8L, "registration-1")).thenReturn(4);
|
||||
when(chargeRuleInitialization.lockForCompensation(8L, "registration-1"))
|
||||
.thenReturn(defaultChargeRule());
|
||||
when(chargeRuleInitialization.isUnchangedDefault(any())).thenReturn(true);
|
||||
|
||||
service.compensateDefault(8L, "registration-1");
|
||||
|
||||
verify(repository).deleteUnchangedDefaults(8L, "registration-1");
|
||||
verify(chargeRuleInitialization).deleteUnchangedDefault(8L, "registration-1");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -228,4 +240,11 @@ class CustomerDimensionConfigServiceTest {
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
private static com.baiyue.firstleg.entity.CustomerChargeRuleEntity defaultChargeRule() {
|
||||
com.baiyue.firstleg.entity.CustomerChargeRuleEntity value =
|
||||
new com.baiyue.firstleg.entity.CustomerChargeRuleEntity();
|
||||
value.setId(191L);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user