优化
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
package com.baiyue.finance;
|
||||
|
||||
import com.baiyue.finance.client.FinanceFileClient;
|
||||
import com.baiyue.finance.client.FirstlegCostSnapshotClient;
|
||||
import com.baiyue.finance.controller.PlatformFinanceController;
|
||||
import com.baiyue.finance.dto.FinanceReadModels.CustomerAccountSummary;
|
||||
import com.baiyue.finance.service.FinanceQueryService;
|
||||
import com.baiyue.finance.service.FinanceService;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class CustomerAccountSummaryBehaviorTest {
|
||||
|
||||
@Test
|
||||
void aggregatesFormalSettlementsInOneCustomerScopedQuery() throws Exception {
|
||||
JdbcTemplate jdbc = mock(JdbcTemplate.class);
|
||||
ResultSet rs = summaryRow("300.00", "140.00", "160.00", "25.00", "80.00");
|
||||
when(jdbc.queryForObject(anyString(), any(RowMapper.class), any(), any(), any())).thenAnswer(invocation ->
|
||||
((RowMapper<?>) invocation.getArgument(1)).mapRow(rs, 0));
|
||||
FinanceQueryService service = new FinanceQueryService(jdbc, new ObjectMapper());
|
||||
|
||||
CustomerAccountSummary result = service.customerAccountSummary(9L);
|
||||
|
||||
assertThat(result.customerId()).isEqualTo(9L);
|
||||
assertThat(result.currency()).isEqualTo("CNY");
|
||||
assertThat(result.totalReceivable()).isEqualByComparingTo("300.00");
|
||||
assertThat(result.receivedAmount()).isEqualByComparingTo("140.00");
|
||||
assertThat(result.outstandingReceivable()).isEqualByComparingTo("160.00");
|
||||
assertThat(result.pendingBilling()).isEqualByComparingTo("25.00");
|
||||
assertThat(result.outstandingPayable()).isEqualByComparingTo("80.00");
|
||||
|
||||
var sql = org.mockito.ArgumentCaptor.forClass(String.class);
|
||||
verify(jdbc).queryForObject(sql.capture(), any(RowMapper.class),
|
||||
org.mockito.ArgumentMatchers.eq(9L), org.mockito.ArgumentMatchers.eq(9L), org.mockito.ArgumentMatchers.eq(9L));
|
||||
assertThat(sql.getValue())
|
||||
.contains("FROM fin_settlement s WHERE s.tenant_id=?")
|
||||
.contains("s.direction='RECEIVABLE' AND s.status<>'VOIDED'")
|
||||
.contains("s.direction='PAYABLE' AND s.status<>'VOIDED'")
|
||||
.contains("f.customer_id=?", "f.status='AVAILABLE'", "'$.reviewStatus'", "'$.settlementIncluded'")
|
||||
.contains("b.status<>'VOIDED'")
|
||||
.doesNotContain("SUM(received_amount)", "FROM fin_receipt r");
|
||||
}
|
||||
|
||||
@Test
|
||||
void emptyCustomerReturnsZeroAmounts() throws Exception {
|
||||
JdbcTemplate jdbc = mock(JdbcTemplate.class);
|
||||
ResultSet rs = summaryRow("0", "0", "0", "0", "0");
|
||||
when(jdbc.queryForObject(anyString(), any(RowMapper.class), any(), any(), any())).thenAnswer(invocation ->
|
||||
((RowMapper<?>) invocation.getArgument(1)).mapRow(rs, 0));
|
||||
|
||||
CustomerAccountSummary result = new FinanceQueryService(jdbc, new ObjectMapper()).customerAccountSummary(77L);
|
||||
|
||||
assertThat(result.totalReceivable()).isZero();
|
||||
assertThat(result.receivedAmount()).isZero();
|
||||
assertThat(result.outstandingReceivable()).isZero();
|
||||
assertThat(result.pendingBilling()).isZero();
|
||||
assertThat(result.outstandingPayable()).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
void controllerUsesListPermissionAndDelegatesSummary() throws Exception {
|
||||
FinanceQueryService query = mock(FinanceQueryService.class);
|
||||
PlatformFinanceController controller = new PlatformFinanceController(mock(FinanceService.class),
|
||||
mock(FinanceFileClient.class), mock(FirstlegCostSnapshotClient.class), query);
|
||||
|
||||
controller.customerAccountSummary(11L);
|
||||
|
||||
verify(query).customerAccountSummary(11L);
|
||||
PreAuthorize permission = PlatformFinanceController.class
|
||||
.getMethod("customerAccountSummary", long.class).getAnnotation(PreAuthorize.class);
|
||||
assertThat(permission.value()).isEqualTo("hasAuthority('platform:finance:customer-account:list')");
|
||||
}
|
||||
|
||||
private static ResultSet summaryRow(String total, String paid, String outstanding,
|
||||
String pending, String payable) throws Exception {
|
||||
ResultSet rs = mock(ResultSet.class);
|
||||
when(rs.getBigDecimal("total_receivable")).thenReturn(new BigDecimal(total));
|
||||
when(rs.getBigDecimal("received_amount")).thenReturn(new BigDecimal(paid));
|
||||
when(rs.getBigDecimal("outstanding_receivable")).thenReturn(new BigDecimal(outstanding));
|
||||
when(rs.getBigDecimal("pending_billing")).thenReturn(new BigDecimal(pending));
|
||||
when(rs.getBigDecimal("outstanding_payable")).thenReturn(new BigDecimal(payable));
|
||||
when(rs.getTimestamp("last_changed_at")).thenReturn(Timestamp.valueOf(LocalDateTime.of(2026, 8, 13, 12, 0)));
|
||||
return rs;
|
||||
}
|
||||
}
|
||||
@@ -15,14 +15,14 @@ class FinancePhase1PermissionContractTest {
|
||||
@Test
|
||||
void freezesG1AndG2ControllerPermissionsAndHttpActions() throws Exception {
|
||||
assertEndpoint("listDerivedCustomerAccounts", GetMapping.class,
|
||||
"platform:finance:customer-account:list", "platform:finance:account:view",
|
||||
"platform:finance:customer-account:list", null,
|
||||
int.class, int.class, String.class, String.class);
|
||||
assertEndpoint("listDerivedCustomerAccountLedger", GetMapping.class,
|
||||
"platform:finance:customer-account:list", "platform:finance:account:view",
|
||||
"platform:finance:customer-account:list", null,
|
||||
long.class, int.class, int.class,
|
||||
String.class, java.time.LocalDate.class, java.time.LocalDate.class);
|
||||
assertEndpoint("getFinanceFeeSource", GetMapping.class,
|
||||
"platform:finance:customer-arap:list", "platform:finance:fee-source:view", long.class);
|
||||
"platform:finance:customer-arap:list", null, long.class);
|
||||
assertEndpoint("reviewFinanceFeeSource", PostMapping.class,
|
||||
"platform:finance:fee-source:review", null,
|
||||
com.baiyue.common.security.AuthenticatedUser.class, long.class, String.class,
|
||||
|
||||
@@ -30,8 +30,8 @@ class FinancePlatformListContractTest {
|
||||
Map<String, String> expected = Map.of(
|
||||
"feePool", "platform:finance:customer-arap:list",
|
||||
"statements", "platform:finance:customer-statement:list",
|
||||
"receivableSettlements", "platform:finance:settlement-ar:view",
|
||||
"payableSettlements", "platform:finance:settlement-ap:view");
|
||||
"receivableSettlements", "platform:finance:settlement-ar:list",
|
||||
"payableSettlements", "platform:finance:settlement-ap:list");
|
||||
for (var entry : expected.entrySet()) {
|
||||
assertThat(find(entry.getKey()).getAnnotation(PreAuthorize.class).value()).contains(entry.getValue());
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ class FinanceSettlementBehaviorTest {
|
||||
FinanceSettlementController controller = new FinanceSettlementController(controllerService);
|
||||
SettlementDetail payable = detail("PAYABLE", "ISSUED", BigDecimal.ZERO, new BigDecimal("100.00"), 0);
|
||||
when(controllerService.getSettlement(88L)).thenReturn(payable);
|
||||
AuthenticatedUser apViewer = user(Set.of("platform:finance:settlement-ap:view"));
|
||||
AuthenticatedUser apViewer = user(Set.of("platform:finance:settlement-ap:list"));
|
||||
|
||||
var response = controller.getSettlement(apViewer, 88L);
|
||||
|
||||
@@ -62,7 +62,7 @@ class FinanceSettlementBehaviorTest {
|
||||
assertThat(response.data()).isSameAs(payable);
|
||||
assertThat(response.requestId()).isNotBlank();
|
||||
assertThatThrownBy(() -> controller.getSettlement(
|
||||
user(Set.of("platform:finance:settlement-ar:view")), 88L)).isInstanceOf(AccessDeniedException.class);
|
||||
user(Set.of("platform:finance:settlement-ar:list")), 88L)).isInstanceOf(AccessDeniedException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user