update:对账消息推送,军保账单统计,退款数据统计

This commit is contained in:
Yuan
2025-10-20 14:39:29 +08:00
parent 9fb2ea9cb4
commit ff5bad9967
35 changed files with 3649 additions and 100 deletions

View File

@@ -0,0 +1,219 @@
package com.saye.hospitalgd.commons.excel;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
/**
* @author thuang
* @version 1.0
* @description: 退款统计报表Excel导出工具类
* @date 2024/12/19 10:00
*/
public class RefundStatisticsExportXLSX {
/**
* 导出退款统计报表
* @param dataList 统计数据列表
* @param summaryData 汇总数据
* @param filePath 文件路径
* @throws IOException
*/
public void exportRefundStatistics(List<HashMap<Object, Object>> dataList,
HashMap<Object, Object> summaryData,
String filePath) throws IOException {
Workbook workbook = new XSSFWorkbook();
// 创建样式
CellStyle titleStyle = createTitleStyle(workbook);
CellStyle headerStyle = createHeaderStyle(workbook);
CellStyle dataStyle = createDataStyle(workbook);
CellStyle summaryStyle = createSummaryStyle(workbook);
// 创建汇总数据表
createSummarySheet(workbook, summaryData, titleStyle, summaryStyle);
// 创建详细数据表
createDataSheet(workbook, dataList, titleStyle, headerStyle, dataStyle);
// 写入文件
try (FileOutputStream fileOut = new FileOutputStream(filePath)) {
workbook.write(fileOut);
}
workbook.close();
}
/**
* 创建汇总数据表
*/
private void createSummarySheet(Workbook workbook, HashMap<Object, Object> summaryData,
CellStyle titleStyle, CellStyle summaryStyle) {
Sheet sheet = workbook.createSheet("汇总统计");
// 标题
Row titleRow = sheet.createRow(0);
Cell titleCell = titleRow.createCell(0);
titleCell.setCellValue("退款数据统计汇总");
titleCell.setCellStyle(titleStyle);
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 7));
// 汇总数据
int rowIndex = 2;
String[] labels = {"退款总笔数", "退款总金额(元)", "平均退款金额(元)", "最大退款金额(元)",
"最小退款金额(元)", "涉及患者数", "操作员数", "支付方式数"};
String[] keys = {"total_refund_count", "total_refund_amount", "avg_refund_amount",
"max_refund_amount", "min_refund_amount", "unique_patients",
"unique_operators", "pay_type_count"};
for (int i = 0; i < labels.length; i++) {
Row row = sheet.createRow(rowIndex++);
Cell labelCell = row.createCell(0);
labelCell.setCellValue(labels[i]);
labelCell.setCellStyle(summaryStyle);
Cell valueCell = row.createCell(1);
Object value = summaryData.get(keys[i]);
if (value != null) {
if (keys[i].contains("amount")) {
valueCell.setCellValue(Double.parseDouble(value.toString()));
} else {
valueCell.setCellValue(value.toString());
}
} else {
valueCell.setCellValue(0);
}
valueCell.setCellStyle(summaryStyle);
}
// 设置列宽
sheet.setColumnWidth(0, 3000);
sheet.setColumnWidth(1, 3000);
}
/**
* 创建详细数据表
*/
private void createDataSheet(Workbook workbook, List<HashMap<Object, Object>> dataList,
CellStyle titleStyle, CellStyle headerStyle, CellStyle dataStyle) {
Sheet sheet = workbook.createSheet("详细统计");
// 标题
Row titleRow = sheet.createRow(0);
Cell titleCell = titleRow.createCell(0);
titleCell.setCellValue("退款数据详细统计");
titleCell.setCellStyle(titleStyle);
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 8));
// 表头
Row headerRow = sheet.createRow(2);
String[] headers = {"统计维度", "维度值", "退款笔数", "退款总金额(元)", "平均退款金额(元)",
"最大退款金额(元)", "最小退款金额(元)", "涉及患者数", "操作员数"};
for (int i = 0; i < headers.length; i++) {
Cell cell = headerRow.createCell(i);
cell.setCellValue(headers[i]);
cell.setCellStyle(headerStyle);
}
// 数据行
int rowIndex = 3;
for (HashMap<Object, Object> data : dataList) {
Row row = sheet.createRow(rowIndex++);
String[] keys = {"dimension_name", "dimension_value", "refund_count", "total_refund_amount",
"avg_refund_amount", "max_refund_amount", "min_refund_amount",
"unique_patients", "unique_operators"};
for (int i = 0; i < keys.length; i++) {
Cell cell = row.createCell(i);
Object value = data.get(keys[i]);
if (value != null) {
if (keys[i].contains("amount")) {
cell.setCellValue(Double.parseDouble(value.toString()));
} else if (keys[i].contains("count") || keys[i].contains("patients") || keys[i].contains("operators")) {
cell.setCellValue(Integer.parseInt(value.toString()));
} else {
cell.setCellValue(value.toString());
}
} else {
cell.setCellValue("");
}
cell.setCellStyle(dataStyle);
}
}
// 设置列宽
for (int i = 0; i < headers.length; i++) {
sheet.setColumnWidth(i, 2000);
}
}
/**
* 创建标题样式
*/
private CellStyle createTitleStyle(Workbook workbook) {
CellStyle style = workbook.createCellStyle();
Font font = workbook.createFont();
font.setBold(true);
font.setFontHeightInPoints((short) 16);
style.setFont(font);
style.setAlignment(CellStyle.ALIGN_CENTER);
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
return style;
}
/**
* 创建表头样式
*/
private CellStyle createHeaderStyle(Workbook workbook) {
CellStyle style = workbook.createCellStyle();
Font font = workbook.createFont();
font.setBold(true);
style.setFont(font);
style.setAlignment(CellStyle.ALIGN_CENTER);
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
style.setBorderTop(CellStyle.BORDER_THIN);
style.setBorderBottom(CellStyle.BORDER_THIN);
style.setBorderLeft(CellStyle.BORDER_THIN);
style.setBorderRight(CellStyle.BORDER_THIN);
style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
style.setFillPattern(CellStyle.SOLID_FOREGROUND);
return style;
}
/**
* 创建数据样式
*/
private CellStyle createDataStyle(Workbook workbook) {
CellStyle style = workbook.createCellStyle();
style.setAlignment(CellStyle.ALIGN_CENTER);
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
style.setBorderTop(CellStyle.BORDER_THIN);
style.setBorderBottom(CellStyle.BORDER_THIN);
style.setBorderLeft(CellStyle.BORDER_THIN);
style.setBorderRight(CellStyle.BORDER_THIN);
return style;
}
/**
* 创建汇总样式
*/
private CellStyle createSummaryStyle(Workbook workbook) {
CellStyle style = workbook.createCellStyle();
Font font = workbook.createFont();
font.setBold(true);
style.setFont(font);
style.setAlignment(CellStyle.ALIGN_LEFT);
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
return style;
}
}

View File

@@ -0,0 +1,240 @@
package com.saye.hospitalgd.controller.FinancialReconciliation;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.saye.hospitalgd.commons.date.DateDUtil;
import com.saye.hospitalgd.commons.log.ExceptionDUtil;
import com.saye.hospitalgd.commons.log.LogUtil;
import com.saye.hospitalgd.model.Dicinfo;
import com.saye.hospitalgd.service.FinancialReconciliation.RefundStatisticsService;
import com.saye.hospitalgd.service.system.DicinfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
/**
* @author thuang
* @version 1.0
* @description: 退款数据统计报表
* @date 2024/12/19 10:00
*/
@Api(tags = "退款数据统计报表")
@Controller
@RequestMapping("/refundStatistics")
public class RefundStatisticsController {
@Autowired
private RefundStatisticsService refundStatisticsService;
@Autowired
private DicinfoService dicinfoService;
/**
* @description: 到退款统计报表页面
* @author thuang
* @date 2024/12/19 10:00
* @version 1.0
*/
@RequestMapping("/toRefundStatistics")
public String toRefundStatistics(ModelMap modelMap) {
try {
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
// 默认查询最近365天的数据一年
calendar.add(Calendar.DATE, -365);
Date startDate = calendar.getTime();
String startTime = DateDUtil.DateToStr(DateDUtil.yyyy_MM_dd, startDate);
String endTime = DateDUtil.getCurrentDate(DateDUtil.yyyy_MM_dd);
modelMap.addAttribute("startTime", startTime);
modelMap.addAttribute("endTime", endTime);
//支付方式
List<Dicinfo> payType = dicinfoService.findDicinfoTreeNodeList("PAY_TYPE");
modelMap.addAttribute("payTypeList", payType);
//退款类型
List<Dicinfo> refundType = dicinfoService.findDicinfoTreeNodeList("REFUND_TYPE");
modelMap.addAttribute("refundTypeList", refundType);
} catch (Exception e) {
e.printStackTrace();
}
return "financialReconciliation/refundStatistics";
}
/**
* @description: 查询退款统计报表数据
* @author thuang
* @date 2024/12/19 10:00
* @version 1.0
*/
@RequestMapping("/findRefundStatistics")
@ResponseBody
@ApiOperation("查询退款统计报表数据")
public HashMap<Object, Object> findRefundStatistics(
@ApiParam("开始时间") String startTime,
@ApiParam("结束时间") String endTime,
@ApiParam("支付方式") String payType,
@ApiParam("退款类型") String refundType,
@ApiParam("统计维度") String dimension,
@ApiParam("页码") int page,
@ApiParam("每页数量") int limit) {
HashMap<Object, Object> responseMap = new HashMap<Object, Object>();
try {
HashMap<Object, Object> map = new HashMap<Object, Object>();
map.put("startTime", startTime);
map.put("endTime", endTime);
map.put("payType", payType);
map.put("refundType", refundType);
map.put("dimension", dimension);
PageHelper.startPage(page, limit);
PageInfo<HashMap<Object, Object>> pageInfo = new PageInfo<HashMap<Object, Object>>(refundStatisticsService.findRefundStatistics(map));
responseMap.put("code", 0);
responseMap.put("msg", "OK");
responseMap.put("count", pageInfo.getTotal());
responseMap.put("data", pageInfo.getList());
} catch (Exception e) {
e.printStackTrace();
String msg = e.getMessage();
responseMap.put("code", 1);
responseMap.put("msg", "查询失败,原因:" + msg);
}
return responseMap;
}
/**
* @description: 获取退款统计汇总数据
* @author thuang
* @date 2024/12/19 10:00
* @version 1.0
*/
@RequestMapping("/getRefundSummary")
@ResponseBody
@ApiOperation("获取退款统计汇总数据")
public HashMap<Object, Object> getRefundSummary(
@ApiParam("开始时间") String startTime,
@ApiParam("结束时间") String endTime,
@ApiParam("支付方式") String payType,
@ApiParam("退款类型") String refundType) {
HashMap<Object, Object> responseMap = new HashMap<Object, Object>();
try {
HashMap<Object, Object> map = new HashMap<Object, Object>();
map.put("startTime", startTime);
map.put("endTime", endTime);
map.put("payType", payType);
map.put("refundType", refundType);
HashMap<Object, Object> summaryData = refundStatisticsService.getRefundSummary(map);
responseMap.put("code", 0);
responseMap.put("msg", "OK");
responseMap.put("data", summaryData);
} catch (Exception e) {
e.printStackTrace();
String msg = e.getMessage();
responseMap.put("code", 1);
responseMap.put("msg", "查询失败,原因:" + msg);
}
return responseMap;
}
/**
* @description: 获取退款趋势数据
* @author thuang
* @date 2024/12/19 10:00
* @version 1.0
*/
@RequestMapping("/getRefundTrend")
@ResponseBody
@ApiOperation("获取退款趋势数据")
public HashMap<Object, Object> getRefundTrend(
@ApiParam("开始时间") String startTime,
@ApiParam("结束时间") String endTime,
@ApiParam("支付方式") String payType,
@ApiParam("退款类型") String refundType) {
HashMap<Object, Object> responseMap = new HashMap<Object, Object>();
try {
HashMap<Object, Object> map = new HashMap<Object, Object>();
map.put("startTime", startTime);
map.put("endTime", endTime);
map.put("payType", payType);
map.put("refundType", refundType);
List<HashMap<Object, Object>> trendData = refundStatisticsService.getRefundTrend(map);
responseMap.put("code", 0);
responseMap.put("msg", "OK");
responseMap.put("data", trendData);
} catch (Exception e) {
e.printStackTrace();
String msg = e.getMessage();
responseMap.put("code", 1);
responseMap.put("msg", "查询失败,原因:" + msg);
}
return responseMap;
}
/**
* @description: 导出退款统计报表
* @author thuang
* @date 2024/12/19 10:00
* @version 1.0
*/
@RequestMapping("/exportRefundStatistics")
@ResponseBody
@ApiOperation("导出退款统计报表")
public HashMap<Object, Object> exportRefundStatistics(
@ApiParam("开始时间") String startTime,
@ApiParam("结束时间") String endTime,
@ApiParam("支付方式") String payType,
@ApiParam("退款类型") String refundType,
@ApiParam("统计维度") String dimension) {
HashMap<Object, Object> responseMap = new HashMap<Object, Object>();
try {
HashMap<Object, Object> map = new HashMap<Object, Object>();
map.put("startTime", startTime);
map.put("endTime", endTime);
map.put("payType", payType);
map.put("refundType", refundType);
map.put("dimension", dimension);
String fileName = refundStatisticsService.exportRefundStatistics(map);
responseMap.put("code", 0);
responseMap.put("msg", "导出成功");
responseMap.put("fileName", fileName);
} catch (Exception e) {
e.printStackTrace();
String msg = e.getMessage();
responseMap.put("code", 1);
responseMap.put("msg", "导出失败,原因:" + msg);
}
return responseMap;
}
}

View File

@@ -160,12 +160,12 @@ public class HisDetailController {
List<HashMap<Object, Object>> list = hisDetailService.findHisDetail(map);
// 支付方式 - 不再使用字典转换,直接显示原始值
// List<Dicinfo> pay_type = dicinfoService.findDicinfoTreeNodeList("PAY_TYPE");
// HashMap<String, String> peyTypeMap = new HashMap<>();
// for (Dicinfo dicinfo : pay_type) {
// peyTypeMap.put(dicinfo.getDicvalue(), dicinfo.getDicname());
// }
// 支付方式
List<Dicinfo> pay_type = dicinfoService.findDicinfoTreeNodeList("PAY_TYPE");
HashMap<String, String> payTypeMap = new HashMap<>();
for (Dicinfo dicinfo : pay_type) {
payTypeMap.put(dicinfo.getDicvalue(), dicinfo.getDicname());
}
// 业务类型
List<Dicinfo> biz_type = dicinfoService.findDicinfoTreeNodeList("BIZ_TYPE");
@@ -196,9 +196,9 @@ public class HisDetailController {
String biztype = StringDUtil.changeNullToEmpty(hashMap.get("BIZTYPE"));
hashMap.put("BIZTYPE", bizTypeMap.get(biztype));
// 支付方式 - 直接使用原始值,不进行字典转换
// String paytype = StringDUtil.changeNullToEmpty(hashMap.get("PAYTYPE"));
// hashMap.put("PAYTYPE", peyTypeMap.get(paytype));
// 支付方式字典转换
String paytype = StringDUtil.changeNullToEmpty(hashMap.get("PAYTYPE"));
hashMap.put("PAYTYPE", payTypeMap.get(paytype));
}

View File

@@ -0,0 +1,277 @@
package com.saye.hospitalgd.controller;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.saye.hospitalgd.commons.date.DateDUtil;
import com.saye.hospitalgd.commons.excel.ExportXLSX;
import com.saye.hospitalgd.commons.excel.HashMapConversionImpl;
import com.saye.hospitalgd.commons.excel.IConversionByExport;
import com.saye.hospitalgd.commons.log.ExceptionDUtil;
import com.saye.hospitalgd.commons.log.LogUtil;
import com.saye.hospitalgd.commons.string.StringDUtil;
import com.saye.hospitalgd.model.Dicinfo;
import com.saye.hospitalgd.model.StatusDefine;
import com.saye.hospitalgd.service.HisDetailService;
import com.saye.hospitalgd.service.system.DicinfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import java.io.File;
import java.math.BigDecimal;
import java.util.*;
/**
* @author thuang
* @version 1.0
* @description: 军保对账统计
* @date 2024/10/16 15:00
*/
@Api(value = "军保对账统计相关接口")
@Controller
@RequestMapping("/militaryInsurance")
public class MilitaryInsuranceController {
@Autowired
private HisDetailService hisDetailService;
@Autowired
private DicinfoService dicinfoService;
@RequestMapping("/toMilitaryInsurance")
public String toMilitaryInsurance(ModelMap modelMap) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(Calendar.DATE, -1);
Date startDate = calendar.getTime();
String startTime = DateDUtil.DateToStr(DateDUtil.yyyy_MM_dd, startDate);
String endTime = DateDUtil.getCurrentDate(DateDUtil.yyyy_MM_dd);
modelMap.addAttribute("startTime", startTime);
modelMap.addAttribute("endTime", endTime);
// 业务类型
List<Dicinfo> biz_type = dicinfoService.findDicinfoTreeNodeList("BIZ_TYPE");
modelMap.addAttribute("bizTypeList", biz_type);
return "financialReconciliation/militaryInsurance";
}
/**
* @description: 查询军保明细记录 (paytype=3)
* @author thuang
* @date 2024/10/16 15:00
* @version 1.0
*/
@ApiOperation(value = "查询军保明细记录", notes = "")
@GetMapping("/findMilitaryInsuranceDetail")
@ResponseBody
public HashMap<Object, Object> findMilitaryInsuranceDetail(@ApiParam(value = "开始时间") String startTime,
@ApiParam(value = "结束时间") String endTime,
@ApiParam(value = "模糊查询字段") String likeFiled,
@ApiParam(value = "页码") int page,
@ApiParam(value = "每页数量") int limit) {
HashMap<Object, Object> responseMap = new HashMap<>();
try {
HashMap<Object, Object> map = new HashMap<Object, Object>();
map.put("payType", "3"); // 固定查询paytype=3的数据
map.put("startTime", startTime);
map.put("endTime", endTime);
map.put("likeFiled", likeFiled);
PageHelper.startPage(page, limit);
PageInfo<HashMap<Object, Object>> pageInfo = new PageInfo<HashMap<Object, Object>>(hisDetailService.findHisDetail(map));
responseMap.put("code", 0);
responseMap.put("msg", "OK");
responseMap.put("count", pageInfo.getTotal());
responseMap.put("data", pageInfo.getList());
} catch (Exception e) {
e.printStackTrace();
String msg = e.getMessage();
responseMap.put("code", 1);
responseMap.put("msg", "查询失败,原因:" + msg);
}
return responseMap;
}
/**
* @description: 查询军保记录统计数据
* @author thuang
* @date 2024/10/16 15:00
* @version 1.0
*/
@RequestMapping("/findMilitaryInsuranceCountData")
@ResponseBody
@ApiOperation(value = "查询军保记录统计数据", notes = "")
public HashMap<Object, Object> findMilitaryInsuranceCountData(@RequestBody HashMap<Object, Object> map) {
HashMap<Object, Object> responseMap = new HashMap<Object, Object>();
String errCode = "0";
String errMsg = "";
try {
// 固定查询paytype=3的数据
map.put("payType", "3");
// 如果没有传递时间参数,设置默认查询今日数据
if (map.get("startTime") == null || "".equals(map.get("startTime"))) {
map.put("startTime", DateDUtil.getCurrentDate(DateDUtil.yyyy_MM_dd) + " 00:00:00");
}
if (map.get("endTime") == null || "".equals(map.get("endTime"))) {
map.put("endTime", DateDUtil.getCurrentDate(DateDUtil.yyyy_MM_dd) + " 23:59:59");
}
List<HashMap<Object, Object>> hisDetailCount = hisDetailService.findHisDetailCountData(map);
if (hisDetailCount != null && hisDetailCount.size() > 0) {
responseMap.put("money", hisDetailCount.get(0).get("MONEY"));
responseMap.put("num", hisDetailCount.get(0).get("NUM"));
} else {
responseMap.put("money", "0");
responseMap.put("num", "0");
}
} catch (Exception e) {
e.printStackTrace();
errCode = "999";
errMsg = "查询军保记录统计数据失败,原因:" + e.getMessage();
responseMap.put("money", "0");
responseMap.put("num", "0");
}
responseMap.put("errCode", errCode);
responseMap.put("errMsg", errMsg);
return responseMap;
}
/**
* @description: 导出军保明细
* @author thuang
* @date 2024/10/16 15:00
* @version 1.0
*/
@RequestMapping("/exportMilitaryInsuranceDetail")
@ResponseBody
@ApiOperation(value = "导出军保明细", notes = "")
public HashMap<Object, Object> exportMilitaryInsuranceDetail(@RequestBody HashMap<Object, Object> map) {
HashMap<Object, Object> responseMap = new HashMap<Object, Object>();
String errCode = "0";
String errMsg = "";
String dlName = "";
String fileName = "";
String dowloadName = StringDUtil.changeNullToEmpty(map.get("dowloadName"));
try {
// 固定查询paytype=3的数据
map.put("payType", "3");
List<HashMap<Object, Object>> list = hisDetailService.findHisDetail(map);
// 支付方式字典
List<Dicinfo> pay_type = dicinfoService.findDicinfoTreeNodeList("PAY_TYPE");
HashMap<String, String> payTypeMap = new HashMap<>();
for (Dicinfo dicinfo : pay_type) {
payTypeMap.put(dicinfo.getDicvalue(), dicinfo.getDicname());
}
// 业务类型
List<Dicinfo> biz_type = dicinfoService.findDicinfoTreeNodeList("BIZ_TYPE");
HashMap<String, String> bizTypeMap = new HashMap<>();
for (Dicinfo dicinfo : biz_type) {
bizTypeMap.put(dicinfo.getDicvalue(), dicinfo.getDicname());
}
for (HashMap<Object, Object> hashMap : list) {
String paymethod = StringDUtil.changeNullToEmpty(hashMap.get("PAYMETHOD"));
if ("1".equals(paymethod)) {
hashMap.put("PAYMETHOD", "门诊");
} else if ("2".equals(paymethod)) {
hashMap.put("PAYMETHOD", "住院");
} else {
hashMap.put("PAYMETHOD", "");
}
String tradingStatus = StringDUtil.changeNullToEmpty(hashMap.get("TRADINGSTATUS"));
if ("1".equals(tradingStatus)) {
hashMap.put("TRADINGSTATUS", "收款记录");
} else if ("2".equals(tradingStatus)) {
hashMap.put("TRADINGSTATUS", "退款记录");
} else {
hashMap.put("TRADINGSTATUS", "");
}
String biztype = StringDUtil.changeNullToEmpty(hashMap.get("BIZTYPE"));
hashMap.put("BIZTYPE", bizTypeMap.get(biztype));
// 支付方式字典转换
String paytype = StringDUtil.changeNullToEmpty(hashMap.get("PAYTYPE"));
hashMap.put("PAYTYPE", payTypeMap.get(paytype));
}
if (list.size() > 0) {
// 定义标题头和文件名
String[] DISTANCE_HEADERNAME = {"交易状态", "业务类型", "支付方式", "交易时间", "交易日期", "操作员", "总金额", "平台交易号", "his订单号", "HIS交易ID", "患者id", "患者姓名", "来源"};
String[] sqlKey = {"TRADINGSTATUS", "BIZTYPE", "PAYTYPE", "TRADETIME", "TRADE_DATE", "HISOPERCODE", "AMOUNT", "PLATFORMTRANSID", "HISTRANSID", "HISTRANSID", "PATIENTID", "PATIENTNAME", "SOURCE"};
List<Object> rulList = new ArrayList<Object>(list);
// 创建工作表
ExportXLSX exportXLS = new ExportXLSX(DISTANCE_HEADERNAME, sqlKey, ExportXLSX.A3, false);
exportXLS.setTitleName(dowloadName);
IConversionByExport conversion = new HashMapConversionImpl();
exportXLS.setConversion(conversion);
exportXLS.setData(rulList);
exportXLS.modifyWidthOfHeader("5000", 0);
exportXLS.modifyWidthOfHeader("5000", 1);
exportXLS.modifyWidthOfHeader("5000", 2);
exportXLS.modifyWidthOfHeader("5000", 3);
exportXLS.modifyWidthOfHeader("5000", 4);
exportXLS.modifyWidthOfHeader("5000", 5);
exportXLS.modifyWidthOfHeader("8000", 6);
exportXLS.modifyWidthOfHeader("5000", 7);
exportXLS.modifyWidthOfHeader("5000", 8);
exportXLS.modifyWidthOfHeader("5000", 9);
exportXLS.modifyWidthOfHeader("5000", 10);
exportXLS.modifyWidthOfHeader("10000", 11);
// 文件名称
// 产生4位长度的随机码由字母和数字组成
String randomStr = StringDUtil.generateRandomCodeForLength(4);
dlName = DateDUtil.DateToStr(DateDUtil.yyyyMMddHHmmss, new Date()) + randomStr;
fileName = dlName + ".xlsx";
String uploadPath = StatusDefine.filePath + "/MilitaryInsurance/";
File uploadPathFile = new File(uploadPath);
if (!uploadPathFile.exists()) uploadPathFile.mkdirs();
String savePath = uploadPath + fileName;
exportXLS.execGenerateExcel(savePath);
}
} catch (Exception e) {
errCode = "999";
errMsg = "未知异常:" + ExceptionDUtil.getDetailExceptionMsg(e);
LogUtil.error(this.getClass(), "@@@系统出错!【" + errMsg + "");
}
responseMap.put("errCode", errCode);
responseMap.put("errMsg", errMsg);
responseMap.put("dlName", "MilitaryInsurance/" + fileName);
return responseMap;
}
}

View File

@@ -0,0 +1,270 @@
package com.saye.hospitalgd.controller.system;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.saye.hospitalgd.commons.date.DateDUtil;
import com.saye.hospitalgd.commons.string.StringDUtil;
import com.saye.hospitalgd.commons.uuid.UUIDGenerator;
import com.saye.hospitalgd.model.FinanceUser;
import com.saye.hospitalgd.service.NotifyService;
import com.saye.hospitalgd.service.system.FinanceUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
/**
* @author thuang
* @version 1.0
* @description: 财务人员管理控制器
* @date 2024/12/19 18:00
*/
@Api(tags = "财务人员管理")
@Controller
@RequestMapping("/financeUser")
public class FinanceUserController {
@Autowired
private FinanceUserService financeUserService;
@Autowired
private NotifyService notifyService;
/**
* @description: 到财务人员管理页面
* @author thuang
* @date 2024/12/19 18:00
* @version 1.0
*/
@RequestMapping("/toFinanceUser")
public String toFinanceUser(ModelMap modelMap) {
return "system/financeUser";
}
/**
* @description: 到财务人员管理测试页面
* @author thuang
* @date 2024/12/19 18:30
* @version 1.0
*/
@RequestMapping("/toFinanceUserTest")
public String toFinanceUserTest(ModelMap modelMap) {
return "system/financeUser_test";
}
/**
* @description: 查询财务人员列表
* @author thuang
* @date 2024/12/19 18:00
* @version 1.0
*/
@RequestMapping("/findFinanceUserPageList")
@ResponseBody
@ApiOperation("查询财务人员列表")
public HashMap<Object, Object> findFinanceUserPageList(
@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "wechatName", required = false) String wechatName,
@RequestParam(value = "phone", required = false) String phone,
@RequestParam(value = "isActive", required = false) String isActive,
@RequestParam(value = "page", defaultValue = "1") int page,
@RequestParam(value = "limit", defaultValue = "20") int limit) {
HashMap<Object, Object> responseMap = new HashMap<Object, Object>();
try {
HashMap<Object, Object> map = new HashMap<Object, Object>();
map.put("name", name);
map.put("wechatName", wechatName);
map.put("phone", phone);
map.put("isActive", isActive);
PageHelper.startPage(page, limit);
PageInfo<FinanceUser> pageInfo = new PageInfo<FinanceUser>(financeUserService.findFinanceUserPageList(map));
responseMap.put("code", 0);
responseMap.put("msg", "OK");
responseMap.put("count", pageInfo.getTotal());
responseMap.put("data", pageInfo.getList());
} catch (Exception e) {
e.printStackTrace();
String msg = e.getMessage();
responseMap.put("code", 1);
responseMap.put("msg", "查询失败,原因:" + msg);
}
return responseMap;
}
/**
* @description: 添加财务人员
* @author thuang
* @date 2024/12/19 18:00
* @version 1.0
*/
@RequestMapping("/addFinanceUser")
@ResponseBody
@ApiOperation("添加财务人员")
public HashMap<Object, Object> addFinanceUser(@RequestBody FinanceUser financeUser) {
HashMap<Object, Object> responseMap = new HashMap<Object, Object>();
try {
financeUser.setId(UUIDGenerator.getUUID());
financeUser.setCreateTime(DateDUtil.getCurrentDate(DateDUtil.yyyy_MM_dd_HH_mm_ss));
financeUser.setModifyTime(DateDUtil.getCurrentDate(DateDUtil.yyyy_MM_dd_HH_mm_ss));
if (StringDUtil.changeNullToEmpty(financeUser.getIsActive()).equals("")) {
financeUser.setIsActive("1");
}
// 如果有手机号尝试通过手机号获取OpenID
if (financeUser.getPhone() != null && !financeUser.getPhone().trim().isEmpty()) {
try {
String openId = notifyService.getUserOpenIdByPhone(financeUser.getPhone());
financeUser.setOpenId(openId);
} catch (Exception e) {
// 获取OpenID失败不影响添加财务人员只记录日志
System.err.println("根据手机号获取OpenID失败: " + e.getMessage());
}
}
financeUserService.addFinanceUser(financeUser);
responseMap.put("code", 0);
responseMap.put("msg", "添加成功");
} catch (Exception e) {
e.printStackTrace();
String msg = e.getMessage();
responseMap.put("code", 1);
responseMap.put("msg", "添加失败,原因:" + msg);
}
return responseMap;
}
/**
* @description: 修改财务人员
* @author thuang
* @date 2024/12/19 18:00
* @version 1.0
*/
@RequestMapping("/updateFinanceUser")
@ResponseBody
@ApiOperation("修改财务人员")
public HashMap<Object, Object> updateFinanceUser(@RequestBody FinanceUser financeUser) {
HashMap<Object, Object> responseMap = new HashMap<Object, Object>();
try {
financeUser.setModifyTime(DateDUtil.getCurrentDate(DateDUtil.yyyy_MM_dd_HH_mm_ss));
// 如果有手机号尝试通过手机号获取OpenID
if (financeUser.getPhone() != null && !financeUser.getPhone().trim().isEmpty()) {
try {
String openId = notifyService.getUserOpenIdByPhone(financeUser.getPhone());
financeUser.setOpenId(openId);
} catch (Exception e) {
// 获取OpenID失败不影响修改财务人员只记录日志
System.err.println("根据手机号获取OpenID失败: " + e.getMessage());
}
}
financeUserService.updateFinanceUser(financeUser);
responseMap.put("code", 0);
responseMap.put("msg", "修改成功");
} catch (Exception e) {
e.printStackTrace();
String msg = e.getMessage();
responseMap.put("code", 1);
responseMap.put("msg", "修改失败,原因:" + msg);
}
return responseMap;
}
/**
* @description: 删除财务人员
* @author thuang
* @date 2024/12/19 18:00
* @version 1.0
*/
@RequestMapping("/deleteFinanceUser")
@ResponseBody
@ApiOperation("删除财务人员")
public HashMap<Object, Object> deleteFinanceUser(@RequestParam("id") @ApiParam("财务人员ID") String id) {
HashMap<Object, Object> responseMap = new HashMap<Object, Object>();
try {
financeUserService.deleteFinanceUser(id);
responseMap.put("code", 0);
responseMap.put("msg", "删除成功");
} catch (Exception e) {
e.printStackTrace();
String msg = e.getMessage();
responseMap.put("code", 1);
responseMap.put("msg", "删除失败,原因:" + msg);
}
return responseMap;
}
/**
* @description: 根据ID查询财务人员
* @author thuang
* @date 2024/12/19 18:00
* @version 1.0
*/
@RequestMapping("/findFinanceUserById")
@ResponseBody
@ApiOperation("根据ID查询财务人员")
public HashMap<Object, Object> findFinanceUserById(@RequestParam("id") @ApiParam("财务人员ID") String id) {
HashMap<Object, Object> responseMap = new HashMap<Object, Object>();
try {
FinanceUser financeUser = financeUserService.findFinanceUserById(id);
responseMap.put("code", 0);
responseMap.put("msg", "查询成功");
responseMap.put("data", financeUser);
} catch (Exception e) {
e.printStackTrace();
String msg = e.getMessage();
responseMap.put("code", 1);
responseMap.put("msg", "查询失败,原因:" + msg);
}
return responseMap;
}
/**
* @description: 获取所有启用的财务人员
* @author thuang
* @date 2024/12/19 18:00
* @version 1.0
*/
@RequestMapping("/findActiveFinanceUsers")
@ResponseBody
@ApiOperation("获取所有启用的财务人员")
public HashMap<Object, Object> findActiveFinanceUsers() {
HashMap<Object, Object> responseMap = new HashMap<Object, Object>();
try {
List<FinanceUser> financeUsers = financeUserService.findActiveFinanceUsers();
responseMap.put("code", 0);
responseMap.put("msg", "查询成功");
responseMap.put("data", financeUsers);
} catch (Exception e) {
e.printStackTrace();
String msg = e.getMessage();
responseMap.put("code", 1);
responseMap.put("msg", "查询失败,原因:" + msg);
}
return responseMap;
}
}

View File

@@ -1,36 +0,0 @@
-- 更新HIS支付方式字典表适配你的四种支付方式
-- 1. 更新现有的PAY_TYPE字典值确保与汇总统计逻辑匹配
-- 现金支付保持为5
UPDATE `dicinfo` SET `dicvalue` = '4' WHERE `diccode` = 'f0230cea94134322982d45544255ee8f' AND `parent_code` = 'PAY_TYPE';
-- 微信支付改为1扫码支付
UPDATE `dicinfo` SET `dicname` = '微信支付', `dicvalue` = '1' WHERE `diccode` = '48c8044ee33649bcaf64181b570c1c75' AND `parent_code` = 'PAY_TYPE';
-- 银行卡支付保持为1但改名为扫码支付
UPDATE `dicinfo` SET `dicname` = '扫码支付', `dicvalue` = '1' WHERE `diccode` = 'a6ef5f470ae744a4ae1571825ddb8ca5' AND `parent_code` = 'PAY_TYPE';
-- 2. 新增聚合支付和军保支付
INSERT INTO `dicinfo` VALUES ('juhezf001', '聚合支付', '1', 'PAY_TYPE', '2024-01-01 00:00:00', '2024-01-01 00:00:00', 6);
INSERT INTO `dicinfo` VALUES ('junbao001', '军保支付', '3', 'PAY_TYPE', '2024-01-01 00:00:00', '2024-01-01 00:00:00', 7);
-- 3. 确保字典表结构正确
-- 最终PAY_TYPE字典应该是
-- 扫码支付(包含微信、聚合) -> 1
-- 银行卡支付 -> 2
-- 军保支付 -> 3
-- 现金支付 -> 4
-- 其他 -> 5
-- 如果需要重新整理,可以删除旧数据重新插入:
/*
DELETE FROM `dicinfo` WHERE `parent_code` = 'PAY_TYPE' AND `diccode` != 'PAY_TYPE';
INSERT INTO `dicinfo` VALUES ('pay_type_001', '扫码支付', '1', 'PAY_TYPE', '2024-01-01 00:00:00', '2024-01-01 00:00:00', 1);
INSERT INTO `dicinfo` VALUES ('pay_type_002', '银行卡支付', '2', 'PAY_TYPE', '2024-01-01 00:00:00', '2024-01-01 00:00:00', 2);
INSERT INTO `dicinfo` VALUES ('pay_type_003', '军保支付', '3', 'PAY_TYPE', '2024-01-01 00:00:00', '2024-01-01 00:00:00', 3);
INSERT INTO `dicinfo` VALUES ('pay_type_004', '现金支付', '4', 'PAY_TYPE', '2024-01-01 00:00:00', '2024-01-01 00:00:00', 4);
INSERT INTO `dicinfo` VALUES ('pay_type_005', '其他', '5', 'PAY_TYPE', '2024-01-01 00:00:00', '2024-01-01 00:00:00', 5);
*/

View File

@@ -1,24 +0,0 @@
-- 严格按照四种HIS支付方式配置字典表用户自定义编码
-- HIS支付方式现金、微信、聚合支付、军保支付
-- 1. 清理现有PAY_TYPE数据保留父节点
DELETE FROM `dicinfo` WHERE `parent_code` = 'PAY_TYPE' AND `diccode` != 'PAY_TYPE';
-- 2. 添加严格匹配的四种支付方式字典用户自定义PayType编码
-- 现金 -> PayType: 5
INSERT INTO `dicinfo` VALUES ('his_pay_001', '现金', '5', 'PAY_TYPE', '2024-01-01 00:00:00', '2024-01-01 00:00:00', 1);
-- 微信 -> PayType: 1
INSERT INTO `dicinfo` VALUES ('his_pay_002', '微信', '1', 'PAY_TYPE', '2024-01-01 00:00:00', '2024-01-01 00:00:00', 2);
-- 聚合支付 -> PayType: 2
INSERT INTO `dicinfo` VALUES ('his_pay_003', '聚合支付', '2', 'PAY_TYPE', '2024-01-01 00:00:00', '2024-01-01 00:00:00', 3);
-- 军保支付 -> PayType: 3
INSERT INTO `dicinfo` VALUES ('his_pay_004', '军保支付', '3', 'PAY_TYPE', '2024-01-01 00:00:00', '2024-01-01 00:00:00', 4);
-- 其他未知支付方式 -> PayType: 4
INSERT INTO `dicinfo` VALUES ('his_pay_005', '其他', '4', 'PAY_TYPE', '2024-01-01 00:00:00', '2024-01-01 00:00:00', 5);
-- 验证插入结果
SELECT * FROM `dicinfo` WHERE `parent_code` = 'PAY_TYPE' ORDER BY `sort_no`;

View File

@@ -0,0 +1,42 @@
package com.saye.hospitalgd.mapper.FinancialReconciliation;
import org.apache.ibatis.annotations.Mapper;
import java.util.HashMap;
import java.util.List;
/**
* @author thuang
* @version 1.0
* @description: 退款数据统计报表Mapper
* @date 2024/12/19 10:00
*/
@Mapper
public interface RefundStatisticsMapper {
/**
* 查询退款统计报表数据
* @param map 查询参数
* @return 退款统计数据列表
* @throws Exception
*/
List<HashMap<Object, Object>> findRefundStatistics(HashMap<Object, Object> map) throws Exception;
/**
* 获取退款统计汇总数据
* @param map 查询参数
* @return 退款统计汇总数据
* @throws Exception
*/
HashMap<Object, Object> getRefundSummary(HashMap<Object, Object> map) throws Exception;
/**
* 获取退款趋势数据
* @param map 查询参数
* @return 退款趋势数据列表
* @throws Exception
*/
List<HashMap<Object, Object>> getRefundTrend(HashMap<Object, Object> map) throws Exception;
}

View File

@@ -18,6 +18,8 @@ public interface OperatorMapper {
List<HashMap<Object, Object>> findAllOperatorByCode(HashMap<Object, Object> map) throws Exception;
List<HashMap<Object, Object>> findMilitaryOperators(HashMap<Object, Object> map) throws Exception;
void addOperator(HashMap<Object, Object> map) throws Exception;
void updateOperatorByCode(HashMap<Object, Object> map) throws Exception;

View File

@@ -0,0 +1,68 @@
package com.saye.hospitalgd.mapper.system;
import com.saye.hospitalgd.model.FinanceUser;
import org.apache.ibatis.annotations.Mapper;
import java.util.HashMap;
import java.util.List;
/**
* @author thuang
* @version 1.0
* @description: 财务人员Mapper接口
* @date 2024/12/19 18:00
*/
@Mapper
public interface FinanceUserMapper {
/**
* 查询财务人员列表
* @param map 查询参数
* @return 财务人员列表
*/
List<FinanceUser> findFinanceUserPageList(HashMap<Object, Object> map);
/**
* 添加财务人员
* @param financeUser 财务人员信息
*/
void addFinanceUser(FinanceUser financeUser);
/**
* 修改财务人员
* @param financeUser 财务人员信息
*/
void updateFinanceUser(FinanceUser financeUser);
/**
* 删除财务人员
* @param id 财务人员ID
*/
void deleteFinanceUser(String id);
/**
* 根据ID查询财务人员
* @param id 财务人员ID
* @return 财务人员信息
*/
FinanceUser findFinanceUserById(String id);
/**
* 获取所有启用的财务人员
* @return 启用的财务人员列表
*/
List<FinanceUser> findActiveFinanceUsers();
}

View File

@@ -0,0 +1,36 @@
package com.saye.hospitalgd.model;
import lombok.Data;
/**
* @author thuang
* @version 1.0
* @description: 财务人员实体类
* @date 2024/12/19 18:00
*/
@Data
public class FinanceUser {
private String id; // 主键ID
private String name; // 姓名
private String wechatName; // 微信名
private String phone; // 手机号
private String openId; // 微信OpenID
private String isActive; // 启用状态(1:启用 0:禁用)
private String createTime; // 创建时间
private String modifyTime; // 修改时间
private String remark; // 备注
}

View File

@@ -39,11 +39,12 @@ public class BankGetData implements Job {
HashMap<Object, Object> wlifSearchMap = new HashMap<>();
wlifSearchMap.put("FUBS", "1");
List<HashMap<Object, Object>> thirdFtpConfigList = thirdFtpConfigService.findThirdFtpConfigList(searchMap);
List<HashMap<Object, Object>> wlConfigList = thirdFtpConfigService.findWLIF(searchMap);
List<HashMap<Object, Object>> wlConfigList = thirdFtpConfigService.findWLIF(wlifSearchMap);
for (int i = 0; i < thirdFtpConfigList.size(); i++) {
HashMap<Object, Object> hashMap = thirdFtpConfigList.get(i);
String execute_class = StringDUtil.changeNullToEmpty(hashMap.get("EXECUTE_CLASS"));

View File

@@ -80,6 +80,7 @@ public class BankGetDataByWXAPI {
// 如果没问题 解析返回的集合
if ("0".equals(errCode)) {
String list = StringDUtil.changeNullToEmpty(jsonObject.get("list"));
log.info("微信获取对账单返回数据:" + list);
List<BankbillHistory> bankbillHistories = JSONArray.parseArray(list, BankbillHistory.class);
// 如果有数据

View File

@@ -75,6 +75,8 @@ public class HISGetDataMethodByJH {
operatorsCodeStr=operatorsCodeStr.substring(0,operatorsCodeStr.length()-1);
}
log.info("HIS获取数据定时任务【"+name+"】开始执行,操作员号:【"+operatorsCodeStr+"】,获取日期:【"+trade_date+"");
//全部支付方式
List<Dicinfo> pay_type = dicinfoService.findDicinfoTreeNodeList("PAY_TYPE");
HashMap<String, String> payTypeMap = new HashMap<>();
@@ -145,11 +147,29 @@ public class HISGetDataMethodByJH {
for (int i = 0; i < hisBillList.size(); i++) {
HashMap<Object, Object> hisBillHashMap = hisBillList.get(i);
//先判断关键id是否为空 为空的这条记录就作废了可能之后会有现金记录进入此id仍为空到时需要另加判断
//获取PowerTranID和ReceiptNO作为唯一标识
String powerTranID = StringDUtil.changeNullToEmpty(hisBillHashMap.get("powerTranID"));
if ("".equals(powerTranID)){
String receiptNO = StringDUtil.changeNullToEmpty(hisBillHashMap.get("receiptNO"));
String hisTransId = StringDUtil.changeNullToEmpty(hisBillHashMap.get("hisTransId"));
// 修改跳过逻辑:只有当关键业务信息都缺失时才跳过
// 检查是否有足够的业务信息来处理这条记录
String patientId = StringDUtil.changeNullToEmpty(hisBillHashMap.get("patientID"));
String amount = StringDUtil.changeNullToEmpty(hisBillHashMap.get("amount"));
String tradeTime = StringDUtil.changeNullToEmpty(hisBillHashMap.get("tradeTime"));
// 只有当缺少关键业务信息时才跳过患者ID、金额、交易时间都为空
if ("".equals(patientId) && "".equals(amount) && "".equals(tradeTime)){
log.warn("跳过缺少关键业务信息的记录: powerTranID={}, receiptNO={}, hisTransId={}",
powerTranID, receiptNO, hisTransId);
continue;
}
// 对于没有唯一标识的记录,记录警告但继续处理
if ("".equals(powerTranID) && "".equals(receiptNO) && "".equals(hisTransId)){
log.warn("处理无唯一标识的记录: patientID={}, amount={}, tradeTime={}",
patientId, amount, tradeTime);
}
//数据类型 1-门诊 2-住院 无需修改
String payMethod = StringDUtil.changeNullToEmpty(hisBillHashMap.get("visitzOrg"));
@@ -168,23 +188,17 @@ public class HISGetDataMethodByJH {
String originalPayType = StringDUtil.changeNullToEmpty(hisBillHashMap.get("payType"));
String payType = convertPayTypeByDictionary(originalPayType, payTypeMap);
//交易时间
String tradeTime = StringDUtil.changeNullToEmpty(hisBillHashMap.get("tradeTime"));
//操作员
String hisOperCode = StringDUtil.changeNullToEmpty(hisBillHashMap.get("hisOperCode"));
//交易金额
String amount = StringDUtil.changeNullToEmpty(hisBillHashMap.get("amount"));
//说明
String remarks = "";
//银商订单号
String platformTransId = StringDUtil.changeNullToEmpty(hisBillHashMap.get("powerTranID"));
//患者 ID
String patientId = StringDUtil.changeNullToEmpty(hisBillHashMap.get("patientID"));
//银商订单号优先使用PowerTranID如果为空则使用ReceiptNO或HisTransId
String platformTransId = powerTranID;
if ("".equals(platformTransId)) {
platformTransId = "".equals(receiptNO) ? hisTransId : receiptNO;
}
//患者姓名
String patientName = StringDUtil.changeNullToEmpty(hisBillHashMap.get("patientName"));

View File

@@ -47,7 +47,7 @@ public class ReconciliationMethod {
HisbillsHistoryService hisbillsHistoryService = GetBeanUtil.getBean(HisbillsHistoryServiceImpl.class);
OperatorService operatorService = GetBeanUtil.getBean(OperatorServiceImpl.class);
//记录是第几次对账
int managerNum = 0;
@@ -56,6 +56,12 @@ public class ReconciliationMethod {
searchMap.put("trade_date", trade_date);
searchMap.put("is_ok", 1);
//查询军保操作员,用于排除军保账单
List<HashMap<Object, Object>> militaryOperators = operatorService.findMilitaryOperators(new HashMap<>());
if (militaryOperators != null && militaryOperators.size() > 0) {
searchMap.put("excludeMilitaryOperators", militaryOperators);
}
//先判断是否已生成
List<HashMap<Object, Object>> reconciliationLog = reconciliationLogService.findReconciliationLogByParam(searchMap);
@@ -803,6 +809,22 @@ public class ReconciliationMethod {
}
reconciliationLogService.insertReconciliationLog(addMap);
// 对账完成后发送消息通知
try {
NotifyService notifyService = (NotifyService) GetBeanUtil.getBean("notifyServiceImpl");
if (notifyService != null) {
String status = "0".equals(errCode) ? "1" : "0"; // 1:成功 0:失败
String message = "0".equals(errCode) ? "对账完成" : errMsg;
notifyService.sendReconciliationNotify(trade_date, status, message);
System.out.println("对账通知发送完成,日期:" + trade_date + ",状态:" + ("1".equals(status) ? "成功" : "失败"));
}
} catch (Exception e) {
System.err.println("发送对账通知失败:" + e.getMessage());
e.printStackTrace();
// 消息推送失败不影响对账结果
}
} catch (Exception e) {
e.printStackTrace();
errCode = "999";

View File

@@ -0,0 +1,47 @@
package com.saye.hospitalgd.service.FinancialReconciliation;
import java.util.HashMap;
import java.util.List;
/**
* @author thuang
* @version 1.0
* @description: 退款数据统计报表服务接口
* @date 2024/12/19 10:00
*/
public interface RefundStatisticsService {
/**
* 查询退款统计报表数据
* @param map 查询参数
* @return 退款统计数据列表
* @throws Exception
*/
List<HashMap<Object, Object>> findRefundStatistics(HashMap<Object, Object> map) throws Exception;
/**
* 获取退款统计汇总数据
* @param map 查询参数
* @return 退款统计汇总数据
* @throws Exception
*/
HashMap<Object, Object> getRefundSummary(HashMap<Object, Object> map) throws Exception;
/**
* 获取退款趋势数据
* @param map 查询参数
* @return 退款趋势数据列表
* @throws Exception
*/
List<HashMap<Object, Object>> getRefundTrend(HashMap<Object, Object> map) throws Exception;
/**
* 导出退款统计报表
* @param map 查询参数
* @return 导出文件名
* @throws Exception
*/
String exportRefundStatistics(HashMap<Object, Object> map) throws Exception;
}

View File

@@ -0,0 +1,92 @@
package com.saye.hospitalgd.service.FinancialReconciliation.impl;
import com.saye.hospitalgd.commons.excel.RefundStatisticsExportXLSX;
import com.saye.hospitalgd.commons.log.ExceptionDUtil;
import com.saye.hospitalgd.mapper.FinancialReconciliation.RefundStatisticsMapper;
import com.saye.hospitalgd.service.FinancialReconciliation.RefundStatisticsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.File;
import java.util.HashMap;
import java.util.List;
/**
* @author thuang
* @version 1.0
* @description: 退款数据统计报表服务实现类
* @date 2024/12/19 10:00
*/
@Service
@Transactional
public class RefundStatisticsServiceImpl implements RefundStatisticsService {
private static final Logger log = LoggerFactory.getLogger(RefundStatisticsServiceImpl.class);
@Autowired
private RefundStatisticsMapper refundStatisticsMapper;
@Override
public List<HashMap<Object, Object>> findRefundStatistics(HashMap<Object, Object> map) throws Exception {
try {
return refundStatisticsMapper.findRefundStatistics(map);
} catch (Exception e) {
log.info("查询退款统计报表数据失败", e);
throw e;
}
}
@Override
public HashMap<Object, Object> getRefundSummary(HashMap<Object, Object> map) throws Exception {
try {
return refundStatisticsMapper.getRefundSummary(map);
} catch (Exception e) {
log.error("获取退款统计汇总数据失败", e);
throw e;
}
}
@Override
public List<HashMap<Object, Object>> getRefundTrend(HashMap<Object, Object> map) throws Exception {
try {
return refundStatisticsMapper.getRefundTrend(map);
} catch (Exception e) {
log.error("获取退款趋势数据失败", e);
throw e;
}
}
@Override
public String exportRefundStatistics(HashMap<Object, Object> map) throws Exception {
try {
// 获取统计数据
List<HashMap<Object, Object>> dataList = refundStatisticsMapper.findRefundStatistics(map);
// 获取汇总数据
HashMap<Object, Object> summaryData = refundStatisticsMapper.getRefundSummary(map);
// 创建导出文件
String fileName = "退款统计报表_" + System.currentTimeMillis() + ".xlsx";
String filePath = System.getProperty("user.dir") + File.separator + "downloadFile" + File.separator + fileName;
// 确保目录存在
File file = new File(filePath);
File parentDir = file.getParentFile();
if (!parentDir.exists()) {
parentDir.mkdirs();
}
// 导出Excel
RefundStatisticsExportXLSX exportXLSX = new RefundStatisticsExportXLSX();
exportXLSX.exportRefundStatistics(dataList, summaryData, filePath);
return fileName;
} catch (Exception e) {
log.error("导出退款统计报表失败", e);
throw e;
}
}
}

View File

@@ -0,0 +1,41 @@
package com.saye.hospitalgd.service;
import com.saye.hospitalgd.model.FinanceUser;
import java.util.List;
/**
* @author thuang
* @version 1.0
* @description: 消息推送服务接口
* @date 2024/12/19 18:00
*/
public interface NotifyService {
/**
* 发送对账完成通知
* @param tradeDate 对账日期
* @param status 对账状态 (1:成功 0:失败)
* @param message 对账消息
* @throws Exception 异常
*/
void sendReconciliationNotify(String tradeDate, String status, String message) throws Exception;
/**
* 获取用户OpenID
* @param wechatName 微信名
* @return OpenID
* @throws Exception 异常
*/
String getUserOpenId(String wechatName) throws Exception;
/**
* 根据手机号获取用户OpenID
* @param phone 手机号
* @return OpenID
* @throws Exception 异常
*/
String getUserOpenIdByPhone(String phone) throws Exception;
}

View File

@@ -12,6 +12,8 @@ import java.util.List;
public interface OperatorService {
List<HashMap<Object, Object>> findAllOperator(HashMap<Object, Object> map) throws Exception;
List<HashMap<Object, Object>> findMilitaryOperators(HashMap<Object, Object> map) throws Exception;
void addOperator(HashMap<Object, Object> map) throws Exception;
void modifyOperator(HashMap<Object, Object> map) throws Exception;

View File

@@ -0,0 +1,263 @@
package com.saye.hospitalgd.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.saye.hospitalgd.commons.string.StringDUtil;
import com.saye.hospitalgd.model.FinanceUser;
import com.saye.hospitalgd.service.NotifyService;
import com.saye.hospitalgd.service.system.FinanceUserService;
import com.saye.hospitalgd.service.system.ServiceParamsService;
import com.saye.hospitalgd.util.HttpClientUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
/**
* @author thuang
* @version 1.0
* @description: 消息推送服务实现类
* @date 2024/12/19 18:00
*/
@Service
public class NotifyServiceImpl implements NotifyService {
private static final Logger log = LoggerFactory.getLogger(NotifyServiceImpl.class);
@Autowired
private FinanceUserService financeUserService;
@Autowired
private ServiceParamsService serviceParamsService;
@Override
public void sendReconciliationNotify(String tradeDate, String status, String message) throws Exception {
try {
// 获取所有启用的财务人员
List<FinanceUser> financeUsers = financeUserService.findActiveFinanceUsers();
if (financeUsers == null || financeUsers.isEmpty()) {
log.info("没有启用的财务人员,跳过消息推送");
return;
}
// 获取中转服务地址
List<HashMap<Object, Object>> serviceParams = serviceParamsService.findParamValByParamCode("hgd_dmz");
String transferUrl = StringDUtil.changeNullToEmpty(serviceParams.get(0).get("PARAM_VAL"));
if (transferUrl == null || transferUrl.trim().isEmpty()) {
log.error("未配置中转服务地址(hgd_dmz)");
return;
}
// 构建消息推送URL
String notifyUrl = transferUrl.endsWith("/") ?
transferUrl + "sendNotifyYJJ" :
transferUrl + "/sendNotifyYJJ";
// 为每个财务人员发送通知
for (FinanceUser financeUser : financeUsers) {
if (financeUser.getOpenId() != null && !financeUser.getOpenId().trim().isEmpty()) {
sendNotifyToFinanceUser(financeUser, tradeDate, status, message, notifyUrl);
} else {
log.warn("财务人员 {} 没有OpenID跳过消息推送", financeUser.getName());
}
}
} catch (Exception e) {
log.error("发送对账通知失败", e);
throw e;
}
}
/**
* 发送通知给指定财务人员
* @param financeUser 财务人员信息
* @param tradeDate 对账日期
* @param status 对账状态
* @param message 对账消息
* @param notifyUrl 通知URL
*/
private void sendNotifyToFinanceUser(FinanceUser financeUser, String tradeDate, String status,
String message, String notifyUrl) {
try {
// 构建通知参数
HashMap<String, Object> notifyParams = new HashMap<>();
notifyParams.put("openid", financeUser.getOpenId());
notifyParams.put("tradeDate", tradeDate);
notifyParams.put("status", status);
notifyParams.put("message", message);
notifyParams.put("userName", financeUser.getName());
// 发送通知
String response = HttpClientUtil.doPost(notifyUrl, notifyParams);
log.debug("发送对账通知响应: " + response);
// 增加空值检查
if (response == null || response.trim().isEmpty()) {
log.error("调用中转服务失败,返回为空,接收人: {}", financeUser.getName());
return;
}
JSONObject jsonResponse = JSON.parseObject(response);
// 兼容多种成功状态码格式
Integer code = jsonResponse.getInteger("code");
Integer errCode = jsonResponse.getInteger("errcode");
Integer errCodeInt = jsonResponse.getInteger("errCode");
// 判断成功条件code=0 或 errcode=0 或 errCode=0 或 errCode="0"
boolean isSuccess = (code != null && code == 0) ||
(errCode != null && errCode == 0) ||
(errCodeInt != null && errCodeInt == 0) ||
"0".equals(jsonResponse.getString("errCode"));
if (isSuccess) {
log.info("对账通知发送成功,接收人: {}", financeUser.getName());
} else {
// 兼容多种错误消息字段msg/errMsg
String errorMsg = jsonResponse.getString("msg");
if (errorMsg == null || errorMsg.trim().isEmpty()) {
errorMsg = jsonResponse.getString("errMsg");
}
log.error("对账通知发送失败,接收人: {}, 错误信息: {}",
financeUser.getName(), errorMsg);
}
} catch (Exception e) {
log.error("发送对账通知异常,接收人: {}", financeUser.getName(), e);
}
}
@Override
public String getUserOpenId(String wechatName) throws Exception {
try {
// 获取中转服务地址
List<HashMap<Object, Object>> serviceParams = serviceParamsService.findParamValByParamCode("hgd_dmz");
String transferUrl = StringDUtil.changeNullToEmpty(serviceParams.get(0).get("PARAM_VAL"));
if (transferUrl == null || transferUrl.trim().isEmpty()) {
throw new Exception("未配置中转服务地址(hgd_dmz)");
}
// 构建获取OpenID的URL
String openIdUrl = transferUrl.endsWith("/") ?
transferUrl + "getUserOpenId" :
transferUrl + "/getUserOpenId";
// 构建请求参数
HashMap<String, Object> params = new HashMap<>();
params.put("wechatName", wechatName);
// 发送请求
String response = HttpClientUtil.doPost(openIdUrl, params);
log.debug("获取OpenID响应: " + response);
// 增加空值检查
if (response == null || response.trim().isEmpty()) {
throw new Exception("调用中转服务失败,返回为空。请检查中转服务地址是否正确或网络是否可达");
}
JSONObject jsonResponse = JSON.parseObject(response);
// 兼容两种返回格式code/errCode
Integer code = jsonResponse.getInteger("code");
Integer errCode = jsonResponse.getInteger("errCode");
// 判断成功条件code=0 或 errCode="0"
boolean isSuccess = (code != null && code == 0) ||
(errCode != null && errCode == 0) ||
"0".equals(jsonResponse.getString("errCode"));
if (isSuccess) {
// 兼容两种数据字段data/openid
String openId = jsonResponse.getString("data");
if (openId == null || openId.trim().isEmpty()) {
openId = jsonResponse.getString("openid");
}
if (openId != null && !openId.trim().isEmpty()) {
log.info("成功获取OpenID: {} for 微信名: {}", openId, wechatName);
return openId;
} else {
throw new Exception("返回的OpenID为空");
}
} else {
// 兼容两种错误消息字段msg/errMsg
String errorMsg = jsonResponse.getString("msg");
if (errorMsg == null || errorMsg.trim().isEmpty()) {
errorMsg = jsonResponse.getString("errMsg");
}
throw new Exception("获取OpenID失败: " + errorMsg);
}
} catch (Exception e) {
log.error("获取OpenID异常微信名: {}", wechatName, e);
throw e;
}
}
@Override
public String getUserOpenIdByPhone(String phone) throws Exception {
try {
// 获取中转服务地址
List<HashMap<Object, Object>> serviceParams = serviceParamsService.findParamValByParamCode("hgd_dmz");
String transferUrl = StringDUtil.changeNullToEmpty(serviceParams.get(0).get("PARAM_VAL"));
if (transferUrl == null || transferUrl.trim().isEmpty()) {
throw new Exception("未配置中转服务地址(hgd_dmz)");
}
// 构建获取OpenID的URL
String openIdUrl = transferUrl.endsWith("/") ?
transferUrl + "getUserOpenId" :
transferUrl + "/getUserOpenId";
// 构建请求参数
HashMap<String, Object> params = new HashMap<>();
params.put("phone", phone);
params.put("yz", "joju@");
// 发送请求
String response = HttpClientUtil.doPost(openIdUrl, params);
log.debug("根据手机号获取OpenID响应: " + response);
// 增加空值检查
if (response == null || response.trim().isEmpty()) {
throw new Exception("调用中转服务失败,返回为空。请检查中转服务地址是否正确或网络是否可达");
}
JSONObject jsonResponse = JSON.parseObject(response);
// 兼容两种返回格式code/errCode
Integer code = jsonResponse.getInteger("code");
Integer errCode = jsonResponse.getInteger("errCode");
// 判断成功条件code=0 或 errCode="0"
boolean isSuccess = (code != null && code == 0) ||
(errCode != null && errCode == 0) ||
"0".equals(jsonResponse.getString("errCode"));
if (isSuccess) {
String openId = jsonResponse.getString("openid");
if (openId != null && !openId.trim().isEmpty()) {
log.info("成功根据手机号获取OpenID: {} for 手机号: {}", openId, phone);
return openId;
} else {
throw new Exception("返回的OpenID为空");
}
} else {
// 兼容两种错误消息字段msg/errMsg
String errorMsg = jsonResponse.getString("msg");
if (errorMsg == null || errorMsg.trim().isEmpty()) {
errorMsg = jsonResponse.getString("errMsg");
}
throw new Exception("根据手机号获取OpenID失败: " + errorMsg);
}
} catch (Exception e) {
log.error("根据手机号获取OpenID异常手机号: {}", phone, e);
throw e;
}
}
}

View File

@@ -29,6 +29,11 @@ public class OperatorServiceImpl implements OperatorService {
return operatorMapper.findAllOperator(map);
}
@Override
public List<HashMap<Object, Object>> findMilitaryOperators(HashMap<Object, Object> map) throws Exception {
return operatorMapper.findMilitaryOperators(map);
}
@Override
public void addOperator(HashMap<Object, Object> map) throws Exception {
String hisOperCode = StringDUtil.changeNullToEmpty(map.get("hisOperCode"));

View File

@@ -0,0 +1,72 @@
package com.saye.hospitalgd.service.system;
import com.saye.hospitalgd.model.FinanceUser;
import java.util.HashMap;
import java.util.List;
/**
* @author thuang
* @version 1.0
* @description: 财务人员服务接口
* @date 2024/12/19 18:00
*/
public interface FinanceUserService {
/**
* 查询财务人员列表
* @param map 查询参数
* @return 财务人员列表
* @throws Exception 异常
*/
List<FinanceUser> findFinanceUserPageList(HashMap<Object, Object> map) throws Exception;
/**
* 添加财务人员
* @param financeUser 财务人员信息
* @throws Exception 异常
*/
void addFinanceUser(FinanceUser financeUser) throws Exception;
/**
* 修改财务人员
* @param financeUser 财务人员信息
* @throws Exception 异常
*/
void updateFinanceUser(FinanceUser financeUser) throws Exception;
/**
* 删除财务人员
* @param id 财务人员ID
* @throws Exception 异常
*/
void deleteFinanceUser(String id) throws Exception;
/**
* 根据ID查询财务人员
* @param id 财务人员ID
* @return 财务人员信息
* @throws Exception 异常
*/
FinanceUser findFinanceUserById(String id) throws Exception;
/**
* 获取所有启用的财务人员
* @return 启用的财务人员列表
* @throws Exception 异常
*/
List<FinanceUser> findActiveFinanceUsers() throws Exception;
}

View File

@@ -0,0 +1,102 @@
package com.saye.hospitalgd.service.system.impl;
import com.saye.hospitalgd.mapper.system.FinanceUserMapper;
import com.saye.hospitalgd.model.FinanceUser;
import com.saye.hospitalgd.service.system.FinanceUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.List;
/**
* @author thuang
* @version 1.0
* @description: 财务人员服务实现类
* @date 2024/12/19 18:00
*/
@Service
@Transactional
public class FinanceUserServiceImpl implements FinanceUserService {
private static final Logger log = LoggerFactory.getLogger(FinanceUserServiceImpl.class);
@Autowired
private FinanceUserMapper financeUserMapper;
@Override
public List<FinanceUser> findFinanceUserPageList(HashMap<Object, Object> map) throws Exception {
try {
return financeUserMapper.findFinanceUserPageList(map);
} catch (Exception e) {
log.error("查询财务人员列表失败", e);
throw e;
}
}
@Override
public void addFinanceUser(FinanceUser financeUser) throws Exception {
try {
financeUserMapper.addFinanceUser(financeUser);
} catch (Exception e) {
log.error("添加财务人员失败", e);
throw e;
}
}
@Override
public void updateFinanceUser(FinanceUser financeUser) throws Exception {
try {
financeUserMapper.updateFinanceUser(financeUser);
} catch (Exception e) {
log.error("修改财务人员失败", e);
throw e;
}
}
@Override
public void deleteFinanceUser(String id) throws Exception {
try {
financeUserMapper.deleteFinanceUser(id);
} catch (Exception e) {
log.error("删除财务人员失败", e);
throw e;
}
}
@Override
public FinanceUser findFinanceUserById(String id) throws Exception {
try {
return financeUserMapper.findFinanceUserById(id);
} catch (Exception e) {
log.error("根据ID查询财务人员失败", e);
throw e;
}
}
@Override
public List<FinanceUser> findActiveFinanceUsers() throws Exception {
try {
return financeUserMapper.findActiveFinanceUsers();
} catch (Exception e) {
log.error("查询启用的财务人员失败", e);
throw e;
}
}
}

View File

@@ -0,0 +1,204 @@
package com.saye.hospitalgd.util;
import com.alibaba.fastjson.JSON;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.HashMap;
/**
* @author thuang
* @version 1.0
* @description: HTTP客户端工具类兼容JDK8
* @date 2024/12/19 16:00
*/
public class HttpClientUtil {
private static final Logger log = LoggerFactory.getLogger(HttpClientUtil.class);
/**
* 发送GET请求
* @param url 请求URL
* @param headers 请求头可为null
* @return 响应结果
*/
public static String doGet(String url, HashMap<String, String> headers) {
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
String result = null;
try {
httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
// 设置请求头
if (headers != null) {
for (String key : headers.keySet()) {
httpGet.setHeader(key, headers.get(key));
}
}
response = httpClient.execute(httpGet);
if (response != null && response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity entity = response.getEntity();
if (entity != null) {
result = EntityUtils.toString(entity, "UTF-8");
}
} else {
log.error("GET请求失败状态码: " + (response != null ? response.getStatusLine().getStatusCode() : "null"));
}
} catch (Exception e) {
log.error("GET请求异常", e);
} finally {
try {
if (response != null) {
response.close();
}
if (httpClient != null) {
httpClient.close();
}
} catch (IOException e) {
log.error("关闭HTTP连接异常", e);
}
}
return result;
}
/**
* 发送POST请求JSON格式
* @param url 请求URL
* @param data 请求数据JSON对象
* @return 响应结果
*/
public static String doPost(String url, Object data) {
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
String result = null;
try {
httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("content-type", "application/json;charset=utf-8");
// 将数据转换为JSON字符串
String jsonData = JSON.toJSONString(data);
StringEntity stringEntity = new StringEntity(jsonData, "UTF-8");
stringEntity.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
httpPost.setEntity(stringEntity);
response = httpClient.execute(httpPost);
if (response != null && response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity entity = response.getEntity();
if (entity != null) {
result = EntityUtils.toString(entity, "UTF-8");
}
} else {
log.error("POST请求失败状态码: " + (response != null ? response.getStatusLine().getStatusCode() : "null"));
}
} catch (Exception e) {
log.error("POST请求异常", e);
} finally {
try {
if (response != null) {
response.close();
}
if (httpClient != null) {
httpClient.close();
}
} catch (IOException e) {
log.error("关闭HTTP连接异常", e);
}
}
return result;
}
/**
* 发送POST请求表单格式
* @param url 请求URL
* @param params 请求参数
* @return 响应结果
*/
public static String doPostForm(String url, HashMap<String, String> params) {
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
String result = null;
try {
httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("content-type", "application/x-www-form-urlencoded;charset=utf-8");
// 构建表单数据
StringBuilder formData = new StringBuilder();
if (params != null) {
for (String key : params.keySet()) {
if (formData.length() > 0) {
formData.append("&");
}
formData.append(key).append("=").append(params.get(key));
}
}
StringEntity stringEntity = new StringEntity(formData.toString(), "UTF-8");
httpPost.setEntity(stringEntity);
response = httpClient.execute(httpPost);
if (response != null && response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity entity = response.getEntity();
if (entity != null) {
result = EntityUtils.toString(entity, "UTF-8");
}
} else {
log.error("POST表单请求失败状态码: " + (response != null ? response.getStatusLine().getStatusCode() : "null"));
}
} catch (Exception e) {
log.error("POST表单请求异常", e);
} finally {
try {
if (response != null) {
response.close();
}
if (httpClient != null) {
httpClient.close();
}
} catch (IOException e) {
log.error("关闭HTTP连接异常", e);
}
}
return result;
}
}