From 43aab58c9ecb1203770ba382efbdbae299ca87ec Mon Sep 17 00:00:00 2001
From: liu <2021943741@qq.com>
Date: 星期一, 26 十月 2026 15:12:31 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_business' into dev_business
---
yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/energy/EnergyRecordServiceTest.java | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 178 insertions(+), 0 deletions(-)
diff --git a/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/energy/EnergyRecordServiceTest.java b/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/energy/EnergyRecordServiceTest.java
new file mode 100644
index 0000000..be2d69c
--- /dev/null
+++ b/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/energy/EnergyRecordServiceTest.java
@@ -0,0 +1,178 @@
+package cn.iocoder.yudao.module.mes.service.energy;
+
+import cn.iocoder.yudao.module.mes.controller.admin.energy.vo.*;
+import cn.iocoder.yudao.module.mes.dal.dataobject.energy.EnergyRecordDO;
+import cn.iocoder.yudao.module.mes.dal.mysql.energy.EnergyRecordMapper;
+import jakarta.validation.Validation;
+import org.apache.ibatis.session.Configuration;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Map;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+
+@ExtendWith(MockitoExtension.class)
+class EnergyRecordServiceTest {
+ @Mock private org.springframework.context.ApplicationEventPublisher applicationEventPublisher;
+ @Mock
+ private EnergyRecordMapper mapper;
+ @InjectMocks
+ private EnergyRecordService service;
+
+ @Test
+ void changedDateChecksBothDaysWithOriginalTenant() {
+ var req = request(); req.setId(77L);
+ var old = new EnergyRecordDO(); old.setId(77L); old.setRecordDate(req.getRecordDate().minusDays(1));
+ when(mapper.selectById(77L)).thenReturn(old);
+ when(mapper.updateById(any(EnergyRecordDO.class))).thenReturn(1);
+ var previousTenant = cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder.getTenantId();
+ try {
+ cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder.setTenantId(42L);
+ service.update(req);
+ var event = org.mockito.ArgumentCaptor.forClass(EnergyRecordChangedEvent.class);
+ verify(applicationEventPublisher).publishEvent(event.capture());
+ assertEquals(42L, event.getValue().tenantId());
+ assertEquals(java.util.Set.of(old.getRecordDate(), req.getRecordDate()), event.getValue().dates());
+ } finally { cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder.setTenantId(previousTenant); }
+ }
+
+ @Test
+ void calculatesMoneyWithDecimalRoundingAndClearsRemark() {
+ EnergyRecordSaveReqVO req = request();
+ req.setQuantity(new BigDecimal("12.345"));
+ req.setUnitPrice(new BigDecimal("0.6789"));
+ EnergyRecordDO record = EnergyRecordService.toRecord(req);
+ assertEquals(new BigDecimal("8.38"), record.getAmount());
+ assertEquals("鐕曠獫鐢熶骇鍖�", record.getUsageArea());
+ assertEquals("", record.getRemark());
+ req.setUnitPrice(BigDecimal.ZERO);
+ assertEquals(new BigDecimal("0.00"), EnergyRecordService.toRecord(req).getAmount());
+ }
+
+ @Test
+ void createIgnoresClientIdAndUpdateRequiresExistingRecord() {
+ EnergyRecordSaveReqVO req = request();
+ req.setId(77L);
+ doAnswer(invocation -> {
+ EnergyRecordDO record = invocation.getArgument(0);
+ assertNull(record.getId());
+ record.setId(9L);
+ return 1;
+ }).when(mapper).insert(any(EnergyRecordDO.class));
+ assertEquals(9L, service.create(req));
+ assertThrows(RuntimeException.class, () -> service.update(req));
+ verify(mapper, never()).updateById(any(EnergyRecordDO.class));
+ req.setId(null);
+ assertThrows(RuntimeException.class, () -> service.update(req));
+ }
+
+ @Test
+ void deleteMissingRecordDoesNotExecuteDelete() {
+ assertThrows(RuntimeException.class, () -> service.delete(8L));
+ verify(mapper, never()).deleteById(any(Long.class));
+ }
+
+ @Test
+ void aggregatesSeparateUnitsAndMergesDatesAreasAndCosts() {
+ EnergyAnalysisRespVO result = EnergyRecordService.aggregate(List.of(
+ row("WATER", "2026-09-01", "鐕曠獫鐢熶骇鍖�", "10", "30", 1),
+ row("WATER", "2026-09-01", "鍘熸祮鐢熶骇鍖�", "5", "15", 2),
+ row("ELECTRICITY", "2026-09-01", "鐕曠獫鐢熶骇鍖�", "100", "80", 1),
+ row("WATER", "2026-09-02", "鐕曠獫鐢熶骇鍖�", "2", "0", 1)));
+ assertEquals(new BigDecimal("125"), result.getTotalAmount());
+ assertEquals(5, result.getRecordCount());
+ assertEquals(new BigDecimal("17"), result.getSummary().get(0).getQuantity());
+ assertEquals(new BigDecimal("100"), result.getSummary().get(1).getQuantity());
+ assertEquals(BigDecimal.ZERO, result.getSummary().get(2).getQuantity());
+ assertEquals(3, result.getTrend().size());
+ assertEquals(new BigDecimal("15"), result.getTrend().get(0).getQuantity());
+ assertEquals(3, result.getAreas().size());
+ assertEquals(new BigDecimal("12"), result.getAreas().get(0).getQuantity());
+ }
+
+ @Test
+ void emptyAnalysisReturnsZeroTotalsAndAllThreeEnergies() {
+ EnergyAnalysisRespVO result = EnergyRecordService.aggregate(List.of());
+ assertEquals(3, result.getSummary().size());
+ assertEquals(BigDecimal.ZERO, result.getTotalAmount());
+ assertTrue(result.getTrend().isEmpty());
+ assertTrue(result.getAreas().isEmpty());
+ }
+
+ @Test
+ void rejectsInvalidTypeNegativePriceZeroQuantityFutureDateAndExcessPrecision() {
+ try (var factory = Validation.buildDefaultValidatorFactory()) {
+ var validator = factory.getValidator();
+ assertTrue(validator.validate(request()).isEmpty());
+ EnergyRecordSaveReqVO req = request();
+ req.setEnergyType("GAS");
+ req.setUnitPrice(new BigDecimal("-1"));
+ req.setQuantity(BigDecimal.ZERO);
+ req.setRecordDate(LocalDate.now().plusDays(1));
+ assertTrue(validator.validate(req).size() >= 4);
+ req = request();
+ req.setQuantity(new BigDecimal("1.0001"));
+ assertFalse(validator.validate(req).isEmpty());
+ EnergyAnalysisReqVO analysis = new EnergyAnalysisReqVO();
+ analysis.setStartDate(LocalDate.of(2026, 1, 1));
+ analysis.setEndDate(LocalDate.of(2025, 1, 1));
+ assertFalse(validator.validate(analysis).isEmpty());
+ analysis.setEndDate(LocalDate.of(2029, 1, 1));
+ assertFalse(validator.validate(analysis).isEmpty());
+ }
+ }
+
+ @Test
+ void analysisSqlBindsFiltersAndSelectsDayOrMonthSafely() {
+ Configuration config = new Configuration();
+ config.addMapper(EnergyRecordMapper.class);
+ var statement = config.getMappedStatement(EnergyRecordMapper.class.getName() + ".selectAnalysis");
+ EnergyAnalysisReqVO req = new EnergyAnalysisReqVO();
+ req.setStartDate(LocalDate.of(2026, 1, 1));
+ req.setEndDate(LocalDate.of(2026, 1, 31));
+ String daily = statement.getBoundSql(Map.of("req", req)).getSql();
+ assertTrue(daily.contains("'%Y-%m-%d'"));
+ assertTrue(daily.contains("deleted = 0"));
+ req.setGroupBy("MONTH");
+ req.setEnergyType("STEAM");
+ req.setUsageArea("' OR 1=1 --");
+ req.setProductCategory("鐕曠獫");
+ String monthly = statement.getBoundSql(Map.of("req", req)).getSql();
+ assertTrue(monthly.contains("'%Y-%m'"));
+ assertTrue(monthly.contains("energy_type = ?"));
+ assertTrue(monthly.contains("product_category = ?"));
+ assertFalse(monthly.contains(req.getUsageArea()));
+ }
+
+ private static EnergyRecordSaveReqVO request() {
+ EnergyRecordSaveReqVO req = new EnergyRecordSaveReqVO();
+ req.setRecordDate(LocalDate.now());
+ req.setEnergyType("WATER");
+ req.setUsageArea(" 鐕曠獫鐢熶骇鍖� ");
+ req.setProductCategory("鐕曠獫");
+ req.setUsagePurpose("璁惧娓呮礂");
+ req.setQuantity(BigDecimal.ONE);
+ req.setUnitPrice(BigDecimal.ONE);
+ req.setRecorder("寮犱笁");
+ return req;
+ }
+
+ private static EnergyRecordMapper.Aggregate row(String type, String period, String area,
+ String quantity, String amount, long count) {
+ EnergyRecordMapper.Aggregate row = new EnergyRecordMapper.Aggregate();
+ row.setEnergyType(type);
+ row.setPeriod(period);
+ row.setUsageArea(area);
+ row.setQuantity(new BigDecimal(quantity));
+ row.setAmount(new BigDecimal(amount));
+ row.setRecordCount(count);
+ return row;
+ }
+}
--
Gitblit v1.9.3