优化
This commit is contained in:
@@ -5,6 +5,7 @@ import com.baiyue.finance.client.FirstlegFeeSourceClient;
|
||||
import com.baiyue.finance.dto.FinanceFeeSourceEvent;
|
||||
import com.baiyue.finance.service.FinanceEventException;
|
||||
import com.baiyue.finance.service.FinanceFeeSourceEventService;
|
||||
import com.baiyue.finance.service.FinanceSupplierValidator;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -30,11 +31,16 @@ class FinanceFeeSourceEventServiceTest {
|
||||
private final JdbcTemplate jdbc = mock(JdbcTemplate.class);
|
||||
private final FirstlegFeeSourceClient firstleg = mock(FirstlegFeeSourceClient.class);
|
||||
private final ObjectMapper mapper = new ObjectMapper().findAndRegisterModules();
|
||||
private final FinanceFeeSourceEventService service = new FinanceFeeSourceEventService(jdbc, firstleg, mapper);
|
||||
private final FinanceSupplierValidator supplierValidator = mock(FinanceSupplierValidator.class);
|
||||
private final FinanceFeeSourceEventService service = new FinanceFeeSourceEventService(jdbc, firstleg, mapper, supplierValidator);
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
ReflectionTestUtils.setField(service, "internalToken", "test-token");
|
||||
lenient().when(supplierValidator.categoryFor(any(), any())).thenReturn("TRUCKING");
|
||||
lenient().when(supplierValidator.requireActive(anyLong(), any())).thenReturn(
|
||||
new com.baiyue.finance.client.WarehouseSupplierClient.SupplierSnapshot(
|
||||
71L, "现有供应商", "TRUCKING", "DOMESTIC", "ACTIVE"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -73,6 +79,8 @@ class FinanceFeeSourceEventServiceTest {
|
||||
|
||||
assertThat(service.consume(event)).isEqualTo(101L);
|
||||
|
||||
verify(supplierValidator).categoryFor("TRUCKING", "拖车费");
|
||||
verify(supplierValidator).requireActive(71L, "TRUCKING");
|
||||
ArgumentCaptor<Object[]> values = ArgumentCaptor.forClass(Object[].class);
|
||||
verify(jdbc).update(startsWith("INSERT INTO fin_fee_source"), values.capture());
|
||||
assertThat(values.getValue()[14].toString())
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.baiyue.finance;
|
||||
|
||||
import com.baiyue.finance.service.FinanceService;
|
||||
import com.baiyue.finance.service.FinanceSupplierValidator;
|
||||
import com.baiyue.finance.service.FinanceVoucherValidator;
|
||||
import com.baiyue.finance.client.FinanceFileClient;
|
||||
import com.baiyue.common.core.api.ApiResponse;
|
||||
@@ -119,7 +120,7 @@ class FinanceServiceValidationTest {
|
||||
void receiptFailsClosedWhenFileValidationCapabilityIsUnavailable() {
|
||||
JdbcTemplate jdbc = mock(JdbcTemplate.class);
|
||||
FinanceService service = new FinanceService(jdbc, new ObjectMapper(),
|
||||
new FinanceVoucherValidator(null, ""));
|
||||
new FinanceVoucherValidator(null, ""), mock(FinanceSupplierValidator.class));
|
||||
var request = new FinanceService.ReceiptRequest("R-FILE", 1L, null, "BANK_TRANSFER", null, List.of("77"), null,
|
||||
List.of(new FinanceService.ReceiptAllocation(10L, BigDecimal.ONE)));
|
||||
|
||||
@@ -275,12 +276,12 @@ class FinanceServiceValidationTest {
|
||||
|
||||
private static FinanceService service(JdbcTemplate jdbc, FinanceFileClient files) {
|
||||
return new FinanceService(jdbc, new ObjectMapper().findAndRegisterModules(),
|
||||
new FinanceVoucherValidator(files, "internal-token"));
|
||||
new FinanceVoucherValidator(files, "internal-token"), mock(FinanceSupplierValidator.class));
|
||||
}
|
||||
|
||||
private static FinanceService service(JdbcTemplate jdbc) {
|
||||
return new FinanceService(jdbc, new ObjectMapper().findAndRegisterModules(),
|
||||
mock(FinanceVoucherValidator.class));
|
||||
mock(FinanceVoucherValidator.class), mock(FinanceSupplierValidator.class));
|
||||
}
|
||||
|
||||
private static FinanceService.BillLine billLine(long sourceId, int version, String amount) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.baiyue.finance.dto.FinanceSettlementDtos.SettlementSummary;
|
||||
import com.baiyue.finance.dto.FinanceSettlementDtos.SettlementActionRequest;
|
||||
import com.baiyue.finance.service.FinanceEventException;
|
||||
import com.baiyue.finance.service.FinanceSettlementService;
|
||||
import com.baiyue.finance.service.FinanceSupplierValidator;
|
||||
import com.baiyue.finance.service.FinanceVoucherValidator;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -38,6 +39,7 @@ import java.util.Set;
|
||||
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.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.startsWith;
|
||||
@@ -302,7 +304,8 @@ class FinanceSettlementBehaviorTest {
|
||||
when(jdbc.queryForList(startsWith("SELECT request_hash"), eq(10L), eq(7L), eq("SETTLEMENT_AP_CREATE"), eq("ap-key"))).thenReturn(List.of());
|
||||
when(jdbc.queryForList(startsWith("SELECT id,customer_id"), eq(31L))).thenReturn(List.of(payableSource(10L, 20L)));
|
||||
when(jdbc.queryForObject(startsWith("SELECT COUNT(*) FROM fin_settlement_line"), eq(Integer.class), eq(31L))).thenReturn(0);
|
||||
FinanceSettlementService service = service(jdbc, org.mockito.Mockito.mock(FinanceFileClient.class));
|
||||
FinanceSupplierValidator supplierValidator = supplierValidator();
|
||||
FinanceSettlementService service = service(jdbc, org.mockito.Mockito.mock(FinanceFileClient.class), supplierValidator);
|
||||
|
||||
SettlementDetail result = service.createPayableSettlement(7L, "ap-key",
|
||||
new CreatePayableSettlementRequest(10L, 20L, List.of(31L), LocalDate.of(2026, 9, 30), "CNY"));
|
||||
@@ -310,6 +313,8 @@ class FinanceSettlementBehaviorTest {
|
||||
assertThat(result.summary().direction()).isEqualTo("PAYABLE");
|
||||
assertThat(result.summary().supplierId()).isEqualTo(20L);
|
||||
assertThat(result.summary().totalAmount()).isEqualByComparingTo("100.00");
|
||||
verify(supplierValidator).categoryFor("FBA_HEAD_FREIGHT", "头程运费");
|
||||
verify(supplierValidator).requireActive(20L, "BOOKING");
|
||||
verify(jdbc).update(startsWith("INSERT INTO fin_settlement_line"), eq(10L), eq(88L), eq(31L),
|
||||
eq(new BigDecimal("100.00")), eq("CNY"));
|
||||
}
|
||||
@@ -363,11 +368,13 @@ class FinanceSettlementBehaviorTest {
|
||||
stubSettlementDetail(jdbc, after);
|
||||
when(fileClient.metadata("internal-token", 10L, 10L, 91L)).thenReturn(ApiResponse.success(
|
||||
new FinanceFileClient.Metadata(91L, 10L, "FINANCE_VOUCHER", "10", "pay.png", "abc", "image/png", 10L)));
|
||||
FinanceSettlementService service = service(jdbc, fileClient);
|
||||
FinanceSupplierValidator supplierValidator = supplierValidator();
|
||||
FinanceSettlementService service = service(jdbc, fileClient, supplierValidator);
|
||||
|
||||
SettlementDetail result = service.createSettlementPayment(88L, 7L, "final-key", payment(new BigDecimal("60.00"), 1));
|
||||
|
||||
assertThat(result.summary().status()).isEqualTo("PAID");
|
||||
verify(supplierValidator).requireActive(20L, "BOOKING");
|
||||
assertThat(result.summary().outstandingAmount()).isZero();
|
||||
}
|
||||
|
||||
@@ -522,8 +529,24 @@ class FinanceSettlementBehaviorTest {
|
||||
}
|
||||
|
||||
private static FinanceSettlementService service(JdbcTemplate jdbc, FinanceFileClient fileClient) {
|
||||
return service(jdbc, fileClient, supplierValidator());
|
||||
}
|
||||
|
||||
private static FinanceSettlementService service(JdbcTemplate jdbc, FinanceFileClient fileClient,
|
||||
FinanceSupplierValidator supplierValidator) {
|
||||
org.mockito.Mockito.lenient().when(jdbc.queryForList(startsWith("SELECT f.fee_item_code"), anyLong(), anyLong()))
|
||||
.thenReturn(List.of(Map.of("fee_item_code", "FBA_HEAD_FREIGHT", "fee_item_name", "头程运费")));
|
||||
return new FinanceSettlementService(jdbc, new ObjectMapper().findAndRegisterModules(),
|
||||
new FinanceVoucherValidator(fileClient, "internal-token"));
|
||||
new FinanceVoucherValidator(fileClient, "internal-token"), supplierValidator);
|
||||
}
|
||||
|
||||
private static FinanceSupplierValidator supplierValidator() {
|
||||
FinanceSupplierValidator supplierValidator = org.mockito.Mockito.mock(FinanceSupplierValidator.class);
|
||||
org.mockito.Mockito.lenient().when(supplierValidator.categoryFor(any(), any())).thenReturn("BOOKING");
|
||||
org.mockito.Mockito.lenient().when(supplierValidator.requireActive(anyLong(), any()))
|
||||
.thenReturn(new com.baiyue.finance.client.WarehouseSupplierClient.SupplierSnapshot(
|
||||
20L, "供应商20", "BOOKING", "INTERNATIONAL", "ACTIVE"));
|
||||
return supplierValidator;
|
||||
}
|
||||
|
||||
private static CreateSettlementPaymentRequest payment(BigDecimal amount, int version) {
|
||||
@@ -558,6 +581,7 @@ class FinanceSettlementBehaviorTest {
|
||||
Map.entry("currency_code", "CNY"), Map.entry("status", "AVAILABLE"),
|
||||
Map.entry("amount", new BigDecimal("100.00")), Map.entry("review_status", "APPROVED"),
|
||||
Map.entry("settlement_included", "true"), Map.entry("supplier_id", supplierId),
|
||||
Map.entry("fee_item_code", "FBA_HEAD_FREIGHT"), Map.entry("fee_item_name", "头程运费"),
|
||||
Map.entry("supplier_name", "供应商20"), Map.entry("source_snapshot",
|
||||
"{\"customerName\":\"客户10\",\"supplierId\":20,\"supplierName\":\"供应商20\"}")));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.baiyue.finance;
|
||||
|
||||
import com.baiyue.common.core.api.ApiResponse;
|
||||
import com.baiyue.finance.client.WarehouseSupplierClient;
|
||||
import com.baiyue.finance.service.FinanceEventException;
|
||||
import com.baiyue.finance.service.FinanceSupplierValidator;
|
||||
import feign.FeignException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class FinanceSupplierValidatorTest {
|
||||
private final WarehouseSupplierClient client = mock(WarehouseSupplierClient.class);
|
||||
private final FinanceSupplierValidator validator = new FinanceSupplierValidator(client, "internal-token");
|
||||
|
||||
@Test
|
||||
void resolvesSupportedFeeCategories() {
|
||||
assertThat(validator.categoryFor("TRUCKING", "拖车费")).isEqualTo("TRUCKING");
|
||||
assertThat(validator.categoryFor("CUSTOMS_CLEARANCE", "报关费")).isEqualTo("CUSTOMS");
|
||||
assertThat(validator.categoryFor("FBA_HEAD_FREIGHT", "头程运费")).isEqualTo("BOOKING");
|
||||
assertThat(validator.categoryFor("CERTIFICATE_FEE", "证书费")).isEqualTo("CERTIFICATE");
|
||||
assertCode(() -> validator.categoryFor("ACPT_UNKNOWN", "操作费"), "FIN_409");
|
||||
}
|
||||
|
||||
@Test
|
||||
void requiresActiveWarehouseSupplierWithMatchingCategory() {
|
||||
var supplier = new WarehouseSupplierClient.SupplierSnapshot(20L, "正式供应商", "TRUCKING", "DOMESTIC", "ACTIVE");
|
||||
when(client.get("internal-token", 20L, true, "TRUCKING")).thenReturn(ApiResponse.success(supplier));
|
||||
|
||||
assertThat(validator.requireActive(20L, "TRUCKING").name()).isEqualTo("正式供应商");
|
||||
verify(client).get("internal-token", 20L, true, "TRUCKING");
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsMismatchedOrUnavailableSupplier() {
|
||||
var mismatched = new WarehouseSupplierClient.SupplierSnapshot(20L, "订舱供应商", "BOOKING", "INTERNATIONAL", "ACTIVE");
|
||||
when(client.get("internal-token", 20L, true, "TRUCKING")).thenReturn(ApiResponse.success(mismatched));
|
||||
assertCode(() -> validator.requireActive(20L, "TRUCKING"), "FIN_409");
|
||||
|
||||
when(client.get("internal-token", 21L, true, "BOOKING")).thenThrow(mock(FeignException.class));
|
||||
assertCode(() -> validator.requireActive(21L, "BOOKING"), "FIN_503");
|
||||
}
|
||||
|
||||
private static void assertCode(org.assertj.core.api.ThrowableAssert.ThrowingCallable call, String code) {
|
||||
assertThatThrownBy(call).isInstanceOf(FinanceEventException.class)
|
||||
.extracting(error -> ((FinanceEventException) error).code()).isEqualTo(code);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user