|
|
|
|
@@ -0,0 +1,250 @@
|
|
|
|
|
package com.healthlink.his.payment;
|
|
|
|
|
|
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
import com.core.common.utils.SecurityUtils;
|
|
|
|
|
import com.healthlink.his.BaseUnitTest;
|
|
|
|
|
import com.healthlink.his.administration.domain.ChargeItem;
|
|
|
|
|
import com.healthlink.his.administration.domain.ChargeItemDefinition;
|
|
|
|
|
import com.healthlink.his.administration.service.IChargeItemDefinitionService;
|
|
|
|
|
import com.healthlink.his.administration.service.IChargeItemService;
|
|
|
|
|
import com.healthlink.his.common.enums.ChargeItemStatus;
|
|
|
|
|
import com.healthlink.his.financial.domain.PaymentRecDetail;
|
|
|
|
|
import com.healthlink.his.financial.domain.PaymentReconciliation;
|
|
|
|
|
import com.healthlink.his.financial.service.IPaymentRecDetailService;
|
|
|
|
|
import com.healthlink.his.financial.service.IPaymentReconciliationService;
|
|
|
|
|
import com.healthlink.his.web.paymentmanage.appservice.impl.ChargeBillCalculationService;
|
|
|
|
|
import com.healthlink.his.yb.enums.YbMedChrgItmType;
|
|
|
|
|
import com.healthlink.his.yb.enums.YbPayment;
|
|
|
|
|
import com.healthlink.his.yb.service.IClinicSettleService;
|
|
|
|
|
import com.healthlink.his.yb.service.IClinicUnSettleService;
|
|
|
|
|
import org.junit.jupiter.api.BeforeEach;
|
|
|
|
|
import org.junit.jupiter.api.Test;
|
|
|
|
|
import org.mockito.InjectMocks;
|
|
|
|
|
import org.mockito.Mock;
|
|
|
|
|
import org.mockito.MockedStatic;
|
|
|
|
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
|
|
|
|
|
import static org.junit.jupiter.api.Assertions.*;
|
|
|
|
|
import static org.mockito.ArgumentMatchers.any;
|
|
|
|
|
import static org.mockito.Mockito.*;
|
|
|
|
|
|
|
|
|
|
class ChargeBillCalculationServiceTest extends BaseUnitTest {
|
|
|
|
|
|
|
|
|
|
@InjectMocks
|
|
|
|
|
private ChargeBillCalculationService service;
|
|
|
|
|
|
|
|
|
|
@Mock
|
|
|
|
|
private IPaymentReconciliationService paymentReconciliationService;
|
|
|
|
|
@Mock
|
|
|
|
|
private IPaymentRecDetailService paymentRecDetailService;
|
|
|
|
|
@Mock
|
|
|
|
|
private IChargeItemService chargeItemService;
|
|
|
|
|
@Mock
|
|
|
|
|
private IChargeItemDefinitionService iChargeItemDefinitionService;
|
|
|
|
|
@Mock
|
|
|
|
|
private IClinicSettleService iClinicSettleService;
|
|
|
|
|
@Mock
|
|
|
|
|
private IClinicUnSettleService iClinicUnSettleService;
|
|
|
|
|
@Mock
|
|
|
|
|
private com.healthlink.his.administration.service.IAccountService iAccountService;
|
|
|
|
|
@Mock
|
|
|
|
|
private com.healthlink.his.administration.service.IEncounterService iEncounterService;
|
|
|
|
|
@Mock
|
|
|
|
|
private com.healthlink.his.financial.service.IContractService iContractService;
|
|
|
|
|
@Mock
|
|
|
|
|
private com.healthlink.his.administration.service.IInvoiceService iInvoiceService;
|
|
|
|
|
@Mock
|
|
|
|
|
private com.healthlink.his.administration.service.IPatientService iPatientService;
|
|
|
|
|
@Mock
|
|
|
|
|
private com.healthlink.his.administration.service.IOrganizationService iOrganizationService;
|
|
|
|
|
@Mock
|
|
|
|
|
private com.healthlink.his.administration.service.IPractitionerService iPractitionerService;
|
|
|
|
|
@Mock
|
|
|
|
|
private com.healthlink.his.web.paymentmanage.mapper.ChargeBillMapper chargeBillMapper;
|
|
|
|
|
|
|
|
|
|
private com.core.common.core.domain.model.LoginUser mockLoginUser;
|
|
|
|
|
|
|
|
|
|
@BeforeEach
|
|
|
|
|
void setUp() {
|
|
|
|
|
mockLoginUser = mock(com.core.common.core.domain.model.LoginUser.class);
|
|
|
|
|
doReturn("测试医院").when(mockLoginUser).getOptionJsonValue("fixmedinsName");
|
|
|
|
|
doReturn("TEST001").when(mockLoginUser).getOptionJsonValue("fixmedinsCode");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
|
private <T> void mockList(com.baomidou.mybatisplus.extension.service.IService<T> svc, List<T> result) {
|
|
|
|
|
doReturn(result).when(svc).list(any(LambdaQueryWrapper.class));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
void getTotal_emptyPaymentList_returnsZeroMap() {
|
|
|
|
|
mockList(paymentReconciliationService, Collections.emptyList());
|
|
|
|
|
|
|
|
|
|
try (MockedStatic<SecurityUtils> securityMock = mockStatic(SecurityUtils.class)) {
|
|
|
|
|
securityMock.when(SecurityUtils::getLoginUser).thenReturn(mockLoginUser);
|
|
|
|
|
|
|
|
|
|
Map<String, Object> result = service.getTotal("2026-01-01", "2026-01-31", null, null);
|
|
|
|
|
|
|
|
|
|
assertNotNull(result);
|
|
|
|
|
assertEquals(BigDecimal.ZERO, result.get("BED_FEE"));
|
|
|
|
|
assertEquals(BigDecimal.ZERO, result.get("DIAGNOSTIC_FEE"));
|
|
|
|
|
assertEquals(BigDecimal.ZERO, result.get("CHECK_FEE"));
|
|
|
|
|
assertEquals(BigDecimal.ZERO, result.get("SUM"));
|
|
|
|
|
assertEquals(BigDecimal.ZERO, result.get("cashSum"));
|
|
|
|
|
assertEquals("测试医院", result.get("fixmedinsName"));
|
|
|
|
|
assertEquals("TEST001", result.get("fixmedinsCode"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
void getTotal_withValidPayments_calculatesCorrectTotals() {
|
|
|
|
|
PaymentReconciliation pr = new PaymentReconciliation();
|
|
|
|
|
pr.setId(1L);
|
|
|
|
|
pr.setChargeItemIds("100,200");
|
|
|
|
|
pr.setPaymentEnum(1);
|
|
|
|
|
pr.setStatusEnum(1);
|
|
|
|
|
mockList(paymentReconciliationService, List.of(pr));
|
|
|
|
|
|
|
|
|
|
PaymentRecDetail detail1 = new PaymentRecDetail();
|
|
|
|
|
detail1.setReconciliationId(1L);
|
|
|
|
|
detail1.setPayEnum(YbPayment.SELF_CASH_PAY.getValue());
|
|
|
|
|
detail1.setAmount(new BigDecimal("100.00"));
|
|
|
|
|
PaymentRecDetail detail2 = new PaymentRecDetail();
|
|
|
|
|
detail2.setReconciliationId(1L);
|
|
|
|
|
detail2.setPayEnum(YbPayment.SELF_CASH_PAY.getValue());
|
|
|
|
|
detail2.setAmount(new BigDecimal("50.00"));
|
|
|
|
|
mockList(paymentRecDetailService, List.of(detail1, detail2));
|
|
|
|
|
|
|
|
|
|
ChargeItem ci1 = createChargeItem(100L, 100L, new BigDecimal("100.00"));
|
|
|
|
|
ChargeItem ci2 = createChargeItem(200L, 200L, new BigDecimal("200.00"));
|
|
|
|
|
mockList(chargeItemService, List.of(ci1, ci2));
|
|
|
|
|
|
|
|
|
|
ChargeItemDefinition def1 = createDefinition(100L, YbMedChrgItmType.BED_FEE);
|
|
|
|
|
ChargeItemDefinition def2 = createDefinition(200L, YbMedChrgItmType.WEST_MEDICINE);
|
|
|
|
|
doReturn(List.of(def1, def2)).when(iChargeItemDefinitionService).listByIds(anyCollection());
|
|
|
|
|
|
|
|
|
|
try (MockedStatic<SecurityUtils> securityMock = mockStatic(SecurityUtils.class)) {
|
|
|
|
|
securityMock.when(SecurityUtils::getLoginUser).thenReturn(mockLoginUser);
|
|
|
|
|
|
|
|
|
|
Map<String, Object> result = service.getTotal("2026-01-01", "2026-01-31", null, null);
|
|
|
|
|
|
|
|
|
|
assertEquals(new BigDecimal("100.00"), result.get("BED_FEE"));
|
|
|
|
|
assertEquals(new BigDecimal("200.00"), result.get("WEST_MEDICINE"));
|
|
|
|
|
assertEquals(new BigDecimal("300.00"), result.get("SUM"));
|
|
|
|
|
assertEquals(new BigDecimal("150.00"), result.get("cashSum"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
void getTotal_multiplePaymentTypes_aggregatesCorrectly() {
|
|
|
|
|
PaymentReconciliation pr = new PaymentReconciliation();
|
|
|
|
|
pr.setId(1L);
|
|
|
|
|
pr.setChargeItemIds("100");
|
|
|
|
|
pr.setPaymentEnum(1);
|
|
|
|
|
pr.setStatusEnum(1);
|
|
|
|
|
mockList(paymentReconciliationService, List.of(pr));
|
|
|
|
|
|
|
|
|
|
PaymentRecDetail cashDetail = new PaymentRecDetail();
|
|
|
|
|
cashDetail.setReconciliationId(1L);
|
|
|
|
|
cashDetail.setPayEnum(YbPayment.SELF_CASH_PAY.getValue());
|
|
|
|
|
cashDetail.setAmount(new BigDecimal("100.00"));
|
|
|
|
|
PaymentRecDetail wxDetail = new PaymentRecDetail();
|
|
|
|
|
wxDetail.setReconciliationId(1L);
|
|
|
|
|
wxDetail.setPayEnum(YbPayment.SELF_CASH_VX_VALUE.getValue());
|
|
|
|
|
wxDetail.setAmount(new BigDecimal("200.00"));
|
|
|
|
|
PaymentRecDetail aliDetail = new PaymentRecDetail();
|
|
|
|
|
aliDetail.setReconciliationId(1L);
|
|
|
|
|
aliDetail.setPayEnum(YbPayment.SELF_CASH_ALI_VALUE.getValue());
|
|
|
|
|
aliDetail.setAmount(new BigDecimal("300.00"));
|
|
|
|
|
mockList(paymentRecDetailService, List.of(cashDetail, wxDetail, aliDetail));
|
|
|
|
|
|
|
|
|
|
ChargeItem ci = createChargeItem(100L, 100L, new BigDecimal("600.00"));
|
|
|
|
|
mockList(chargeItemService, List.of(ci));
|
|
|
|
|
|
|
|
|
|
ChargeItemDefinition def = createDefinition(100L, YbMedChrgItmType.DIAGNOSTIC_FEE);
|
|
|
|
|
doReturn(List.of(def)).when(iChargeItemDefinitionService).listByIds(anyCollection());
|
|
|
|
|
|
|
|
|
|
try (MockedStatic<SecurityUtils> securityMock = mockStatic(SecurityUtils.class)) {
|
|
|
|
|
securityMock.when(SecurityUtils::getLoginUser).thenReturn(mockLoginUser);
|
|
|
|
|
|
|
|
|
|
Map<String, Object> result = service.getTotal("2026-01-01", "2026-01-31", null, null);
|
|
|
|
|
|
|
|
|
|
assertEquals(new BigDecimal("100.00"), result.get("cashSum"));
|
|
|
|
|
assertEquals(new BigDecimal("200.00"), result.get("vxCashSum"));
|
|
|
|
|
assertEquals(new BigDecimal("300.00"), result.get("aliCashSum"));
|
|
|
|
|
assertEquals(new BigDecimal("600.00"), result.get("DIAGNOSTIC_FEE"));
|
|
|
|
|
assertEquals(new BigDecimal("600.00"), result.get("SUM"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
void getTotal_singleChargeItem_returnsCorrectCategorySum() {
|
|
|
|
|
PaymentReconciliation pr = new PaymentReconciliation();
|
|
|
|
|
pr.setId(1L);
|
|
|
|
|
pr.setChargeItemIds("100");
|
|
|
|
|
pr.setPaymentEnum(1);
|
|
|
|
|
pr.setStatusEnum(1);
|
|
|
|
|
mockList(paymentReconciliationService, List.of(pr));
|
|
|
|
|
|
|
|
|
|
PaymentRecDetail detail = new PaymentRecDetail();
|
|
|
|
|
detail.setReconciliationId(1L);
|
|
|
|
|
detail.setPayEnum(YbPayment.SELF_CASH_PAY.getValue());
|
|
|
|
|
detail.setAmount(new BigDecimal("50.00"));
|
|
|
|
|
mockList(paymentRecDetailService, List.of(detail));
|
|
|
|
|
|
|
|
|
|
ChargeItem ci = createChargeItem(100L, 100L, new BigDecimal("50.00"));
|
|
|
|
|
mockList(chargeItemService, List.of(ci));
|
|
|
|
|
|
|
|
|
|
ChargeItemDefinition def = createDefinition(100L, YbMedChrgItmType.OPERATION_FEE);
|
|
|
|
|
doReturn(List.of(def)).when(iChargeItemDefinitionService).listByIds(anyCollection());
|
|
|
|
|
|
|
|
|
|
try (MockedStatic<SecurityUtils> securityMock = mockStatic(SecurityUtils.class)) {
|
|
|
|
|
securityMock.when(SecurityUtils::getLoginUser).thenReturn(mockLoginUser);
|
|
|
|
|
|
|
|
|
|
Map<String, Object> result = service.getTotal("2026-01-01", "2026-01-31", null, null);
|
|
|
|
|
|
|
|
|
|
assertEquals(new BigDecimal("50.00"), result.get("OPERATION_FEE"));
|
|
|
|
|
assertEquals(new BigDecimal("50.00"), result.get("SUM"));
|
|
|
|
|
assertEquals(BigDecimal.ZERO, result.get("BED_FEE"));
|
|
|
|
|
assertEquals(BigDecimal.ZERO, result.get("WEST_MEDICINE"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
void getTotal_allCategoriesHaveDefaultZero() {
|
|
|
|
|
mockList(paymentReconciliationService, Collections.emptyList());
|
|
|
|
|
|
|
|
|
|
try (MockedStatic<SecurityUtils> securityMock = mockStatic(SecurityUtils.class)) {
|
|
|
|
|
securityMock.when(SecurityUtils::getLoginUser).thenReturn(mockLoginUser);
|
|
|
|
|
|
|
|
|
|
Map<String, Object> result = service.getTotal("2026-01-01", "2026-01-31", null, null);
|
|
|
|
|
|
|
|
|
|
String[] categories = {"BED_FEE", "DIAGNOSTIC_FEE", "CHECK_FEE", "DIAGNOSTIC_TEST_FEE",
|
|
|
|
|
"MEDICAL_EXPENSE_FEE", "OPERATION_FEE", "NURSING_FEE", "SANITARY_MATERIALS_FEE",
|
|
|
|
|
"WEST_MEDICINE", "CHINESE_MEDICINE_SLICES_FEE", "CHINESE_MEDICINE_FEE",
|
|
|
|
|
"GENERAL_CONSULTATION_FEE", "REGISTRATION_FEE", "OTHER_FEE", "SUM"};
|
|
|
|
|
for (String cat : categories) {
|
|
|
|
|
assertEquals(BigDecimal.ZERO, result.get(cat), cat + " should default to ZERO");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private ChargeItem createChargeItem(Long id, Long definitionId, BigDecimal totalPrice) {
|
|
|
|
|
ChargeItem ci = new ChargeItem();
|
|
|
|
|
ci.setId(id);
|
|
|
|
|
ci.setDefinitionId(definitionId);
|
|
|
|
|
ci.setTotalPrice(totalPrice);
|
|
|
|
|
ci.setStatusEnum(ChargeItemStatus.BILLED.getValue());
|
|
|
|
|
return ci;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private ChargeItemDefinition createDefinition(Long id, YbMedChrgItmType type) {
|
|
|
|
|
ChargeItemDefinition def = new ChargeItemDefinition();
|
|
|
|
|
def.setId(id);
|
|
|
|
|
def.setYbType(String.valueOf(type.getValue()));
|
|
|
|
|
def.setTypeCode("TEST_TYPE");
|
|
|
|
|
return def;
|
|
|
|
|
}
|
|
|
|
|
}
|