This commit is contained in:
2026-08-13 16:58:17 +08:00
parent bd523036d0
commit 38e8494216
15 changed files with 344 additions and 17 deletions
@@ -8,6 +8,22 @@ import java.nio.charset.StandardCharsets;
import static org.assertj.core.api.Assertions.assertThat;
class FinanceFeeSourceMigrationContractTest {
@Test
void freshSchemaAndMigrationExposeInboundFeePartnerSnapshotsUsedByAllFeeFlows() throws Exception {
String baseline = new ClassPathResource("db/phase2-fee-item-and-inbound-detail.sql")
.getContentAsString(StandardCharsets.UTF_8);
String migration = new ClassPathResource("db/finance-fee-source-migration.sql")
.getContentAsString(StandardCharsets.UTF_8);
assertThat(baseline).contains(
"partner_id BIGINT UNSIGNED NULL",
"partner_name VARCHAR(200) NULL");
assertThat(migration).contains(
"firstleg_finance_add_column('fl_inbound_fee_detail', 'partner_id'",
"firstleg_finance_add_column('fl_inbound_fee_detail', 'partner_name'",
"Firstleg Finance迁移失败:入库费用往来单位快照字段不完整");
}
@Test
void migrationDefinesIdempotentOutboxEnvelopeAndContainerFeeModel() throws Exception {
String sql = new ClassPathResource("db/finance-fee-source-migration.sql")
@@ -0,0 +1,26 @@
package com.baiyue.firstleg.repository;
import com.baiyue.firstleg.mapper.InboundFeeDetailMapper;
import org.apache.ibatis.annotations.Update;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;
import static org.assertj.core.api.Assertions.assertThat;
class InboundFeeDetailMapperContractTest {
@Test
void logicalDeleteIsScopedToCustomerInboundDetailAndActiveRow() throws Exception {
Method method = InboundFeeDetailMapper.class.getMethod(
"logicallyDelete", long.class, long.class, long.class);
String sql = String.join(" ", method.getAnnotation(Update.class).value())
.replaceAll("\\s+", " ").toLowerCase();
assertThat(sql)
.contains("set deleted = 1")
.contains("tenant_id = #{tenantid}")
.contains("inbound_id = #{inboundid}")
.contains("id = #{detailid}")
.contains("deleted = 0");
}
}
@@ -112,15 +112,12 @@ class TenantScopedMutationRepositoryTest {
}
@Test
@SuppressWarnings({"rawtypes", "unchecked"})
void feeDetailDeleteMatchesTenantAndId() {
when(feeDetails.delete(any(Wrapper.class))).thenReturn(1);
when(feeDetails.logicallyDelete(TENANT, 77L, ID)).thenReturn(1);
assertThat(feeRepository.deleteDetail(TENANT, ID)).isEqualTo(1);
assertThat(feeRepository.deleteDetail(TENANT, 77L, ID)).isEqualTo(1);
ArgumentCaptor<Wrapper<InboundFeeDetailEntity>> wrapper = ArgumentCaptor.forClass(Wrapper.class);
verify(feeDetails).delete(wrapper.capture());
assertTenantAndId(wrapper.getValue());
verify(feeDetails).logicallyDelete(TENANT, 77L, ID);
}
@Test
@@ -56,7 +56,20 @@ class FeeManagementServiceTest {
.hasMessageContaining("费用明细不存在");
verify(repository).findDetail(10002L, 21L, 31L);
verify(repository, never()).deleteDetail(10002L, 31L);
verify(repository, never()).deleteDetail(10002L, 21L, 31L);
}
@Test
@DisplayName("待审核费用明细按客户和入库单作用域删除")
void deletesPendingFeeDetailInInboundScope() {
InboundFeeDetailEntity pending = new InboundFeeDetailEntity();
pending.setReviewStatus("PENDING");
when(repository.findDetail(10001L, 21L, 31L)).thenReturn(pending);
when(repository.deleteDetail(10001L, 21L, 31L)).thenReturn(1);
details.delete(10001L, 21L, 31L);
verify(repository).deleteDetail(10001L, 21L, 31L);
}
@Test