148 lines
6.2 KiB
Java
148 lines
6.2 KiB
Java
package com.baiyue.firstleg.service;
|
|
|
|
import com.baiyue.common.core.exception.BizException;
|
|
import com.baiyue.firstleg.dto.ContainerFeeDetailDtos;
|
|
import com.baiyue.firstleg.entity.ContainerFeeDetailEntity;
|
|
import com.baiyue.firstleg.entity.FeeItemEntity;
|
|
import com.baiyue.firstleg.entity.LoadingPlanEntity;
|
|
import com.baiyue.firstleg.entity.LoadingPlanItemEntity;
|
|
import com.baiyue.firstleg.repository.ContainerFeeDetailRepository;
|
|
import com.baiyue.firstleg.repository.FeeItemRepository;
|
|
import com.baiyue.firstleg.repository.SmartLoadingRepository;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.mockito.ArgumentCaptor;
|
|
|
|
import java.math.BigDecimal;
|
|
import java.time.LocalDate;
|
|
import java.time.LocalDateTime;
|
|
import java.util.List;
|
|
|
|
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.eq;
|
|
import static org.mockito.Mockito.mock;
|
|
import static org.mockito.Mockito.never;
|
|
import static org.mockito.Mockito.verify;
|
|
import static org.mockito.Mockito.when;
|
|
|
|
class ContainerFeeDetailServiceTest {
|
|
private final ContainerFeeDetailRepository repository = mock(ContainerFeeDetailRepository.class);
|
|
private final SmartLoadingRepository loading = mock(SmartLoadingRepository.class);
|
|
private final FeeItemRepository feeItems = mock(FeeItemRepository.class);
|
|
private final FinanceFeeSourceOutboxService outbox = mock(FinanceFeeSourceOutboxService.class);
|
|
private final ContainerFeeDetailService service =
|
|
new ContainerFeeDetailService(repository, loading, feeItems, outbox);
|
|
|
|
@Test
|
|
void rejectsContainerThatDoesNotContainCustomerOrders() {
|
|
LoadingPlanEntity plan = new LoadingPlanEntity();
|
|
plan.setId(41L);
|
|
when(loading.plan(41L)).thenReturn(plan);
|
|
LoadingPlanItemEntity other = new LoadingPlanItemEntity();
|
|
other.setAccountId(20002L);
|
|
when(loading.items(41L)).thenReturn(List.of(other));
|
|
|
|
assertThatThrownBy(() -> service.create(10001L, 41L, 9L, request(true)))
|
|
.isInstanceOf(BizException.class).hasMessageContaining("不属于该客户");
|
|
verify(repository, never()).insert(any());
|
|
}
|
|
|
|
@Test
|
|
void approvedSettlementFeePublishesContainerSource() {
|
|
ownedPlan();
|
|
ContainerFeeDetailEntity approved = new ContainerFeeDetailEntity();
|
|
approved.setId(51L);
|
|
approved.setTenantId(10001L);
|
|
approved.setLoadingPlanId(41L);
|
|
approved.setSourceVersion(1);
|
|
approved.setSettlementIncluded(true);
|
|
when(repository.find(10001L, 41L, 51L)).thenReturn(approved);
|
|
when(repository.review(10001L, 41L, 51L, "APPROVED", 9L, "admin", null)).thenReturn(1);
|
|
|
|
service.approve(10001L, 41L, 51L, 9L, "admin");
|
|
|
|
verify(outbox).publishContainer(eq(FinanceFeeSourceOutboxService.PUBLISHED),
|
|
eq(10001L), eq(41L), eq(51L), eq(1), any(LocalDateTime.class));
|
|
}
|
|
|
|
@Test
|
|
void adjustmentIncrementsSourceVersionAndReturnsToReview() {
|
|
ownedPlan();
|
|
FeeItemEntity item = item();
|
|
when(feeItems.findItem(11L)).thenReturn(item);
|
|
ContainerFeeDetailEntity current = new ContainerFeeDetailEntity();
|
|
current.setId(51L);
|
|
current.setTenantId(10001L);
|
|
current.setLoadingPlanId(41L);
|
|
current.setSourceVersion(1);
|
|
when(repository.find(10001L, 41L, 51L)).thenReturn(current);
|
|
when(repository.adjust(any(), eq(1))).thenReturn(1);
|
|
|
|
service.adjust(10001L, 41L, 51L, 1, 9L, request(true));
|
|
|
|
ArgumentCaptor<ContainerFeeDetailEntity> captor = ArgumentCaptor.forClass(ContainerFeeDetailEntity.class);
|
|
verify(repository).adjust(captor.capture(), eq(1));
|
|
assertThat(captor.getValue().getSourceVersion()).isEqualTo(2);
|
|
assertThat(captor.getValue().getReviewStatus()).isEqualTo("PENDING");
|
|
assertThat(captor.getValue().getPartnerId()).isEqualTo(71L);
|
|
assertThat(captor.getValue().getPartnerName()).isEqualTo("现有往来单位");
|
|
}
|
|
|
|
@Test
|
|
void payableRequiresCounterpartySnapshot() {
|
|
ownedPlan();
|
|
when(feeItems.findItem(11L)).thenReturn(item());
|
|
|
|
var missingPartner = new ContainerFeeDetailDtos.SaveRequest(11L, "PAYABLE",
|
|
LocalDate.of(2026, 8, 11), new BigDecimal("300.00"), "CNY",
|
|
true, null, null, "整柜拖车费");
|
|
|
|
assertThatThrownBy(() -> service.create(10001L, 41L, 9L, missingPartner))
|
|
.isInstanceOf(BizException.class).hasMessageContaining("必须选择有效往来单位");
|
|
verify(repository, never()).insert(any());
|
|
}
|
|
|
|
@Test
|
|
void receivableClearsCounterpartyFields() {
|
|
ownedPlan();
|
|
when(feeItems.findItem(11L)).thenReturn(item());
|
|
|
|
var request = new ContainerFeeDetailDtos.SaveRequest(11L, "RECEIVABLE",
|
|
LocalDate.of(2026, 8, 11), new BigDecimal("300.00"), "CNY",
|
|
true, 71L, "不应保留", "整柜操作费");
|
|
service.create(10001L, 41L, 9L, request);
|
|
|
|
ArgumentCaptor<ContainerFeeDetailEntity> captor = ArgumentCaptor.forClass(ContainerFeeDetailEntity.class);
|
|
verify(repository).insert(captor.capture());
|
|
assertThat(captor.getValue().getPartnerId()).isNull();
|
|
assertThat(captor.getValue().getPartnerName()).isNull();
|
|
}
|
|
|
|
private void ownedPlan() {
|
|
LoadingPlanEntity plan = new LoadingPlanEntity();
|
|
plan.setId(41L);
|
|
when(loading.plan(41L)).thenReturn(plan);
|
|
LoadingPlanItemEntity item = new LoadingPlanItemEntity();
|
|
item.setAccountId(10001L);
|
|
when(loading.items(41L)).thenReturn(List.of(item));
|
|
}
|
|
|
|
private static FeeItemEntity item() {
|
|
FeeItemEntity value = new FeeItemEntity();
|
|
value.setId(11L);
|
|
value.setFeeCode("TRUCKING");
|
|
value.setFeeTypeName("拖车费");
|
|
value.setWarehouseReceivable(true);
|
|
value.setWarehousePayable(true);
|
|
value.setStatus("ACTIVE");
|
|
return value;
|
|
}
|
|
|
|
private static ContainerFeeDetailDtos.SaveRequest request(boolean settlementIncluded) {
|
|
return new ContainerFeeDetailDtos.SaveRequest(11L, "PAYABLE",
|
|
LocalDate.of(2026, 8, 11), new BigDecimal("300.00"), "CNY",
|
|
settlementIncluded, 71L, " 现有往来单位 ", "整柜拖车费");
|
|
}
|
|
}
|