From 83b85ebe8d7c5cd66e88d61d5bbc95c9e256a352 Mon Sep 17 00:00:00 2001
From: longz <longzhaoz@qq.com>
Date: 星期二, 21 七月 2026 21:38:22 +0800
Subject: [PATCH] 充电时段统计fix
---
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingBillServiceImpl.java | 243 ++++++++++++++-------
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/ChargingBillController.java | 30 +-
ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingSettlementBillMapper.xml | 31 ++
ruoyi-service/ruoyi-chargingPile/src/test/java/com/ruoyi/chargingPile/service/impl/SiteImportExcelTest.java | 52 ++++
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingSettlementBillMapper.java | 5
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TAccountSettlementStatementMapper.java | 22 ++
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TAccountSettlementStatementServiceImpl.java | 20 +
ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TAccountSettlementStatementMapper.xml | 53 ++++
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/PartnerController.java | 2
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/TChargingPileServiceImpl.java | 6
ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/SiteMapper.xml | 2
ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/TFaultMessageMapper.xml | 31 ++
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/ITAccountSettlementStatementService.java | 12 +
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingSettlementBillServiceImpl.java | 5
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppUserController.java | 6
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/SiteServiceImpl.java | 9
ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/ChargingBillIncomeIndexTest.java | 47 ++++
ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/ChargingPeriodIncomeTest.java | 38 +++
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/ITChargingSettlementBillService.java | 2
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingBillService.java | 3
20 files changed, 510 insertions(+), 109 deletions(-)
diff --git a/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppUserController.java b/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppUserController.java
index fd2bb96..2373bea 100644
--- a/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppUserController.java
+++ b/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppUserController.java
@@ -748,6 +748,12 @@
UserDetailDto userDetailDto = new UserDetailDto();
BeanUtils.copyProperties(user,userDetailDto);
+ Map<Long, BigDecimal> exchangeCodeBalanceMap = otherClient
+ .getExchangeCodeBalanceMap(Collections.singletonList(id))
+ .getData();
+ userDetailDto.setExchangeCodeBalance(exchangeCodeBalanceMap == null
+ ? BigDecimal.ZERO
+ : exchangeCodeBalanceMap.getOrDefault(id, BigDecimal.ZERO));
//获取累计充电数量
R<Long> useOrderCount = chargingOrderClient.useOrderCount(user.getId());
diff --git a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/PartnerController.java b/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/PartnerController.java
index 1145ae3..857b9d3 100644
--- a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/PartnerController.java
+++ b/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/PartnerController.java
@@ -64,7 +64,7 @@
- @RequiresPermissions(value = {"/balanceSheetRecord", "/partners", "/parkingRecord", "/chargingPile/add", "/chargingPile/select", "/chargingPile/update", "/invoiceManagement"}, logical = Logical.OR)
+ @RequiresPermissions(value = {"/balanceSheetRecord", "/partners", "/parkingRecord", "/chargingPile/add", "/chargingPile/select", "/chargingPile/update", "/invoiceManagement", "/faultInformationList"}, logical = Logical.OR)
@ResponseBody
@GetMapping("/getPartnerList")
@ApiOperation(value = "获取合作商列表", tags = {"管理后台-合作商管理"})
diff --git a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/SiteServiceImpl.java b/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/SiteServiceImpl.java
index d663f00..5298ef0 100644
--- a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/SiteServiceImpl.java
+++ b/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/SiteServiceImpl.java
@@ -50,6 +50,7 @@
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
+import java.io.InputStream;
import java.math.BigDecimal;
import java.time.format.DateTimeFormatter;
import java.util.*;
@@ -179,7 +180,13 @@
throw new ServiceException("请选择要导入的Excel文件");
}
ExcelUtil<SiteExcelDTO> util = new ExcelUtil<>(SiteExcelDTO.class);
- List<SiteExcelDTO> rows = util.importExcel(file.getInputStream(), 0);
+ List<SiteExcelDTO> rows;
+ try (InputStream inputStream = file.getInputStream()) {
+ rows = util.importExcel(inputStream, 0);
+ } catch (Exception e) {
+ throw new ServiceException("Excel文件已损坏或格式不正确,请重新下载站点导入模板后填写")
+ .setDetailMessage(e.getMessage());
+ }
if (rows == null || rows.isEmpty()) {
throw new ServiceException("导入文件没有数据");
}
diff --git a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/TChargingPileServiceImpl.java b/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/TChargingPileServiceImpl.java
index a685641..7a7cf30 100644
--- a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/TChargingPileServiceImpl.java
+++ b/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/TChargingPileServiceImpl.java
@@ -423,6 +423,12 @@
ChargingPileBatchBuildResultDTO result = new ChargingPileBatchBuildResultDTO();
TChargingPile pileTemplate = dto.getChargingPile();
TChargingGunDTO gunTemplate = dto.getChargingGun();
+ if (gunTemplate.getAuxPower() == null) {
+ throw new ServiceException("辅助电源不能为空");
+ }
+ if (gunTemplate.getOpreateStatus() == null) {
+ throw new ServiceException("运营状态不能为空");
+ }
String namePrefix = StringUtils.isEmpty(dto.getNamePrefix()) ? "" : dto.getNamePrefix().trim();
for (int i = 0; i < codes.size(); i++) {
TChargingPile chargingPile = new TChargingPile();
diff --git a/ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/SiteMapper.xml b/ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/SiteMapper.xml
index bc5523d..1cd169b 100644
--- a/ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/SiteMapper.xml
+++ b/ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/SiteMapper.xml
@@ -258,7 +258,7 @@
</where>
</select>
<select id="getSiteListGun" resultType="com.ruoyi.chargingPile.api.model.Site">
- select id, `name`, partner_id
+ select id, `name`, partner_id, venue_partner_id
from t_site
<where>
<if test="null != ids and ids.size()>0">
diff --git a/ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/TFaultMessageMapper.xml b/ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/TFaultMessageMapper.xml
index f8e3e7e..37a4987 100644
--- a/ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/TFaultMessageMapper.xml
+++ b/ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/TFaultMessageMapper.xml
@@ -34,7 +34,6 @@
from t_fault_message a
left join t_charging_pile b on (a.charging_pile_id = b.id)
left join t_site c on (a.site_id = c.id)
- left join t_partner d on (c.partner_id = d.id)
where a.del_flag = 0
<if test="null != siteIds and siteIds.size() > 0">
and a.site_id in
@@ -42,12 +41,30 @@
#{item}
</foreach>
</if>
- <if test="partnerId != null">
- and c.partner_id = #{partnerId}
- </if>
- <if test="partnerType != null">
- and d.partner_type = #{partnerType}
- </if>
+ <choose>
+ <when test="partnerType != null and partnerType == 2">
+ <if test="partnerId != null">
+ and c.venue_partner_id = #{partnerId}
+ </if>
+ and exists (
+ select 1 from t_partner venue_partner
+ where venue_partner.id = c.venue_partner_id
+ and venue_partner.partner_type = 2
+ )
+ </when>
+ <otherwise>
+ <if test="partnerId != null">
+ and c.partner_id = #{partnerId}
+ </if>
+ <if test="partnerType != null">
+ and exists (
+ select 1 from t_partner owner_partner
+ where owner_partner.id = c.partner_id
+ and owner_partner.partner_type = #{partnerType}
+ )
+ </if>
+ </otherwise>
+ </choose>
order by a.create_time desc
</select>
</mapper>
diff --git a/ruoyi-service/ruoyi-chargingPile/src/test/java/com/ruoyi/chargingPile/service/impl/SiteImportExcelTest.java b/ruoyi-service/ruoyi-chargingPile/src/test/java/com/ruoyi/chargingPile/service/impl/SiteImportExcelTest.java
new file mode 100644
index 0000000..97f9162
--- /dev/null
+++ b/ruoyi-service/ruoyi-chargingPile/src/test/java/com/ruoyi/chargingPile/service/impl/SiteImportExcelTest.java
@@ -0,0 +1,52 @@
+package com.ruoyi.chargingPile.service.impl;
+
+import com.ruoyi.chargingPile.dto.SiteExcelDTO;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.utils.poi.ExcelUtil;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.junit.jupiter.api.Test;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockMultipartFile;
+
+import java.io.ByteArrayInputStream;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class SiteImportExcelTest {
+
+ @Test
+ void generatedTemplateCanBeOpenedAsXlsx() throws Exception {
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ ExcelUtil<SiteExcelDTO> util = new ExcelUtil<>(SiteExcelDTO.class);
+
+ util.importTemplateExcel(response, "站点导入模板", "填写说明");
+
+ byte[] content = response.getContentAsByteArray();
+ assertTrue(content.length > 4);
+ assertEquals('P', content[0]);
+ assertEquals('K', content[1]);
+ assertDoesNotThrow(() -> {
+ try (Workbook ignored = WorkbookFactory.create(new ByteArrayInputStream(content))) {
+ // Opening and closing the generated workbook verifies the complete XLSX ZIP structure.
+ }
+ });
+ }
+
+ @Test
+ void corruptWorkbookReturnsReadableBusinessError() {
+ SiteServiceImpl service = new SiteServiceImpl();
+ MockMultipartFile file = new MockMultipartFile(
+ "file", "站点导入模板.xlsx",
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+ new byte[]{'P', 'K', 3, 4, 1, 2, 3});
+
+ ServiceException error = assertThrows(ServiceException.class,
+ () -> service.importSites(file, false));
+
+ assertEquals("Excel文件已损坏或格式不正确,请重新下载站点导入模板后填写", error.getMessage());
+ }
+}
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/ChargingBillController.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/ChargingBillController.java
index a6fda40..37cf4b7 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/ChargingBillController.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/ChargingBillController.java
@@ -145,20 +145,7 @@
@PostMapping(value = "/accountBillList")
@ApiOperation(value = "列表查询", tags = {"管理后台-账户结算账单"})
public R<AccountListVO> accountBillList(@RequestBody ChargingListQuery dto) {
- AccountListVO accountListVO = new AccountListVO();
- ChargingBillVO res = chargingBillService.chargingBillList1(dto);
- List<ChargingBillListVO> records = res.getList().getRecords();
- accountListVO.setBillCount(records.size());
- accountListVO.setTotalAmount(res.getPaymentAmount().subtract(res.getCommissionAmount()).subtract(res.getSharingAmount()).setScale(2, BigDecimal.ROUND_DOWN));
- accountListVO.setPaymentAmount(res.getPaymentAmount().setScale(2, BigDecimal.ROUND_DOWN));
- accountListVO.setRefundAmount(res.getRefundAmount().setScale(2, BigDecimal.ROUND_DOWN));
- accountListVO.setCommissionAmount(res.getCommissionAmount().setScale(2, BigDecimal.ROUND_DOWN));
- accountListVO.setSharingAmount(res.getSharingAmount().setScale(2, BigDecimal.ROUND_DOWN));
- accountListVO.setPlatformIncome(res.getPlatformIncome().setScale(2, BigDecimal.ROUND_DOWN));
- accountListVO.setPartnerIncome(res.getPartnerIncome().setScale(2, BigDecimal.ROUND_DOWN));
- accountListVO.setList(res.getList());
- accountListVO.setOrderList(res.getExportList());
- return R.ok(accountListVO);
+ return R.ok(chargingBillService.accountSettlementBillList(dto));
}
@@ -262,7 +249,9 @@
@PutMapping("/exportAccount")
public void exportAccount(@RequestBody ChargingListQuery dto)
{
- ChargingBillVO res = chargingBillService.chargingBillList1(dto);
+ dto.setPageCurr(1);
+ dto.setPageSize(100000);
+ AccountListVO res = chargingBillService.accountSettlementBillList(dto);
List<ChargingBillListVO> list = res.getList().getRecords();
List<TChargingBillExport> tChargingBillExports = new ArrayList<>();
for (ChargingBillListVO orderInvoiceVO : list) {
@@ -285,7 +274,7 @@
tChargingBillExport.setElectrovalence(orderInvoiceVO.getElectrovalence());
tChargingBillExport.setServiceCharge(orderInvoiceVO.getServiceCharge());
tChargingBillExport.setChargingCapacity(orderInvoiceVO.getChargingCapacity());
- Integer chargingSecond = orderInvoiceVO.getChargingSecond();
+ Integer chargingSecond = Optional.ofNullable(orderInvoiceVO.getChargingSecond()).orElse(0);
// 根据秒数 转换为xx小时xx分钟xx秒 如果小时为0不展示 如果分钟为0则不展示
// 计算小时、分钟和秒
int hours = chargingSecond / 60 / 60;
@@ -304,7 +293,8 @@
}
tChargingBillExport.setChargingTime(result.toString());
tChargingBillExport.setOrderCount(orderInvoiceVO.getOrderCount());
- tChargingBillExport.setBillTime(orderInvoiceVO.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+ tChargingBillExport.setBillTime(orderInvoiceVO.getCreateTime() == null ? "-"
+ : orderInvoiceVO.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
tChargingBillExports.add(tChargingBillExport);
}
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), TChargingBillExport.class, tChargingBillExports);
@@ -313,7 +303,7 @@
response.setCharacterEncoding("utf-8");
ServletOutputStream outputStream = null;
try {
- String fileName = URLEncoder.encode("月账单-"+res.getCategory()+"-"+res.getBillWeek()+"-"+res.getSiteName()+".xls", "utf-8");
+ String fileName = URLEncoder.encode("账户结算账单.xls", "utf-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
response.setContentType("application/vnd.ms-excel;charset=UTF-8");
response.setHeader("Pragma", "no-cache");
@@ -324,7 +314,9 @@
e.printStackTrace();
} finally {
try {
- outputStream.close();
+ if (outputStream != null) {
+ outputStream.close();
+ }
} catch (IOException e) {
e.printStackTrace();
}
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TAccountSettlementStatementMapper.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TAccountSettlementStatementMapper.java
index f6ab633..b37752f 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TAccountSettlementStatementMapper.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TAccountSettlementStatementMapper.java
@@ -1,7 +1,29 @@
package com.ruoyi.order.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.common.core.web.page.PageInfo;
+import com.ruoyi.order.api.model.ChargingListQuery;
import com.ruoyi.order.api.model.TAccountSettlementStatement;
+import com.ruoyi.order.api.vo.AccountListVO;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import java.time.LocalDate;
+import java.util.List;
+
+@Mapper
public interface TAccountSettlementStatementMapper extends BaseMapper<TAccountSettlementStatement> {
+
+ List<TAccountSettlementStatement> selectStatementPage(
+ @Param("pageInfo") PageInfo<TAccountSettlementStatement> pageInfo,
+ @Param("req") ChargingListQuery req,
+ @Param("siteIds") List<Integer> siteIds,
+ @Param("startCycle") LocalDate startCycle,
+ @Param("endCycle") LocalDate endCycle);
+
+ AccountListVO selectStatementSummary(
+ @Param("req") ChargingListQuery req,
+ @Param("siteIds") List<Integer> siteIds,
+ @Param("startCycle") LocalDate startCycle,
+ @Param("endCycle") LocalDate endCycle);
}
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingSettlementBillMapper.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingSettlementBillMapper.java
index a6c0d80..6b9cdfa 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingSettlementBillMapper.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingSettlementBillMapper.java
@@ -23,6 +23,11 @@
@Param("status") Integer status, @Param("dateRange") List<String> dateRange,
@Param("statisticalDateType") Integer statisticalDateType, @Param("siteIds") List<Integer> siteIds);
+ List<Map<String, Object>> queryIncomeList(@Param("status") Integer status,
+ @Param("dateRange") List<String> dateRange,
+ @Param("statisticalDateType") Integer statisticalDateType,
+ @Param("siteIds") List<Integer> siteIds);
+
/**
* 获取汇总数据
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/ITAccountSettlementStatementService.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/ITAccountSettlementStatementService.java
index c6e8a17..557c67f 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/ITAccountSettlementStatementService.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/ITAccountSettlementStatementService.java
@@ -1,7 +1,19 @@
package com.ruoyi.order.service;
import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.core.web.page.PageInfo;
+import com.ruoyi.order.api.model.ChargingListQuery;
import com.ruoyi.order.api.model.TAccountSettlementStatement;
+import com.ruoyi.order.api.vo.AccountListVO;
+
+import java.time.LocalDate;
+import java.util.List;
public interface ITAccountSettlementStatementService extends IService<TAccountSettlementStatement> {
+
+ PageInfo<TAccountSettlementStatement> queryPage(ChargingListQuery req, List<Integer> siteIds,
+ LocalDate startCycle, LocalDate endCycle);
+
+ AccountListVO querySummary(ChargingListQuery req, List<Integer> siteIds,
+ LocalDate startCycle, LocalDate endCycle);
}
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/ITChargingSettlementBillService.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/ITChargingSettlementBillService.java
index 0a1f973..c79c2c8 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/ITChargingSettlementBillService.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/ITChargingSettlementBillService.java
@@ -20,6 +20,8 @@
*/
List<Map<String, Object>> queryList(PageInfo<Map<String, Object>> page, Integer type, Integer status, List<String> dateRange, Integer statisticalDateType, List<Integer> siteIds);
+ List<Map<String, Object>> queryIncomeList(Integer status, List<String> dateRange, Integer statisticalDateType, List<Integer> siteIds);
+
/**
* 获取汇总数据
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingBillService.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingBillService.java
index c8ec84f..4d8ee6e 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingBillService.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingBillService.java
@@ -4,6 +4,7 @@
import com.ruoyi.order.api.model.TChargingBill;
import com.ruoyi.order.api.vo.ChargingBillVO;
import com.ruoyi.order.api.model.ChargingListQuery;
+import com.ruoyi.order.api.vo.AccountListVO;
import com.ruoyi.order.api.vo.ChargingBillWapper;
/**
@@ -24,6 +25,8 @@
ChargingBillVO chargingBillList1(ChargingListQuery dto);
+ AccountListVO accountSettlementBillList(ChargingListQuery dto);
+
ChargingBillVO chargingBillListExport(ChargingListQuery dto);
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TAccountSettlementStatementServiceImpl.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TAccountSettlementStatementServiceImpl.java
index 6c71f13..379940d 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TAccountSettlementStatementServiceImpl.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TAccountSettlementStatementServiceImpl.java
@@ -1,11 +1,31 @@
package com.ruoyi.order.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.core.web.page.PageInfo;
+import com.ruoyi.order.api.model.ChargingListQuery;
import com.ruoyi.order.api.model.TAccountSettlementStatement;
+import com.ruoyi.order.api.vo.AccountListVO;
import com.ruoyi.order.mapper.TAccountSettlementStatementMapper;
import com.ruoyi.order.service.ITAccountSettlementStatementService;
import org.springframework.stereotype.Service;
+import java.time.LocalDate;
+import java.util.List;
+
@Service
public class TAccountSettlementStatementServiceImpl extends ServiceImpl<TAccountSettlementStatementMapper, TAccountSettlementStatement> implements ITAccountSettlementStatementService {
+
+ @Override
+ public PageInfo<TAccountSettlementStatement> queryPage(ChargingListQuery req, List<Integer> siteIds,
+ LocalDate startCycle, LocalDate endCycle) {
+ PageInfo<TAccountSettlementStatement> page = new PageInfo<>(req.getPageCurr(), req.getPageSize());
+ page.setRecords(baseMapper.selectStatementPage(page, req, siteIds, startCycle, endCycle));
+ return page;
+ }
+
+ @Override
+ public AccountListVO querySummary(ChargingListQuery req, List<Integer> siteIds,
+ LocalDate startCycle, LocalDate endCycle) {
+ return baseMapper.selectStatementSummary(req, siteIds, startCycle, endCycle);
+ }
}
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingBillServiceImpl.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingBillServiceImpl.java
index 9562cc2..5df6900 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingBillServiceImpl.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingBillServiceImpl.java
@@ -23,6 +23,7 @@
import com.ruoyi.order.api.vo.ChargingBillListVO;
import com.ruoyi.order.api.vo.ChargingBillVO;
import com.ruoyi.order.api.vo.ChargingBillWapper;
+import com.ruoyi.order.api.vo.AccountListVO;
import com.ruoyi.order.mapper.TChargingBillMapper;
import com.ruoyi.order.mapper.TChargingOrderMapper;
import com.ruoyi.order.service.*;
@@ -87,6 +88,137 @@
private TChargingOrderService chargingOrderService;
@Resource
private ITChargingSettlementBillService chargingSettlementBillService;
+ @Resource
+ private ITAccountSettlementStatementService accountSettlementStatementService;
+
+ @Override
+ public AccountListVO accountSettlementBillList(ChargingListQuery dto) {
+ SysUser sysUser = sysUserClient.getSysUser(tokenService.getLoginUser().getUserid()).getData();
+ List<Integer> siteIds = resolveAccountStatementSiteIds(dto, sysUser);
+ LocalDate[] cycleRange = resolveBillingCycleRange(dto.getDateRange());
+
+ PageInfo<TAccountSettlementStatement> statementPage = accountSettlementStatementService.queryPage(
+ dto, siteIds, cycleRange[0], cycleRange[1]);
+ AccountListVO result = accountSettlementStatementService.querySummary(
+ dto, siteIds, cycleRange[0], cycleRange[1]);
+ if (result == null) {
+ result = new AccountListVO();
+ }
+
+ Set<Integer> pageSiteIds = statementPage.getRecords().stream()
+ .map(TAccountSettlementStatement::getSiteId)
+ .filter(siteId -> siteId != null && siteId > 0)
+ .collect(Collectors.toSet());
+ Map<Integer, String> siteNameMap = pageSiteIds.isEmpty() ? Collections.emptyMap()
+ : safeData(siteClient.getSiteByIds(new ArrayList<>(pageSiteIds))).stream()
+ .collect(Collectors.toMap(Site::getId, Site::getName, (first, ignored) -> first));
+
+ List<ChargingBillListVO> records = statementPage.getRecords().stream()
+ .map(statement -> toAccountStatementVO(statement, siteNameMap))
+ .collect(Collectors.toList());
+ PageInfo<ChargingBillListVO> page = new PageInfo<>(statementPage.getCurrent(), statementPage.getSize());
+ page.setTotal(statementPage.getTotal());
+ page.setRecords(records);
+ result.setList(page);
+ result.setOrderList(Collections.emptyList());
+ result.setBillCount(result.getBillCount() == null ? 0 : result.getBillCount());
+ result.setTotalAmount(zeroIfNull(result.getTotalAmount()));
+ result.setPaymentAmount(zeroIfNull(result.getPaymentAmount()));
+ result.setRefundAmount(zeroIfNull(result.getRefundAmount()));
+ result.setCommissionAmount(zeroIfNull(result.getCommissionAmount()));
+ result.setSharingAmount(zeroIfNull(result.getSharingAmount()));
+ result.setPlatformIncome(zeroIfNull(result.getPlatformIncome()));
+ result.setPartnerIncome(zeroIfNull(result.getPartnerIncome()));
+ return result;
+ }
+
+ private List<Integer> resolveAccountStatementSiteIds(ChargingListQuery dto, SysUser sysUser) {
+ List<Integer> siteIds = new ArrayList<>();
+ if (dto.getSiteId() != null) {
+ siteIds.add(dto.getSiteId());
+ } else {
+ List<GetSiteListDTO> sites = safeData(siteClient.getSiteListByUserId(tokenService.getLoginUser().getUserid()));
+ siteIds.addAll(sites.stream().map(GetSiteListDTO::getId).filter(Objects::nonNull).collect(Collectors.toList()));
+ }
+ if (Integer.valueOf(2).equals(sysUser.getRoleType())) {
+ siteIds = siteIds.stream().filter(siteId -> {
+ List<Boolean> permissions = safeData(partnerClient.getAccountMenu(sysUser.getObjectId(), siteId));
+ return permissions.size() > 1 && Boolean.TRUE.equals(permissions.get(1));
+ }).collect(Collectors.toList());
+ }
+ if (Integer.valueOf(1).equals(sysUser.getRoleType())) {
+ siteIds.add(0);
+ }
+ if (siteIds.isEmpty()) {
+ siteIds.add(-1);
+ }
+ return siteIds.stream().distinct().collect(Collectors.toList());
+ }
+
+ private LocalDate[] resolveBillingCycleRange(List<String> dateRange) {
+ LocalDate start = null;
+ LocalDate end = null;
+ if (dateRange != null && !dateRange.isEmpty()) {
+ start = parseBillingMonth(dateRange.get(0));
+ String endValue = dateRange.size() > 1 ? dateRange.get(1) : dateRange.get(0);
+ LocalDate endMonth = parseBillingMonth(endValue);
+ end = endMonth == null ? null : endMonth.plusMonths(1);
+ }
+ return new LocalDate[]{start, end};
+ }
+
+ private LocalDate parseBillingMonth(String value) {
+ if (!StringUtils.hasLength(value) || value.length() < 7) {
+ return null;
+ }
+ return LocalDate.parse(value.substring(0, 7) + "-01");
+ }
+
+ private ChargingBillListVO toAccountStatementVO(TAccountSettlementStatement statement,
+ Map<Integer, String> siteNameMap) {
+ ChargingBillListVO vo = new ChargingBillListVO();
+ vo.setId(statement.getId());
+ vo.setUid(String.valueOf(statement.getId()));
+ vo.setCode(statement.getCode());
+ vo.setType(Integer.valueOf(0).equals(statement.getSiteId()) ? 1 : 2);
+ vo.setSiteId(statement.getSiteId());
+ vo.setSiteName(Integer.valueOf(0).equals(statement.getSiteId())
+ ? "全站" : siteNameMap.getOrDefault(statement.getSiteId(), "-"));
+ vo.setStatus(statement.getStatus());
+ vo.setOrderState(2);
+ vo.setPayType(statement.getAccountType());
+ vo.setPayTypeName(accountTypeName(statement.getAccountType()));
+ vo.setBillWeek(statement.getBillingCycle() == null
+ ? null : statement.getBillingCycle().format(DateTimeFormatter.ofPattern("yyyy-MM")));
+ vo.setBillTime(statement.getCreateTime());
+ vo.setCreateTime(statement.getCreateTime());
+ vo.setPaymentAmount(zeroIfNull(statement.getRechargeAmount()));
+ vo.setRefundAmount(zeroIfNull(statement.getRefundAmount()));
+ vo.setCommissionAmount(zeroIfNull(statement.getPlatformFee()));
+ vo.setSharingAmount(zeroIfNull(statement.getTripartiteCommission()));
+ vo.setBillMoney(zeroIfNull(statement.getRecordedAmount()));
+ vo.setPlatformIncome(BigDecimal.ZERO);
+ vo.setPartnerIncome(BigDecimal.ZERO);
+ vo.setAuthDownLoad(false);
+ return vo;
+ }
+
+ private String accountTypeName(Integer accountType) {
+ if (Integer.valueOf(1).equals(accountType)) {
+ return "微信商户";
+ }
+ if (Integer.valueOf(2).equals(accountType)) {
+ return "支付宝商户";
+ }
+ if (Integer.valueOf(3).equals(accountType)) {
+ return "工商银行商户";
+ }
+ return "-";
+ }
+
+ private BigDecimal zeroIfNull(BigDecimal value) {
+ return value == null ? BigDecimal.ZERO : value;
+ }
@Override
@@ -1063,6 +1195,7 @@
Integer roleType = sysUser.getRoleType();
//如果没传siteId,获取当前登陆人所有的siteIds
List<Integer> siteIds = new ArrayList<>();
+ Map<Integer, List<Boolean>> chargingBillPermissionMap = new HashMap<>();
List<GetSiteListDTO> data = siteClient.getSiteListByUserId(userId).getData();
for (GetSiteListDTO datum : data) {
siteIds.add(datum.getId());
@@ -1074,10 +1207,9 @@
List<Integer> integers = new ArrayList<>();
for (Integer siteId : siteIds) {
// 校验有没有这个站点的权限
- List<Boolean> t1= partnerClient.getChargingBillMenu(sysUser.getObjectId(),siteId).getData();
-
- Boolean b = t1.get(1);
- if (b){
+ List<Boolean> permissions = safeData(partnerClient.getChargingBillMenu(sysUser.getObjectId(), siteId));
+ chargingBillPermissionMap.put(siteId, permissions);
+ if (permissions.size() > 1 && Boolean.TRUE.equals(permissions.get(1))){
integers.add(siteId);
}
}
@@ -1098,9 +1230,9 @@
ChargingBillWapper chargingBillVO = new ChargingBillWapper();
List<Map<String, Object>> pageList = new ArrayList<>();
Map<Integer, BigDecimal> siteServiceShareRatioMap = loadSiteServiceShareRatioMap();
- PageInfo<Map<String, Object>> sumPageInfo = new PageInfo<>(1, 100000);
- List<Map<String, Object>> sumList = chargingSettlementBillService.queryList(sumPageInfo, dto.getType(), dto.getState(), dto.getDateRange(), statisticalDateType, dto.getSiteIds());
- Map<String, Map<String, BigDecimal>> incomeIndex = buildChargingBillIncomeIndex(sumList, siteServiceShareRatioMap);
+ List<Map<String, Object>> incomeRows = chargingSettlementBillService.queryIncomeList(
+ dto.getState(), dto.getDateRange(), statisticalDateType, dto.getSiteIds());
+ Map<String, Map<String, BigDecimal>> incomeIndex = buildChargingBillIncomeIndex(incomeRows, siteServiceShareRatioMap);
Set<Integer> settlementSiteIds = new HashSet<>();
if (list != null) {
list.stream().map(item -> item.get("site_id")).filter(Objects::nonNull)
@@ -1147,9 +1279,8 @@
data1.put("serviceCharge", serviceCharge);
data1.put("authDownLoad", true);
if (roleType == 2 && 0 != site_id){
- // 校验有没有这个站点的权限
- List<Boolean> t1= partnerClient.getChargingBillMenu(sysUser.getObjectId(),site_id).getData();
- data1.put("authDownLoad", t1.get(0));
+ List<Boolean> permissions = chargingBillPermissionMap.getOrDefault(site_id, Collections.emptyList());
+ data1.put("authDownLoad", !permissions.isEmpty() && Boolean.TRUE.equals(permissions.get(0)));
}
pageList.add(data1);
}
@@ -1167,8 +1298,8 @@
BigDecimal discount = (null == map || null == map.get("couponDeduction")) ? BigDecimal.ZERO : new BigDecimal(map.get("couponDeduction").toString());
BigDecimal platformIncome = BigDecimal.ZERO;
BigDecimal partnerIncome = BigDecimal.ZERO;
- if (sumList != null) {
- for (Map<String, Object> row : sumList) {
+ if (incomeRows != null) {
+ for (Map<String, Object> row : incomeRows) {
Integer siteId = Integer.valueOf(row.get("site_id").toString());
String billingCycle = row.get("billingCycle").toString();
Map<String, BigDecimal> incomeMap = getChargingBillIncome(incomeIndex, siteId, billingCycle);
@@ -1192,86 +1323,40 @@
return chargingBillVO;
}
- private Map<String, Map<String, BigDecimal>> buildChargingBillIncomeIndex(List<Map<String, Object>> billRows,
- Map<Integer, BigDecimal> siteServiceShareRatioMap) {
+ Map<String, Map<String, BigDecimal>> buildChargingBillIncomeIndex(List<Map<String, Object>> billRows,
+ Map<Integer, BigDecimal> siteServiceShareRatioMap) {
Map<String, Map<String, BigDecimal>> incomeIndex = new HashMap<>();
if (billRows == null || billRows.isEmpty()) {
return incomeIndex;
}
- Set<String> billingCycles = billRows.stream()
- .map(row -> row.get("billingCycle"))
- .filter(Objects::nonNull)
- .map(Object::toString)
- .collect(Collectors.toSet());
- if (billingCycles.isEmpty()) {
- return incomeIndex;
- }
- LocalDate firstMonth = billingCycles.stream()
- .map(cycle -> LocalDate.parse(cycle + "-01"))
- .min(LocalDate::compareTo)
- .orElse(null);
- LocalDate lastMonth = billingCycles.stream()
- .map(cycle -> LocalDate.parse(cycle + "-01"))
- .max(LocalDate::compareTo)
- .orElse(null);
- if (firstMonth == null || lastMonth == null) {
- return incomeIndex;
- }
-
- List<TChargingOrder> orders = chargingOrderList.selectList(new LambdaQueryWrapper<>(TChargingOrder.class)
- .select(TChargingOrder::getId, TChargingOrder::getSiteId, TChargingOrder::getPayTime, TChargingOrder::getOrderSource)
- .ge(TChargingOrder::getPayTime, firstMonth.atStartOfDay())
- .lt(TChargingOrder::getPayTime, lastMonth.plusMonths(1).atStartOfDay()));
- if (orders == null || orders.isEmpty()) {
- return incomeIndex;
- }
-
- Map<Long, BigDecimal[]> strategyAmountMap = new HashMap<>();
- List<Long> orderIds = orders.stream().map(TChargingOrder::getId).filter(Objects::nonNull).collect(Collectors.toList());
- final int batchSize = 1000;
- for (int from = 0; from < orderIds.size(); from += batchSize) {
- List<Long> batchIds = orderIds.subList(from, Math.min(from + batchSize, orderIds.size()));
- List<TChargingOrderAccountingStrategy> strategies = chargingOrderAccountingStrategyService.list(
- new LambdaQueryWrapper<TChargingOrderAccountingStrategy>()
- .select(TChargingOrderAccountingStrategy::getChargingOrderId,
- TChargingOrderAccountingStrategy::getPeriodElectricPrice,
- TChargingOrderAccountingStrategy::getPeriodServicePrice)
- .in(TChargingOrderAccountingStrategy::getChargingOrderId, batchIds));
- for (TChargingOrderAccountingStrategy strategy : strategies) {
- BigDecimal[] amounts = strategyAmountMap.computeIfAbsent(strategy.getChargingOrderId(), key -> new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO});
- amounts[0] = amounts[0].add(strategy.getPeriodElectricPrice() == null ? BigDecimal.ZERO : strategy.getPeriodElectricPrice());
- amounts[1] = amounts[1].add(strategy.getPeriodServicePrice() == null ? BigDecimal.ZERO : strategy.getPeriodServicePrice());
- }
- }
-
- for (TChargingOrder order : orders) {
- if (order.getPayTime() == null || order.getSiteId() == null) {
+ for (Map<String, Object> row : billRows) {
+ if (row == null || row.get("site_id") == null || row.get("billingCycle") == null) {
continue;
}
- String billingCycle = order.getPayTime().format(DateTimeFormatter.ofPattern("yyyy-MM"));
- if (!billingCycles.contains(billingCycle)) {
- continue;
- }
- BigDecimal[] amounts = strategyAmountMap.getOrDefault(order.getId(), new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO});
- BigDecimal paymentAmount;
+ Integer siteId = Integer.valueOf(row.get("site_id").toString());
+ String billingCycle = row.get("billingCycle").toString();
+ BigDecimal electricAmount = decimalValue(row.get("total_electricity_charge"));
+ BigDecimal serviceAmount = decimalValue(row.get("total_service_fee"));
+ BigDecimal tripartiteCommission = decimalValue(row.get("tripartite_commission"));
+ BigDecimal paymentAmount = electricAmount.add(serviceAmount).subtract(tripartiteCommission);
+ BigDecimal tripartiteServiceAmount = tripartiteCommission.multiply(new BigDecimal("5"));
+ BigDecimal commissionableServiceAmount = serviceAmount.subtract(tripartiteServiceAmount).max(BigDecimal.ZERO);
BigDecimal partnerIncome = BigDecimal.ZERO;
- if (Integer.valueOf(2).equals(order.getOrderSource())) {
- paymentAmount = amounts[0].add(amounts[1].multiply(new BigDecimal("0.8")).setScale(2, RoundingMode.DOWN));
- } else {
- paymentAmount = amounts[0].add(amounts[1]);
- if (Integer.valueOf(1).equals(order.getOrderSource())) {
- BigDecimal serviceShareRatio = siteServiceShareRatioMap.get(order.getSiteId());
- if (serviceShareRatio != null && serviceShareRatio.compareTo(BigDecimal.ZERO) > 0) {
- partnerIncome = amounts[1].multiply(serviceShareRatio).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
- }
- }
+ BigDecimal serviceShareRatio = siteServiceShareRatioMap.get(siteId);
+ if (serviceShareRatio != null && serviceShareRatio.compareTo(BigDecimal.ZERO) > 0) {
+ partnerIncome = commissionableServiceAmount.multiply(serviceShareRatio)
+ .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
}
addChargingBillIncome(incomeIndex, chargingBillIncomeKey(0, billingCycle), paymentAmount, partnerIncome);
- addChargingBillIncome(incomeIndex, chargingBillIncomeKey(order.getSiteId(), billingCycle), paymentAmount, partnerIncome);
+ addChargingBillIncome(incomeIndex, chargingBillIncomeKey(siteId, billingCycle), paymentAmount, partnerIncome);
}
return incomeIndex;
}
+ private BigDecimal decimalValue(Object value) {
+ return value == null ? BigDecimal.ZERO : new BigDecimal(value.toString());
+ }
+
private void addChargingBillIncome(Map<String, Map<String, BigDecimal>> incomeIndex, String key,
BigDecimal paymentAmount, BigDecimal partnerIncome) {
Map<String, BigDecimal> income = incomeIndex.computeIfAbsent(key, ignored -> {
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingSettlementBillServiceImpl.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingSettlementBillServiceImpl.java
index 194880f..050b52f 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingSettlementBillServiceImpl.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingSettlementBillServiceImpl.java
@@ -28,6 +28,11 @@
return this.baseMapper.queryList(page, type, status, dateRange, statisticalDateType, siteIds);
}
+ @Override
+ public List<Map<String, Object>> queryIncomeList(Integer status, List<String> dateRange, Integer statisticalDateType, List<Integer> siteIds) {
+ return this.baseMapper.queryIncomeList(status, dateRange, statisticalDateType, siteIds);
+ }
+
/**
* 获取汇总数据
diff --git a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TAccountSettlementStatementMapper.xml b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TAccountSettlementStatementMapper.xml
index 2d66002..a03ea0c 100644
--- a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TAccountSettlementStatementMapper.xml
+++ b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TAccountSettlementStatementMapper.xml
@@ -2,5 +2,56 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.order.mapper.TAccountSettlementStatementMapper">
+ <sql id="statementWhere">
+ <where>
+ <if test="req.type != null and req.type == 1">
+ AND site_id = 0
+ </if>
+ <if test="req.type != null and req.type == 2">
+ AND site_id > 0
+ </if>
+ <if test="req.state != null">
+ AND status = #{req.state}
+ </if>
+ <if test="req.payType != null and req.payType != 0">
+ AND account_type = #{req.payType}
+ </if>
+ <if test="req.uid != null and req.uid != ''">
+ AND id = #{req.uid}
+ </if>
+ <if test="startCycle != null">
+ AND billing_cycle >= #{startCycle}
+ </if>
+ <if test="endCycle != null">
+ AND billing_cycle < #{endCycle}
+ </if>
+ AND site_id IN
+ <foreach collection="siteIds" open="(" close=")" separator="," item="siteId">
+ #{siteId}
+ </foreach>
+ </where>
+ </sql>
-</mapper>
\ No newline at end of file
+ <select id="selectStatementPage" resultType="com.ruoyi.order.api.model.TAccountSettlementStatement">
+ SELECT id, site_id, billing_cycle, status, code, account_type,
+ recharge_amount, refund_amount, platform_fee,
+ tripartite_commission, recorded_amount, create_time
+ FROM t_account_settlement_statement
+ <include refid="statementWhere"/>
+ ORDER BY billing_cycle DESC, account_type ASC, site_id ASC
+ </select>
+
+ <select id="selectStatementSummary" resultType="com.ruoyi.order.api.vo.AccountListVO">
+ SELECT COUNT(*) AS billCount,
+ COALESCE(SUM(recorded_amount), 0) AS totalAmount,
+ COALESCE(SUM(recharge_amount), 0) AS paymentAmount,
+ COALESCE(SUM(refund_amount), 0) AS refundAmount,
+ COALESCE(SUM(platform_fee), 0) AS commissionAmount,
+ COALESCE(SUM(tripartite_commission), 0) AS sharingAmount,
+ 0 AS platformIncome,
+ 0 AS partnerIncome
+ FROM t_account_settlement_statement
+ <include refid="statementWhere"/>
+ </select>
+
+</mapper>
diff --git a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingSettlementBillMapper.xml b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingSettlementBillMapper.xml
index 86cb279..e403a10 100644
--- a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingSettlementBillMapper.xml
+++ b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingSettlementBillMapper.xml
@@ -37,6 +37,37 @@
order by a.site_id
</select>
+ <select id="queryIncomeList" resultType="map">
+ select
+ site_id,
+ DATE_FORMAT(billing_cycle, '%Y-%m') as billingCycle,
+ total_electricity_charge,
+ total_service_fee,
+ tripartite_commission
+ from t_charging_settlement_bill
+ <where>
+ and site_id != 0
+ <if test="null != status">
+ and `status` = #{status}
+ </if>
+ <if test="null != statisticalDateType">
+ and statistical_date_type = #{statisticalDateType}
+ </if>
+ <if test="null != dateRange and dateRange.size() > 0">
+ and DATE_FORMAT(billing_cycle, '%Y-%m') in
+ <foreach collection="dateRange" item="item" open="(" separator="," close=")">
+ #{item}
+ </foreach>
+ </if>
+ <if test="null != siteIds and siteIds.size() > 0">
+ and site_id in
+ <foreach collection="siteIds" item="item" open="(" separator="," close=")">
+ #{item}
+ </foreach>
+ </if>
+ </where>
+ </select>
+
<select id="queryListSum" resultType="map">
select
diff --git a/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/ChargingBillIncomeIndexTest.java b/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/ChargingBillIncomeIndexTest.java
new file mode 100644
index 0000000..9ba9fd4
--- /dev/null
+++ b/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/ChargingBillIncomeIndexTest.java
@@ -0,0 +1,47 @@
+package com.ruoyi.order.service.impl;
+
+import org.junit.jupiter.api.Test;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ChargingBillIncomeIndexTest {
+
+ @Test
+ void calculatesIncomeFromSettlementRowsWithoutSharingThirdPartyServiceFees() {
+ TChargingBillServiceImpl service = new TChargingBillServiceImpl();
+ Map<Integer, BigDecimal> ratios = new HashMap<>();
+ ratios.put(1, new BigDecimal("15"));
+ ratios.put(2, new BigDecimal("50"));
+
+ Map<String, Map<String, BigDecimal>> incomeIndex = service.buildChargingBillIncomeIndex(
+ Arrays.asList(
+ settlementRow(1, "2026-06", "6.12", "1.85", "0.00"),
+ settlementRow(2, "2026-06", "1.00", "1.00", "0.20")
+ ),
+ ratios
+ );
+
+ assertEquals(new BigDecimal("7.69"), incomeIndex.get("1|2026-06").get("platformIncome"));
+ assertEquals(new BigDecimal("0.28"), incomeIndex.get("1|2026-06").get("partnerIncome"));
+ assertEquals(new BigDecimal("1.80"), incomeIndex.get("2|2026-06").get("platformIncome"));
+ assertEquals(new BigDecimal("0.00"), incomeIndex.get("2|2026-06").get("partnerIncome"));
+ assertEquals(new BigDecimal("9.49"), incomeIndex.get("0|2026-06").get("platformIncome"));
+ assertEquals(new BigDecimal("0.28"), incomeIndex.get("0|2026-06").get("partnerIncome"));
+ }
+
+ private Map<String, Object> settlementRow(Integer siteId, String billingCycle, String electricAmount,
+ String serviceAmount, String tripartiteCommission) {
+ Map<String, Object> row = new HashMap<>();
+ row.put("site_id", siteId);
+ row.put("billingCycle", billingCycle);
+ row.put("total_electricity_charge", new BigDecimal(electricAmount));
+ row.put("total_service_fee", new BigDecimal(serviceAmount));
+ row.put("tripartite_commission", new BigDecimal(tripartiteCommission));
+ return row;
+ }
+}
diff --git a/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/ChargingPeriodIncomeTest.java b/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/ChargingPeriodIncomeTest.java
new file mode 100644
index 0000000..00d47d2
--- /dev/null
+++ b/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/ChargingPeriodIncomeTest.java
@@ -0,0 +1,38 @@
+package com.ruoyi.order.service.impl;
+
+import com.ruoyi.order.api.vo.ChargingOrderListVO;
+import org.junit.jupiter.api.Test;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ChargingPeriodIncomeTest {
+
+ @Test
+ void usesActualChargingOrderShareIncome() {
+ TChargingOrderServiceImpl service = new TChargingOrderServiceImpl();
+ ChargingOrderListVO item = new ChargingOrderListVO();
+ Map<String, Object> row = new HashMap<>();
+ row.put("platformIncome", new BigDecimal("0.73"));
+ row.put("partnerIncome", new BigDecimal("0.27"));
+
+ service.applyChargingPeriodShareIncome(item, row);
+
+ assertEquals(new BigDecimal("0.73"), item.getPlatformIncome());
+ assertEquals(new BigDecimal("0.27"), item.getPartnerIncome());
+ }
+
+ @Test
+ void usesZeroIncomeWhenNoEffectiveShareRecordExists() {
+ TChargingOrderServiceImpl service = new TChargingOrderServiceImpl();
+ ChargingOrderListVO item = new ChargingOrderListVO();
+
+ service.applyChargingPeriodShareIncome(item, null);
+
+ assertEquals(BigDecimal.ZERO, item.getPlatformIncome());
+ assertEquals(BigDecimal.ZERO, item.getPartnerIncome());
+ }
+}
--
Gitblit v1.7.1