费用提交
This commit is contained in:
+8
@@ -19,6 +19,14 @@ public class InternalOverseasStorageFeeController {
|
||||
@Value("${baiyue.security.internal-service-token}") private String internalToken;
|
||||
private byte[] expected;
|
||||
@PostConstruct void init() { expected = internalToken.getBytes(StandardCharsets.UTF_8); }
|
||||
|
||||
/** 内部计租只读入口,先校验服务身份再查询客户配置。 */
|
||||
@GetMapping("/{customerId}/pricing")
|
||||
public ApiResponse<OverseasStorageFeeDtos.PricingView> pricing(
|
||||
@RequestHeader(value="X-Internal-Service-Token", required=false) String token,
|
||||
@PathVariable long customerId) {
|
||||
verify(token); return ApiResponse.success(service.pricing(customerId));
|
||||
}
|
||||
@PostMapping("/defaults")
|
||||
public ApiResponse<OverseasStorageFeeDtos.DefaultInitializationResponse> defaults(
|
||||
@RequestHeader(value="X-Internal-Service-Token", required=false) String token,
|
||||
|
||||
@@ -97,4 +97,9 @@ public final class OverseasStorageFeeDtos {
|
||||
Long operatorId, String customerName) {}
|
||||
public record DefaultInitializationResponse(String configId, boolean createdByThisInitialization) {}
|
||||
public record CompensationRequest(@NotNull @Positive Long tenantId, @NotBlank String initializationKey) {}
|
||||
|
||||
/** 计租专用的客户配置一致性快照;默认档位不生成配置记录。 */
|
||||
@Schema(name = "OverseasStorageFeePricingView", description = "客户海外仓计租配置快照")
|
||||
public record PricingView(String configId, Long customerId, Integer version, String currency,
|
||||
List<TierView> tiers, String source) {}
|
||||
}
|
||||
|
||||
+6
@@ -38,6 +38,12 @@ public class OverseasStorageFeeRepository {
|
||||
public OverseasStorageFeeRuleEntity find(long id) {
|
||||
return ruleMapper.selectById(id);
|
||||
}
|
||||
|
||||
/** 按客户读取唯一有效配置,不借用其他客户或默认初始化标识。 */
|
||||
public OverseasStorageFeeRuleEntity findByCustomer(long customerId) {
|
||||
return ruleMapper.selectOne(new LambdaQueryWrapper<OverseasStorageFeeRuleEntity>()
|
||||
.eq(OverseasStorageFeeRuleEntity::getTenantId, customerId));
|
||||
}
|
||||
public OverseasStorageFeeRuleEntity findByTenantAndKey(long tenantId, String key) {
|
||||
return ruleMapper.selectOne(new LambdaQueryWrapper<OverseasStorageFeeRuleEntity>()
|
||||
.eq(OverseasStorageFeeRuleEntity::getTenantId, tenantId)
|
||||
|
||||
@@ -12,6 +12,7 @@ import jakarta.annotation.Resource;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
@@ -26,6 +27,53 @@ public class OverseasStorageFeeService {
|
||||
@Resource
|
||||
private OverseasStorageFeeRepository repository;
|
||||
|
||||
/** 同一可重复读快照中读取主档和阶梯;异常配置拒绝计租,不写入或修补存量。 */
|
||||
@Transactional(readOnly = true, isolation = Isolation.REPEATABLE_READ)
|
||||
public OverseasStorageFeeDtos.PricingView pricing(long customerId) {
|
||||
if (customerId <= 0) throw new BizException(ResultCode.VALIDATION_FAILED, "客户ID必须为正数");
|
||||
var rule = repository.findByCustomer(customerId);
|
||||
if (rule == null) return new OverseasStorageFeeDtos.PricingView(null, customerId, null, "USD",
|
||||
pricingViews(tierEntities(0, customerId, defaultTiers())), "DEFAULT");
|
||||
if (!Long.valueOf(customerId).equals(rule.getTenantId()) || rule.getId() == null
|
||||
|| rule.getVersion() == null || rule.getVersion() < 0 || Boolean.TRUE.equals(rule.getDeleted())
|
||||
|| rule.getCurrency() == null || !rule.getCurrency().matches("[A-Z]{3}"))
|
||||
throw new BizException(ResultCode.CONFLICT, "客户仓租配置无效,请先核对配置");
|
||||
var effective = new ArrayList<>(repository.findTiers(List.of(rule.getId())));
|
||||
if (effective.stream().anyMatch(tier -> tier == null || !rule.getId().equals(tier.getRuleId())
|
||||
|| !Long.valueOf(customerId).equals(tier.getTenantId())))
|
||||
throw new BizException(ResultCode.CONFLICT, "客户仓租阶梯归属不一致");
|
||||
if (effective.stream().anyMatch(tier -> tier.getStartDay() == null || tier.getStartDay() < 1
|
||||
|| tier.getStartDay() > 36500 || tier.getEndDay() != null && (tier.getEndDay() < 1 || tier.getEndDay() > 36500)))
|
||||
throw new BizException(ResultCode.CONFLICT, "客户仓租阶梯天数无效");
|
||||
for (String type : List.of("STORAGE", "RETURN_STORAGE")) {
|
||||
if (effective.stream().noneMatch(tier -> type.equals(tier.getFeeType()))) {
|
||||
if (!"USD".equals(rule.getCurrency()))
|
||||
throw new BizException(ResultCode.CONFLICT, "非美元仓租配置缺少计租类型,请先补全配置");
|
||||
effective.addAll(tierEntities(rule.getId(), customerId,
|
||||
defaultTiers().stream().filter(tier -> type.equals(tier.feeType())).toList()));
|
||||
}
|
||||
}
|
||||
var normalized = normalize(effective.stream().map(tier -> new OverseasStorageFeeDtos.TierRequest(
|
||||
tier.getFeeType(), tier.getBillingUnit(), tier.getStartDay(), tier.getEndDay(), tier.getUnitPrice())).toList());
|
||||
for (String type : List.of("STORAGE", "RETURN_STORAGE")) {
|
||||
var group = normalized.stream().filter(tier -> type.equals(tier.feeType())).toList();
|
||||
if (group.get(group.size() - 1).endDay() != null)
|
||||
throw new BizException(ResultCode.CONFLICT, "客户仓租阶梯必须包含无上限尾档");
|
||||
}
|
||||
effective.sort(Comparator.comparingInt((OverseasStorageFeeTierEntity tier) ->
|
||||
"STORAGE".equals(tier.getFeeType()) ? 0 : 1).thenComparingInt(OverseasStorageFeeTierEntity::getStartDay));
|
||||
return new OverseasStorageFeeDtos.PricingView(String.valueOf(rule.getId()), customerId, rule.getVersion(),
|
||||
rule.getCurrency(), pricingViews(effective), "CUSTOMER");
|
||||
}
|
||||
|
||||
/** 转换为稳定顺序的只读计租档位,补齐默认组的档位ID保持为空。 */
|
||||
private static List<OverseasStorageFeeDtos.TierView> pricingViews(List<OverseasStorageFeeTierEntity> tiers) {
|
||||
var result = new ArrayList<OverseasStorageFeeDtos.TierView>();
|
||||
for (var tier : tiers) result.add(new OverseasStorageFeeDtos.TierView(tier.getId(), tier.getStartDay(),
|
||||
tier.getEndDay(), tier.getUnitPrice(), result.size() + 1, tier.getFeeType(), tier.getBillingUnit()));
|
||||
return List.copyOf(result);
|
||||
}
|
||||
|
||||
public PageResult<OverseasStorageFeeDtos.View> page(OverseasStorageFeeDtos.PageQuery query) {
|
||||
PageResult<OverseasStorageFeeRuleEntity> source = repository.page(query);
|
||||
Map<Long, List<OverseasStorageFeeTierEntity>> tiers = repository.findTiers(
|
||||
|
||||
@@ -59,6 +59,7 @@ BEGIN
|
||||
END$$
|
||||
DELIMITER ;
|
||||
CALL supplier_add_column_if_missing('license_file_id', "VARCHAR(128) NULL COMMENT 'File服务营业执照文件ID' AFTER business_license_no");
|
||||
CALL supplier_add_column_if_missing('trucking_scope', "VARCHAR(16) NULL COMMENT '拖车类型:DOMESTIC国内拖车、OVERSEAS海外车队;非拖车为空' AFTER category");
|
||||
CALL supplier_add_column_if_missing('created_by', "BIGINT UNSIGNED NULL COMMENT '创建人ID'");
|
||||
CALL supplier_add_column_if_missing('created_at', "DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间'");
|
||||
CALL supplier_add_column_if_missing('updated_by', "BIGINT UNSIGNED NULL COMMENT '最后修改人ID'");
|
||||
|
||||
@@ -3,6 +3,31 @@ info:
|
||||
title: Warehouse catalog and receiving options
|
||||
version: 1.0.0
|
||||
paths:
|
||||
/internal/warehouse/v1/customer-overseas-storage-fees/{customerId}/pricing:
|
||||
get:
|
||||
summary: 读取客户海外仓自动计租配置
|
||||
description: 内部只读接口,不经公网网关。按客户读取同一REPEATABLE_READ快照中的配置及阶梯,不创建或修改配置。无配置返回完整USD默认中转及退货两表;USD配置漏组仅补齐缺失组。非USD配置漏组、已配置组不连续或缺少无上限尾档时明确失败,不能因读取异常降级为默认价。完整客户配置保留原币种,由调用方按确认汇率换算。
|
||||
security:
|
||||
- internalServiceToken: []
|
||||
parameters:
|
||||
- name: customerId
|
||||
in: path
|
||||
required: true
|
||||
schema: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||
responses:
|
||||
'200':
|
||||
description: 统一业务响应,code为200时返回完整计租快照;客户ID或配置非法返回业务失败code,不返回默认价。
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [code]
|
||||
properties:
|
||||
code: {type: string}
|
||||
message: {type: string}
|
||||
data:
|
||||
$ref: '#/components/schemas/OverseasStorageFeePricingView'
|
||||
'403': {description: 内部服务凭据缺失或错误}
|
||||
/internal/warehouses/platform-metadata/batch:
|
||||
post:
|
||||
summary: 内部批量读取公共仓库历史展示资料
|
||||
@@ -94,6 +119,31 @@ paths:
|
||||
'200': {description: 返回仓库 ID、编码、名称、类型和国家编码}
|
||||
components:
|
||||
schemas:
|
||||
OverseasStorageFeePricingView:
|
||||
type: object
|
||||
required: [customerId, currency, tiers, source]
|
||||
properties:
|
||||
configId: {type: string, nullable: true, description: 客户配置ID,无配置时为空}
|
||||
customerId: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||
version: {type: integer, nullable: true, minimum: 0, description: 客户配置版本,无配置时为空}
|
||||
currency: {type: string, pattern: '^[A-Z]{3}$'}
|
||||
source: {type: string, enum: [CUSTOMER, DEFAULT], description: CUSTOMER包含仅补全缺失默认组的USD客户配置}
|
||||
tiers:
|
||||
type: array
|
||||
minItems: 2
|
||||
items:
|
||||
$ref: '#/components/schemas/OverseasStorageFeePricingTier'
|
||||
OverseasStorageFeePricingTier:
|
||||
type: object
|
||||
required: [startDay, unitPrice, sortNo, feeType, billingUnit]
|
||||
properties:
|
||||
id: {type: string, nullable: true, description: 客户阶梯ID,默认或补齐档位为空}
|
||||
startDay: {type: integer, minimum: 1}
|
||||
endDay: {type: integer, nullable: true, minimum: 1, description: 含当日,空值为无上限尾档}
|
||||
unitPrice: {type: number, minimum: 0, description: 每CBM每天或每托每天的单价,币种取快照currency}
|
||||
sortNo: {type: integer, minimum: 1}
|
||||
feeType: {type: string, enum: [STORAGE, RETURN_STORAGE], description: STORAGE中转仓租,RETURN_STORAGE退货仓租}
|
||||
billingUnit: {type: string, enum: [CBM, PALLET]}
|
||||
ReceivingWarehouseOption:
|
||||
type: object
|
||||
required: [id, customerId, warehouseCode, warehouseName, warehouseType, status]
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.baiyue.warehouse.controller;
|
||||
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
import com.baiyue.warehouse.dto.OverseasStorageFeeDtos;
|
||||
import com.baiyue.warehouse.service.OverseasStorageFeeService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import java.util.List;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
class InternalOverseasStoragePricingControllerTest {
|
||||
@Test void pricingRequiresInternalTokenBeforeReadingCustomerAndReturnsSnapshot() throws Exception {
|
||||
var service=mock(OverseasStorageFeeService.class);
|
||||
var controller=new InternalOverseasStorageFeeController();
|
||||
ReflectionTestUtils.setField(controller,"service",service);
|
||||
ReflectionTestUtils.setField(controller,"internalToken","internal-test"); controller.init();
|
||||
assertThatThrownBy(() -> controller.pricing(null,17)).isInstanceOf(BizException.class);
|
||||
assertThatThrownBy(() -> controller.pricing("wrong",17)).isInstanceOf(BizException.class);
|
||||
verifyNoInteractions(service);
|
||||
var expected=new OverseasStorageFeeDtos.PricingView(null,17L,null,"USD",List.of(),"DEFAULT");
|
||||
when(service.pricing(17)).thenReturn(expected);
|
||||
assertThat(controller.pricing("internal-test",17).data()).isSameAs(expected);
|
||||
assertThat(InternalOverseasStorageFeeController.class.getMethod("pricing",String.class,long.class)
|
||||
.getAnnotation(GetMapping.class).value()).containsExactly("/{customerId}/pricing");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package com.baiyue.warehouse.service;
|
||||
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
import com.baiyue.warehouse.entity.OverseasStorageFeeRuleEntity;
|
||||
import com.baiyue.warehouse.entity.OverseasStorageFeeTierEntity;
|
||||
import com.baiyue.warehouse.repository.OverseasStorageFeeRepository;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
class OverseasStoragePricingTest {
|
||||
private final OverseasStorageFeeRepository repository = mock(OverseasStorageFeeRepository.class);
|
||||
private final OverseasStorageFeeService service = new OverseasStorageFeeService();
|
||||
|
||||
@BeforeEach void setup() { ReflectionTestUtils.setField(service, "repository", repository); }
|
||||
|
||||
@Test void absentConfigurationReturnsBothConfirmedDefaultTablesWithoutWriting() {
|
||||
var pricing = service.pricing(17);
|
||||
assertThat(pricing.source()).isEqualTo("DEFAULT");
|
||||
assertThat(pricing.customerId()).isEqualTo(17);
|
||||
assertThat(pricing.configId()).isNull(); assertThat(pricing.version()).isNull();
|
||||
assertThat(pricing.currency()).isEqualTo("USD");
|
||||
assertThat(pricing.tiers()).hasSize(9).allSatisfy(tier -> assertThat(tier.id()).isNull());
|
||||
assertThat(pricing.tiers().stream().filter(tier -> "STORAGE".equals(tier.feeType())).toList())
|
||||
.extracting(tier -> tier.unitPrice().stripTrailingZeros()).containsExactly(
|
||||
BigDecimal.ZERO, new BigDecimal("0.8"), BigDecimal.ONE, new BigDecimal("1.5"), new BigDecimal("2"));
|
||||
assertThat(pricing.tiers().stream().filter(tier -> "RETURN_STORAGE".equals(tier.feeType())).toList())
|
||||
.extracting(tier -> tier.unitPrice().stripTrailingZeros()).containsExactly(
|
||||
new BigDecimal("1.5"), new BigDecimal("2"), new BigDecimal("3"), new BigDecimal("4"));
|
||||
assertThat(pricing.tiers().get(0).startDay()).isEqualTo(1);
|
||||
assertThat(pricing.tiers().get(0).endDay()).isEqualTo(7);
|
||||
verify(repository).findByCustomer(17); verifyNoMoreInteractions(repository);
|
||||
}
|
||||
|
||||
@Test void configuredCustomerKeepsVersionCurrencyAndPricesInSortedOrder() {
|
||||
configured("CNY", List.of(tier("RETURN_STORAGE",1,null,"13"),tier("STORAGE",8,null,"6"),tier("STORAGE",1,7,"0")));
|
||||
var pricing = service.pricing(17);
|
||||
assertThat(pricing.source()).isEqualTo("CUSTOMER");
|
||||
assertThat(pricing.configId()).isEqualTo("51"); assertThat(pricing.version()).isEqualTo(3);
|
||||
assertThat(pricing.currency()).isEqualTo("CNY");
|
||||
assertThat(pricing.tiers()).extracting(tier -> tier.unitPrice().toPlainString()).containsExactly("0","6","13");
|
||||
verify(repository).findByCustomer(17); verify(repository).findTiers(List.of(51L)); verifyNoMoreInteractions(repository);
|
||||
}
|
||||
|
||||
@ParameterizedTest @ValueSource(strings={"STORAGE","RETURN_STORAGE"})
|
||||
void dollarConfigurationCompletesOnlyMissingGroup(String existingType) {
|
||||
configured("USD",List.of(tier(existingType,1,null,"9")));
|
||||
var pricing=service.pricing(17);
|
||||
assertThat(pricing.tiers().stream().filter(tier -> existingType.equals(tier.feeType())).toList())
|
||||
.singleElement().satisfies(tier -> assertThat(tier.unitPrice()).isEqualByComparingTo("9"));
|
||||
assertThat(pricing.tiers().stream().filter(tier -> !existingType.equals(tier.feeType())).toList())
|
||||
.hasSize("STORAGE".equals(existingType)?4:5).allSatisfy(tier -> assertThat(tier.id()).isNull());
|
||||
}
|
||||
|
||||
@Test void foreignCurrencyMissingGroupCannotMixDollarDefaults() {
|
||||
configured("CNY",List.of(tier("STORAGE",1,null,"9")));
|
||||
assertThatThrownBy(() -> service.pricing(17)).isInstanceOf(BizException.class).hasMessageContaining("非美元");
|
||||
}
|
||||
|
||||
@Test void finiteLastBandRefusesBillingInsteadOfZeroOrDefaultPrice() {
|
||||
configured("USD",List.of(tier("STORAGE",1,30,"9")));
|
||||
assertThatThrownBy(() -> service.pricing(17)).isInstanceOf(BizException.class).hasMessageContaining("无上限");
|
||||
}
|
||||
|
||||
@Test void gapAndUnknownUnitRefuseBilling() {
|
||||
configured("USD",List.of(tier("STORAGE",1,7,"0"),tier("STORAGE",9,null,"9")));
|
||||
assertThatThrownBy(() -> service.pricing(17)).isInstanceOf(BizException.class).hasMessageContaining("连续");
|
||||
var invalid=tier("STORAGE",1,null,"9"); invalid.setBillingUnit("PALLET");
|
||||
when(repository.findTiers(List.of(51L))).thenReturn(List.of(invalid));
|
||||
assertThatThrownBy(() -> service.pricing(17)).isInstanceOf(BizException.class).hasMessageContaining("不匹配");
|
||||
}
|
||||
|
||||
@Test void wrongCustomerTierRefusesBilling() {
|
||||
var wrong=tier("STORAGE",1,null,"9"); wrong.setTenantId(18L);
|
||||
configured("USD",List.of(wrong));
|
||||
assertThatThrownBy(() -> service.pricing(17)).isInstanceOf(BizException.class).hasMessageContaining("归属");
|
||||
}
|
||||
|
||||
@Test void configurationReadFailurePropagatesWithoutDefaultFallback() {
|
||||
when(repository.findByCustomer(17)).thenThrow(new IllegalStateException("database unavailable"));
|
||||
assertThatThrownBy(() -> service.pricing(17)).isInstanceOf(IllegalStateException.class);
|
||||
}
|
||||
|
||||
@ParameterizedTest @ValueSource(longs={0,-1})
|
||||
void invalidCustomerNeverQueries(long customer) {
|
||||
assertThatThrownBy(() -> service.pricing(customer)).isInstanceOf(BizException.class);
|
||||
verifyNoInteractions(repository);
|
||||
}
|
||||
|
||||
@Test void pricingRequiresReadOnlyRepeatableSnapshot() throws Exception {
|
||||
var transaction=OverseasStorageFeeService.class.getMethod("pricing",long.class).getAnnotation(Transactional.class);
|
||||
assertThat(transaction.readOnly()).isTrue(); assertThat(transaction.isolation()).isEqualTo(Isolation.REPEATABLE_READ);
|
||||
}
|
||||
|
||||
@Test void ruleAndTierReadsShareOneActiveRepeatableReadTransactionConnection() {
|
||||
var data=new org.springframework.jdbc.datasource.DriverManagerDataSource(
|
||||
"jdbc:h2:mem:pricing-snapshot-"+java.util.UUID.randomUUID(),"sa","");
|
||||
var transactionManager=new org.springframework.jdbc.datasource.DataSourceTransactionManager(data);
|
||||
var proxy=new org.springframework.aop.framework.ProxyFactory(service); proxy.setProxyTargetClass(true);
|
||||
proxy.addAdvice(new org.springframework.transaction.interceptor.TransactionInterceptor(transactionManager,
|
||||
new org.springframework.transaction.annotation.AnnotationTransactionAttributeSource()));
|
||||
var transactional=(OverseasStorageFeeService)proxy.getProxy();
|
||||
var connection=new java.util.concurrent.atomic.AtomicReference<java.sql.Connection>();
|
||||
when(repository.findByCustomer(17)).thenAnswer(invocation -> {
|
||||
assertThat(org.springframework.transaction.support.TransactionSynchronizationManager.isActualTransactionActive()).isTrue();
|
||||
assertThat(org.springframework.transaction.support.TransactionSynchronizationManager.isCurrentTransactionReadOnly()).isTrue();
|
||||
var current=org.springframework.jdbc.datasource.DataSourceUtils.getConnection(data); connection.set(current);
|
||||
assertThat(current.getTransactionIsolation()).isEqualTo(java.sql.Connection.TRANSACTION_REPEATABLE_READ);
|
||||
var rule=new OverseasStorageFeeRuleEntity(); rule.setId(51L); rule.setTenantId(17L);
|
||||
rule.setCurrency("USD"); rule.setVersion(3); return rule;
|
||||
});
|
||||
when(repository.findTiers(List.of(51L))).thenAnswer(invocation -> {
|
||||
assertThat(org.springframework.jdbc.datasource.DataSourceUtils.getConnection(data)).isSameAs(connection.get());
|
||||
assertThat(org.springframework.transaction.support.TransactionSynchronizationManager.isActualTransactionActive()).isTrue();
|
||||
return List.of(tier("STORAGE",1,null,"9"),tier("RETURN_STORAGE",1,null,"8"));
|
||||
});
|
||||
assertThat(transactional.pricing(17).version()).isEqualTo(3);
|
||||
assertThat(org.springframework.transaction.support.TransactionSynchronizationManager.isActualTransactionActive()).isFalse();
|
||||
}
|
||||
|
||||
private void configured(String currency,List<OverseasStorageFeeTierEntity> tiers) {
|
||||
var rule=new OverseasStorageFeeRuleEntity(); rule.setId(51L); rule.setTenantId(17L);
|
||||
rule.setCurrency(currency); rule.setVersion(3);
|
||||
when(repository.findByCustomer(17)).thenReturn(rule); when(repository.findTiers(List.of(51L))).thenReturn(tiers);
|
||||
}
|
||||
|
||||
private OverseasStorageFeeTierEntity tier(String type,int start,Integer end,String price) {
|
||||
var tier=new OverseasStorageFeeTierEntity(); tier.setId(71L); tier.setRuleId(51L); tier.setTenantId(17L);
|
||||
tier.setFeeType(type); tier.setBillingUnit("STORAGE".equals(type)?"CBM":"PALLET");
|
||||
tier.setStartDay(start); tier.setEndDay(end); tier.setUnitPrice(new BigDecimal(price)); return tier;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user