优化
This commit is contained in:
@@ -15,18 +15,20 @@ class FinancePhase1PermissionContractTest {
|
||||
@Test
|
||||
void freezesG1AndG2ControllerPermissionsAndHttpActions() throws Exception {
|
||||
assertEndpoint("listDerivedCustomerAccounts", GetMapping.class,
|
||||
"hasAuthority('platform:finance:account:view')", int.class, int.class, String.class, String.class);
|
||||
"platform:finance:customer-account:list", "platform:finance:account:view",
|
||||
int.class, int.class, String.class, String.class);
|
||||
assertEndpoint("listDerivedCustomerAccountLedger", GetMapping.class,
|
||||
"hasAuthority('platform:finance:account:view')", long.class, int.class, int.class,
|
||||
"platform:finance:customer-account:list", "platform:finance:account:view",
|
||||
long.class, int.class, int.class,
|
||||
String.class, java.time.LocalDate.class, java.time.LocalDate.class);
|
||||
assertEndpoint("getFinanceFeeSource", GetMapping.class,
|
||||
"hasAuthority('platform:finance:fee-source:view')", long.class);
|
||||
"platform:finance:customer-arap:list", "platform:finance:fee-source:view", long.class);
|
||||
assertEndpoint("reviewFinanceFeeSource", PostMapping.class,
|
||||
"hasAuthority('platform:finance:fee-source:review')",
|
||||
"platform:finance:fee-source:review", null,
|
||||
com.baiyue.common.security.AuthenticatedUser.class, long.class, String.class,
|
||||
com.baiyue.finance.dto.FinancePhase1Dtos.ReviewRequest.class);
|
||||
assertEndpoint("updateFeeSourceSettlementInclusion", PutMapping.class,
|
||||
"hasAuthority('platform:finance:fee-source:settlement')",
|
||||
"platform:finance:fee-source:settlement", null,
|
||||
com.baiyue.common.security.AuthenticatedUser.class, long.class, String.class,
|
||||
com.baiyue.finance.dto.FinancePhase1Dtos.SettlementInclusionRequest.class);
|
||||
}
|
||||
@@ -34,9 +36,13 @@ class FinancePhase1PermissionContractTest {
|
||||
private static void assertEndpoint(String methodName,
|
||||
Class<? extends java.lang.annotation.Annotation> mapping,
|
||||
String authority,
|
||||
String compatibleAuthority,
|
||||
Class<?>... parameterTypes) throws Exception {
|
||||
Method method = FinancePhase1OperationController.class.getMethod(methodName, parameterTypes);
|
||||
assertThat(method.isAnnotationPresent(mapping)).isTrue();
|
||||
assertThat(method.getAnnotation(PreAuthorize.class).value()).isEqualTo(authority);
|
||||
assertThat(method.getAnnotation(PreAuthorize.class).value()).contains(authority);
|
||||
if (compatibleAuthority != null) {
|
||||
assertThat(method.getAnnotation(PreAuthorize.class).value()).contains(compatibleAuthority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,12 +28,12 @@ class FinancePlatformListContractTest {
|
||||
@Test
|
||||
void platformListPermissionsRemainSeparatedByReceivableAndPayableData() throws Exception {
|
||||
Map<String, String> expected = Map.of(
|
||||
"feePool", "hasAuthority('platform:finance:bill:view')",
|
||||
"statements", "hasAuthority('platform:finance:bill:view')",
|
||||
"receivableSettlements", "hasAuthority('platform:finance:settlement-ar:view')",
|
||||
"payableSettlements", "hasAuthority('platform:finance:settlement-ap:view')");
|
||||
"feePool", "platform:finance:customer-arap:list",
|
||||
"statements", "platform:finance:customer-statement:list",
|
||||
"receivableSettlements", "platform:finance:settlement-ar:view",
|
||||
"payableSettlements", "platform:finance:settlement-ap:view");
|
||||
for (var entry : expected.entrySet()) {
|
||||
assertThat(find(entry.getKey()).getAnnotation(PreAuthorize.class).value()).isEqualTo(entry.getValue());
|
||||
assertThat(find(entry.getKey()).getAnnotation(PreAuthorize.class).value()).contains(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.baiyue.finance.dto.FinanceSettlementDtos.CreateReceivableSettlementRe
|
||||
import com.baiyue.finance.dto.FinanceSettlementDtos.CreateSettlementPaymentRequest;
|
||||
import com.baiyue.finance.dto.FinanceSettlementDtos.SettlementDetail;
|
||||
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.fasterxml.jackson.databind.ObjectMapper;
|
||||
@@ -161,6 +162,55 @@ class FinanceSettlementBehaviorTest {
|
||||
verify(jdbc, never()).update(startsWith("INSERT INTO fin_settlement_payment"), (Object[]) any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void unpaidSettlementCanBeVoidedAndReopenedWithAuditAndVersionCheck() {
|
||||
JdbcTemplate jdbc = org.mockito.Mockito.mock(JdbcTemplate.class, invocation ->
|
||||
"update".equals(invocation.getMethod().getName()) ? 1 : RETURNS_DEFAULTS.answer(invocation));
|
||||
Map<String, Object> issued = settlementRow("PAYABLE", "ISSUED", BigDecimal.ZERO,
|
||||
new BigDecimal("100.00"), 2);
|
||||
Map<String, Object> voided = settlementRow("PAYABLE", "VOIDED", BigDecimal.ZERO,
|
||||
new BigDecimal("100.00"), 3);
|
||||
when(jdbc.queryForList(startsWith("SELECT id,tenant_id,total_amount"), eq(88L)))
|
||||
.thenReturn(List.of(issued));
|
||||
when(jdbc.queryForList(startsWith("SELECT request_hash"), eq(10L), eq(7L),
|
||||
eq("SETTLEMENT_STATE_ACTION"), eq("void-key"))).thenReturn(List.of());
|
||||
stubSettlementDetail(jdbc, voided);
|
||||
FinanceSettlementService service = service(jdbc, org.mockito.Mockito.mock(FinanceFileClient.class));
|
||||
|
||||
SettlementDetail result = service.actionSettlement(88L, 7L, "void-key",
|
||||
new SettlementActionRequest("VOID", "业务取消", 2));
|
||||
|
||||
assertThat(result.summary().status()).isEqualTo("VOIDED");
|
||||
verify(jdbc).update(startsWith("UPDATE fin_settlement SET status="), eq("VOIDED"), eq(7L),
|
||||
eq(88L), eq(10L), eq(2));
|
||||
verify(jdbc).update(startsWith("INSERT INTO fin_audit_log"), eq(10L), eq("FIN_SETTLEMENT"),
|
||||
eq(88L), eq("VOID"), eq("业务取消"), any(), any(), eq(7L), any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void settlementActionRejectsPaidInvalidStateAndStaleVersion() {
|
||||
JdbcTemplate paidJdbc = org.mockito.Mockito.mock(JdbcTemplate.class);
|
||||
when(paidJdbc.queryForList(startsWith("SELECT id,tenant_id,total_amount"), eq(88L)))
|
||||
.thenReturn(List.of(settlementRow("PAYABLE", "PARTIALLY_PAID", new BigDecimal("40.00"),
|
||||
new BigDecimal("60.00"), 2)));
|
||||
when(paidJdbc.queryForList(startsWith("SELECT request_hash"), eq(10L), eq(7L),
|
||||
eq("SETTLEMENT_STATE_ACTION"), anyString())).thenReturn(List.of());
|
||||
FinanceSettlementService paidService = service(paidJdbc, org.mockito.Mockito.mock(FinanceFileClient.class));
|
||||
assertCode(() -> paidService.actionSettlement(88L, 7L, "paid-key",
|
||||
new SettlementActionRequest("VOID", "不能作废", 2)), "FIN_409");
|
||||
|
||||
JdbcTemplate staleJdbc = org.mockito.Mockito.mock(JdbcTemplate.class);
|
||||
when(staleJdbc.queryForList(startsWith("SELECT id,tenant_id,total_amount"), eq(88L)))
|
||||
.thenReturn(List.of(settlementRow("PAYABLE", "VOIDED", BigDecimal.ZERO,
|
||||
new BigDecimal("100.00"), 3)));
|
||||
when(staleJdbc.queryForList(startsWith("SELECT request_hash"), eq(10L), eq(7L),
|
||||
eq("SETTLEMENT_STATE_ACTION"), eq("stale-action"))).thenReturn(List.of());
|
||||
FinanceSettlementService staleService = service(staleJdbc, org.mockito.Mockito.mock(FinanceFileClient.class));
|
||||
assertCode(() -> staleService.actionSettlement(88L, 7L, "stale-action",
|
||||
new SettlementActionRequest("REOPEN", "恢复结算", 2)), "FIN_409");
|
||||
verify(staleJdbc, never()).update(startsWith("UPDATE fin_settlement SET status="), (Object[]) any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void partialPaymentUpdatesOutstandingAndReturnsTypedDetail() {
|
||||
JdbcTemplate jdbc = org.mockito.Mockito.mock(JdbcTemplate.class, invocation ->
|
||||
|
||||
Reference in New Issue
Block a user