feat: 初始化

This commit is contained in:
2024-04-09 11:34:46 +08:00
commit 39f3acc15f
3209 changed files with 253442 additions and 0 deletions
@@ -0,0 +1,26 @@
package com.yida.data.mall;
import cc.mrbird.febs.common.security.starter.annotation.EnableFebsCloudResourceServer;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootConfiguration
@EnableAsync
@EnableFeignClients(basePackages = "com.yida.data")
@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class)
@EnableFebsCloudResourceServer
@MapperScan("com.yida.data.mall.mapper")
public class EduMallApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(EduMallApplication.class)
.web(WebApplicationType.SERVLET)
.run(args);
}
}
@@ -0,0 +1,140 @@
package com.yida.data.mall.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yida.data.common.core.common.ResultBean;
import com.yida.data.mall.dto.*;
import com.yida.data.mall.service.EduBillService;
import com.yida.data.mall.service.EduBillStudentService;
import com.yida.data.mall.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
/**
* 缴费账单表 Controller
*
* @author ZYJ
* @date 2021-12-24 09:47:02
*/
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("eduBill")
@Api(tags = "缴费账单后台api")
public class EduBillController {
private final EduBillService eduBillService;
private final EduBillStudentService eduBillStudentService;
@PostMapping(value = "listBillPage")
@ApiOperation(value = "查询缴费账单列表数据")
public ResultBean<IPage<BillSelectPageVO>> listBillPage(@Valid BillSelectPageDTO billSelectPageDTO) {
IPage<BillSelectPageVO> page = eduBillService.listBillPage(billSelectPageDTO);
return ResultBean.buildSuccess(page);
}
@GetMapping(value = "getBillInfo")
@ApiOperation(value = "获取账单详细信息")
public ResultBean<BillInfoVO> getBillInfo(@ApiParam(value = "账单id", required = true) @RequestParam Long billId) {
return ResultBean.buildSuccess(eduBillService.getBillInfo(billId));
}
@PostMapping(value = "/saveBill", consumes = MediaType.APPLICATION_JSON_VALUE)
@ApiOperation(value = "保存缴费单数据", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResultBean<String> saveBill(@Valid @RequestBody BillSaveDTO billSaveDTO) {
eduBillService.saveBill(billSaveDTO);
return ResultBean.buildSuccess();
}
@GetMapping("updateBillEnableStatus")
@ApiOperation("修改缴费单状态")
public ResultBean<String> updateBillEnableStatus(
@ApiParam(value = "账单id", required = true) @RequestParam Long billId,
@ApiParam(value = "状态", required = true) @RequestParam Integer enableStatus) {
eduBillService.updateBillEnableStatus(billId, enableStatus);
return ResultBean.buildSuccess();
}
@GetMapping(value = "deleteBill")
@ApiOperation(value = "删除账单")
public ResultBean<String> deleteBill(@ApiParam(value = "账单id", required = true) @RequestParam Long billId) {
eduBillService.deleteBill(billId);
return ResultBean.buildSuccess();
}
@PostMapping("/listBillUserPage")
@ApiOperation("查询账单人员分页列表")
public ResultBean<IPage<BillStudentInfoVO>> listBillUserPage(BillStudentSelectPageDTO billStudentSelectPageDTO) {
IPage<BillStudentInfoVO> page = eduBillStudentService.listBillUserPage(billStudentSelectPageDTO);
return ResultBean.buildSuccess(page);
}
@PostMapping("/listBillUser")
@ApiOperation("查询账单人员列表")
public ResultBean<List<BillStudentInfoVO>> listBillUser(
@ApiParam(value = "账单id", required = true) @RequestParam Long billId) {
return ResultBean.buildSuccess(eduBillStudentService.listBillUser(billId));
}
@PostMapping(value = "/saveBillUser", consumes = MediaType.APPLICATION_JSON_VALUE)
@ApiOperation(value = "添加缴费单人员", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResultBean<String> saveBillUser(@Valid @RequestBody BillUserSaveDTO billUserSaveDTO) {
eduBillStudentService.saveBillUser(billUserSaveDTO);
return ResultBean.buildSuccess();
}
@GetMapping(value = "deleteBillUser")
@ApiOperation(value = "删除账单人员")
public ResultBean<String> deleteBillUser(
@ApiParam(value = "账单人员id", required = true) @RequestParam Long billStudentId,
@ApiParam(value = "学生id", required = true) @RequestParam Long studentId,
@ApiParam(value = "账单id", required = true) @RequestParam Long billId) {
eduBillStudentService.deleteBillUser(billStudentId, studentId, billId);
return ResultBean.buildSuccess();
}
@GetMapping(value = "listBillPayDetailTableCol")
@ApiOperation(value = "查询账单明细缴费项动态表头")
public ResultBean<List<BillItemInfoVO>> listBillPayDetailTableCol(
@ApiParam(value = "账单id", required = true) @RequestParam Long billId) {
return ResultBean.buildSuccess(eduBillService.listBillPayDetailTableCol(billId));
}
@PostMapping("/listBillPayDetailPage")
@ApiOperation("查询账单人员缴费明细")
public ResultBean<IPage<Map<String, String>>> listBillPayDetailPage(BillStudentSelectPageDTO billStudentSelectPageDTO) {
IPage<Map<String, String>> page = eduBillStudentService.listBillPayDetailPage(billStudentSelectPageDTO);
return ResultBean.buildSuccess(page);
}
@PostMapping("/exportBillPayData")
@ApiOperation("导出缴费明细数据")
public ResultBean<String> exportBillPayData(@RequestBody BillStudentSelectPageDTO billStudentSelectPageDTO,
HttpServletResponse response) {
return ResultBean.buildSuccess(eduBillStudentService.exportBillPayData(billStudentSelectPageDTO, response));
}
@PostMapping(value = "listBillOrderPage")
@ApiOperation(value = "查询账单订单列表数据")
public ResultBean<IPage<BillOrderSelectPageVO>> listBillOrderPage(BillOrderSelectPageDTO dto) {
IPage<BillOrderSelectPageVO> page = eduBillService.listBillOrderPage(dto);
return ResultBean.buildSuccess(page);
}
@GetMapping(value = "refundOrder")
@ApiOperation(value = "缴费账单退款")
public ResultBean<String> refundOrder(
@ApiParam(value = "订单号", required = true) @RequestParam String orderCode) {
eduBillService.refundOrder(orderCode);
return ResultBean.buildSuccess();
}
}
@@ -0,0 +1,54 @@
package com.yida.data.mall.controller;
import com.yida.data.common.core.common.ResultBean;
import com.yida.data.common.core.entity.mall.EduBill;
import com.yida.data.mall.dto.ExportBillStatisticsDTO;
import com.yida.data.mall.service.EduBillService;
import com.yida.data.mall.service.EduBillStatisticsService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
* 缴费账单统计 Controller
*
* @author ZYJ
* @date 2022/7/7
*/
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("bill/statistics")
@Api(tags = "缴费账单统计后台api")
public class EduBillStatisticsController {
private final EduBillService eduBillService;
private final EduBillStatisticsService eduBillStatisticsService;
@GetMapping("/listBill")
@ApiOperation("查询账单集合数据")
public ResultBean<List<EduBill>> listBill(
@ApiParam(value = "查询类型. 0-全部, 1-已开始账单") @RequestParam(required = false) Integer type) {
List<EduBill> list = eduBillService.listBill(type);
return ResultBean.buildSuccess(list);
}
@GetMapping("/billStatistics")
@ApiOperation("查询账单缴费统计数据")
public ResultBean<List<Map<String, Object>>> billStatistics(@RequestParam Long billId) {
List<Map<String, Object>> list = eduBillStatisticsService.billStatistics(billId);
return ResultBean.buildSuccess(list);
}
@PostMapping("/exportBillStatistics")
@ApiOperation("导出账单缴费统计数据")
public ResultBean<String> exportBillStatistics(@RequestBody ExportBillStatisticsDTO dto) {
return ResultBean.buildSuccess(eduBillStatisticsService.exportBillStatistics(dto));
}
}
@@ -0,0 +1,62 @@
package com.yida.data.mall.controller;
import cn.hutool.json.JSONUtil;
import com.yida.data.common.core.common.ResultBean;
import com.yida.data.common.core.entity.FebsResponse;
import com.yida.data.mall.service.EduBillOrderService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* 缴费账单订单 Controller(不鉴权)
*
* @author ZYJ
* @date 2022/4/14
*/
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("in/eduBillOrder")
@Api(tags = "缴费账单后台api")
public class InEduBillOrderController {
private final EduBillOrderService eduBillOrderService;
@ApiOperation("微信支付通知结果回调 此接口暂时无用(需手动查询订单支付状态)")
@PostMapping("/wxPayNotify")
public FebsResponse wxPayNotify(@RequestBody Map<String, Object> res) {
return new FebsResponse().put("code", "SUCCESS");
}
@ApiOperation("微信退款通知结果回调 此接口暂时无用(需手动查询订单退款状态)")
@PostMapping("/wxRefundNotify")
public FebsResponse wxRefundNotify(@RequestBody Map<String, Object> res) {
return new FebsResponse().put("code", "SUCCESS");
}
@ApiOperation("银联支付通知结果回调")
@PostMapping("/unionPayNotify")
public String unionPayNotify(@RequestParam Map<String, Object> map) {
log.info("银联支付通知结果回调, result: {}", JSONUtil.toJsonStr(map));
return eduBillOrderService.unionPayNotify(map);
}
@GetMapping(value = "updateBillOrderStatus")
@ApiOperation(value = "更新超时账单订单状态")
public ResultBean<String> updateBillOrderStatus() {
eduBillOrderService.updateBillOrderStatus();
return ResultBean.buildSuccess();
}
@GetMapping(value = "updateRefundStatus")
@ApiOperation(value = "更新退款订单状态")
public ResultBean<String> updateRefundStatus() {
eduBillOrderService.updateRefundStatus();
return ResultBean.buildSuccess();
}
}
@@ -0,0 +1,49 @@
package com.yida.data.mall.controller;
import com.yida.data.common.core.common.ResultBean;
import com.yida.data.mall.service.EduBillStatisticsService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* 缴费账单统计 Controller(不鉴权)
*
* @author ZYJ
* @date 2022/7/28
*/
@Slf4j
@RestController
@RequiredArgsConstructor
@Api(tags = "缴费账单统计")
@RequestMapping("in/bill/billStatistics")
public class InEduBillStatisticsController {
private final EduBillStatisticsService eduBillStatisticsService;
@GetMapping(value = "updateBillStatistics")
@ApiOperation(value = "更新缴费统计数据")
public ResultBean<String> updateBillStatistics() {
eduBillStatisticsService.updateBillStatistics();
return ResultBean.buildSuccess();
}
@GetMapping(value = "updateBillPayDetail")
@ApiOperation(value = "更新缴费账单明细数据")
public ResultBean<String> updateBillPayDetail() {
eduBillStatisticsService.updateBillPayDetail(null);
return ResultBean.buildSuccess();
}
@GetMapping(value = "updateChooseBillPayDetail")
@ApiOperation(value = "更新指定缴费账单明细数据")
public ResultBean<String> updateChooseBillPayDetail(@RequestParam Long billId) {
eduBillStatisticsService.updateBillPayDetail(billId);
return ResultBean.buildSuccess();
}
}
@@ -0,0 +1,111 @@
package com.yida.data.mall.controller.h5;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yida.data.common.core.common.ResultBean;
import com.yida.data.mall.dto.h5.CreateBillOrderDTO;
import com.yida.data.mall.dto.h5.H5BillInfoDTO;
import com.yida.data.mall.dto.h5.H5BillOrderPageDTO;
import com.yida.data.mall.dto.h5.H5BillSelectDTO;
import com.yida.data.mall.service.H5EduBillService;
import com.yida.data.mall.vo.h5.BillPayInfoVO;
import com.yida.data.mall.vo.h5.H5BillOrderInfoVO;
import com.yida.data.mall.vo.h5.H5BillOrderPageVO;
import com.yida.data.mall.vo.h5.H5BillSelectVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 缴费账单前端 Controller
*
* @author ZYJ
* @date 2022-3-30 19:40:02
*/
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("h5/eduBill")
@Api(tags = "缴费账单前端接口api")
public class H5EduBillController {
private final H5EduBillService h5EduBillService;
@PostMapping("/listH5Bill")
@ApiOperation("查询前台账单列表")
public ResultBean<List<H5BillSelectVO>> listH5Bill(@RequestBody H5BillSelectDTO h5BillSelectDTO) {
return ResultBean.buildSuccess(h5EduBillService.listH5Bill(h5BillSelectDTO));
}
@PostMapping("/getH5BillInfo")
@ApiOperation("查询前台账单详情")
public ResultBean<H5BillSelectVO> getH5BillInfo(@RequestBody H5BillInfoDTO h5BillInfoDTO) {
return ResultBean.buildSuccess(h5EduBillService.getH5BillInfo(h5BillInfoDTO));
}
@PostMapping("/createBillOrder")
@ApiOperation("生成账单订单")
public ResultBean<BillPayInfoVO> createBillOrder(@RequestBody CreateBillOrderDTO createBillOrderDTO) {
return ResultBean.buildSuccess(h5EduBillService.createBillOrder(createBillOrderDTO));
}
@GetMapping("/billOrderSuccess")
@ApiOperation("账单订单完成(前台支付完成后调用)")
public ResultBean<String> billOrderSuccess(
@ApiParam(value = "订单号", required = true) @RequestParam String orderCode) {
h5EduBillService.billOrderSuccess(orderCode);
return ResultBean.buildSuccess();
}
@PostMapping(value = "listH5BillOrderPage")
@ApiOperation(value = "前端查询账单订单列表数据")
public ResultBean<IPage<H5BillOrderPageVO>> listH5BillOrderPage(@RequestBody H5BillOrderPageDTO h5BillOrderPageDTO) {
IPage<H5BillOrderPageVO> page = h5EduBillService.listH5BillOrderPage(h5BillOrderPageDTO);
return ResultBean.buildSuccess(page);
}
@GetMapping(value = "getH5BillOrderInfo")
@ApiOperation(value = "前端查询账单订单详情")
public ResultBean<H5BillOrderInfoVO> getH5BillOrderInfo(
@ApiParam(value = "账单订单id") @RequestParam(required = false) Long billOrderId,
@ApiParam(value = "订单号") @RequestParam(required = false) String orderCode) {
return ResultBean.buildSuccess(h5EduBillService.getH5BillOrderInfo(billOrderId, orderCode));
}
@GetMapping("continuePayOrder")
@ApiOperation("继续支付")
public ResultBean<BillPayInfoVO> continuePayOrder(
@ApiParam(value = "订单号", required = true) @RequestParam String orderCode,
@ApiParam(value = "学校id", required = true) @RequestParam Long deptId) {
BillPayInfoVO infoVO = h5EduBillService.continuePayOrder(orderCode, deptId);
return ResultBean.buildSuccess(infoVO);
}
@GetMapping(value = "cancelOrder")
@ApiOperation(value = "取消订单")
public ResultBean<String> cancelOrder(
@ApiParam(value = "订单号", required = true) @RequestParam String orderCode) {
h5EduBillService.cancelOrder(orderCode);
return ResultBean.buildSuccess();
}
@GetMapping(value = "refundOrder")
@ApiOperation(value = "缴费账单退款")
public ResultBean<String> refundOrder(
@ApiParam(value = "订单号", required = true) @RequestParam String orderCode) {
h5EduBillService.refundOrder(orderCode);
return ResultBean.buildSuccess();
}
@GetMapping(value = "checkExistOrder")
@ApiOperation(value = "查看是否存在待支付的订单")
public ResultBean<String> checkExistOrder(
@ApiParam(value = "账单id", required = true) @RequestParam Long billId,
@ApiParam(value = "学生id", required = true) @RequestParam Long studentId) {
return ResultBean.buildSuccess(h5EduBillService.checkExistOrder(billId, studentId));
}
}
@@ -0,0 +1,28 @@
package com.yida.data.mall.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yida.data.common.core.entity.mall.EduBillItem;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
/**
* 缴费账单项目表 Mapper
*
* @author ZYJ
* @date 2021-12-24 09:47:16
*/
public interface EduBillItemMapper extends BaseMapper<EduBillItem> {
/**
* 根据是否缴费类型查询金额
*
* @param billId 缴费单id
* @param status 类型
* @return java.math.BigDecimal
* @author ZYJ
* @date 2021/12/24 16:36
*/
BigDecimal selectMoneyByStatus(@Param("billId") Long billId,
@Param("status") Integer status);
}
@@ -0,0 +1,15 @@
package com.yida.data.mall.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yida.data.common.core.entity.mall.EduBillItemSub;
/**
* 缴费账单项目选项表 Mapper
*
* @author ZYJ
* @date 2021-12-24 09:47:16
*/
public interface EduBillItemSubMapper extends BaseMapper<EduBillItemSub> {
}
@@ -0,0 +1,90 @@
package com.yida.data.mall.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yida.data.common.core.entity.mall.EduBill;
import com.yida.data.common.core.entity.user.EduStudent;
import com.yida.data.mall.dto.BillOrderSelectPageDTO;
import com.yida.data.mall.dto.BillSelectPageDTO;
import com.yida.data.mall.dto.h5.H5BillInfoDTO;
import com.yida.data.mall.dto.h5.H5BillSelectDTO;
import com.yida.data.mall.vo.BillOrderSelectPageVO;
import com.yida.data.mall.vo.BillSelectPageVO;
import com.yida.data.mall.vo.h5.H5BillSelectVO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 缴费账单表 Mapper
*
* @author ZYJ
* @date 2021-12-24 09:47:02
*/
public interface EduBillMapper extends BaseMapper<EduBill> {
/**
* 查询缴费账单列表数据
*
* @param page 分页信息
* @param billSelectPageDTO 账单后台列表请求类
* @return com.baomidou.mybatisplus.core.metadata.IPage<com.yida.data.mall.vo.BillSelectPageVO>
* @author ZYJ
* @date 2021/12/24 11:27
*/
IPage<BillSelectPageVO> listBillPage(Page<EduBill> page,
@Param("dto") BillSelectPageDTO billSelectPageDTO);
/**
* 查询前台账单列表
*
* @param h5BillSelectDTO 账单前端列表请求类
* @return java.util.List<com.yida.data.mall.vo.h5.H5BillSelectVO>
* @author ZYJ
* @date 2022/3/30 20:28
*/
List<H5BillSelectVO> listH5Bill(@Param("dto") H5BillSelectDTO h5BillSelectDTO);
/**
* 查询前台账单详情
*
* @param h5BillInfoDTO 前端账单详情请求类
* @return com.yida.data.mall.vo.h5.H5BillSelectVO
* @author ZYJ
* @date 2022/3/31 14:17
*/
H5BillSelectVO getH5BillInfo(@Param("dto") H5BillInfoDTO h5BillInfoDTO);
/**
* 查询账单订单列表数据
*
* @param page 分页信息
* @param dto 账单订单后台列表请求类
* @param studentList 学生列表
* @return java.util.List<com.yida.data.mall.vo.BillOrderSelectPageVO>
* @author ZYJ
* @date 2022/6/29 15:10
*/
List<BillOrderSelectPageVO> listBillOrderPage(Page page,
@Param("dto") BillOrderSelectPageDTO dto,
@Param("studentList") List<EduStudent> studentList);
/**
* 查询已开始未结束的账单
*
* @return java.util.List<com.yida.data.common.core.entity.mall.EduBill>
* @author ZYJ
* @date 2022/7/28 17:31
*/
List<EduBill> selectNeedStatisticsBill();
/**
* 查询已开始的账单
*
* @return java.util.List<com.yida.data.common.core.entity.mall.EduBill>
* @author ZYJ
* @date 2022/10/12 9:49
*/
List<EduBill> selectStartBill();
}
@@ -0,0 +1,56 @@
package com.yida.data.mall.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yida.data.common.core.entity.mall.EduBillOrderItem;
import com.yida.data.mall.vo.BillPayVO;
import com.yida.data.mall.vo.h5.H5BillItemVO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 账单订单关联项目表 Mapper
*
* @author ZYJ
* @date 2022-03-31 14:50:18
*/
public interface EduBillOrderItemMapper extends BaseMapper<EduBillOrderItem> {
/**
* 查询学生对应账单项目的缴费信息
*
* @param billId 账单id
* @param studentId 学生id
* @param itemId 项目id
* @return com.yida.data.mall.vo.h5.H5BillItemVO
* @author ZYJ
* @date 2022/3/31 16:01
*/
H5BillItemVO getItemPayInfo(@Param("billId") Long billId,
@Param("studentId") Long studentId,
@Param("itemId") Long itemId);
/**
* 查询学生账单缴费信息
*
* @param billId 账单id
* @param studentId 学生id
* @return java.util.List<com.yida.data.mall.vo.h5.H5BillItemVO>
* @author ZYJ
* @date 2022/4/2 15:58
*/
List<H5BillItemVO> getPayInfo(@Param("billId") Long billId,
@Param("studentId") Long studentId);
/**
* 查询学生具体缴费金额
*
* @param billId 账单id
* @param studentId 学生id
* @return java.util.List<com.yida.data.mall.vo.BillPayVO>
* @author ZYJ
* @date 2022/4/19 17:06
*/
List<BillPayVO> listItemPayInfo(@Param("billId") Long billId,
@Param("studentId") Long studentId);
}
@@ -0,0 +1,14 @@
package com.yida.data.mall.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yida.data.common.core.entity.mall.EduBillOrderItemSub;
/**
* 账单订单关联项目选项表 Mapper
*
* @author ZYJ
* @date 2022-03-31 14:50:33
*/
public interface EduBillOrderItemSubMapper extends BaseMapper<EduBillOrderItemSub> {
}
@@ -0,0 +1,104 @@
package com.yida.data.mall.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yida.data.common.core.entity.mall.EduBillOrder;
import com.yida.data.mall.dto.h5.H5BillOrderPageDTO;
import com.yida.data.mall.vo.BillRefundOrderVO;
import com.yida.data.mall.vo.h5.H5BillOrderInfoVO;
import com.yida.data.mall.vo.h5.H5BillOrderPageVO;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.util.List;
/**
* 账单订单表 Mapper
*
* @author ZYJ
* @date 2022-03-31 14:49:59
*/
public interface EduBillOrderMapper extends BaseMapper<EduBillOrder> {
/**
* 查询已支付金额
*
* @param billId 账单id
* @param studentId 学生id
* @return java.math.BigDecimal
* @author ZYJ
* @date 2022/3/31 15:36
*/
BigDecimal sumPayOrderPrice(@Param("billId") Long billId,
@Param("studentId") Long studentId);
/**
* 前端查询账单订单列表数据
* 未支付、成功、退款中
*
* @param page 分页数据
* @param dto 账单订单列表请求类
* @return com.baomidou.mybatisplus.core.metadata.IPage<com.yida.data.mall.vo.h5.H5BillOrderPageVO>
* @author ZYJ
* @date 2022/4/1 16:56
*/
IPage<H5BillOrderPageVO> listH5BillOrderPage(Page<EduBillOrder> page,
@Param("dto") H5BillOrderPageDTO dto);
/**
* 前端查询账单订单详情
*
* @param billOrderId 账单订单id
* @param orderCode 订单号
* @return com.yida.data.mall.vo.h5.H5BillOrderInfoVO
* @author ZYJ
* @date 2022/4/1 17:38
*/
H5BillOrderInfoVO getH5BillOrderInfo(@Param("billOrderId") Long billOrderId,
@Param("orderCode") String orderCode);
/**
* 查询账单缴费人数
* 缴费金额大于0
*
* @param billId 账单id
* @return java.lang.Long
* @author ZYJ
* @date 2022/4/18 16:30
*/
Long sumPayStudentNumber(@Param("billId") Long billId);
/**
* 查询所有已经超时订单
* 未支付状态
*
* @return java.util.List<com.yida.data.common.core.entity.mall.EduBillOrder>
* @author ZYJ
* @date 2022/4/14 10:48
*/
List<EduBillOrder> selectTimeOutBillOrder();
/**
* 查询退款中状态的账单订单
*
* @return java.util.List<com.yida.data.mall.vo.BillRefundOrderVO>
* @author ZYJ
* @date 2022/4/18 13:38
*/
List<BillRefundOrderVO> selectRefundOrder();
/**
* 部门缴费总金额
*
* @param billId 账单id
* @param deptId 家校部门id
* @param type 家校部门类型
* @return java.math.BigDecimal
* @author ZYJ
* @date 2022/7/11 15:57
*/
BigDecimal sumDeptPayOrderPrice(@Param("billId") Long billId,
@Param("deptId") Long deptId,
@Param("type") Integer type);
}
@@ -0,0 +1,14 @@
package com.yida.data.mall.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yida.data.common.core.entity.mall.EduBillOrderRefund;
/**
* 缴费账单退款信息表 Mapper
*
* @author ZYJ
* @date 2022-04-18 10:29:24
*/
public interface EduBillOrderRefundMapper extends BaseMapper<EduBillOrderRefund> {
}
@@ -0,0 +1,14 @@
package com.yida.data.mall.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yida.data.common.core.entity.mall.EduBillOrderStudent;
/**
* 账单订单学生详细信息 Mapper
*
* @author ZYJ
* @date 2022-03-31 14:50:42
*/
public interface EduBillOrderStudentMapper extends BaseMapper<EduBillOrderStudent> {
}
@@ -0,0 +1,64 @@
package com.yida.data.mall.mapper;
import com.yida.data.mall.vo.BillPayVO;
import com.yida.data.mall.vo.BillStatisticsItemVO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 缴费账单统计 Mapper
*
* @author ZYJ
* @date 2022/7/7
*/
public interface EduBillStatisticsMapper {
/**
* 查询账单总缴费信息
*
* @param billId 账单id
* @return java.util.List<com.yida.data.mall.vo.BillStatisticsItemVO>
* @author ZYJ
* @date 2022/7/8 14:15
*/
List<BillStatisticsItemVO> getPayInfo(Long billId);
/**
* 账单部门缴费信息统计
*
* @param billId 账单id
* @param deptId 家校部门id
* @param type 家校部门类型
* @return java.util.List<com.yida.data.mall.vo.BillStatisticsItemVO>
* @author ZYJ
* @date 2022/7/8 16:55
*/
List<BillStatisticsItemVO> getDeptPayInfo(@Param("billId") Long billId,
@Param("deptId") Long deptId,
@Param("type") Integer type);
/**
* 查询账单总缴费信息
*
* @param billId 账单id
* @return java.util.List<com.yida.data.mall.vo.BillPayVO>
* @author ZYJ
* @date 2022/7/12 14:20
*/
List<BillPayVO> listTotalItemPayInfo(@Param("billId") Long billId);
/**
* 账单部门缴费信息统计
*
* @param billId 账单id
* @param deptId 家校部门id
* @param type 家校部门类型
* @return java.util.List<com.yida.data.mall.vo.BillPayVO>
* @author ZYJ
* @date 2022/7/12 16:12
*/
List<BillPayVO> listDeptItemPayInfo(@Param("billId") Long billId,
@Param("deptId") Long deptId,
@Param("type") Integer type);
}
@@ -0,0 +1,34 @@
package com.yida.data.mall.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yida.data.common.core.entity.mall.EduBillStudent;
import com.yida.data.common.core.entity.user.EduStudent;
import com.yida.data.mall.dto.BillStudentSelectPageDTO;
import com.yida.data.mall.vo.BillStudentInfoVO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 缴费单缴费学生 Mapper
*
* @author ZYJ
* @date 2021-12-30
*/
public interface EduBillStudentMapper extends BaseMapper<EduBillStudent> {
/**
* 查询账单人员列表
*
* @param page 分页信息
* @param dto 账单人员后台列表请求类
* @param studentList 学生列表
* @return java.util.List<com.yida.data.mall.vo.BillStudentInfoVO>
* @author ZYJ
* @date 2022/3/30 14:47
*/
List<BillStudentInfoVO> listBillUserPage(Page page,
@Param("dto") BillStudentSelectPageDTO dto,
@Param("studentList") List<EduStudent> studentList);
}
@@ -0,0 +1,13 @@
package com.yida.data.mall.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yida.data.common.core.entity.mall.EduBillItem;
/**
* 缴费账单项目表 Service接口
*
* @author ZYJ
* @date 2021-12-24 09:47:16
*/
public interface EduBillItemService extends IService<EduBillItem> {
}
@@ -0,0 +1,14 @@
package com.yida.data.mall.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yida.data.common.core.entity.mall.EduBillItemSub;
/**
* 缴费账单项目选项表 Service接口
*
* @author ZYJ
* @date 2021-12-24 09:47:16
*/
public interface EduBillItemSubService extends IService<EduBillItemSub> {
}
@@ -0,0 +1,51 @@
package com.yida.data.mall.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yida.data.common.core.entity.mall.EduBillOrderItem;
import com.yida.data.mall.vo.BillPayVO;
import com.yida.data.mall.vo.h5.H5BillItemVO;
import java.util.List;
/**
* 账单订单关联项目表 Service接口
*
* @author ZYJ
* @date 2022-03-31 14:50:18
*/
public interface EduBillOrderItemService extends IService<EduBillOrderItem> {
/**
* 查询学生对应账单项目的缴费信息
*
* @param billId 账单id
* @param studentId 学生id
* @param itemId 项目id
* @return java.util.List<com.yida.data.mall.vo.h5.H5BillItemVO>
* @author ZYJ
* @date 2022/3/31 15:59
*/
H5BillItemVO getItemPayInfo(Long billId, Long studentId, Long itemId);
/**
* 查询学生账单缴费信息
*
* @param billId 账单id
* @param studentId 学生id
* @return java.util.List<com.yida.data.mall.vo.h5.H5BillItemVO>
* @author ZYJ
* @date 2022/4/2 15:58
*/
List<H5BillItemVO> getPayInfo(Long billId, Long studentId);
/**
* 查询学生具体缴费金额
*
* @param billId 账单id
* @param studentId 学生id
* @return java.util.List<com.yida.data.mall.vo.BillPayVO>
* @author ZYJ
* @date 2022/4/19 17:04
*/
List<BillPayVO> listItemPayInfo(Long billId, Long studentId);
}
@@ -0,0 +1,13 @@
package com.yida.data.mall.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yida.data.common.core.entity.mall.EduBillOrderItemSub;
/**
* 账单订单关联项目选项表 Service接口
*
* @author ZYJ
* @date 2022-03-31 14:50:33
*/
public interface EduBillOrderItemSubService extends IService<EduBillOrderItemSub> {
}
@@ -0,0 +1,14 @@
package com.yida.data.mall.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yida.data.common.core.entity.mall.EduBillOrderRefund;
/**
* 缴费账单退款信息表 Service接口
*
* @author ZYJ
* @date 2022-04-18 10:29:24
*/
public interface EduBillOrderRefundService extends IService<EduBillOrderRefund> {
}
@@ -0,0 +1,76 @@
package com.yida.data.mall.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yida.data.common.core.entity.mall.EduBillOrder;
import java.math.BigDecimal;
import java.util.Map;
/**
* 账单订单表 Service接口
*
* @author ZYJ
* @date 2022-03-31 14:49:59
*/
public interface EduBillOrderService extends IService<EduBillOrder> {
/**
* 查询已支付金额
*
* @param billId 账单id
* @param studentId 学生id
* @return java.math.BigDecimal
* @author ZYJ
* @date 2022/3/31 15:35
*/
BigDecimal sumPayOrderPrice(Long billId, Long studentId);
/**
* 更新超时账单订单状态
* 未支付状态
*
* @author ZYJ
* @date 2022/4/14 10:47
*/
void updateBillOrderStatus();
/**
* 更新退款订单状态
*
* @author ZYJ
* @date 2022/4/18 11:16
*/
void updateRefundStatus();
/**
* 查询账单缴费人数
*
* @param billId 账单id
* @return java.lang.Long
* @author ZYJ
* @date 2022/4/18 16:29
*/
Long sumPayStudentNumber(Long billId);
/**
* 银联支付通知结果回调
*
* @param map 回调值
* @return java.lang.String
* @author ZYJ
* @date 2022/6/27 15:03
*/
String unionPayNotify(Map<String, Object> map);
/**
* 部门缴费总金额
*
* @param billId 账单id
* @param deptId 家校部门id
* @param type 家校部门类型
* @return java.math.BigDecimal
* @author ZYJ
* @date 2022/7/11 15:55
*/
BigDecimal sumDeptPayOrderPrice(Long billId, Long deptId, Integer type);
}
@@ -0,0 +1,13 @@
package com.yida.data.mall.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yida.data.common.core.entity.mall.EduBillOrderStudent;
/**
* 账单订单学生详细信息 Service接口
*
* @author ZYJ
* @date 2022-03-31 14:50:42
*/
public interface EduBillOrderStudentService extends IService<EduBillOrderStudent> {
}
@@ -0,0 +1,111 @@
package com.yida.data.mall.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yida.data.common.core.entity.mall.EduBill;
import com.yida.data.common.core.enums.BillStatusEnum;
import com.yida.data.mall.dto.BillOrderSelectPageDTO;
import com.yida.data.mall.dto.BillSaveDTO;
import com.yida.data.mall.dto.BillSelectPageDTO;
import com.yida.data.mall.vo.BillInfoVO;
import com.yida.data.mall.vo.BillItemInfoVO;
import com.yida.data.mall.vo.BillOrderSelectPageVO;
import com.yida.data.mall.vo.BillSelectPageVO;
import java.util.List;
/**
* 缴费账单表 Service接口
*
* @author ZYJ
* @date 2021-12-24 09:47:02
*/
public interface EduBillService extends IService<EduBill> {
/**
* 查询缴费账单列表数据
*
* @param billSelectPageDTO 账单后台列表请求类
* @return com.baomidou.mybatisplus.core.metadata.IPage<com.yida.data.mall.vo.BillSelectPageVO>
* @author ZYJ
* @date 2021/12/24 11:24
*/
IPage<BillSelectPageVO> listBillPage(BillSelectPageDTO billSelectPageDTO);
/**
* 获取账单详细信息
*
* @param billId 账单id
* @return com.yida.data.mall.vo.BillInfoVO
* @author ZYJ
* @date 2021/12/24 13:38
*/
BillInfoVO getBillInfo(Long billId);
/**
* 保存缴费单数据
*
* @param billSaveDTO 保存缴费单请求类
* @author ZYJ
* @date 2021/12/29 15:07
*/
void saveBill(BillSaveDTO billSaveDTO);
/**
* 修改缴费单状态
*
* @param billId 账单id
* @param enableStatus 状态 {@link BillStatusEnum}
* @author ZYJ
* @date 2022/3/28 19:49
*/
void updateBillEnableStatus(Long billId, Integer enableStatus);
/**
* 删除账单
*
* @param billId 账单id
* @author ZYJ
* @date 2022/3/30 16:30
*/
void deleteBill(Long billId);
/**
* 查询账单明细缴费项动态表头
*
* @param billId 账单id
* @return java.lang.Object
* @author ZYJ
* @date 2022/4/2 14:31
*/
List<BillItemInfoVO> listBillPayDetailTableCol(Long billId);
/**
* 查询账单订单列表数据
*
* @param dto 账单订单后台列表请求类
* @return com.baomidou.mybatisplus.core.metadata.IPage<com.yida.data.mall.vo.BillOrderSelectPageVO>
* @author ZYJ
* @date 2022/6/29 15:01
*/
IPage<BillOrderSelectPageVO> listBillOrderPage(BillOrderSelectPageDTO dto);
/**
* 缴费账单退款
*
* @param orderCode 订单号
* @author ZYJ
* @date 2022/6/29 20:37
*/
void refundOrder(String orderCode);
/**
* 查询账单集合数据
*
* @param type 查询类型. 0-全部, 1-已开始账单
* @return java.util.List<com.yida.data.common.core.entity.mall.EduBill>
* @author ZYJ
* @date 2022/7/7 10:07
*/
List<EduBill> listBill(Integer type);
}
@@ -0,0 +1,52 @@
package com.yida.data.mall.service;
import com.yida.data.mall.dto.ExportBillStatisticsDTO;
import java.util.List;
import java.util.Map;
/**
* 缴费账单统计
*
* @author ZYJ
* @date 2022/7/7
*/
public interface EduBillStatisticsService {
/**
* 查询账单缴费统计数据
*
* @param billId 账单id
* @return java.util.List<java.util.Map < java.lang.String, java.lang.Object>>
* @author ZYJ
* @date 2022/7/11 10:00
*/
List<Map<String, Object>> billStatistics(Long billId);
/**
* 导出账单缴费统计数据
*
* @param dto 导出账单缴费统计数据请求类
* @return java.lang.String
* @author ZYJ
* @date 2022/7/28 17:54
*/
String exportBillStatistics(ExportBillStatisticsDTO dto);
/**
* 更新缴费统计数据
*
* @author ZYJ
* @date 2022/7/28 17:12
*/
void updateBillStatistics();
/**
* 更新缴费账单明细数据
*
* @param billId 账单id
* @author ZYJ
* @date 2022/10/11 14:39
*/
void updateBillPayDetail(Long billId);
}
@@ -0,0 +1,82 @@
package com.yida.data.mall.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yida.data.common.core.entity.mall.EduBillStudent;
import com.yida.data.mall.dto.BillStudentSelectPageDTO;
import com.yida.data.mall.dto.BillUserSaveDTO;
import com.yida.data.mall.vo.BillStudentInfoVO;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
/**
* 缴费单缴费学生 Service接口
*
* @author ZYJ
* @date 2021-12-30
*/
public interface EduBillStudentService extends IService<EduBillStudent> {
/**
* 查询账单人员分页列表
*
* @param dto 账单人员后台列表请求类
* @return com.baomidou.mybatisplus.core.metadata.IPage<com.yida.data.mall.vo.BillStudentInfoVO>
* @author ZYJ
* @date 2022/3/29 15:29
*/
IPage<BillStudentInfoVO> listBillUserPage(BillStudentSelectPageDTO dto);
/**
* 查询账单人员列表
*
* @param billId 账单id
* @return java.util.List<com.yida.data.mall.vo.BillStudentInfoVO>
* @author ZYJ
* @date 2022/3/30 15:01
*/
List<BillStudentInfoVO> listBillUser(Long billId);
/**
* 添加缴费单人员
*
* @param billUserSaveDTO 添加缴费单人员请求类
* @author ZYJ
* @date 2022/3/30 16:11
*/
void saveBillUser(BillUserSaveDTO billUserSaveDTO);
/**
* 删除账单人员
*
* @param billStudentId 账单人员id
* @param studentId 学生id
* @param billId 账单id
* @author ZYJ
* @date 2022/3/30 16:41
*/
void deleteBillUser(Long billStudentId, Long studentId, Long billId);
/**
* 查询账单人员缴费明细
*
* @param billStudentSelectPageDTO 账单人员后台列表请求类
* @return com.baomidou.mybatisplus.core.metadata.IPage<java.util.Map < java.lang.String, java.lang.String>>
* @author ZYJ
* @date 2022/4/2 15:34
*/
IPage<Map<String, String>> listBillPayDetailPage(BillStudentSelectPageDTO billStudentSelectPageDTO);
/**
* 导出缴费明细数据
*
* @param billStudentSelectPageDTO 账单人员后台列表请求类
* @param response response
* @return java.lang.String
* @author ZYJ
* @date 2022/10/11 17:29
*/
String exportBillPayData(BillStudentSelectPageDTO billStudentSelectPageDTO, HttpServletResponse response);
}
@@ -0,0 +1,133 @@
package com.yida.data.mall.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yida.data.mall.dto.h5.CreateBillOrderDTO;
import com.yida.data.mall.dto.h5.H5BillInfoDTO;
import com.yida.data.mall.dto.h5.H5BillOrderPageDTO;
import com.yida.data.mall.dto.h5.H5BillSelectDTO;
import com.yida.data.mall.vo.h5.BillPayInfoVO;
import com.yida.data.mall.vo.h5.H5BillOrderInfoVO;
import com.yida.data.mall.vo.h5.H5BillOrderPageVO;
import com.yida.data.mall.vo.h5.H5BillSelectVO;
import java.time.LocalDateTime;
import java.util.List;
/**
* 缴费账单前端 Service接口
*
* @author ZYJ
* @date 2022-3-30 19:47:02
*/
public interface H5EduBillService {
/**
* 查询前台账单列表
*
* @param h5BillSelectDTO 账单前端列表请求类
* @return java.util.List<com.yida.data.mall.vo.h5.H5BillSelectVO>
* @author ZYJ
* @date 2022/3/30 20:25
*/
List<H5BillSelectVO> listH5Bill(H5BillSelectDTO h5BillSelectDTO);
/**
* 查询前台账单详情
*
* @param h5BillInfoDTO 前端账单详情请求类
* @return com.yida.data.mall.vo.h5.H5BillSelectVO
* @author ZYJ
* @date 2022/3/31 14:15
*/
H5BillSelectVO getH5BillInfo(H5BillInfoDTO h5BillInfoDTO);
/**
* 生成账单订单
*
* @param createBillOrderDTO 生成账单订单请求类
* @return com.yida.data.mall.vo.h5.BillPayInfoVO
* @author ZYJ
* @date 2022/3/31 19:53
*/
BillPayInfoVO createBillOrder(CreateBillOrderDTO createBillOrderDTO);
/**
* 账单订单完成(前台支付完成后调用)
*
* @param orderCode 订单号
* @author ZYJ
* @date 2022/4/1 15:42
*/
void billOrderSuccess(String orderCode);
/**
* 账单订单支付成功
*
* @param orderCode 订单号
* @param payDate 支付完成时间
* @author ZYJ
* @date 2022/4/1 16:15
*/
void billOrderPaySuccess(String orderCode, LocalDateTime payDate);
/**
* 前端查询账单订单列表数据
*
* @param h5BillOrderPageDTO 账单订单列表请求类
* @return com.baomidou.mybatisplus.core.metadata.IPage<com.yida.data.mall.vo.h5.H5BillOrderPageVO>
* @author ZYJ
* @date 2022/4/1 16:54
*/
IPage<H5BillOrderPageVO> listH5BillOrderPage(H5BillOrderPageDTO h5BillOrderPageDTO);
/**
* 前端查询账单订单详情
*
* @param billOrderId 账单订单id
* @param orderCode 订单号
* @return com.yida.data.mall.vo.h5.H5BillOrderInfoVO
* @author ZYJ
* @date 2022/4/1 17:25
*/
H5BillOrderInfoVO getH5BillOrderInfo(Long billOrderId, String orderCode);
/**
* 继续支付
*
* @param orderCode 订单号
* @param deptId 学校id
* @return com.yida.data.mall.vo.h5.BillPayInfoVO
* @author ZYJ
* @date 2022/4/1 17:15
*/
BillPayInfoVO continuePayOrder(String orderCode, Long deptId);
/**
* 取消订单
*
* @param orderCode 订单号
* @author ZYJ
* @date 2022/4/1 17:07
*/
void cancelOrder(String orderCode);
/**
* 缴费账单退款
*
* @param orderCode 订单号
* @author ZYJ
* @date 2022/4/18 10:04
*/
void refundOrder(String orderCode);
/**
* 查看是否存在待支付的订单
*
* @param billId 账单id
* @param studentId 学生id
* @return java.lang.String
* @author ZYJ
* @date 2022/7/28 15:23
*/
String checkExistOrder(Long billId, Long studentId);
}
@@ -0,0 +1,26 @@
package com.yida.data.mall.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.common.core.entity.mall.EduBillItem;
import com.yida.data.mall.mapper.EduBillItemMapper;
import com.yida.data.mall.service.EduBillItemService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* 缴费账单项目表 Service实现
*
* @author ZYJ
* @date 2021-12-24 09:47:16
*/
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class EduBillItemServiceImpl extends ServiceImpl
<EduBillItemMapper, EduBillItem> implements EduBillItemService {
}
@@ -0,0 +1,26 @@
package com.yida.data.mall.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.common.core.entity.mall.EduBillItemSub;
import com.yida.data.mall.mapper.EduBillItemSubMapper;
import com.yida.data.mall.service.EduBillItemSubService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* 缴费账单项目选项表 Service实现
*
* @author ZYJ
* @date 2021-12-24 09:47:16
*/
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class EduBillItemSubServiceImpl extends ServiceImpl
<EduBillItemSubMapper, EduBillItemSub> implements EduBillItemSubService {
}
@@ -0,0 +1,41 @@
package com.yida.data.mall.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.common.core.entity.mall.EduBillOrderItem;
import com.yida.data.mall.mapper.EduBillOrderItemMapper;
import com.yida.data.mall.service.EduBillOrderItemService;
import com.yida.data.mall.vo.BillPayVO;
import com.yida.data.mall.vo.h5.H5BillItemVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* 账单订单关联项目表 Service实现
*
* @author ZYJ
* @date 2022-03-31 14:50:18
*/
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class EduBillOrderItemServiceImpl extends ServiceImpl
<EduBillOrderItemMapper, EduBillOrderItem> implements EduBillOrderItemService {
@Override
public H5BillItemVO getItemPayInfo(Long billId, Long studentId, Long itemId) {
return baseMapper.getItemPayInfo(billId, studentId, itemId);
}
@Override
public List<H5BillItemVO> getPayInfo(Long billId, Long studentId) {
return baseMapper.getPayInfo(billId, studentId);
}
@Override
public List<BillPayVO> listItemPayInfo(Long billId, Long studentId) {
return baseMapper.listItemPayInfo(billId, studentId);
}
}
@@ -0,0 +1,24 @@
package com.yida.data.mall.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.common.core.entity.mall.EduBillOrderItemSub;
import com.yida.data.mall.mapper.EduBillOrderItemSubMapper;
import com.yida.data.mall.service.EduBillOrderItemSubService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* 账单订单关联项目选项表 Service实现
*
* @author ZYJ
* @date 2022-03-31 14:50:33
*/
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class EduBillOrderItemSubServiceImpl extends ServiceImpl
<EduBillOrderItemSubMapper, EduBillOrderItemSub> implements EduBillOrderItemSubService {
}
@@ -0,0 +1,25 @@
package com.yida.data.mall.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.common.core.entity.mall.EduBillOrderRefund;
import com.yida.data.mall.mapper.EduBillOrderRefundMapper;
import com.yida.data.mall.service.EduBillOrderRefundService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* 缴费账单退款信息表 Service实现
*
* @author ZYJ
* @date 2022-04-18 10:29:24
*/
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class EduBillOrderRefundServiceImpl extends ServiceImpl
<EduBillOrderRefundMapper, EduBillOrderRefund> implements EduBillOrderRefundService {
}
@@ -0,0 +1,374 @@
package com.yida.data.mall.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.common.core.entity.constant.UnionPayConstant;
import com.yida.data.common.core.entity.constant.WxPayConstant;
import com.yida.data.common.core.entity.mall.EduBillOrder;
import com.yida.data.common.core.entity.mall.EduBillOrderRefund;
import com.yida.data.common.core.entity.system.EduPayWxConfig;
import com.yida.data.common.core.entity.system.UnionPayConfig;
import com.yida.data.common.core.enums.*;
import com.yida.data.common.core.utils.EnumUtils;
import com.yida.data.common.core.utils.UnionPayPublicUtil;
import com.yida.data.common.core.utils.UnionPayUtil;
import com.yida.data.common.core.utils.WxPayUtil;
import com.yida.data.common.service.CommonService;
import com.yida.data.mall.mapper.EduBillOrderMapper;
import com.yida.data.mall.service.EduBillOrderRefundService;
import com.yida.data.mall.service.EduBillOrderService;
import com.yida.data.mall.service.H5EduBillService;
import com.yida.data.mall.vo.BillRefundOrderVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* 账单订单表 Service实现
*
* @author ZYJ
* @date 2022-03-31 14:49:59
*/
@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class EduBillOrderServiceImpl extends ServiceImpl
<EduBillOrderMapper, EduBillOrder> implements EduBillOrderService {
private final CommonService commonService;
private final UnionPayPublicUtil unionPayPublicUtil;
@Lazy
@Resource
private H5EduBillService h5EduBillService;
private final EduBillOrderRefundService eduBillOrderRefundService;
@Override
public BigDecimal sumPayOrderPrice(Long billId, Long studentId) {
return baseMapper.sumPayOrderPrice(billId, studentId);
}
@Override
public Long sumPayStudentNumber(Long billId) {
return baseMapper.sumPayStudentNumber(billId);
}
@Override
public void updateBillOrderStatus() {
// 查询超时订单
List<EduBillOrder> list = baseMapper.selectTimeOutBillOrder();
if (CollUtil.isNotEmpty(list)) {
for (EduBillOrder order : list) {
// 微信订单
if (PayWay.WEI_XIN.getValue().equals(order.getPayWay())) {
updateWxBillOrderStatus(order);
} else if (PayWay.UNION.getValue().equals(order.getPayWay())) {
updateUnionBillOrderStatus(order);
}
}
}
}
/**
* 更新微信超时账单订单状态
*
* @param order 订单信息
* @author ZYJ
* @date 2022/6/27 19:28
*/
private void updateWxBillOrderStatus(EduBillOrder order) {
try {
// 查询学校微信支付配置信息
EduPayWxConfig config = commonService.getPayWxConfigBySchool(order.getDeptId());
// 主动查询订单支付状态
JSONObject resultJson = JSONUtil.parseObj(WxPayUtil.queryOrder(config, order.getOrderCode()));
log.info("微信账单订单查询返回数据, billOrderCode: {}, resultJson: {}", order.getOrderCode(), resultJson);
if (resultJson.containsKey(WxPayConstant.CODE_NAME)
&& WxPayConstant.ORDER_NOT_EXIST.equals(resultJson.getStr(WxPayConstant.CODE_NAME))) {
// 订单不存在 取消订单
order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
order.setPayStatus(PayStatusEnum.CANCEL.getStatus());
} else {
String tradeState = resultJson.getStr("trade_state");
// 未支付则关闭订单
if (WxTradeStateEnum.NOT_PAY.getStatus().equals(tradeState)) {
WxPayUtil.closeOrder(config, order.getOrderCode());
}
WxTradeStateEnum wxTradeStateEnum = EnumUtils.valueOf(WxTradeStateEnum.class, tradeState,
WxTradeStateEnum.class.getMethod("getStatus"));
switch (Objects.requireNonNull(wxTradeStateEnum)) {
// 支付成功情况
case SUCCESS:
h5EduBillService.billOrderPaySuccess(order.getOrderCode(),
DateUtil.parseLocalDateTime(resultJson.getStr("success_time"),
"yyyy-MM" + "-dd'T" + "'HH:mm" + ":ssXXX"));
break;
// 作废订单
case NOT_PAY:
case CLOSED:
case REVOKED:
case PAY_ERROR:
order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
order.setPayStatus(PayStatusEnum.CANCEL.getStatus());
break;
default:
break;
}
}
if (OrderStatusEnum.CLOSED.getStatus().equals(order.getOrderStatus())) {
baseMapper.updateById(order);
}
} catch (Exception e) {
log.error("更新微信账单订单状态失败, order: {}", order, e);
}
}
/**
* 更新银联超时账单订单状态
*
* @param order 订单信息
* @author ZYJ
* @date 2022/6/27 19:28
*/
private void updateUnionBillOrderStatus(EduBillOrder order) {
try {
// 查询学校银联配置信息
UnionPayConfig config = commonService.getUnionPayConfigByDept(order.getDeptId());
// 主商户信息
UnionPayConfig parentConfig = config.getParentConfig();
// 开发者ID
String appId = Objects.nonNull(parentConfig) ? parentConfig.getAppId() : config.getAppId();
// 开发者key
String appKey = Objects.nonNull(parentConfig) ? parentConfig.getAppKey() : config.getAppKey();
// 主动查询订单支付状态
JSONObject resultJson = UnionPayUtil.queryOrder(config, unionPayPublicUtil.getAccessToken(appId, appKey), order.getOrderCode());
log.info("银联账单订单查询返回数据, billOrderCode: {}, resultJson: {}", order.getOrderCode(), resultJson);
// 返回code
String code = (String) resultJson.get(UnionPayConstant.CODE_NAME);
// 无法找到指定的订单 需要直接关闭订单
if (UnionPayConstant.NO_ORDER_CODE.equalsIgnoreCase(code)
|| UnionPayConstant.TARGET_FAIL_CODE.equalsIgnoreCase(code)) {
order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
order.setPayStatus(PayStatusEnum.CANCEL.getStatus());
baseMapper.updateById(order);
return;
}
// 支付状态
String status = (String) resultJson.get("status");
// 未支付则关闭订单 (银联云闪付不支付关闭订单)
if (UnionTradeStateEnum.NEW_ORDER.getStatus().equals(status)
&& !UnionPayTypeEnum.UNION_H5_TYPE.getType().equals(order.getPayType())) {
UnionPayUtil.closeOrder(config, unionPayPublicUtil.getAccessToken(appId, appKey), order.getOrderCode());
}
UnionTradeStateEnum tradeStateEnum = EnumUtils.valueOf(UnionTradeStateEnum.class, status,
UnionTradeStateEnum.class.getMethod("getStatus"));
switch (Objects.requireNonNull(tradeStateEnum)) {
// 支付成功
case TRADE_SUCCESS:
h5EduBillService.billOrderPaySuccess(order.getOrderCode(),
LocalDateTimeUtil.parse((String) resultJson.get("payTime"), DatePattern.NORM_DATETIME_PATTERN));
break;
// 作废订单
case NEW_ORDER:
case TRADE_CLOSED:
case WAIT_BUYER_PAY:
order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
order.setPayStatus(PayStatusEnum.CANCEL.getStatus());
break;
default:
break;
}
if (OrderStatusEnum.CLOSED.getStatus().equals(order.getOrderStatus())) {
baseMapper.updateById(order);
}
} catch (Exception e) {
log.error("更新银联账单订单状态失败, order: {}", order, e);
}
}
@Override
public void updateRefundStatus() {
// 查询退款中状态的账单订单
List<BillRefundOrderVO> refundOrderList = baseMapper.selectRefundOrder();
if (CollUtil.isNotEmpty(refundOrderList)) {
refundOrderList.forEach(billRefundOrderVO -> {
// 微信
if (PayWay.WEI_XIN.getValue().equals(billRefundOrderVO.getPayWay())) {
updateWxRefundStatus(billRefundOrderVO);
} else if (PayWay.UNION.getValue().equals(billRefundOrderVO.getPayWay())) {
updateUnionRefundStatus(billRefundOrderVO);
}
});
}
}
/**
* 更新微信退款订单状态
*
* @param billRefundOrderVO 退款信息
* @author ZYJ
* @date 2022/6/27 19:44
*/
private void updateWxRefundStatus(BillRefundOrderVO billRefundOrderVO) {
try {
EduPayWxConfig config = commonService.getPayWxConfigBySchool(billRefundOrderVO.getDeptId());
// 主动查询退款状态
JSONObject resultJson = JSONUtil.parseObj(WxPayUtil.queryRefund(config, billRefundOrderVO.getRefundCode()));
log.info("账单订单退款查询返回数据, refundOrderCode: {}, resultJson: {}", billRefundOrderVO.getRefundCode(), resultJson);
// 状态
String status = resultJson.getStr("status");
WxRefundStatusEnum wxRefundStatusEnum = EnumUtils.valueOf(WxRefundStatusEnum.class, status,
WxRefundStatusEnum.class.getMethod("getStatus"));
switch (Objects.requireNonNull(wxRefundStatusEnum)) {
case REFUND_SUCCESS:
// 更新订单退款状态
EduBillOrder eduBillOrder = getById(billRefundOrderVO.getOrderId());
eduBillOrder.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
eduBillOrder.setPayStatus(PayStatusEnum.REFUND_SUCCESS.getStatus());
eduBillOrder.setIsRefund(RefundStatusEnum.IS_REFUND.getStatus());
baseMapper.updateById(eduBillOrder);
// 更新退款时间
EduBillOrderRefund eduBillOrderRefund = eduBillOrderRefundService.getById(billRefundOrderVO.getRefundId());
eduBillOrderRefund.setRefundTime(DateUtil.parseLocalDateTime(resultJson.getStr("success_time"), "yyyy-MM-dd'T'HH:mm:ssXXX"));
eduBillOrderRefundService.updateById(eduBillOrderRefund);
break;
case REFUND_ABNORMAL:
// TODO 2022/6/27 需要后续处理退款失败情况
break;
default:
break;
}
} catch (Exception e) {
log.error("查询微信账单订单退款状态失败, refundOrder: {}", billRefundOrderVO, e);
}
}
/**
* 更新银联退款订单状态
*
* @param billRefundOrderVO 退款信息
* @author ZYJ
* @date 2022/6/27 19:44
*/
private void updateUnionRefundStatus(BillRefundOrderVO billRefundOrderVO) {
try {
// 查询学校银联配置信息
UnionPayConfig config = commonService.getUnionPayConfigByDept(billRefundOrderVO.getDeptId());
// 主商户信息
UnionPayConfig parentConfig = config.getParentConfig();
// 开发者ID
String appId = Objects.nonNull(parentConfig) ? parentConfig.getAppId() : config.getAppId();
// 开发者key
String appKey = Objects.nonNull(parentConfig) ? parentConfig.getAppKey() : config.getAppKey();
// 主动查询退款状态
JSONObject resultJson = UnionPayUtil.refundQuery(config, billRefundOrderVO.getRefundCode(), unionPayPublicUtil.getAccessToken(appId, appKey));
log.info("银联账单订单退款查询返回数据, refundOrderCode: {}, resultJson: {}", billRefundOrderVO.getRefundCode(), resultJson);
// 退款状态
String refundStatus = resultJson.getStr("refundStatus");
UnionRefundStatusEnum refundStatusEnum = EnumUtils.valueOf(UnionRefundStatusEnum.class, refundStatus,
UnionRefundStatusEnum.class.getMethod("getStatus"));
switch (Objects.requireNonNull(refundStatusEnum)) {
case REFUND_SUCCESS:
// 更新订单退款状态
EduBillOrder eduBillOrder = getById(billRefundOrderVO.getOrderId());
eduBillOrder.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
eduBillOrder.setPayStatus(PayStatusEnum.REFUND_SUCCESS.getStatus());
eduBillOrder.setIsRefund(RefundStatusEnum.IS_REFUND.getStatus());
baseMapper.updateById(eduBillOrder);
// 更新退款时间
EduBillOrderRefund eduBillOrderRefund = eduBillOrderRefundService.getById(billRefundOrderVO.getRefundId());
eduBillOrderRefund.setRefundTime(LocalDateTimeUtil.parse((String) resultJson.get("responseTimestamp"), DatePattern.NORM_DATETIME_PATTERN));
eduBillOrderRefundService.updateById(eduBillOrderRefund);
break;
case REFUND_FAIL:
// TODO 2022/6/27 需要后续处理退款失败情况
break;
default:
break;
}
} catch (Exception e) {
log.error("查询银联账单订单退款状态失败, refundOrder: {}", billRefundOrderVO, e);
}
}
@Override
public String unionPayNotify(Map<String, Object> map) {
try {
// 根据订单号查询对应的订单信息
EduBillOrder order = getOne(new LambdaQueryWrapper<>(new EduBillOrder()).eq(EduBillOrder::getOrderCode, map.get("merOrderId")));
if (Objects.isNull(order)) {
log.error("银联支付回调, 未找到订单信息, orderNO: {}", map.get("merOrderId"));
return UnionNotifyResultEnum.FAILED_STATUS.getValue();
}
// 返回的订单状态
String status = (String) map.get("status");
// 根据是否为退款信息直接返回
if (UnionTradeStateEnum.TRADE_REFUND.getStatus().equals(status)) {
log.info("银联退款回调, 暂不处理退款信息: {}", order.getOrderCode());
return UnionNotifyResultEnum.SUCCESS_STATUS.getValue();
}
// 判断支付结果是否处理
if (OrderStatusEnum.PAY_SUCCESS.getStatus().equals(order.getOrderStatus())) {
log.info("银联支付回调, 该订单已经处理: {}", order.getOrderCode());
return UnionNotifyResultEnum.SUCCESS_STATUS.getValue();
}
// 验签
boolean checkFlag = UnionPayUtil.checkSign(commonService.getUnionPayConfigByDept(order.getDeptId()), map);
if (!checkFlag) {
log.error("银联支付回调, 验签失败");
return UnionNotifyResultEnum.FAILED_STATUS.getValue();
}
// 新订单和不明确订单直接返回
if (UnionTradeStateEnum.NEW_ORDER.getStatus().equals(status)
|| UnionTradeStateEnum.UNKNOWN.getStatus().equals(status)) {
log.info("新订单和不明确订单, orderNo: {}", order.getOrderCode());
return UnionNotifyResultEnum.FAILED_STATUS.getValue();
}
// 支付时间
String payTime = (String) map.get("payTime");
// 修改订单状态
UnionTradeStateEnum tradeStateEnum = EnumUtils.valueOf(UnionTradeStateEnum.class, status,
UnionTradeStateEnum.class.getMethod("getStatus"));
switch (Objects.requireNonNull(tradeStateEnum)) {
// 支付成功
case TRADE_SUCCESS:
h5EduBillService.billOrderPaySuccess(order.getOrderCode(), LocalDateTimeUtil.parse(payTime, DatePattern.NORM_DATETIME_PATTERN));
break;
// 订单关闭
case TRADE_CLOSED:
order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
order.setPayStatus(PayStatusEnum.CANCEL.getStatus());
updateById(order);
break;
default:
break;
}
} catch (Exception e) {
log.error("处理银联支付回调数据失败", e);
return UnionNotifyResultEnum.FAILED_STATUS.getValue();
}
return UnionNotifyResultEnum.SUCCESS_STATUS.getValue();
}
@Override
public BigDecimal sumDeptPayOrderPrice(Long billId, Long deptId, Integer type) {
return baseMapper.sumDeptPayOrderPrice(billId, deptId, type);
}
}
@@ -0,0 +1,24 @@
package com.yida.data.mall.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.common.core.entity.mall.EduBillOrderStudent;
import com.yida.data.mall.mapper.EduBillOrderStudentMapper;
import com.yida.data.mall.service.EduBillOrderStudentService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* 账单订单学生详细信息 Service实现
*
* @author ZYJ
* @date 2022-03-31 14:50:42
*/
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class EduBillOrderStudentServiceImpl extends ServiceImpl
<EduBillOrderStudentMapper, EduBillOrderStudent> implements EduBillOrderStudentService {
}
@@ -0,0 +1,390 @@
package com.yida.data.mall.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.common.core.entity.CurrentUser;
import com.yida.data.common.core.entity.constant.StringConstant;
import com.yida.data.common.core.entity.mall.*;
import com.yida.data.common.core.entity.user.EduStudent;
import com.yida.data.common.core.enums.BillStatusEnum;
import com.yida.data.common.core.exception.FebsException;
import com.yida.data.common.core.utils.FebsUtil;
import com.yida.data.common.service.CommonService;
import com.yida.data.mall.dto.BillOrderSelectPageDTO;
import com.yida.data.mall.dto.BillSaveDTO;
import com.yida.data.mall.dto.BillSelectPageDTO;
import com.yida.data.mall.mapper.EduBillMapper;
import com.yida.data.mall.service.*;
import com.yida.data.mall.vo.*;
import com.yida.data.system.feign.RemoteUserService;
import com.yida.data.user.feign.RemoteStudentService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
/**
* 缴费账单表 Service实现
*
* @author ZYJ
* @date 2021-12-24 09:47:02
*/
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class EduBillServiceImpl extends ServiceImpl
<EduBillMapper, EduBill> implements EduBillService {
private final CommonService commonService;
private final RemoteUserService remoteUserService;
private final RemoteStudentService remoteStudentService;
private final EduBillItemService eduBillItemService;
private final EduBillStudentService eduBillStudentService;
private final EduBillItemSubService eduBillItemSubService;
private final EduBillOrderService eduBillOrderService;
private final EduBillOrderItemService eduBillOrderItemService;
private final EduBillOrderItemSubService eduBillOrderItemSubService;
@Lazy
@Resource
private H5EduBillService h5EduBillService;
@Override
public IPage<BillSelectPageVO> listBillPage(BillSelectPageDTO billSelectPageDTO) {
// 登陆用户信息
CurrentUser currentUser = FebsUtil.getCurrentUser();
// TODO 2021/12/24 此处暂时只有学校, 后续处理其它角色类型
billSelectPageDTO.setDeptId(currentUser.getDeptId());
IPage<BillSelectPageVO> page = baseMapper.listBillPage(billSelectPageDTO.toPage(), billSelectPageDTO);
// 查询学生id信息
EduStudent eduStudent = new EduStudent();
eduStudent.setSchoolId(currentUser.getDeptId());
List<Long> studentIds = remoteStudentService.listBaseStudentIds(eduStudent).getData();
page.getRecords().forEach(billSelectPageVO -> {
// 查询部门数据
billSelectPageVO.setDeptName(commonService.getDept(billSelectPageVO.getDeptId()).getDeptName());
// 创建人
billSelectPageVO.setCreateName(remoteUserService.getInfoById(billSelectPageVO.getCreateId()).getData().getNickname());
// 账单总人数
long totalNumber = CollUtil.isNotEmpty(studentIds) ? eduBillStudentService.count(new LambdaQueryWrapper<>(new EduBillStudent())
.eq(EduBillStudent::getBillId, billSelectPageVO.getId())
.in(EduBillStudent::getStudentId, studentIds)) : 0;
billSelectPageVO.setTotalNumber(totalNumber);
// 缴费人数 缴费金额大于0
if (totalNumber > 0) {
billSelectPageVO.setPayNumber(eduBillOrderService.sumPayStudentNumber(billSelectPageVO.getId()));
}
});
return page;
}
@Override
public BillInfoVO getBillInfo(Long billId) {
EduBill eduBill = getById(billId);
BillInfoVO billInfoVO = new BillInfoVO();
Optional.ofNullable(eduBill).ifPresent(bill -> {
BeanUtils.copyProperties(eduBill, billInfoVO);
// 学校名称
billInfoVO.setDeptName(commonService.getDept(bill.getDeptId()).getDeptName());
// 创建人
billInfoVO.setCreateName(remoteUserService.getInfoById(bill.getCreateId()).getData().getNickname());
// 查询缴费项目信息
List<EduBillItem> itemList = eduBillItemService.list(
new LambdaQueryWrapper<>(new EduBillItem()).eq(EduBillItem::getBillId, billId)
.orderByAsc(EduBillItem::getId));
billInfoVO.setItemList(itemList.stream().map(eduBillItem -> {
BillItemInfoVO billItemInfoVO = new BillItemInfoVO();
BeanUtils.copyProperties(eduBillItem, billItemInfoVO);
// 判断家庭类型
if (StringUtils.isNotBlank(eduBillItem.getFamilyType())) {
billItemInfoVO.setFamilyType(eduBillItem.getFamilyType().split(","));
} else {
billItemInfoVO.setFamilyType(new String[]{});
}
// 查询选项数据
List<EduBillItemSub> subItemList = eduBillItemSubService.list(
new LambdaQueryWrapper<>(new EduBillItemSub()).eq(EduBillItemSub::getItemId, eduBillItem.getId())
.orderByAsc(EduBillItemSub::getId));
billItemInfoVO.setSubItemList(subItemList.stream().map(subItem -> {
BillSubItemInfoVO billSubItemInfoVO = new BillSubItemInfoVO();
BeanUtils.copyProperties(subItem, billSubItemInfoVO);
return billSubItemInfoVO;
}).collect(Collectors.toList()));
return billItemInfoVO;
}).collect(Collectors.toList()));
// 查询学生信息
EduStudent eduStudent = new EduStudent();
eduStudent.setSchoolId(FebsUtil.getDeptId());
List<EduStudent> studentList = remoteStudentService.listBaseStudent(eduStudent).getData();
// 学生id
List<Long> studentIdList = studentList.stream().map(EduStudent::getId).collect(Collectors.toList());
// 学生分组
Map<Long, List<EduStudent>> studentMap = studentList.stream().collect(Collectors.groupingBy(EduStudent::getId));
// 查询账单学生
List<EduBillStudent> billStudentList = eduBillStudentService.list(
new LambdaQueryWrapper<>(new EduBillStudent())
.eq(EduBillStudent::getBillId, billId)
.in(EduBillStudent::getStudentId, studentIdList)
);
billInfoVO.setAchieveList(billStudentList.stream().map(eduBillStudent -> {
BillStudentInfoVO billStudentInfoVO = new BillStudentInfoVO();
// 匹配学生信息
EduStudent student = studentMap.get(eduBillStudent.getStudentId()).get(0);
BeanUtils.copyProperties(student, billStudentInfoVO);
// 设置选中信息
billStudentInfoVO.setDeptId(eduBillStudent.getDeptId());
billStudentInfoVO.setDeptName(eduBillStudent.getDeptName());
billStudentInfoVO.setStudentName(eduBillStudent.getStudentName());
// 判断是否禁用
boolean disabled = !(Objects.isNull(bill.getBillStartDate()) || bill.getBillStartDate().isAfter(LocalDateTime.now()));
billStudentInfoVO.setDisabled(disabled);
// 设置学生信息
billStudentInfoVO.setStudentId(student.getId());
billStudentInfoVO.setBillStudentId(eduBillStudent.getId());
return billStudentInfoVO;
}).collect(Collectors.toList()));
});
return billInfoVO;
}
@Override
public void saveBill(BillSaveDTO billSaveDTO) {
// log.info("保存缴费单数据: {}", billSaveDTO);
EduBill eduBill = new EduBill();
BeanUtils.copyProperties(billSaveDTO, eduBill);
CurrentUser currentUser = FebsUtil.getCurrentUser();
// TODO 2021/12/29 此处暂时只有学校, 后续处理其它角色类型
eduBill.setDeptId(currentUser.getDeptId());
if (Objects.nonNull(eduBill.getBillStartDate())
&& Objects.nonNull(eduBill.getBillEndDate())
&& eduBill.getBillEndDate().isBefore(eduBill.getBillStartDate())) {
throw new FebsException("缴费单结束时间应大于开始时间");
}
// 开始时间大于当前时间, 删除对应的缴费学生列表数据和缴费项目数据
if (Objects.nonNull(billSaveDTO.getId())
&& (Objects.isNull(billSaveDTO.getOldBillStartDate())
|| billSaveDTO.getOldBillStartDate().isAfter(LocalDateTime.now()))) {
// 删除对应的缴费项目选项数据
List<Long> itemIdList = eduBillItemService.list(
new LambdaQueryWrapper<>(new EduBillItem()).eq(EduBillItem::getBillId, billSaveDTO.getId()))
.stream().map(EduBillItem::getId).collect(Collectors.toList());
eduBillItemSubService.remove(
new LambdaQueryWrapper<>(new EduBillItemSub()).in(EduBillItemSub::getItemId, itemIdList));
// 删除对应的缴费项目数据
eduBillItemService.remove(
new LambdaQueryWrapper<>(new EduBillItem()).eq(EduBillItem::getBillId, billSaveDTO.getId()));
// 删除对应的缴费学生列表数据
eduBillStudentService.remove(
new LambdaQueryWrapper<>(new EduBillStudent()).eq(EduBillStudent::getBillId, billSaveDTO.getId()));
}
saveOrUpdate(eduBill);
boolean flag = Objects.isNull(billSaveDTO.getId()) ||
(Objects.nonNull(billSaveDTO.getId()) &&
(Objects.isNull(billSaveDTO.getOldBillStartDate())
|| billSaveDTO.getOldBillStartDate().isAfter(LocalDateTime.now())));
List<EduBillItem> saveItemList = new ArrayList<>();
if (flag) {
// 保存对应的缴费项目数据
billSaveDTO.getItemList().forEach(billItemSaveDTO -> {
EduBillItem eduBillItem = new EduBillItem();
BeanUtils.copyProperties(billItemSaveDTO, eduBillItem);
eduBillItem.setId(null);
eduBillItem.setBillId(eduBill.getId());
if (ArrayUtil.isNotEmpty(billItemSaveDTO.getFamilyType())) {
eduBillItem.setFamilyType(ArrayUtil.join(billItemSaveDTO.getFamilyType(), ","));
}
// 添加子选项
if (CollUtil.isNotEmpty(billItemSaveDTO.getSubItemList())) {
List<EduBillItemSub> subItemList = new ArrayList<>();
billItemSaveDTO.getSubItemList().forEach(billSubItemSaveDTO -> {
EduBillItemSub eduBillItemSub =
EduBillItemSub.builder()
.billId(eduBill.getId())
.subItemName(billSubItemSaveDTO.getSubItemName())
.subItemPrice(billSubItemSaveDTO.getSubItemPrice())
.build();
subItemList.add(eduBillItemSub);
});
eduBillItem.setSubItemList(subItemList);
}
saveItemList.add(eduBillItem);
});
// 保存对应的缴费学生列表数据
List<EduBillStudent> saveStudentList = new ArrayList<>();
billSaveDTO.getAchieveList().forEach(billChooseStudentDTO -> {
EduBillStudent eduBillStudent = new EduBillStudent();
BeanUtils.copyProperties(billChooseStudentDTO, eduBillStudent);
eduBillStudent.setBillId(eduBill.getId());
saveStudentList.add(eduBillStudent);
});
if (CollUtil.isNotEmpty(saveStudentList)) {
eduBillStudentService.saveBatch(saveStudentList);
}
} else {
// 修改是否必选
billSaveDTO.getItemList().forEach(billItemSaveDTO -> {
EduBillItem eduBillItem = new EduBillItem();
eduBillItem.setId(billItemSaveDTO.getId());
eduBillItem.setMustPay(billItemSaveDTO.getMustPay());
saveItemList.add(eduBillItem);
});
}
if (CollUtil.isNotEmpty(saveItemList)) {
saveItemList.forEach(eduBillItem -> {
eduBillItemService.saveOrUpdate(eduBillItem);
if (CollUtil.isNotEmpty(eduBillItem.getSubItemList())) {
// 添加子选项
eduBillItem.getSubItemList().forEach(itemSub -> itemSub.setItemId(eduBillItem.getId()));
eduBillItemSubService.saveOrUpdateBatch(eduBillItem.getSubItemList());
}
});
}
// TODO 2021/12/30 开始时间定时发送通知给家长
}
@Override
public void updateBillEnableStatus(Long billId, Integer enableStatus) {
EduBill eduBill = new EduBill();
eduBill.setId(billId);
eduBill.setEnableStatus(enableStatus);
eduBill.setLastEnableDate(LocalDateTime.now());
saveOrUpdate(eduBill);
}
@Override
public void deleteBill(Long billId) {
// 判断能否删除
EduBill bill = getById(billId);
if (Objects.nonNull(bill)) {
if (BillStatusEnum.ENABLE_STATUS.getStatus().equals(bill.getEnableStatus())) {
throw new FebsException("当前账单已启用, 无法删除!");
}
if (Objects.isNull(bill.getBillStartDate()) ||
Objects.nonNull(bill.getBillStartDate()) && bill.getBillStartDate().isAfter(LocalDateTime.now())) {
// 删除项目子选项
eduBillItemSubService.remove(
new LambdaQueryWrapper<>(new EduBillItemSub()).eq(EduBillItemSub::getBillId, billId));
// 删除对应的缴费项目数据
eduBillItemService.remove(
new LambdaQueryWrapper<>(new EduBillItem()).eq(EduBillItem::getBillId, billId));
// 删除对应的缴费学生列表数据
eduBillStudentService.remove(
new LambdaQueryWrapper<>(new EduBillStudent()).eq(EduBillStudent::getBillId, billId));
// 删除账单
removeById(billId);
} else {
throw new FebsException("当前账单无法删除");
}
}
}
@Override
public List<BillItemInfoVO> listBillPayDetailTableCol(Long billId) {
// 查询缴费项目信息
List<EduBillItem> itemList = eduBillItemService.list(
new LambdaQueryWrapper<>(new EduBillItem()).eq(EduBillItem::getBillId, billId)
.orderByAsc(EduBillItem::getId));
List<BillItemInfoVO> list;
if (CollUtil.isNotEmpty(itemList)) {
list = itemList.stream().map(eduBillItem -> {
BillItemInfoVO billItemInfoVO = new BillItemInfoVO();
BeanUtils.copyProperties(eduBillItem, billItemInfoVO);
// 查询子选项数据
List<EduBillItemSub> subItemList = eduBillItemSubService.list(
new LambdaQueryWrapper<>(new EduBillItemSub())
.eq(EduBillItemSub::getItemId, eduBillItem.getId()));
billItemInfoVO.setSubItemList(subItemList.stream().map(subItem -> {
BillSubItemInfoVO billSubItemInfoVO = new BillSubItemInfoVO();
BeanUtils.copyProperties(subItem, billSubItemInfoVO);
return billSubItemInfoVO;
}).collect(Collectors.toList()));
return billItemInfoVO;
}).collect(Collectors.toList());
} else {
list = new ArrayList<>();
}
return list;
}
@Override
public IPage<BillOrderSelectPageVO> listBillOrderPage(BillOrderSelectPageDTO dto) {
// 登陆用户信息
CurrentUser currentUser = FebsUtil.getCurrentUser();
// TODO 2022/6/29 此处暂时只有学校, 后续处理其它角色类型
dto.setSchoolId(currentUser.getDeptId());
Page<BillOrderSelectPageVO> page = Page.of(dto.getPageNum(), dto.getPageSize());
// 查询账单人员列表
List<BillOrderSelectPageVO> list = baseMapper.listBillOrderPage(page, dto, new ArrayList<>());
if (CollUtil.isNotEmpty(list)) {
list.forEach(vo -> {
final String[] result = {""};
// 查询缴费项目信息
List<EduBillOrderItem> orderItemList = eduBillOrderItemService.list(
new LambdaQueryWrapper<>(new EduBillOrderItem())
.eq(EduBillOrderItem::getOrderId, vo.getOrderId()));
// 查询子选项信息
orderItemList.forEach(item -> {
List<EduBillOrderItemSub> itemSubList = eduBillOrderItemSubService.list(
new LambdaQueryWrapper<>(new EduBillOrderItemSub())
.eq(EduBillOrderItemSub::getOrderItemId, item.getId()));
// 有子选项
if (CollUtil.isNotEmpty(itemSubList)) {
String collect = itemSubList.stream()
.map(EduBillOrderItemSub::getSubItemName)
.collect(Collectors.joining(","));
result[0] += item.getItemName() + "(" + collect + ")" + StringConstant.COMMA;
} else {
// 没有子选项
result[0] += item.getItemName() + StringConstant.COMMA;
}
});
if (StringUtils.isNotBlank(result[0])) {
vo.setItems(StrUtil.removeSuffix(result[0], StringConstant.COMMA));
}
});
}
page.setRecords(list);
return page;
}
@Override
public void refundOrder(String orderCode) {
h5EduBillService.refundOrder(orderCode);
}
@Override
public List<EduBill> listBill(Integer type) {
return list(Wrappers.lambdaQuery(new EduBill())
.eq(EduBill::getDeptId, FebsUtil.getTopDeptId())
.lt(type == 1, EduBill::getBillStartDate, LocalDateTime.now()));
}
}
@@ -0,0 +1,621 @@
package com.yida.data.mall.service.impl;
import cc.mrbird.febs.common.redis.service.RedisService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yida.data.common.core.entity.Dict;
import com.yida.data.common.core.entity.constant.CachePrefixConstant;
import com.yida.data.common.core.entity.constant.StringConstant;
import com.yida.data.common.core.entity.mall.EduBill;
import com.yida.data.common.core.entity.mall.EduBillStudent;
import com.yida.data.common.core.entity.user.EduStudent;
import com.yida.data.common.core.entity.user.EduUserDept;
import com.yida.data.common.core.entity.user.enums.UserDeptTypeEnum;
import com.yida.data.common.core.enums.DictType;
import com.yida.data.common.core.utils.FileUtil;
import com.yida.data.common.service.CommonService;
import com.yida.data.mall.dto.BillStudentSelectPageDTO;
import com.yida.data.mall.dto.ExportBillStatisticsDTO;
import com.yida.data.mall.mapper.EduBillMapper;
import com.yida.data.mall.mapper.EduBillStatisticsMapper;
import com.yida.data.mall.mapper.EduBillStudentMapper;
import com.yida.data.mall.service.*;
import com.yida.data.mall.vo.*;
import com.yida.data.system.feign.RemoteCommonService;
import com.yida.data.user.feign.RemoteStudentService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.File;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* 缴费账单统计
*
* @author ZYJ
* @date 2022/7/7
*/
@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class EduBillStatisticsServiceImpl implements EduBillStatisticsService {
private final EduBillService eduBillService;
private final EduBillOrderService eduBillOrderService;
private final EduBillStudentService eduBillStudentService;
private final EduBillOrderItemService eduBillOrderItemService;
private final EduBillMapper eduBillMapper;
private final EduBillStudentMapper eduBillStudentMapper;
private final EduBillStatisticsMapper eduBillStatisticsMapper;
private final RemoteCommonService remoteCommonService;
private final RemoteStudentService remoteStudentService;
private final CommonService commonService;
private final RedisService redisService;
@Value("${febs.uploadUrl}")
private String uploadUrl;
private static final ExecutorService BILL_STATISTICS_POOL = new ThreadPoolExecutor(5, 10, 1,
TimeUnit.MINUTES, new LinkedBlockingQueue<>(),
ThreadUtil.newNamedThreadFactory("bill-statistics-pool-%d", false));
@Override
public List<Map<String, Object>> billStatistics(Long billId) {
List<Map<String, Object>> resultList = new ArrayList<>();
String result = (String) redisService.get(CachePrefixConstant.BILL_STATISTICS_DATA + billId);
JSONArray jsonArray = JSONUtil.parseArray(result);
for (Object object : jsonArray) {
// 取出list里面的值转为map
Map<String, Object> ret = (Map<String, Object>) object;
resultList.add(ret);
}
return resultList;
}
@Override
public String exportBillStatistics(ExportBillStatisticsDTO dto) {
return (String) redisService.get(CachePrefixConstant.BILL_STATISTICS_EXPORT_URL + dto.getBillId());
}
@Override
public void updateBillStatistics() {
// 查询已开始未结束的账单
List<EduBill> billList = eduBillMapper.selectNeedStatisticsBill();
if (CollUtil.isNotEmpty(billList)) {
billList.forEach(eduBill -> {
// 更新账单缴费统计数据
BILL_STATISTICS_POOL.execute(() -> updateBillStatistics(eduBill));
// 更新账单导出excel缓存
BILL_STATISTICS_POOL.execute(() -> updateExportBillStatistics(ExportBillStatisticsDTO.builder().billId(eduBill.getId()).build()));
});
}
}
@Override
public void updateBillPayDetail(Long billId) {
List<EduBill> billList = new ArrayList<>();
if (Objects.isNull(billId)) {
// 查询已开始未结束的账单
billList = eduBillMapper.selectNeedStatisticsBill();
} else {
// 查询指定账单数据
billList.add(eduBillService.getById(billId));
}
// 查询已开始的账单
// List<EduBill> billList = eduBillMapper.selectStartBill();
if (CollUtil.isNotEmpty(billList)) {
for (EduBill eduBill : billList) {
String fileName = FileUtil.getLocalUploadAddress() + UUID.randomUUID() + ".xls";
File file = null;
try {
// 查询学生列表
EduStudent eduStudent = new EduStudent();
eduStudent.setSchoolId(eduBill.getDeptId());
List<EduStudent> studentList = remoteStudentService.listBaseStudent(eduStudent).getData();
// 导出人员列表数据
List<List<String>> exportDataList = new ArrayList<>();
if (CollUtil.isNotEmpty(studentList)) {
// 学生分组
Map<Long, List<EduStudent>> studentMap = studentList.stream().collect(
Collectors.groupingBy(EduStudent::getId));
// 查询账单人员列表
List<BillStudentInfoVO> list = eduBillStudentMapper.listBillUserPage(null,
BillStudentSelectPageDTO.builder()
.billId(eduBill.getId())
.build(),
studentList);
// 查询家庭类型
List<Dict> familyTypeList = remoteCommonService.getDict(DictType.FAMILY_TYPE.getValue()).getData();
list.forEach(billStudentInfoVO -> {
// 匹配学生信息
EduStudent student = studentMap.get(billStudentInfoVO.getStudentId()).get(0);
// 查询学生具体缴费金额
List<BillPayVO> payList = eduBillOrderItemService.listItemPayInfo(eduBill.getId(), student.getId());
List<String> price = payList.stream().map(billPayVO -> {
BillPayPriceVO billPayPriceVO = billPayVO.getBillPayPriceVO();
if (Objects.isNull(billPayPriceVO) || Objects.isNull(billPayPriceVO.getItemPrice())) {
return "";
}
BigDecimal returnPrice = NumberUtil.sub(billPayPriceVO.getItemPrice(), billPayPriceVO.getReductionPrice());
return Objects.isNull(returnPrice) ? "" : returnPrice.toString();
}).collect(Collectors.toList());
// 查询总金额数据
BigDecimal payOrderPrice = eduBillOrderService.sumPayOrderPrice(eduBill.getId(), student.getId());
// 封装每一行数据
ArrayList<String> singleList = CollUtil.newArrayList(student.getStuName(),
student.getCampusName(), student.getGradeName(),
student.getClassName(), student.getStuNumber(),
handelStudentType(student.getType()),
handleFamilyType(student.getFamilyType(), familyTypeList));
singleList.addAll(price);
singleList.add(Objects.isNull(payOrderPrice) ? "" : payOrderPrice.toString());
// 添加excel数据
exportDataList.add(singleList);
});
}
file = new File(fileName);
// 导出数据
EasyExcel.write(file)
.excelType(ExcelTypeEnum.XLS)
// 这里放入动态头
.head(getDetailExportHead(eduBill.getId())).sheet("缴费明细")
// 当然这里数据也可以用 List<List<String>> 去传入
.doWrite(exportDataList);
// 上传文件到媒资
String fileUrl = FileUtil.uploadFileToMediaServer(uploadUrl, file);
redisService.set(CachePrefixConstant.BILL_PAY_DETAIL_EXPORT_URL + eduBill.getId(), fileUrl);
} catch (Exception e) {
log.error("更新导出缴费明细数据错误, billId: {}", eduBill.getId(), e);
} finally {
if (Objects.nonNull(file)) {
cn.hutool.core.io.FileUtil.del(file);
}
}
}
}
}
/**
* 生成缴费账单动态表头数据
*
* @param billId 账单id
* @return java.util.List<java.util.List < java.lang.String>>
* @author ZYJ
* @date 2022/4/19 16:06
*/
private List<List<String>> getDetailExportHead(Long billId) {
// 表头list的生成,实际的表头信息可以从数据库或者缓存等处动态读取
List<List<String>> allColList = new ArrayList<>();
// 姓名表头
allColList.add(CollUtil.newArrayList("姓名"));
// 校区表头
allColList.add(CollUtil.newArrayList("校区"));
// 年级表头
allColList.add(CollUtil.newArrayList("年级"));
// 班级表头
allColList.add(CollUtil.newArrayList("班级"));
// 学号表头
allColList.add(CollUtil.newArrayList("学号"));
// 学生类型表头
allColList.add(CollUtil.newArrayList("学生类型"));
// 家庭类型表头
allColList.add(CollUtil.newArrayList("家庭类型"));
// 项目动态表头
List<BillItemInfoVO> colList = eduBillService.listBillPayDetailTableCol(billId);
colList.forEach(item -> {
if (CollUtil.isNotEmpty(item.getSubItemList())) {
item.getSubItemList().forEach(subItem -> allColList.add(CollUtil.newArrayList("缴费项目", item.getItemName(), subItem.getSubItemName())));
} else {
allColList.add(CollUtil.newArrayList("缴费项目", item.getItemName()));
}
});
// 总金额表头
allColList.add(CollUtil.newArrayList("总金额"));
return allColList;
}
/**
* 转换学生类别
*
* @param studentType 学生类别,0-走读,1-住宿
* @return java.lang.String
* @author ZYJ
* @date 2022/4/19 16:19
*/
private String handelStudentType(Integer studentType) {
if (Objects.nonNull(studentType)) {
return studentType.equals(0) ? "走读" : "住宿";
} else {
return "";
}
}
/**
* 转换家庭类型
*
* @param familyType 学生家庭类型
* @param familyTypeList 家庭类型字典
* @return java.lang.String
* @author ZYJ
* @date 2022/4/19 16:21
*/
private String handleFamilyType(String familyType, List<Dict> familyTypeList) {
if (StringUtils.isNotBlank(familyType)) {
List<String> list = new ArrayList<>();
for (Dict dict : familyTypeList) {
if (familyType.contains(dict.getValue())) {
list.add(dict.getLabel());
}
}
return String.join(StringConstant.COMMA, list);
} else {
return "";
}
}
/**
* 更新账单缴费统计数据
*
* @param eduBill 账单信息
* @author ZYJ
* @date 2022/7/28 17:48
*/
private void updateBillStatistics(EduBill eduBill) {
Long billId = eduBill.getId();
try {
// 返回数据
List<Map<String, Object>> result = new ArrayList<>();
// 统计全校总数
Map<String, Object> total = new HashMap<>(16);
// 部门名称
total.put("deptId", "all");
total.put("deptName", "全校");
// 缴费总金额
BigDecimal totalMoney = eduBillOrderService.sumPayOrderPrice(billId, null);
total.put("payMoney", String.valueOf(totalMoney));
// 缴费单总人数
Long totalCount = eduBillStudentService.count(Wrappers.lambdaQuery(new EduBillStudent()).eq(EduBillStudent::getBillId, billId));
total.put("totalCount", String.valueOf(totalCount));
// 缴费项目统计
if (Objects.nonNull(totalMoney)) {
// 查询账单总缴费信息
List<BillStatisticsItemVO> payInfo = eduBillStatisticsMapper.getPayInfo(billId);
payInfo.forEach(item -> {
String itemPayName = "i" + item.getItemId() + item.getItemName();
if (CollUtil.isNotEmpty(item.getSubItemList())) {
item.getSubItemList().forEach(subItem -> {
// 选项金额拼接方式为 i+项目id+项目名称+s+选项id+选项名称
total.put(itemPayName + "s" + subItem.getSubItemId() + subItem.getSubItemName(),
NumberUtil.sub(subItem.getSubItemPrice(), item.getReductionPrice()).toString());
// 选项缴费人数拼接方式为 i+项目id+项目名称+s+选项id+选项名称+n
total.put(itemPayName + "s" + subItem.getSubItemId() + subItem.getSubItemName() + "n",
String.valueOf(subItem.getPayNum()));
});
} else {
// 项目金额拼接方式为 i+项目id+项目名称
total.put(itemPayName, NumberUtil.sub(item.getItemPrice(), item.getReductionPrice()).toString());
// 项目人数拼接方式为 i+项目id+项目名称+n
total.put(itemPayName + "n", String.valueOf(item.getPayNum()));
}
});
}
result.add(total);
// 查询年级信息
List<EduUserDept> gradeList = commonService.findChildIdByParentAndType(-eduBill.getDeptId(), UserDeptTypeEnum.GRADE_TYPE.getValue());
if (CollUtil.isNotEmpty(gradeList)) {
gradeList.forEach(gradeDept -> {
Map<String, Object> gradeMap = new HashMap<>(16);
gradeMap.put("deptId", gradeDept.getDeptId());
gradeMap.put("deptType", UserDeptTypeEnum.GRADE_TYPE.getValue());
// 查询班级信息
List<EduUserDept> classList = commonService.findChildIdByParentAndType(gradeDept.getDeptId(), UserDeptTypeEnum.CLASS_TYPE.getValue());
// 年级缴费总金额
BigDecimal gradeTotalMoney = eduBillOrderService.sumDeptPayOrderPrice(billId, gradeDept.getDeptId(), UserDeptTypeEnum.GRADE_TYPE.getValue());
gradeMap.put("payMoney", String.valueOf(gradeTotalMoney));
// 年级总缴费人数
gradeMap.put("totalCount", String.valueOf(eduBillStudentService.count(
Wrappers.lambdaQuery(new EduBillStudent())
.eq(EduBillStudent::getBillId, billId)
.in(EduBillStudent::getDeptId, classList.stream().map(EduUserDept::getDeptId).collect(Collectors.toList()))
)));
// 账单年级缴费信息统计
List<BillStatisticsItemVO> gradePayInfo = eduBillStatisticsMapper.getDeptPayInfo(billId, gradeDept.getDeptId(), UserDeptTypeEnum.GRADE_TYPE.getValue());
if (CollUtil.isEmpty(gradePayInfo)) {
gradeMap.put("deptName", gradeDept.getDeptName());
}
gradePayInfo.forEach(item -> {
if (!gradeMap.containsKey("deptName")) {
gradeMap.put("deptName", item.getDeptName());
}
String itemPayName = "i" + item.getItemId() + item.getItemName();
if (CollUtil.isNotEmpty(item.getSubItemList())) {
item.getSubItemList().forEach(subItem -> {
// 选项金额拼接方式为 i+项目id+项目名称+s+选项id+选项名称
gradeMap.put(itemPayName + "s" + subItem.getSubItemId() + subItem.getSubItemName(),
NumberUtil.sub(subItem.getSubItemPrice(), item.getReductionPrice()).toString());
// 选项缴费人数拼接方式为 i+项目id+项目名称+s+选项id+选项名称+n
gradeMap.put(itemPayName + "s" + subItem.getSubItemId() + subItem.getSubItemName() + "n",
String.valueOf(subItem.getPayNum()));
});
} else {
// 项目金额拼接方式为 i+项目id+项目名称
gradeMap.put(itemPayName, NumberUtil.sub(item.getItemPrice(), item.getReductionPrice()).toString());
// 项目人数拼接方式为 i+项目id+项目名称+n
gradeMap.put(itemPayName + "n", String.valueOf(item.getPayNum()));
}
});
List<Map<String, Object>> children = new ArrayList<>();
if (CollUtil.isNotEmpty(classList)) {
classList.forEach(classDept -> {
// 班级缴费信息
Map<String, Object> classMap = new HashMap<>(16);
classMap.put("deptId", classDept.getDeptId());
classMap.put("deptType", UserDeptTypeEnum.CLASS_TYPE.getValue());
// 班级缴费总金额
BigDecimal classTotalMoney = eduBillOrderService.sumDeptPayOrderPrice(billId, classDept.getDeptId(), UserDeptTypeEnum.CLASS_TYPE.getValue());
classMap.put("payMoney", String.valueOf(classTotalMoney));
// 班级总缴费人数
classMap.put("totalCount", String.valueOf(eduBillStudentService.count(
Wrappers.lambdaQuery(new EduBillStudent())
.eq(EduBillStudent::getBillId, billId)
.eq(EduBillStudent::getDeptId, classDept.getDeptId())
)));
// 账单班级缴费信息统计
List<BillStatisticsItemVO> classPayInfo = eduBillStatisticsMapper.getDeptPayInfo(billId, classDept.getDeptId(), UserDeptTypeEnum.CLASS_TYPE.getValue());
if (CollUtil.isEmpty(classPayInfo)) {
classMap.put("deptName", classDept.getDeptName());
}
classPayInfo.forEach(item -> {
if (!classMap.containsKey("deptName")) {
classMap.put("deptName", item.getDeptName());
}
String itemPayName = "i" + item.getItemId() + item.getItemName();
if (CollUtil.isNotEmpty(item.getSubItemList())) {
item.getSubItemList().forEach(subItem -> {
// 选项金额拼接方式为 i+项目id+项目名称+s+选项id+选项名称
classMap.put(itemPayName + "s" + subItem.getSubItemId() + subItem.getSubItemName(),
NumberUtil.sub(subItem.getSubItemPrice(), item.getReductionPrice()).toString());
// 选项缴费人数拼接方式为 i+项目id+项目名称+s+选项id+选项名称+n
classMap.put(itemPayName + "s" + subItem.getSubItemId() + subItem.getSubItemName() + "n",
String.valueOf(subItem.getPayNum()));
});
} else {
// 项目金额拼接方式为 i+项目id+项目名称
classMap.put(itemPayName, NumberUtil.sub(item.getItemPrice(), item.getReductionPrice()).toString());
// 项目人数拼接方式为 i+项目id+项目名称+n
classMap.put(itemPayName + "n", String.valueOf(item.getPayNum()));
}
});
children.add(classMap);
});
}
gradeMap.put("children", children);
result.add(gradeMap);
});
}
redisService.set(CachePrefixConstant.BILL_STATISTICS_DATA + billId, JSONUtil.toJsonStr(result));
} catch (Exception e) {
log.error("更新账单缴费统计数据失败, billId: {}", billId, e);
}
}
/**
* 更新账单导出excel缓存
*
* @param dto 导出账单缴费统计数据请求类
* @author ZYJ
* @date 2022/7/28 17:45
*/
private void updateExportBillStatistics(ExportBillStatisticsDTO dto) {
String fileName = FileUtil.getLocalUploadAddress() + UUID.randomUUID() + ".xls";
File file = null;
try {
// 账单信息
EduBill eduBill = eduBillService.getById(dto.getBillId());
// 导出数据总集合
List<List<String>> exportDataList = new ArrayList<>();
// 缴费单总人数
Long totalCount = eduBillStudentService.count(Wrappers.lambdaQuery(new EduBillStudent()).eq(EduBillStudent::getBillId, dto.getBillId()));
// 处理缴费信息
List<BillPayVO> payList = eduBillStatisticsMapper.listTotalItemPayInfo(dto.getBillId());
// 处理第一行数据
ArrayList<String> firstList = CollUtil.newArrayList("全校");
payList.forEach(billPayVO -> {
// 处理人数
firstList.add(billPayVO.getPayNum() + "/" + totalCount);
// 缴费数据
String price;
BillPayPriceVO billPayPriceVO = billPayVO.getBillPayPriceVO();
if (Objects.isNull(billPayPriceVO) || Objects.isNull(billPayPriceVO.getItemPrice())) {
price = "";
} else {
BigDecimal returnPrice = NumberUtil.sub(billPayPriceVO.getItemPrice(), billPayPriceVO.getReductionPrice());
price = Objects.isNull(returnPrice) ? "" : returnPrice.toString();
}
firstList.add(price);
});
// 缴费总金额
BigDecimal totalMoney = eduBillOrderService.sumPayOrderPrice(dto.getBillId(), null);
firstList.add(Objects.isNull(totalMoney) ? "" : totalMoney.toString());
// 添加excel数据
exportDataList.add(firstList);
// 查询年级信息
List<EduUserDept> gradeList = commonService.findChildIdByParentAndType(-eduBill.getDeptId(), UserDeptTypeEnum.GRADE_TYPE.getValue());
gradeList.forEach(gradeDept -> {
// 查询班级信息
List<EduUserDept> classList = commonService.findChildIdByParentAndType(gradeDept.getDeptId(), UserDeptTypeEnum.CLASS_TYPE.getValue());
// 年级总缴费人数
Long gradeCount = eduBillStudentService.count(Wrappers.lambdaQuery(new EduBillStudent())
.eq(EduBillStudent::getBillId, dto.getBillId())
.in(EduBillStudent::getDeptId, classList.stream().map(EduUserDept::getDeptId).collect(Collectors.toList())));
// 账单年级缴费信息统计
List<BillPayVO> gradePayList = eduBillStatisticsMapper.listDeptItemPayInfo(dto.getBillId(), gradeDept.getDeptId(), UserDeptTypeEnum.GRADE_TYPE.getValue());
// 部门名称
String gradeName = "";
if (CollUtil.isEmpty(gradePayList)) {
gradeName = gradeDept.getDeptName();
}
// 处理年级每一行数据
ArrayList<String> gradeCheckList = CollUtil.newArrayList();
for (BillPayVO deptPayInfo : gradePayList) {
if (StringUtils.isEmpty(gradeName)) {
if (Objects.nonNull(deptPayInfo.getBillPayPriceVO())) {
gradeName = deptPayInfo.getBillPayPriceVO().getDeptName();
} else {
gradeName = gradeDept.getDeptName();
}
}
// 处理人数
gradeCheckList.add(deptPayInfo.getPayNum() + "/" + gradeCount);
// 缴费数据
String price;
BillPayPriceVO gradePayPriceVO = deptPayInfo.getBillPayPriceVO();
if (Objects.isNull(gradePayPriceVO) || Objects.isNull(gradePayPriceVO.getItemPrice())) {
price = "";
} else {
BigDecimal returnPrice = NumberUtil.sub(gradePayPriceVO.getItemPrice(), gradePayPriceVO.getReductionPrice());
price = Objects.isNull(returnPrice) ? "" : returnPrice.toString();
}
gradeCheckList.add(price);
}
ArrayList<String> singleGradeList = CollUtil.newArrayList(gradeName);
singleGradeList.addAll(gradeCheckList);
// 年级缴费总金额
BigDecimal gradeTotalMoney = eduBillOrderService.sumDeptPayOrderPrice(dto.getBillId(), gradeDept.getDeptId(), UserDeptTypeEnum.GRADE_TYPE.getValue());
singleGradeList.add(Objects.isNull(gradeTotalMoney) ? "" : gradeTotalMoney.toString());
// 添加excel数据
exportDataList.add(singleGradeList);
// 处理班级数据
for (EduUserDept classDept : classList) {
// 班级总缴费人数
Long classCount = eduBillStudentService.count(Wrappers.lambdaQuery(new EduBillStudent())
.eq(EduBillStudent::getBillId, dto.getBillId())
.eq(EduBillStudent::getDeptId, classDept.getDeptId()));
// 账单班级缴费信息统计
List<BillPayVO> classPayList = eduBillStatisticsMapper.listDeptItemPayInfo(dto.getBillId(), classDept.getDeptId(), UserDeptTypeEnum.CLASS_TYPE.getValue());
// 部门名称
String className = "";
if (CollUtil.isEmpty(classPayList)) {
className = classDept.getDeptName();
}
// 处理班级每一行数据
ArrayList<String> classCheckList = CollUtil.newArrayList();
for (BillPayVO classPayInfo : classPayList) {
if (StringUtils.isEmpty(className)) {
if (Objects.nonNull(classPayInfo.getBillPayPriceVO())) {
className = classPayInfo.getBillPayPriceVO().getDeptName();
} else {
className = classDept.getDeptName();
}
}
// 处理人数
classCheckList.add(classPayInfo.getPayNum() + "/" + classCount);
// 缴费数据
String price;
BillPayPriceVO classPayPriceVO = classPayInfo.getBillPayPriceVO();
if (Objects.isNull(classPayPriceVO) || Objects.isNull(classPayPriceVO.getItemPrice())) {
price = "";
} else {
BigDecimal returnPrice = NumberUtil.sub(classPayPriceVO.getItemPrice(), classPayPriceVO.getReductionPrice());
price = Objects.isNull(returnPrice) ? "" : returnPrice.toString();
}
classCheckList.add(price);
}
ArrayList<String> singleClassList = CollUtil.newArrayList(className);
singleClassList.addAll(classCheckList);
// 年级缴费总金额
BigDecimal classTotalMoney = eduBillOrderService.sumDeptPayOrderPrice(dto.getBillId(), classDept.getDeptId(), UserDeptTypeEnum.CLASS_TYPE.getValue());
singleClassList.add(Objects.isNull(classTotalMoney) ? "" : classTotalMoney.toString());
// 添加excel数据
exportDataList.add(singleClassList);
}
});
file = new File(fileName);
// 导出数据
EasyExcel.write(file)
.excelType(ExcelTypeEnum.XLS)
// 这里放入动态头
.head(getExportHead(eduBill)).sheet("缴费统计")
// 当然这里数据也可以用 List<List<String>> 去传入
.doWrite(exportDataList);
// 上传文件到媒资
String fileUrl = FileUtil.uploadFileToMediaServer(uploadUrl, file);
redisService.set(CachePrefixConstant.BILL_STATISTICS_EXPORT_URL + dto.getBillId(), fileUrl);
} catch (Exception e) {
log.error("更新导出缴费统计数据错误, billId: {}", dto.getBillId(), e);
} finally {
if (Objects.nonNull(file)) {
cn.hutool.core.io.FileUtil.del(file);
}
}
}
/**
* 生成缴费账单统计动态表头数据
*
* @param bill 账单信息
* @return java.util.List<java.util.List < java.lang.String>>
* @author ZYJ
* @date 2022/7/12 10:08
*/
private List<List<String>> getExportHead(EduBill bill) {
// 表头list的生成,实际的表头信息可以从数据库或者缓存等处动态读取
List<List<String>> allColList = new ArrayList<>();
// 部门名称表头
allColList.add(CollUtil.newArrayList(commonService.getDept(bill.getDeptId()).getDeptName()));
// 项目动态表头
List<BillItemInfoVO> colList = eduBillService.listBillPayDetailTableCol(bill.getId());
colList.forEach(item -> {
if (CollUtil.isNotEmpty(item.getSubItemList())) {
item.getSubItemList().forEach(subItem -> {
allColList.add(CollUtil.newArrayList("缴费项目", item.getItemName(), subItem.getSubItemName(), "缴费人数"));
allColList.add(CollUtil.newArrayList("缴费项目", item.getItemName(), subItem.getSubItemName(), "缴费金额"));
});
} else {
allColList.add(CollUtil.newArrayList("缴费项目", item.getItemName(), "缴费人数"));
allColList.add(CollUtil.newArrayList("缴费项目", item.getItemName(), "缴费金额"));
}
});
// 总金额表头
allColList.add(CollUtil.newArrayList("总金额"));
return allColList;
}
}
@@ -0,0 +1,366 @@
package com.yida.data.mall.service.impl;
import cc.mrbird.febs.common.redis.service.RedisService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yida.data.common.core.entity.Dict;
import com.yida.data.common.core.entity.constant.CachePrefixConstant;
import com.yida.data.common.core.entity.constant.StringConstant;
import com.yida.data.common.core.entity.mall.EduBill;
import com.yida.data.common.core.entity.mall.EduBillOrder;
import com.yida.data.common.core.entity.mall.EduBillStudent;
import com.yida.data.common.core.entity.user.EduStudent;
import com.yida.data.common.core.enums.OrderStatusEnum;
import com.yida.data.common.core.exception.FebsException;
import com.yida.data.common.core.utils.FebsUtil;
import com.yida.data.mall.dto.BillStudentSelectPageDTO;
import com.yida.data.mall.dto.BillUserSaveDTO;
import com.yida.data.mall.mapper.EduBillMapper;
import com.yida.data.mall.mapper.EduBillStudentMapper;
import com.yida.data.mall.service.EduBillOrderItemService;
import com.yida.data.mall.service.EduBillOrderService;
import com.yida.data.mall.service.EduBillService;
import com.yida.data.mall.service.EduBillStudentService;
import com.yida.data.mall.vo.BillItemInfoVO;
import com.yida.data.mall.vo.BillStudentInfoVO;
import com.yida.data.mall.vo.h5.H5BillItemVO;
import com.yida.data.system.feign.RemoteCommonService;
import com.yida.data.user.feign.RemoteStudentService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 缴费单缴费学生 Service实现
*
* @author ZYJ
* @date 2021-12-30
*/
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class EduBillStudentServiceImpl extends ServiceImpl
<EduBillStudentMapper, EduBillStudent> implements EduBillStudentService {
private final RemoteStudentService remoteStudentService;
private final RemoteCommonService remoteCommonService;
private final EduBillOrderService eduBillOrderService;
private final EduBillOrderItemService eduBillOrderItemService;
@Lazy
@Resource
private EduBillService eduBillService;
private final EduBillMapper eduBillMapper;
private final RedisService redisService;
@Override
public IPage<BillStudentInfoVO> listBillUserPage(BillStudentSelectPageDTO dto) {
// 查询学生信息
EduStudent eduStudent = new EduStudent();
BeanUtils.copyProperties(dto, eduStudent);
eduStudent.setSchoolId(FebsUtil.getDeptId());
List<EduStudent> studentList = remoteStudentService.listBaseStudent(eduStudent).getData();
Page<BillStudentInfoVO> page = Page.of(dto.getPageNum(), dto.getPageSize());
if (CollUtil.isNotEmpty(studentList)) {
// 学生分组
Map<Long, List<EduStudent>> studentMap = studentList.stream().collect(Collectors.groupingBy(EduStudent::getId));
// 查询账单人员列表
page.setRecords(baseMapper.listBillUserPage(page, dto, studentList));
EduBill bill = eduBillMapper.selectById(dto.getBillId());
page.getRecords().forEach(billStudentInfoVO -> {
// 匹配学生信息
EduStudent student = studentMap.get(billStudentInfoVO.getStudentId()).get(0);
BeanUtils.copyProperties(student, billStudentInfoVO);
// 判断是否禁用
boolean disabled = !(Objects.isNull(bill.getBillStartDate()) || bill.getBillStartDate().isAfter(LocalDateTime.now()));
billStudentInfoVO.setDisabled(disabled);
// 判断缴费金额
billStudentInfoVO.setPayMoney(eduBillOrderService.sumPayOrderPrice(dto.getBillId(), billStudentInfoVO.getStudentId()));
});
} else {
page = new Page<>();
}
return page;
}
@Override
public List<BillStudentInfoVO> listBillUser(Long billId) {
// 查询学生信息
EduStudent eduStudent = new EduStudent();
eduStudent.setSchoolId(FebsUtil.getDeptId());
List<EduStudent> studentList = remoteStudentService.listBaseStudent(eduStudent).getData();
if (CollUtil.isNotEmpty(studentList)) {
// 学生分组
Map<Long, List<EduStudent>> studentMap = studentList.stream().collect(Collectors.groupingBy(EduStudent::getId));
// 查询账单人员列表
List<BillStudentInfoVO> list = baseMapper.listBillUserPage(null,
BillStudentSelectPageDTO.builder()
.billId(billId)
.build(),
studentList);
list.forEach(billStudentInfoVO -> {
// 匹配学生信息
EduStudent student = studentMap.get(billStudentInfoVO.getStudentId()).get(0);
BeanUtils.copyProperties(student, billStudentInfoVO);
// 判断是否禁用
billStudentInfoVO.setDisabled(true);
});
return list;
} else {
return new ArrayList<>();
}
}
@Override
public void saveBillUser(BillUserSaveDTO billUserSaveDTO) {
billUserSaveDTO.getAchieveList().forEach(dto -> {
EduBillStudent eduBillStudent = new EduBillStudent();
BeanUtils.copyProperties(dto, eduBillStudent);
eduBillStudent.setBillId(billUserSaveDTO.getBillId());
this.save(eduBillStudent);
});
}
@Override
public void deleteBillUser(Long billStudentId, Long studentId, Long billId) {
// 判断是否有缴费
BigDecimal payPrice = eduBillOrderService.sumPayOrderPrice(billId, studentId);
if (Objects.nonNull(payPrice)) {
throw new FebsException("当前学生已经缴费过,无法删除!");
}
// 判断是否有未关闭订单
long count = eduBillOrderService.count(Wrappers.lambdaQuery(new EduBillOrder())
.eq(EduBillOrder::getBillId, billId)
.eq(EduBillOrder::getStudentId, studentId)
.eq(EduBillOrder::getOrderStatus, OrderStatusEnum.NOT_PAY.getStatus())
);
if (count > 0) {
throw new FebsException("当前学生有未关闭的订单,暂时无法删除!");
}
this.removeById(billStudentId);
}
@Override
public IPage<Map<String, String>> listBillPayDetailPage(BillStudentSelectPageDTO dto) {
// 查询学生信息
EduStudent eduStudent = new EduStudent();
BeanUtils.copyProperties(dto, eduStudent);
eduStudent.setSchoolId(FebsUtil.getDeptId());
List<EduStudent> studentList = remoteStudentService.listBaseStudent(eduStudent).getData();
if (CollUtil.isNotEmpty(studentList)) {
Page<BillStudentInfoVO> page = Page.of(dto.getPageNum(), dto.getPageSize());
// 学生分组
Map<Long, List<EduStudent>> studentMap = studentList.stream().collect(Collectors.groupingBy(EduStudent::getId));
// 查询账单人员列表
List<BillStudentInfoVO> list = baseMapper.listBillUserPage(page, dto, studentList);
// 实际返回的分页数据
Page<Map<String, String>> returnPage = new Page<>();
BeanUtils.copyProperties(page, returnPage);
List<Map<String, String>> returnList = new ArrayList<>();
// 查询缴费信息
list.forEach(billStudentInfoVO -> {
// 匹配学生信息
EduStudent student = studentMap.get(billStudentInfoVO.getStudentId()).get(0);
BeanUtils.copyProperties(student, billStudentInfoVO);
Map<String, String> map = JSONObject.parseObject(JSONObject.toJSONString(billStudentInfoVO), new TypeReference<Map<String, String>>() {
});
// 查询总金额
map.put("payMoney", String.valueOf(eduBillOrderService.sumPayOrderPrice(dto.getBillId(), student.getId())));
// 查询学生缴费信息
List<H5BillItemVO> payInfo = eduBillOrderItemService.getPayInfo(dto.getBillId(), student.getId());
payInfo.forEach(item -> {
String itemPayName = "i" + item.getItemId() + item.getItemName();
if (CollUtil.isNotEmpty(item.getSubItemList())) {
item.getSubItemList().forEach(subItem -> {
// 选项拼接方式为 i+项目id+项目名称+s+选项id+选项名称
map.put(itemPayName + "s" + subItem.getSubItemId() + subItem.getSubItemName(),
NumberUtil.sub(subItem.getSubItemPrice(), item.getReductionPrice()).toString());
});
} else {
// 项目拼接方式为 i+项目id+项目名称
map.put(itemPayName, NumberUtil.sub(item.getItemPrice(), item.getReductionPrice()).toString());
}
});
returnList.add(map);
});
returnPage.setRecords(returnList);
return returnPage;
} else {
return new Page<>();
}
}
// @Override
// public void exportBillPayData(BillStudentSelectPageDTO dto, HttpServletResponse response) {
// try {
// // 查询学生信息
// EduStudent eduStudent = new EduStudent();
// BeanUtils.copyProperties(dto, eduStudent);
// eduStudent.setSchoolId(FebsUtil.getDeptId());
// List<EduStudent> studentList = remoteStudentService.listBaseStudent(eduStudent).getData();
//
// // 导出人员列表数据
// List<List<String>> exportDataList = new ArrayList<>();
//
// if (CollUtil.isNotEmpty(studentList)) {
// // 学生分组
// Map<Long, List<EduStudent>> studentMap = studentList.stream().collect(Collectors.groupingBy(EduStudent::getId));
// // 查询账单人员列表
// List<BillStudentInfoVO> list = baseMapper.listBillUserPage(null, dto, studentList);
// // 查询家庭类型
// List<Dict> familyTypeList = remoteCommonService.getDict(DictType.FAMILY_TYPE.getValue()).getData();
//
// list.forEach(billStudentInfoVO -> {
// // 匹配学生信息
// EduStudent student = studentMap.get(billStudentInfoVO.getStudentId()).get(0);
// // 查询学生具体缴费金额
// List<BillPayVO> payList = eduBillOrderItemService.listItemPayInfo(dto.getBillId(), student.getId());
//
// List<String> price = payList.stream().map(billPayVO -> {
// BillPayPriceVO billPayPriceVO = billPayVO.getBillPayPriceVO();
// if (Objects.isNull(billPayPriceVO) || Objects.isNull(billPayPriceVO.getItemPrice())) {
// return "—";
// }
// BigDecimal returnPrice = NumberUtil.sub(billPayPriceVO.getItemPrice(), billPayPriceVO.getReductionPrice());
// return Objects.isNull(returnPrice) ? "—" : returnPrice.toString();
// }).collect(Collectors.toList());
// // 查询总金额数据
// BigDecimal payOrderPrice = eduBillOrderService.sumPayOrderPrice(dto.getBillId(), student.getId());
// // 封装每一行数据
// ArrayList<String> singleList = CollUtil.newArrayList(student.getStuName(), student.getGradeName(),
// student.getClassName(), student.getStuNumber(),
// handelStudentType(student.getType()),
// handleFamilyType(student.getFamilyType(), familyTypeList));
// singleList.addAll(price);
// singleList.add(Objects.isNull(payOrderPrice) ? "—" : payOrderPrice.toString());
// // 添加excel数据
// exportDataList.add(singleList);
// });
// }
// // 导出数据
// EasyExcel.write(response.getOutputStream())
// .excelType(ExcelTypeEnum.XLS)
// // 这里放入动态头
// .head(getExportHead(dto.getBillId())).sheet("缴费明细")
// // 当然这里数据也可以用 List<List<String>> 去传入
// .doWrite(exportDataList);
// } catch (Exception e) {
// log.error("导出缴费明细数据错误", e);
// throw new FebsException("导出缴费明细数据错误");
// }
// }
@Override
public String exportBillPayData(BillStudentSelectPageDTO dto, HttpServletResponse response) {
return (String) redisService.get(CachePrefixConstant.BILL_PAY_DETAIL_EXPORT_URL + dto.getBillId());
}
/**
* 生成缴费账单动态表头数据
*
* @param billId 账单id
* @return java.util.List<java.util.List < java.lang.String>>
* @author ZYJ
* @date 2022/4/19 16:06
*/
private List<List<String>> getExportHead(Long billId) {
// 表头list的生成,实际的表头信息可以从数据库或者缓存等处动态读取
List<List<String>> allColList = new ArrayList<>();
// 姓名表头
allColList.add(CollUtil.newArrayList("姓名"));
// 年级表头
allColList.add(CollUtil.newArrayList("年级"));
// 班级表头
allColList.add(CollUtil.newArrayList("班级"));
// 学号表头
allColList.add(CollUtil.newArrayList("学号"));
// 学生类型表头
allColList.add(CollUtil.newArrayList("学生类型"));
// 家庭类型表头
allColList.add(CollUtil.newArrayList("家庭类型"));
// 项目动态表头
List<BillItemInfoVO> colList = eduBillService.listBillPayDetailTableCol(billId);
colList.forEach(item -> {
if (CollUtil.isNotEmpty(item.getSubItemList())) {
item.getSubItemList().forEach(subItem -> allColList.add(CollUtil.newArrayList("缴费项目", item.getItemName(), subItem.getSubItemName())));
} else {
allColList.add(CollUtil.newArrayList("缴费项目", item.getItemName()));
}
});
// 总金额表头
allColList.add(CollUtil.newArrayList("总金额"));
return allColList;
}
/**
* 转换学生类别
*
* @param studentType 学生类别,0-走读,1-住宿
* @return java.lang.String
* @author ZYJ
* @date 2022/4/19 16:19
*/
private String handelStudentType(Integer studentType) {
if (Objects.nonNull(studentType)) {
return studentType.equals(0) ? "走读" : "住宿";
} else {
return "";
}
}
/**
* 转换家庭类型
*
* @param familyType 学生家庭类型
* @param familyTypeList 家庭类型字典
* @return java.lang.String
* @author ZYJ
* @date 2022/4/19 16:21
*/
private String handleFamilyType(String familyType, List<Dict> familyTypeList) {
if (StringUtils.isNotBlank(familyType)) {
List<String> list = new ArrayList<>();
for (Dict dict : familyTypeList) {
if (familyType.contains(dict.getValue())) {
list.add(dict.getLabel());
}
}
return String.join(StringConstant.COMMA, list);
} else {
return "";
}
}
}
@@ -0,0 +1,920 @@
package com.yida.data.mall.service.impl;
import cc.mrbird.febs.common.redis.service.RedisService;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.Sign;
import cn.hutool.crypto.asymmetric.SignAlgorithm;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yida.data.common.core.common.ResultMsgType;
import com.yida.data.common.core.entity.CurrentUser;
import com.yida.data.common.core.entity.apply.EduApplyProductOrder;
import com.yida.data.common.core.entity.constant.CachePrefixConstant;
import com.yida.data.common.core.entity.constant.StringConstant;
import com.yida.data.common.core.entity.constant.UnionPayConstant;
import com.yida.data.common.core.entity.mall.*;
import com.yida.data.common.core.entity.mall.enums.BillItemOptionEnum;
import com.yida.data.common.core.entity.mall.enums.BillItemPayStatusEnum;
import com.yida.data.common.core.entity.mall.enums.MustPayEnum;
import com.yida.data.common.core.entity.pay.UnionPayOrder;
import com.yida.data.common.core.entity.pay.UnionRefund;
import com.yida.data.common.core.entity.system.EduDeptPayType;
import com.yida.data.common.core.entity.system.EduPayWxConfig;
import com.yida.data.common.core.entity.system.UnionPayConfig;
import com.yida.data.common.core.entity.user.EduParent;
import com.yida.data.common.core.entity.user.EduStudent;
import com.yida.data.common.core.enums.*;
import com.yida.data.common.core.exception.FebsException;
import com.yida.data.common.core.utils.*;
import com.yida.data.common.service.CommonService;
import com.yida.data.mall.dto.h5.CreateBillOrderDTO;
import com.yida.data.mall.dto.h5.H5BillInfoDTO;
import com.yida.data.mall.dto.h5.H5BillOrderPageDTO;
import com.yida.data.mall.dto.h5.H5BillSelectDTO;
import com.yida.data.mall.mapper.EduBillMapper;
import com.yida.data.mall.mapper.EduBillOrderMapper;
import com.yida.data.mall.service.*;
import com.yida.data.mall.utils.ThreadPoolUtil;
import com.yida.data.mall.vo.h5.*;
import com.yida.data.user.feign.RemoteStudentService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;
/**
* 缴费账单前端 Service接口
*
* @author ZYJ
* @date 2022-3-30 19:47:02
*/
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class H5EduBillServiceImpl implements H5EduBillService {
private final CommonService commonService;
private final RemoteStudentService remoteStudentService;
private final EduBillService eduBillService;
private final EduBillItemService eduBillItemService;
private final EduBillItemSubService eduBillItemSubService;
private final EduBillOrderService eduBillOrderService;
private final EduBillOrderItemService eduBillOrderItemService;
private final EduBillOrderItemSubService eduBillOrderItemSubService;
private final EduBillOrderStudentService eduBillOrderStudentService;
private final EduBillOrderRefundService eduBillOrderRefundService;
private final EduBillMapper eduBillMapper;
private final EduBillOrderMapper eduBillOrderMapper;
private final RedisService redisService;
private final UnionPayPublicUtil unionPayPublicUtil;
private static final ExecutorService BILL_ORDER_SUCCESS_POOL = ThreadPoolUtil.getBillOrderThreadPool();
private static final Snowflake ORDER_CODE_GENERATOR = new Snowflake(1, 1);
private static final String BILL_WX_PAY_NOTIFY_URL = "mall/in/eduBillOrder/wxPayNotify";
private static final String BILL_WX_REFUND_NOTIFY_URL = "mall/in/eduBillOrder/wxRefundNotify";
@Value("${febs.apiUrl}")
private String apiUrl;
@Value("${febs.pageUrl}")
private String pageUrl;
@Override
public List<H5BillSelectVO> listH5Bill(H5BillSelectDTO h5BillSelectDTO) {
// 查询前台账单列表
List<H5BillSelectVO> list = eduBillMapper.listH5Bill(h5BillSelectDTO);
list.forEach(h5BillSelectVO -> {
// 查询已支付金额
BigDecimal payMoney = eduBillOrderService.sumPayOrderPrice(h5BillSelectVO.getBillId(), h5BillSelectDTO.getStudentId());
if (Objects.isNull(payMoney)) {
payMoney = BigDecimal.ZERO;
}
h5BillSelectVO.setPayMoney(payMoney);
});
return list;
}
@Override
public H5BillSelectVO getH5BillInfo(H5BillInfoDTO h5BillInfoDTO) {
H5BillSelectVO h5BillSelectVO = eduBillMapper.getH5BillInfo(h5BillInfoDTO);
if (Objects.nonNull(h5BillSelectVO)) {
// 查询学生信息
EduStudent student = remoteStudentService.getStudentNoPermission(h5BillInfoDTO.getStudentId()).getData();
if (Objects.isNull(student)) {
throw new FebsException("学生信息错误");
}
h5BillSelectVO.setStudentFamilyType(student.getFamilyType());
// TODO 2022/4/22 需要优化查询学生已缴费数据的查询
// 判断支付数量
int payNumber = 0;
// 判断已支付选项
for (H5BillItemVO itemVO : h5BillSelectVO.getItemList()) {
H5BillItemVO itemPayInfo = eduBillOrderItemService.getItemPayInfo(h5BillInfoDTO.getBillId(), h5BillInfoDTO.getStudentId(), itemVO.getItemId());
// 没有支付数据
if (Objects.isNull(itemPayInfo)) {
itemVO.setChecked(MustPayEnum.MUST_PAY_STATUS.getStatus().equals(itemVO.getMustPay()));
itemVO.setItemPayStatus(BillItemPayStatusEnum.NOT_PAY.getStatus());
// 设置是否选中
itemVO.getSubItemList().forEach(subItemVO -> subItemVO.setChecked(false));
continue;
}
payNumber++;
// 单选
if (BillItemOptionEnum.ONE_SELECT_ONE.getStatus().equals(itemVO.getItemOption())) {
itemVO.setItemPayStatus(BillItemPayStatusEnum.PAY_SUCCESS.getStatus());
} else {
// 多项选一项、多项选多项
List<Long> subItemIdList = itemPayInfo.getSubItemList().stream().map(H5BillItemSubVO::getSubItemId).collect(Collectors.toList());
itemVO.getSubItemList().forEach(subItemVO -> {
// 设置是否选中
subItemVO.setChecked(false);
// 设置支付状态
subItemVO.setSubItemPayStatus(subItemIdList.contains(subItemVO.getSubItemId()) ?
BillItemPayStatusEnum.PAY_SUCCESS.getStatus() :
BillItemPayStatusEnum.NOT_PAY.getStatus());
});
// 判断单项选择一项是否购买
if (CollUtil.isNotEmpty(subItemIdList)
&& BillItemOptionEnum.MANY_SELECT_ONE.getStatus().equals(itemVO.getItemOption())) {
itemVO.setItemPayStatus(BillItemPayStatusEnum.PAY_SUCCESS.getStatus());
}
}
}
// 判断是否显示支付按钮 TODO 2022/4/22 需要判断是否还有未完成的订单
boolean showPay = payNumber != h5BillSelectVO.getItemList().size();
h5BillSelectVO.setShowPay(showPay);
// 判断支付方式
EduDeptPayType payType = commonService.getDeptPayWay(h5BillInfoDTO.getDeptId());
h5BillSelectVO.setPayType(payType);
} else {
throw new FebsException("当前账单暂时无法缴费");
}
return h5BillSelectVO;
}
@Override
public BillPayInfoVO createBillOrder(CreateBillOrderDTO createBillOrderDTO) {
CurrentUser currentUser = FebsUtil.getCurrentUser();
// 判断是否有下单缓存信息
BillOrderStudentCacheVO existBillOrderStudent = (BillOrderStudentCacheVO) redisService.get(
CachePrefixConstant.BILL_ORDER_STUDENT + createBillOrderDTO.getStudentId().toString()
+ StringConstant.DOT + createBillOrderDTO.getBillId().toString());
if (Objects.nonNull(existBillOrderStudent)) {
throw new FebsException(String.format("%s%s正在支付中, 请耐心等待",
existBillOrderStudent.getStudentName(), existBillOrderStudent.getParentType()));
}
if (StringUtils.isEmpty(createBillOrderDTO.getPayWay()) ||
PayWay.ALIPAY.getValue().equals(createBillOrderDTO.getPayWay())) {
throw new FebsException(ResultMsgType.PAY_TYPE_ERROR.getValue());
}
// 查询账单信息
EduBill bill = eduBillService.getById(createBillOrderDTO.getBillId());
if (Objects.isNull(bill)
|| BillStatusEnum.DISABLE_STATUS.getStatus().equals(bill.getEnableStatus())
|| bill.getBillEndDate().isBefore(LocalDateTime.now())) {
throw new FebsException("当前账单暂时无法缴费");
}
// 查询学生信息
EduStudent student = remoteStudentService.getStudentNoPermission(createBillOrderDTO.getStudentId()).getData();
if (Objects.isNull(student)) {
throw new FebsException("学生信息错误");
}
// 家长信息
List<EduParent> parents = student.getParents();
EduParent orderParent = parents.stream().filter(
x -> currentUser.getMobile().equals(x.getMobile())).collect(Collectors.toList()).get(0);
if (Objects.isNull(orderParent)) {
throw new FebsException("家长信息错误");
}
String orderCode = "";
try {
// 订单号 需要根据支付方式生成不同的订单号
String orderNo = "";
if (PayWay.WEI_XIN.getValue().equals(createBillOrderDTO.getPayWay())) {
// 微信
orderNo = String.valueOf(ORDER_CODE_GENERATOR.nextId());
} else if (PayWay.UNION.getValue().equals(createBillOrderDTO.getPayWay())) {
// 银联
// 获取银联商户号相关信息
UnionPayConfig config = commonService.getUnionPayConfigByDept(student.getSchoolId());
orderNo = UnionPayUtil.getOrderNumber(Objects.nonNull(config.getParentConfig())
? config.getParentConfig().getSourceNumber() : config.getSourceNumber());
}
if (StringUtils.isEmpty(orderNo)) {
log.error("生成订单号失败!");
throw new FebsException(ResultMsgType.ORDER_FAIL.getValue());
}
orderCode = orderNo;
BillOrderStudentCacheVO billOrderStudentCacheVO = BillOrderStudentCacheVO.builder()
.billId(createBillOrderDTO.getBillId())
.studentId(createBillOrderDTO.getStudentId())
.studentName(student.getStuName())
.parentId(orderParent.getId())
.parentType(orderParent.getParentType())
.mobile(currentUser.getMobile())
.orderNo(orderNo)
.build();
// 添加学生账单订单缓存
redisService.set(CachePrefixConstant.BILL_ORDER_STUDENT + createBillOrderDTO.getStudentId().toString()
+ StringConstant.DOT + createBillOrderDTO.getBillId().toString(), billOrderStudentCacheVO, 900L);
return checkBillOrder(createBillOrderDTO, bill, student, orderParent, currentUser, orderNo);
} catch (Exception e) {
// 删除学生账单订单缓存
redisService.del(CachePrefixConstant.BILL_ORDER_STUDENT + createBillOrderDTO.getStudentId()
+ StringConstant.DOT + createBillOrderDTO.getBillId());
// 删除账单订单对应缓存
if (StringUtils.isNotBlank(orderCode)) {
redisService.del(CachePrefixConstant.BILL_ORDER + orderCode);
redisService.del(CachePrefixConstant.BILL_ORDER_FLAG + orderCode);
}
throw new FebsException(e.getMessage());
}
}
/**
* 设置订单基本信息
*
* @param createBillOrderDTO 生成账单订单请求类
* @param bill 账单信息
* @param student 学生信息
* @param orderParent 下单家长
* @param currentUser 登录用户信息
* @param orderNo 订单号
* @return com.yida.data.mall.vo.h5.BillPayInfoVO
* @author ZYJ
* @date 2022/4/1 14:56
*/
private BillPayInfoVO checkBillOrder(CreateBillOrderDTO createBillOrderDTO, EduBill bill,
EduStudent student, EduParent orderParent,
CurrentUser currentUser, String orderNo) {
// 订单总金额
BigDecimal totalMoney = BigDecimal.ZERO;
// 订单减免金额
BigDecimal reductionMoney = BigDecimal.ZERO;
// 学生家庭类型
String studentFamilyType = student.getFamilyType();
// 保存的订单项目集合
List<EduBillOrderItem> orderItemList = new ArrayList<>();
// 判断账单项目
for (CreateBillOrderDTO.CreateBillOrderItemDTO itemDTO : createBillOrderDTO.getItemList()) {
// 根据项目id查询具体信息
EduBillItem billItem = eduBillItemService.getById(itemDTO.getItemId());
String itemFamilyType = billItem.getFamilyType();
// 判断当前学生能否减免
boolean reductionFlag = false;
if (ReductionStatusEnum.IS_REDUCTION_STATUS.getStatus().equals(billItem.getReductionStatus()) &&
StringUtils.isNotBlank(studentFamilyType) && StringUtils.isNotBlank(itemFamilyType)) {
String[] studentFamilyArray = studentFamilyType.split(StringConstant.COMMA);
for (String studentFamily : studentFamilyArray) {
if (itemFamilyType.contains(studentFamily)) {
reductionFlag = true;
break;
}
}
}
// 不定费项时的自定义金额
if (Objects.nonNull(itemDTO.getItemPrice())) {
billItem.setItemPrice(itemDTO.getItemPrice());
}
// 账单订单项目信息
EduBillOrderItem eduBillOrderItem = new EduBillOrderItem();
eduBillOrderItem.setBillId(createBillOrderDTO.getBillId());
eduBillOrderItem.setStudentId(student.getId());
eduBillOrderItem.setItemId(billItem.getId());
eduBillOrderItem.setItemName(billItem.getItemName());
eduBillOrderItem.setItemPrice(billItem.getItemPrice());
eduBillOrderItem.setReductionPrice(BigDecimal.ZERO);
// 保存的订单项目选项集合
List<EduBillOrderItemSub> orderItemSubList = new ArrayList<>();
// 前端选择的项目选项列表
List<CreateBillOrderDTO.CreateBillOrderSubItemDTO> subItemList = itemDTO.getSubItemList();
// 单选
if (BillItemOptionEnum.ONE_SELECT_ONE.getStatus().equals(billItem.getItemOption())) {
totalMoney = NumberUtil.add(totalMoney, billItem.getItemPrice());
// 减免
if (reductionFlag) {
reductionMoney = NumberUtil.add(reductionMoney, billItem.getReductionPrice());
eduBillOrderItem.setReductionPrice(billItem.getReductionPrice());
}
} else {
if (BillItemOptionEnum.MANY_SELECT_ONE.getStatus().equals(billItem.getItemOption())) {
// 多项选一项
if (CollUtil.isEmpty(subItemList) || subItemList.size() > 1) {
throw new FebsException(String.format("%s仅支持选择一个选项", billItem.getItemName()));
}
// 减免
if (reductionFlag) {
reductionMoney = NumberUtil.add(reductionMoney, billItem.getReductionPrice());
eduBillOrderItem.setReductionPrice(billItem.getReductionPrice());
}
}
// 多项选多项 TODO 2022/4/12 暂时没有多项选多项
// else {
// if (CollUtil.isEmpty(subItemList)) {
// throw new FebsException(String.format("请选择%s缴费选项", billItem.getItemName()));
// }
// // 查询是否有缴费信息 不能重复减免
// H5BillItemVO itemPayInfo = eduBillOrderItemService.getItemPayInfo(
// createBillOrderDTO.getBillId(), createBillOrderDTO.getStudentId(), billItem.getId());
// // 减免
// if ((Objects.isNull(itemPayInfo) || CollUtil.isEmpty(itemPayInfo.getSubItemList())) && reductionFlag) {
// reductionMoney = NumberUtil.add(reductionMoney, billItem.getReductionPrice());
// eduBillOrderItem.setReductionPrice(billItem.getReductionPrice());
// }
// }
// 查询子选项信息
for (CreateBillOrderDTO.CreateBillOrderSubItemDTO subItemDTO : subItemList) {
EduBillItemSub subItem = eduBillItemSubService.getById(subItemDTO.getSubItemId());
totalMoney = NumberUtil.add(totalMoney, subItem.getSubItemPrice());
// 设置订单项目子选项信息
EduBillOrderItemSub eduBillOrderItemSub = new EduBillOrderItemSub();
eduBillOrderItemSub.setBillId(createBillOrderDTO.getBillId());
eduBillOrderItemSub.setStudentId(student.getId());
eduBillOrderItemSub.setItemId(billItem.getId());
eduBillOrderItemSub.setSubItemId(subItem.getId());
eduBillOrderItemSub.setSubItemName(subItem.getSubItemName());
eduBillOrderItemSub.setSubItemPrice(subItem.getSubItemPrice());
orderItemSubList.add(eduBillOrderItemSub);
}
}
eduBillOrderItem.setOrderItemSubList(orderItemSubList);
orderItemList.add(eduBillOrderItem);
}
return createOrder(orderItemList, createBillOrderDTO, student, totalMoney,
reductionMoney, bill, orderParent, currentUser, orderNo);
}
/**
* 生成订单并返回支付信息
*
* @param orderItemList 订单项目集合
* @param createBillOrderDTO 生成账单订单请求类
* @param student 学生信息
* @param totalMoney 订单总金额
* @param reductionMoney 减免金额
* @param bill 账单信息
* @param orderParent 下单家长
* @param currentUser 登录用户信息
* @param orderNo 订单号
* @return com.yida.data.mall.vo.h5.BillPayInfoVO
* @author ZYJ
* @date 2022/4/1 14:50
*/
private BillPayInfoVO createOrder(List<EduBillOrderItem> orderItemList, CreateBillOrderDTO createBillOrderDTO,
EduStudent student, BigDecimal totalMoney, BigDecimal reductionMoney,
EduBill bill, EduParent orderParent, CurrentUser currentUser, String orderNo) {
// 生成账单订单信息
EduBillOrder eduBillOrder = new EduBillOrder();
eduBillOrder.setOrderCode(orderNo);
// 流水号
eduBillOrder.setTransactionNumber(PayUtil.generateSerialNumber("P", student.getSchoolId(), ""));
eduBillOrder.setStudentId(student.getId());
eduBillOrder.setBillId(bill.getId());
eduBillOrder.setBillTitle(bill.getBillTitle());
eduBillOrder.setTotalMoney(totalMoney);
// 判断实际金额
eduBillOrder.setPracticalMoney(NumberUtil.isLessOrEqual(totalMoney, reductionMoney)
? BigDecimal.ZERO : NumberUtil.sub(totalMoney, reductionMoney));
eduBillOrder.setPhone(currentUser.getMobile());
// 订单状态和支付状态
eduBillOrder.setOrderStatus(OrderStatusEnum.NOT_PAY.getStatus());
eduBillOrder.setPayStatus(PayStatusEnum.NOT_PAY.getStatus());
eduBillOrder.setPayWay(createBillOrderDTO.getPayWay());
eduBillOrder.setPayType(createBillOrderDTO.getPayType());
eduBillOrder.setDeptId(student.getSchoolId());
// 保存订单主体信息
eduBillOrderService.save(eduBillOrder);
// 保存账单订单相关信息
saveBillOrderInfo(eduBillOrder, orderItemList, student, orderParent);
// 返回值
BillPayInfoVO payInfoVO = new BillPayInfoVO();
// 金额为0,直接为成功订单
if (NumberUtil.isLessOrEqual(eduBillOrder.getPracticalMoney(), BigDecimal.ZERO)) {
billOrderPaySuccess(eduBillOrder.getOrderCode(), LocalDateTime.now());
payInfoVO.setNeedToPay(false);
payInfoVO.setOrderCode(eduBillOrder.getOrderCode());
} else {
// 下单返回信息
String result = placeOrder(bill, student, eduBillOrder, orderParent);
// 添加账单订单缓存
redisService.set(CachePrefixConstant.BILL_ORDER + eduBillOrder.getOrderCode(), eduBillOrder, 900L);
redisService.set(CachePrefixConstant.BILL_ORDER_FLAG + eduBillOrder.getOrderCode(), result, 900L);
payInfoVO = getPayInfo(eduBillOrder.getOrderCode(), result, eduBillOrder.getDeptId(), true,
createBillOrderDTO.getPayWay(), createBillOrderDTO.getPayType());
}
return payInfoVO;
}
/**
* 保存账单订单相关信息
*
* @param eduBillOrder 账单订单
* @param orderItemList 订单项目集合
* @param student 学生信息
* @param parent 下单家长信息
* @author ZYJ
* @date 2022/4/1 15:13
*/
private void saveBillOrderInfo(EduBillOrder eduBillOrder, List<EduBillOrderItem> orderItemList,
EduStudent student, EduParent parent) {
// 保存缴费项目信息
orderItemList.forEach(eduBillOrderItem -> {
eduBillOrderItem.setOrderId(eduBillOrder.getOrderId());
eduBillOrderItemService.save(eduBillOrderItem);
// 保存选项信息
if (CollUtil.isNotEmpty(eduBillOrderItem.getOrderItemSubList())) {
eduBillOrderItem.getOrderItemSubList().forEach(eduBillOrderItemSub -> {
eduBillOrderItemSub.setOrderItemId(eduBillOrderItem.getId());
eduBillOrderItemSub.setOrderId(eduBillOrder.getOrderId());
eduBillOrderItemSubService.save(eduBillOrderItemSub);
});
}
});
// 保存学生信息
EduBillOrderStudent eduBillOrderStudent = new EduBillOrderStudent();
BeanUtils.copyProperties(student, eduBillOrderStudent);
eduBillOrderStudent.setId(null);
eduBillOrderStudent.setOrderId(eduBillOrder.getOrderId());
eduBillOrderStudent.setBillId(eduBillOrder.getBillId());
eduBillOrderStudent.setStudentId(student.getId());
eduBillOrderStudent.setStudentName(student.getStuName());
eduBillOrderStudent.setStudentNumber(student.getStuNumber());
eduBillOrderStudent.setStudentFamilyType(student.getFamilyType());
eduBillOrderStudent.setStudentParentType(parent.getParentType());
eduBillOrderStudentService.save(eduBillOrderStudent);
}
/**
* 调用第三方接口生成支付信息
*
* @param student 学生信息
* @param bill 账单信息
* @param eduBillOrder 订单信息
* @param orderParent 下单家长
* @return java.lang.String
* @author ZYJ
* @date 2022/6/23 17:35
*/
private String placeOrder(EduBill bill, EduStudent student,
EduBillOrder eduBillOrder, EduParent orderParent) {
// 下单返回信息
String result = "";
try {
if (PayWay.WEI_XIN.getValue().equals(eduBillOrder.getPayWay())) {
// 微信支付
EduPayWxConfig config = commonService.getPayWxConfigBySchool(student.getSchoolId());
EduApplyProductOrder order = new EduApplyProductOrder();
order.setProductName(bill.getBillTitle());
order.setOrderCode(eduBillOrder.getOrderCode());
order.setPraccticalMoney(eduBillOrder.getPracticalMoney().doubleValue());
String ip = FebsUtil.getHttpServletRequestIpAddress();
// js api下单
if (WxPayTypeEnum.JS_TYPE.getStatus().equals(eduBillOrder.getPayType())) {
result = WxPayUtil.placeOrderJs(config, order, orderParent.getWxPublicOpenId(), ip,
apiUrl + BILL_WX_PAY_NOTIFY_URL);
} else {
// h5下单
result = WxPayUtil.placeOrderH5(config, order, ip, apiUrl + BILL_WX_PAY_NOTIFY_URL);
}
} else if (PayWay.UNION.getValue().equals(eduBillOrder.getPayWay())) {
// 获取对应支付类型枚举
UnionPayTypeEnum unionPayTypeEnum = EnumUtils.valueOf(UnionPayTypeEnum.class, eduBillOrder.getPayType(),
UnionPayTypeEnum.class.getMethod("getType"));
// 银联云闪付
result = UnionPayUtil.placeOrder(commonService.getUnionPayConfigByDept(student.getSchoolId()),
UnionPayOrder.builder()
.orderNo(eduBillOrder.getOrderCode())
.transactionNumber(eduBillOrder.getTransactionNumber())
.payMoney(eduBillOrder.getPracticalMoney())
.notifyUrl(apiUrl + UnionPayConstant.BILL_UNION_PAY_NOTIFY_URL)
.returnUrl(pageUrl + UnionPayConstant.BILL_UNION_PAY_RETURN_URL)
.payTypeEnum(unionPayTypeEnum)
.build());
}
} catch (Exception e) {
log.error("账单下单失败", e);
throw new FebsException(ResultMsgType.ORDER_FAIL.getValue());
}
if (StringUtils.isEmpty(result)) {
log.error("账单下单失败, 没有支付信息");
throw new FebsException(ResultMsgType.ORDER_FAIL.getValue());
}
return result;
}
/**
* 获取订单支付信息
*
* @param orderCode 订单号
* @param billOrderFlag 微信js支付prepayId, h5支付跳转地址
* @param deptId 学校id
* @param needToPay 是否需要跳转支付
* @param payWay 支付方式 {@link com.yida.data.common.core.enums.PayWay}
* @param payType 支付类型
* @return com.yida.data.mall.vo.h5.BillPayInfoVO
* @author ZYJ
* @date 2022/6/24 14:37
*/
public BillPayInfoVO getPayInfo(String orderCode, String billOrderFlag, Long deptId,
boolean needToPay, String payWay, Integer payType) {
BillPayInfoVO billPayInfoVO = null;
if (PayWay.WEI_XIN.getValue().equals(payWay)) {
// 微信
billPayInfoVO = getWxJsSign(orderCode, billOrderFlag, deptId, needToPay, payType);
} else if (PayWay.UNION.getValue().equals(payWay)) {
// 银联
billPayInfoVO = BillPayInfoVO.builder()
.orderCode(orderCode)
.needToPay(needToPay)
.payWay(payWay)
.payType(payType)
.payDomain(UnionPayConstant.URL)
.payUrl(billOrderFlag)
.build();
}
return billPayInfoVO;
}
/**
* 生成微信支付信息
*
* @param orderCode 订单号
* @param billOrderFlag 微信js支付prepayId, h5支付跳转地址
* @param deptId 学校id
* @param needToPay 是否需要跳转支付
* @param wxPayType 微信支付类型 {@link WxPayTypeEnum}
* @return com.yida.data.mall.vo.h5.BillPayInfoVO
* @author ZYJ
* @date 2022/6/24 14:39
*/
public BillPayInfoVO getWxJsSign(String orderCode, String billOrderFlag, Long deptId,
boolean needToPay, Integer wxPayType) {
BillPayInfoVO infoVO = new BillPayInfoVO();
infoVO.setOrderCode(orderCode);
infoVO.setNeedToPay(needToPay);
infoVO.setPayWay(PayWay.WEI_XIN.getValue());
infoVO.setPayType(wxPayType);
// js api类型
if (Objects.isNull(wxPayType) || WxPayTypeEnum.JS_TYPE.getStatus().equals(wxPayType)) {
EduPayWxConfig config = commonService.getPayWxConfigBySchool(deptId);
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
String nonceStr = RandomUtil.randomString(32);
String packages = "prepay_id=" + billOrderFlag;
String code = config.getWxPublicId() + "\n" + timestamp + "\n" + nonceStr + "\n" + packages + "\n";
Sign sign = SecureUtil.sign(SignAlgorithm.SHA256withRSA, config.getApiCreditPrivateKeyNoHead(),
null);
byte[] res = sign.sign(code.getBytes());
String signRes = Base64.encode(res);
infoVO.setWxAppId(config.getWxPublicId());
infoVO.setWxSign(signRes);
infoVO.setWxTimestamp(timestamp);
infoVO.setWxPackage(packages);
infoVO.setWxNonceStr(nonceStr);
} else {
infoVO.setPayUrl(billOrderFlag);
}
return infoVO;
}
@Override
public void billOrderSuccess(String orderCode) {
BILL_ORDER_SUCCESS_POOL.execute(() -> {
EduBillOrder order = eduBillOrderService.getOne(new LambdaQueryWrapper<>(new EduBillOrder())
.eq(EduBillOrder::getOrderCode, orderCode));
if (Objects.nonNull(order)
&& (OrderStatusEnum.NOT_PAY.getStatus().equals(order.getOrderStatus()) || OrderStatusEnum.USER_PAYING.getStatus().equals(order.getOrderStatus()))) {
if (PayWay.WEI_XIN.getValue().equals(order.getPayWay())) {
// 微信
wxBillOrderSuccess(order);
} else if (PayWay.UNION.getValue().equals(order.getPayWay())) {
// 银联
unionBillOrderSuccess(order);
}
}
});
}
/**
* 处理微信查询订单
*
* @param order 订单信息
* @author ZYJ
* @date 2022/6/27 17:51
*/
private void wxBillOrderSuccess(EduBillOrder order) {
boolean flag = false;
// 订单号
String orderCode = order.getOrderCode();
// 查询学校微信配置信息
EduPayWxConfig config = commonService.getPayWxConfigBySchool(order.getDeptId());
while (LocalDateTimeUtil.between(order.getCreateDate(), LocalDateTime.now()).getSeconds() < 900L) {
try {
JSONObject resJson = JSONUtil.parseObj(WxPayUtil.queryOrder(config, orderCode));
String tradeState = resJson.getStr("trade_state");
if (WxTradeStateEnum.NOT_PAY.getStatus().equals(tradeState)) {
continue;
}
WxTradeStateEnum wxTradeStateEnum = EnumUtils.valueOf(WxTradeStateEnum.class, tradeState,
WxTradeStateEnum.class.getMethod("getStatus"));
switch (Objects.requireNonNull(wxTradeStateEnum)) {
// 支付成功
case SUCCESS:
billOrderPaySuccess(orderCode, DateUtil.parseLocalDateTime(resJson.getStr("success_time"), "yyyy-MM" + "-dd'T" + "'HH:mm" + ":ssXXX"));
flag = true;
break;
// 作废订单
case CLOSED:
case REVOKED:
case PAY_ERROR:
order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
order.setPayStatus(PayStatusEnum.CANCEL.getStatus());
eduBillOrderService.updateById(order);
flag = true;
break;
default:
break;
}
if (flag) {
break;
}
Thread.sleep(1000L);
} catch (Exception e) {
log.error("账单订单(微信支付方式)完成失败, orderNo: {}", orderCode, e);
}
}
}
/**
* 处理银联查询订单
*
* @param order 订单信息
* @author ZYJ
* @date 2022/6/27 17:51
*/
private void unionBillOrderSuccess(EduBillOrder order) {
boolean flag = false;
// 订单号
String orderCode = order.getOrderCode();
// 查询学校银联配置信息
UnionPayConfig config = commonService.getUnionPayConfigByDept(order.getDeptId());
// 主商户信息
UnionPayConfig parentConfig = config.getParentConfig();
while (LocalDateTimeUtil.between(order.getCreateDate(), LocalDateTime.now()).getSeconds() < 900L) {
try {
JSONObject resJson = UnionPayUtil.queryOrder(config,
unionPayPublicUtil.getAccessToken(
Objects.nonNull(parentConfig) ? parentConfig.getAppId() : config.getAppId(),
Objects.nonNull(parentConfig) ? parentConfig.getAppKey() : config.getAppKey()
), orderCode);
// 支付状态
String status = (String) resJson.get("status");
if (UnionTradeStateEnum.NEW_ORDER.getStatus().equals(status)
|| UnionTradeStateEnum.UNKNOWN.getStatus().equals(status)
|| UnionTradeStateEnum.WAIT_BUYER_PAY.getStatus().equals(status)) {
return;
}
UnionTradeStateEnum tradeStateEnum = EnumUtils.valueOf(UnionTradeStateEnum.class, status,
UnionTradeStateEnum.class.getMethod("getStatus"));
switch (Objects.requireNonNull(tradeStateEnum)) {
// 支付成功
case TRADE_SUCCESS:
billOrderPaySuccess(order.getOrderCode(),
LocalDateTimeUtil.parse((String) resJson.get("payTime"), DatePattern.NORM_DATETIME_PATTERN));
flag = true;
break;
// 订单关闭
case TRADE_CLOSED:
order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
order.setPayStatus(PayStatusEnum.CANCEL.getStatus());
eduBillOrderService.updateById(order);
flag = true;
break;
default:
break;
}
if (flag) {
break;
}
Thread.sleep(1000L);
} catch (Exception e) {
log.error("账单订单(云闪付支付方式)完成失败, orderNo: {}", orderCode, e);
}
}
}
@Override
public void billOrderPaySuccess(String orderCode, LocalDateTime payDate) {
EduBillOrder order = eduBillOrderService.getOne(new LambdaQueryWrapper<>(new EduBillOrder()).eq(EduBillOrder::getOrderCode, orderCode));
order.setPayDate(payDate);
order.setOrderStatus(OrderStatusEnum.PAY_SUCCESS.getStatus());
order.setPayStatus(PayStatusEnum.PAY_SUCCESS.getStatus());
eduBillOrderService.updateById(order);
// 删除学生账单订单缓存
redisService.del(CachePrefixConstant.BILL_ORDER_STUDENT + order.getStudentId().toString() + StringConstant.DOT + order.getBillId().toString());
// 删除账单订单对应缓存
redisService.del(CachePrefixConstant.BILL_ORDER + orderCode);
redisService.del(CachePrefixConstant.BILL_ORDER_FLAG + orderCode);
}
@Override
public IPage<H5BillOrderPageVO> listH5BillOrderPage(H5BillOrderPageDTO dto) {
return eduBillOrderMapper.listH5BillOrderPage(dto.toPage(), dto);
}
@Override
public H5BillOrderInfoVO getH5BillOrderInfo(Long billOrderId, String orderCode) {
H5BillOrderInfoVO h5BillOrderInfo = eduBillOrderMapper.getH5BillOrderInfo(billOrderId, orderCode);
if (Objects.nonNull(h5BillOrderInfo)) {
h5BillOrderInfo.setDeptName(commonService.getDept(h5BillOrderInfo.getDeptId()).getDeptName());
}
return h5BillOrderInfo;
}
@Override
public BillPayInfoVO continuePayOrder(String orderCode, Long deptId) {
EduBillOrder order = eduBillOrderService.getOne(new LambdaQueryWrapper<>(new EduBillOrder()).eq(EduBillOrder::getOrderCode, orderCode));
if (Objects.isNull(order) || OrderStatusEnum.CLOSED.getStatus().equals(order.getOrderStatus())) {
throw new FebsException(ResultMsgType.ORDER_INVALID.getValue());
}
// 判断当前订单能否被当前用户支付
BillOrderStudentCacheVO existBillOrderStudent = (BillOrderStudentCacheVO) redisService.get(
CachePrefixConstant.BILL_ORDER_STUDENT + order.getStudentId().toString()
+ StringConstant.DOT + order.getBillId().toString());
if (Objects.nonNull(existBillOrderStudent)
&& !FebsUtil.getCurrentUser().getMobile().equals(existBillOrderStudent.getMobile())) {
throw new FebsException(String.format("%s%s正在支付中, 请耐心等待",
existBillOrderStudent.getStudentName(),
existBillOrderStudent.getParentType()));
}
// 获取对应待支付信息缓存
Object billOrderFlag = redisService.get(CachePrefixConstant.BILL_ORDER_FLAG + orderCode);
if (Objects.isNull(billOrderFlag)) {
throw new FebsException("当前订单已失效!");
}
return getPayInfo(orderCode, billOrderFlag.toString(), deptId, true, order.getPayWay(), order.getPayType());
}
@Override
public void cancelOrder(String orderCode) {
EduBillOrder order = eduBillOrderService.getOne(new LambdaQueryWrapper<>(new EduBillOrder()).eq(EduBillOrder::getOrderCode, orderCode));
if (OrderStatusEnum.CLOSED.getStatus().equals(order.getOrderStatus())) {
throw new FebsException(ResultMsgType.ORDER_INVALID.getValue());
}
// 判断当前订单能否被当前用户取消
BillOrderStudentCacheVO existBillOrderStudent = (BillOrderStudentCacheVO) redisService.get(
CachePrefixConstant.BILL_ORDER_STUDENT + order.getStudentId().toString()
+ StringConstant.DOT + order.getBillId().toString());
if (Objects.nonNull(existBillOrderStudent)
&& !FebsUtil.getCurrentUser().getMobile().equals(existBillOrderStudent.getMobile())) {
throw new FebsException(String.format("%s%s正在支付中, 请耐心等待",
existBillOrderStudent.getStudentName(), existBillOrderStudent.getParentType()));
}
order.setOrderStatus(OrderStatusEnum.CLOSED.getStatus());
order.setPayStatus(PayStatusEnum.CANCEL.getStatus());
eduBillOrderService.updateById(order);
try {
// 判断支付方式
if (PayWay.WEI_XIN.getValue().equals(order.getPayWay())) {
// 关闭微信订单
WxPayUtil.closeOrder(commonService.getPayWxConfigBySchool(order.getDeptId()), order.getOrderCode());
} else if (PayWay.UNION.getValue().equals(order.getPayWay())
&& !UnionPayTypeEnum.UNION_H5_TYPE.getType().equals(order.getPayType())) {
// 关闭银联订单 (银联云闪付不支付关闭订单)
UnionPayConfig unionPayConfig = commonService.getUnionPayConfigByDept(order.getDeptId());
UnionPayConfig parentConfig = unionPayConfig.getParentConfig();
UnionPayUtil.closeOrder(unionPayConfig,
unionPayPublicUtil.getAccessToken(
Objects.nonNull(parentConfig) ? parentConfig.getAppId() : unionPayConfig.getAppId(),
Objects.nonNull(parentConfig) ? parentConfig.getAppKey() : unionPayConfig.getAppKey()
), order.getOrderCode());
}
} catch (Exception e) {
log.error("关闭订单失败, order: {}", order, e);
throw new FebsException("取消订单失败");
}
// 删除学生账单订单缓存
redisService.del(CachePrefixConstant.BILL_ORDER_STUDENT + order.getStudentId().toString()
+ StringConstant.DOT + order.getBillId().toString());
// 删除账单订单对应缓存
redisService.del(CachePrefixConstant.BILL_ORDER + orderCode);
redisService.del(CachePrefixConstant.BILL_ORDER_FLAG + orderCode);
}
@Override
public void refundOrder(String orderCode) {
EduBillOrder order = eduBillOrderService.getOne(new LambdaQueryWrapper<>(new EduBillOrder()).eq(EduBillOrder::getOrderCode, orderCode));
// 判断订单能否退款
Asserts.isTrue(OrderStatusEnum.PAY_SUCCESS.getStatus().equals(order.getOrderStatus())
&& PayStatusEnum.PAY_SUCCESS.getStatus().equals(order.getPayStatus()), "该笔订单无法进行退款");
// 保存退款信息
EduBillOrderRefund eduBillOrderRefund = new EduBillOrderRefund();
eduBillOrderRefund.setOrderCode(orderCode);
// 生成退款订单号
String refundOrderCode = "";
if (PayWay.WEI_XIN.getValue().equals(order.getPayWay())) {
// 微信
refundOrderCode = "R" + orderCode;
} else if (PayWay.UNION.getValue().equals(order.getPayWay())) {
// 银联
// 获取银联商户号相关信息
UnionPayConfig config = commonService.getUnionPayConfigByDept(order.getDeptId());
refundOrderCode = UnionPayUtil.getOrderNumber(Objects.nonNull(config.getParentConfig())
? config.getParentConfig().getSourceNumber() : config.getSourceNumber());
}
eduBillOrderRefund.setRefundCode(refundOrderCode);
eduBillOrderRefund.setRefundSerialNumber(order.getTransactionNumber().replace("P", "R"));
eduBillOrderRefundService.save(eduBillOrderRefund);
// 修改订单状态
order.setOrderStatus(OrderStatusEnum.USER_REFUNDING.getStatus());
eduBillOrderService.updateById(order);
try {
// 调用退款接口
PayWay payWay = EnumUtils.valueOf(PayWay.class, order.getPayWay(),
PayWay.class.getMethod("getValue"));
switch (Objects.requireNonNull(payWay)) {
// 微信
case WEI_XIN:
// 查询学校微信支付配置
EduPayWxConfig config = commonService.getPayWxConfigBySchool(order.getDeptId());
WxPayUtil.refund(config, eduBillOrderRefund.getOrderCode(),
eduBillOrderRefund.getRefundReason(),
eduBillOrderRefund.getRefundCode(),
NumberUtil.mul(order.getPracticalMoney(), new BigDecimal("100")).longValue(),
NumberUtil.mul(order.getPracticalMoney(), new BigDecimal("100")).longValue(),
apiUrl + BILL_WX_REFUND_NOTIFY_URL);
break;
case UNION:
// 查询学校银联云闪付支付配置
UnionPayConfig unionPayConfig = commonService.getUnionPayConfigByDept(order.getDeptId());
UnionPayConfig parentConfig = unionPayConfig.getParentConfig();
UnionPayUtil.refund(unionPayConfig, UnionRefund.builder()
.orderNo(orderCode)
.refundOrderNo(eduBillOrderRefund.getRefundCode())
.transactionNumber(eduBillOrderRefund.getRefundSerialNumber())
.refundAmount(order.getPracticalMoney())
.build()
, unionPayPublicUtil.getAccessToken(
Objects.nonNull(parentConfig) ? parentConfig.getAppId() : unionPayConfig.getAppId(),
Objects.nonNull(parentConfig) ? parentConfig.getAppKey() : unionPayConfig.getAppKey()
));
break;
default:
break;
}
} catch (Exception e) {
log.error("退款失败", e);
throw new FebsException("退款失败");
}
}
@Override
public String checkExistOrder(Long billId, Long studentId) {
BillOrderStudentCacheVO existBillOrderStudent = (BillOrderStudentCacheVO) redisService.get(
CachePrefixConstant.BILL_ORDER_STUDENT + studentId.toString()
+ StringConstant.DOT + billId.toString());
if (Objects.nonNull(existBillOrderStudent)) {
return existBillOrderStudent.getOrderNo();
}
return "";
}
}
@@ -0,0 +1,30 @@
package com.yida.data.mall.utils;
import cn.hutool.core.thread.ThreadUtil;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import java.util.concurrent.*;
/**
* 线程池工具类
*
* @author ZYJ
* @date 2022/4/14
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ThreadPoolUtil {
/**
* 生成账单订单线程池
*
* @return java.util.concurrent.ExecutorService
* @author ZYJ
* @date 2022/4/14 10:10
*/
public static ExecutorService getBillOrderThreadPool() {
ThreadFactory threadFactory = ThreadUtil.newNamedThreadFactory("bill-order-pool-%d", false);
return new ThreadPoolExecutor(5, 10, 1,
TimeUnit.MINUTES, new LinkedBlockingQueue<>(), threadFactory);
}
}
@@ -0,0 +1,9 @@
████████ ██████ ████████ ████████ ███████ ██ ██
░░░░░░██ ░█░░░░██ ░░░░░░██ ░██░░░░░ ░██░░░░██ ░██ ░██
██ ░█ ░██ ██ ░██ ░██ ░██░██ ░██
██ ░██████ ██ █████░███████ ░██ ░██░██ ░██
██ ░█░░░░ ██ ██ ░░░░░ ░██░░░░ ░██ ░██░██ ░██
██ ░█ ░██ ██ ░██ ░██ ██ ░██ ░██
████████░███████ ████████ ░████████░███████ ░░███████
░░░░░░░░ ░░░░░░░ ░░░░░░░░ ░░░░░░░░ ░░░░░░░ ░░░░░░░
${spring.application.name}
@@ -0,0 +1,27 @@
spring:
profiles:
active: "@env-name@"
cloud:
nacos:
config:
server-addr: ${nacos.url}
prefix: edu-mall
file-extension: yaml
discovery:
server-addr: ${nacos.url}
application:
name: Edu-Mall
logging:
level:
org:
springframework:
boot:
actuate:
endpoint:
EndpointId: error
com:
alibaba:
cloud:
nacos:
client:
NacosPropertySourceBuilder: error
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yida.data.mall.mapper.EduBillItemMapper">
<!-- 根据是否缴费类型查询金额 -->
<select id="selectMoneyByStatus"
resultType="java.math.BigDecimal">
SELECT
IFNULL( SUM( item_price ), 0 ) AS price
FROM
edu_bill_item
WHERE
del_flag = 0
AND bill_id = #{billId}
<if test='status != null'>
AND must_pay = #{status}
</if>
</select>
</mapper>
@@ -0,0 +1,268 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yida.data.mall.mapper.EduBillMapper">
<resultMap id="h5BillInfoMap" type="com.yida.data.mall.vo.h5.H5BillSelectVO">
<id column="id" property="billId"/>
<result column="bill_title" property="billTitle"/>
<result column="bill_start_date" property="billStartDate"/>
<result column="bill_end_date" property="billEndDate"/>
<result column="bill_instruction" property="billInstruction"/>
<result column="last_enable_date" property="lastEnableDate"/>
<collection property="itemList" ofType="com.yida.data.mall.vo.h5.H5BillItemVO"
select="listH5BillItem"
column="{billId=id,studentId=student_id}">
</collection>
</resultMap>
<resultMap id="h5BillItemMap" type="com.yida.data.mall.vo.h5.H5BillItemVO">
<id column="id" property="itemId"/>
<result column="item_name" property="itemName"/>
<result column="item_price" property="itemPrice"/>
<result column="must_pay" property="mustPay"/>
<result column="reduction_status" property="reductionStatus"/>
<result column="family_type" property="familyType"/>
<result column="reduction_price" property="reductionPrice"/>
<result column="item_option" property="itemOption"/>
<result column="indefinite_status" property="indefiniteStatus"/>
<association property="itemPayStatus" select="getItemPayStatus"
javaType="java.lang.Integer" jdbcType="INTEGER"
column="{itemId=id,billId=bill_id,studentId=student_id}" />
<collection property="subItemList" ofType="com.yida.data.mall.vo.h5.H5BillItemSubVO"
select="listH5BillItemSub"
column="{itemId=id,billId=bill_id,studentId=student_id}">
</collection>
</resultMap>
<resultMap id="h5BillItemSubMap" type="com.yida.data.mall.vo.h5.H5BillItemSubVO">
<id column="id" property="subItemId"/>
<result column="sub_item_name" property="subItemName"/>
<result column="sub_item_price" property="subItemPrice"/>
<association property="subItemPayStatus" select="getSubItemPayStatus"
javaType="java.lang.Integer" jdbcType="INTEGER"
column="{subItemId=id,billId=bill_id,studentId=student_id,itemId=item_id}" />
</resultMap>
<!-- 查询缴费账单列表数据 -->
<select id="listBillPage"
resultType="com.yida.data.mall.vo.BillSelectPageVO">
SELECT
*
FROM
edu_bill
WHERE
del_flag = 0
AND dept_id = #{dto.deptId}
<if test='dto.billTitle != null and dto.billTitle != ""'>
AND bill_title LIKE CONCAT( '%', #{dto.billTitle}, '%' )
</if>
<if test='dto.enableStatus != null'>
AND enable_status = #{dto.enableStatus}
</if>
ORDER BY
create_date DESC
</select>
<!-- 查询前台账单列表 -->
<select id="listH5Bill"
resultMap="h5BillInfoMap">
SELECT DISTINCT
*,
${dto.studentId} as student_id
FROM
edu_bill b
LEFT JOIN edu_bill_student s ON b.id = s.bill_id
WHERE
b.del_flag = 0
AND s.del_flag = 0
AND b.dept_id = #{dto.deptId}
AND b.bill_start_date &lt; NOW( )
AND b.bill_end_date &gt; NOW()
AND s.student_id = #{dto.studentId}
AND b.enable_status = 1
ORDER BY
b.last_enable_date DESC
</select>
<!-- 查询前台账单详情 -->
<select id="getH5BillInfo"
resultMap="h5BillInfoMap">
SELECT DISTINCT
*
FROM
edu_bill b
LEFT JOIN edu_bill_student s ON b.id = s.bill_id
WHERE
b.del_flag = 0
AND s.del_flag = 0
AND b.dept_id = #{dto.deptId}
AND b.bill_start_date &lt; NOW( )
AND s.student_id = #{dto.studentId}
AND b.enable_status = 1
AND b.id = #{dto.billId}
ORDER BY
b.last_enable_date DESC
</select>
<!-- 查询前台账单项目 -->
<select id="listH5BillItem"
resultMap="h5BillItemMap">
SELECT
*,
${studentId} as student_id
FROM
edu_bill_item
WHERE
del_flag = 0
and bill_id = #{billId}
</select>
<!-- 查询前台账单项目选项 -->
<select id="listH5BillItemSub"
resultMap="h5BillItemSubMap">
SELECT
*,
${studentId} as student_id
FROM
edu_bill_item_sub
WHERE
del_flag = 0
and item_id = #{itemId}
</select>
<!-- 查询学生缴费项目支付状态 -->
<select id="getItemPayStatus" resultType="java.lang.Integer">
SELECT
IF(SUM(i.item_price) IS NULL, 0, 1) AS item_pay_status
FROM
edu_bill_order_item i
LEFT JOIN edu_bill_order o ON i.order_id = o.order_id
WHERE
o.del_flag = 0
AND i.del_flag = 0
AND i.item_id = #{itemId}
AND o.bill_id = #{billId}
AND o.student_id = #{studentId}
AND o.pay_status = '1'
</select>
<!-- 查询学生缴费项目子选项支付状态 -->
<select id="getSubItemPayStatus" resultType="java.lang.Integer">
SELECT
IF(SUM(s.sub_item_price) IS NULL, 0, 1) AS sub_item_pay_status
FROM
edu_bill_order_item_sub s
LEFT JOIN edu_bill_order_item i ON s.order_item_id = i.id
LEFT JOIN edu_bill_order o ON i.order_id = o.order_id
WHERE
s.del_flag = 0
AND o.del_flag = 0
AND i.del_flag = 0
AND s.sub_item_id = #{subItemId}
AND s.item_id = #{itemId}
AND o.bill_id = #{billId}
AND o.student_id = #{studentId}
AND o.pay_status = '1'
</select>
<resultMap id="billOrderMap" type="com.yida.data.mall.vo.BillOrderSelectPageVO">
<id column="order_id" property="orderId"/>
<result column="order_code" property="orderCode" />
<result column="transaction_number" property="transactionNumber" />
<result column="bill_id" property="billId" />
<result column="bill_title" property="billTitle" />
<result column="total_money" property="totalMoney" />
<result column="practical_money" property="practicalMoney" />
<result column="phone" property="phone" />
<result column="pay_date" property="payDate" />
<result column="order_status" property="orderStatus" />
<result column="pay_status" property="payStatus" />
<result column="pay_way" property="payWay" />
<result column="pay_type" property="payType" />
<result column="is_refund" property="isRefund" />
<result column="refund_date" property="refundDate" />
<association property="student" javaType="com.yida.data.common.core.entity.mall.EduBillOrderStudent">
<id column="order_student_id" property="id" />
<id column="student_id" property="studentId" />
<result column="student_name" property="studentName" />
<result column="student_number" property="studentNumber" />
<result column="student_family_type" property="studentFamilyType" />
<result column="student_parent_type" property="studentParentType" />
<result column="school_id" property="schoolId" />
<result column="school_name" property="schoolName" />
<result column="campus_id" property="campusId" />
<result column="campus_name" property="campusName" />
<result column="section_id" property="sectionId" />
<result column="section_name" property="sectionName" />
<result column="grade_id" property="gradeId" />
<result column="grade_name" property="gradeName" />
<result column="class_id" property="classId" />
<result column="class_name" property="className" />
</association>
</resultMap>
<!-- 查询账单订单列表数据 -->
<select id="listBillOrderPage"
resultMap="billOrderMap">
SELECT
o.*,
s.*,
s.id as order_student_id
FROM
edu_bill_order o
LEFT JOIN edu_bill_order_student s ON o.order_id = s.order_id
WHERE
o.del_flag = 0
AND o.dept_id = #{dto.schoolId}
<if test='dto.billTitle != null and dto.billTitle != ""'>
AND o.bill_title LIKE CONCAT( '%', #{dto.billTitle}, '%' )
</if>
<if test='dto.orderStatus != null and dto.orderStatus != ""'>
AND o.order_status = #{dto.orderStatus}
</if>
<if test='dto.searchData != null and dto.searchData != ""'>
AND (
s.student_name LIKE CONCAT( '%', #{dto.searchData}, '%' )
or s.student_number LIKE CONCAT( '%', #{dto.searchData}, '%' )
)
</if>
<if test="studentList != null and studentList.size() > 0">
AND s.student_id in
<foreach collection="studentList" open="(" close=")" separator="," item="student">
#{student.id}
</foreach>
</if>
order by
create_date desc
</select>
<!-- 查询已开始未结束的账单 -->
<select id="selectNeedStatisticsBill"
resultType="com.yida.data.common.core.entity.mall.EduBill">
SELECT
*
FROM
edu_bill
WHERE
del_flag = 0
AND NOW( ) BETWEEN bill_start_date
AND date_add( bill_end_date, INTERVAL 1 HOUR )
</select>
<!-- 查询已开始的账单 -->
<select id="selectStartBill"
resultType="com.yida.data.common.core.entity.mall.EduBill">
SELECT
*
FROM
edu_bill
WHERE
del_flag = 0
AND NOW( ) >= bill_start_date
</select>
</mapper>
@@ -0,0 +1,129 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yida.data.mall.mapper.EduBillOrderItemMapper">
<resultMap id="orderItemMap" type="com.yida.data.mall.vo.h5.H5BillItemVO">
<id column="item_id" property="itemId"/>
<result column="item_price" property="itemPrice"/>
<result column="item_name" property="itemName"/>
<result column="reduction_price" property="reductionPrice"/>
<collection property="subItemList" ofType="com.yida.data.mall.vo.h5.H5BillItemSubVO"
select="getSubItemPayInfo"
column="{itemId=item_id,orderId=order_id,studentId=student_id}">
</collection>
</resultMap>
<!-- 查询学生对应账单项目的缴费信息 -->
<select id="getItemPayInfo"
resultMap="orderItemMap">
SELECT DISTINCT
i.item_id,
o.student_id,
o.order_id
FROM
edu_bill_order_item i
LEFT JOIN edu_bill_order o ON i.order_id = o.order_id
WHERE
o.pay_status = '1'
AND o.bill_id = #{billId}
AND o.student_id = #{studentId}
AND i.item_id = #{itemId}
</select>
<!-- 查询学生对应账单项目选项的缴费信息 -->
<select id="getSubItemPayInfo"
resultType="com.yida.data.mall.vo.h5.H5BillItemSubVO">
SELECT DISTINCT
*
FROM
edu_bill_order_item_sub
WHERE
item_id = #{itemId}
AND order_id = #{orderId}
AND student_id = #{studentId}
</select>
<!-- 查询学生账单缴费信息 -->
<select id="getPayInfo"
resultMap="orderItemMap">
SELECT DISTINCT
i.item_id,
i.item_name,
i.item_price,
i.reduction_price,
o.student_id,
o.order_id
FROM
edu_bill_order_item i
LEFT JOIN edu_bill_order o ON i.order_id = o.order_id
WHERE
o.pay_status = '1'
AND o.bill_id = #{billId}
AND o.student_id = #{studentId}
</select>
<resultMap id="itemMap" type="com.yida.data.mall.vo.BillPayVO">
<result column="item_id" property="itemId"/>
<result column="sub_item_id" property="subItemId"/>
<collection property="billPayPriceVO" ofType="com.yida.data.mall.vo.BillPayPriceVO"
select="getPayPrice"
column="{itemId=item_id,subItemId=sub_item_id,studentId=student_id,billId=bill_id}">
</collection>
</resultMap>
<!-- 查询学生具体缴费金额 -->
<select id="listItemPayInfo" resultMap="itemMap">
SELECT
i.id AS item_id,
s.id AS sub_item_id,
i.bill_id,
${studentId} AS student_id
FROM
edu_bill_item i
LEFT JOIN ( SELECT id, item_id FROM edu_bill_item_sub WHERE del_flag = 0 AND bill_id = #{billId} ) s ON i.id = s.item_id
WHERE
i.del_flag = 0
AND i.bill_id = #{billId}
</select>
<!-- 查询项目或选项缴费金额 -->
<select id="getPayPrice" resultType="com.yida.data.mall.vo.BillPayPriceVO">
<choose>
<when test="subItemId == null">
SELECT
SUM(i.item_price) as item_price,
SUM(i.reduction_price) as reduction_price
FROM
edu_bill_order_item i
LEFT JOIN edu_bill_order o ON i.order_id = o.order_id
WHERE
o.del_flag = 0
AND i.del_flag = 0
AND i.item_id = #{itemId}
AND o.bill_id = #{billId}
AND o.student_id = #{studentId}
AND o.pay_status = '1'
</when>
<otherwise>
SELECT
SUM(s.sub_item_price) AS item_price,
SUM(i.reduction_price) as reduction_price
FROM
edu_bill_order_item_sub s
LEFT JOIN edu_bill_order_item i ON s.order_item_id = i.id
LEFT JOIN edu_bill_order o ON i.order_id = o.order_id
WHERE
s.del_flag = 0
AND o.del_flag = 0
AND i.del_flag = 0
AND s.sub_item_id = #{subItemId}
AND s.item_id = #{itemId}
AND o.bill_id = #{billId}
AND o.student_id = #{studentId}
AND o.pay_status = '1'
</otherwise>
</choose>
</select>
</mapper>
@@ -0,0 +1,153 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yida.data.mall.mapper.EduBillOrderMapper">
<!--查询已支付金额-->
<select id="sumPayOrderPrice" resultType="java.math.BigDecimal">
SELECT SUM(practical_money) AS pay_money
FROM edu_bill_order
WHERE bill_id = #{billId}
<if test="studentId != null">
AND student_id = #{studentId}
</if>
AND pay_status = '1'
</select>
<!-- 查询账单缴费人数 -->
<select id="sumPayStudentNumber" resultType="java.lang.Long">
SELECT
COUNT( DISTINCT o.student_id )
FROM
edu_bill_order o
LEFT JOIN edu_bill_student s ON ( o.student_id = s.student_id AND o.bill_id = s.bill_id )
WHERE
o.del_flag = 0
AND s.del_flag = 0
AND o.pay_status = '1'
AND o.bill_id = #{billId}
</select>
<!-- 前端查询账单订单列表数据 -->
<select id="listH5BillOrderPage"
resultType="com.yida.data.mall.vo.h5.H5BillOrderPageVO">
SELECT o.*,
s.student_name
FROM edu_bill_order o
LEFT JOIN edu_bill_order_student s ON o.order_id = s.order_id
WHERE o.dept_id = #{dto.deptId}
AND o.student_id = #{dto.studentId}
AND o.del_flag = 0
ORDER BY o.create_date DESC
</select>
<resultMap id="h5BillOrderInfoMap" type="com.yida.data.mall.vo.h5.H5BillOrderInfoVO">
<id column="order_id" property="orderId"/>
<result column="bill_id" property="billId"/>
<result column="bill_title" property="billTitle"/>
<result column="order_status" property="orderStatus"/>
<result column="pay_status" property="payStatus"/>
<result column="total_money" property="totalMoney"/>
<result column="practical_money" property="practicalMoney"/>
<result column="student_name" property="studentName"/>
<result column="pay_date" property="payDate"/>
<result column="dept_id" property="deptId"/>
<collection property="itemList" ofType="com.yida.data.mall.vo.h5.H5BillItemVO"
select="listH5BillOrderItem"
column="order_id">
</collection>
</resultMap>
<resultMap id="h5BillOrderItemMap" type="com.yida.data.mall.vo.h5.H5BillItemVO">
<id column="item_id" property="itemId"/>
<result column="item_name" property="itemName"/>
<collection property="subItemList" ofType="com.yida.data.mall.vo.h5.H5BillItemSubVO"
select="listH5BillOrderItemSub"
column="{itemId=item_id,orderId=order_id}">
</collection>
</resultMap>
<!-- 前端查询账单订单详情 -->
<select id="getH5BillOrderInfo"
resultMap="h5BillOrderInfoMap">
SELECT o.*,
s.student_name
FROM edu_bill_order o
LEFT JOIN edu_bill_order_student s ON o.order_id = s.order_id
WHERE
o.del_flag = 0
<if test="billOrderId != null">
AND o.order_id = #{billOrderId}
</if>
<if test="orderCode != null and orderCode != ''">
AND o.order_code = #{orderCode}
</if>
</select>
<!-- 前端查询账单订单项目详情 -->
<select id="listH5BillOrderItem" resultMap="h5BillOrderItemMap">
select *
from edu_bill_order_item
where order_id = #{orderId}
</select>
<!-- 前端查询账单订单项目选项详情 -->
<select id="listH5BillOrderItemSub"
resultType="com.yida.data.mall.vo.h5.H5BillItemSubVO">
select *
from edu_bill_order_item_sub
where order_id = #{orderId}
and item_id = #{itemId}
</select>
<!-- 查询所有已经超时订单 -->
<select id="selectTimeOutBillOrder"
resultType="com.yida.data.common.core.entity.mall.EduBillOrder">
SELECT
*
FROM
edu_bill_order
WHERE
order_status = '0'
AND TIMESTAMPDIFF( SECOND, create_date, now( ) ) > 900
</select>
<!-- 查询退款中状态的账单订单 -->
<select id="selectRefundOrder"
resultType="com.yida.data.mall.vo.BillRefundOrderVO">
SELECT
b.order_id,
b.order_code,
r.refund_code,
r.id refund_id,
b.pay_way,
b.dept_id
FROM
edu_bill_order b
LEFT JOIN edu_bill_order_refund r ON b.order_code = r.order_code
WHERE
b.del_flag = 0
AND b.order_status = '3'
AND b.pay_status = '1'
</select>
<!--查询部门已支付金额-->
<select id="sumDeptPayOrderPrice" resultType="java.math.BigDecimal">
SELECT
SUM( o.practical_money ) AS pay_money
FROM
edu_bill_order o
LEFT JOIN edu_bill_order_student s on o.order_id = s.order_id
WHERE
o.bill_id = #{billId}
AND o.pay_status = '1'
<if test="type == 1">
AND s.class_id = #{deptId}
</if>
<if test="type == 2">
AND s.grade_id = #{deptId}
</if>
</select>
</mapper>
@@ -0,0 +1,388 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yida.data.mall.mapper.EduBillStatisticsMapper">
<resultMap id="itemMap" type="com.yida.data.mall.vo.BillStatisticsItemVO">
<id column="item_id" property="itemId"/>
<result column="item_name" property="itemName"/>
<result column="item_price" property="itemPrice"/>
<result column="reduction_price" property="reductionPrice"/>
<collection property="subItemList" ofType="com.yida.data.mall.vo.h5.H5BillItemSubVO"
select="getSubItemPayInfo"
column="{itemId=item_id,billId=bill_id}">
</collection>
</resultMap>
<!-- 查询账单总缴费信息 -->
<select id="getPayInfo" resultMap="itemMap">
SELECT
i.item_id,
i.item_name,
i.bill_id,
SUM( i.item_price ) AS item_price,
SUM( i.reduction_price ) AS reduction_price,
COUNT( s.student_id ) AS pay_num
FROM
edu_bill_order_item i
LEFT JOIN edu_bill_order o ON i.order_id = o.order_id
LEFT JOIN edu_bill_order_student s ON o.order_id = s.order_id
WHERE
o.pay_status = '1'
AND o.bill_id = #{billId}
GROUP BY
i.item_id,
i.item_name,
i.bill_id
</select>
<!-- 查询对应账单项目选项的缴费信息 -->
<select id="getSubItemPayInfo"
resultType="com.yida.data.mall.vo.h5.H5BillItemSubVO">
SELECT
s.sub_item_id,
s.sub_item_name,
SUM( s.sub_item_price ) AS sub_item_price,
COUNT( s.student_id ) AS pay_num
FROM
edu_bill_order_item_sub s
LEFT JOIN edu_bill_order o ON s.order_id = o.order_id
LEFT JOIN edu_bill_order_student bs ON o.order_id = bs.order_id
WHERE
o.pay_status = '1'
AND o.bill_id = #{billId}
AND s.item_id = #{itemId}
GROUP BY
s.sub_item_id,
s.sub_item_name
</select>
<resultMap id="deptItemMap" type="com.yida.data.mall.vo.BillStatisticsItemVO">
<id column="item_id" property="itemId"/>
<result column="item_name" property="itemName"/>
<result column="item_price" property="itemPrice"/>
<result column="reduction_price" property="reductionPrice"/>
<result column="dept_name" property="deptName"/>
<result column="pay_num" property="payNum"/>
<collection property="subItemList" ofType="com.yida.data.mall.vo.h5.H5BillItemSubVO"
select="getDeptSubItemPayInfo"
column="{itemId=item_id,billId=bill_id,deptId=dept_id,deptType=dept_type}">
</collection>
</resultMap>
<!-- 账单部门缴费信息统计 -->
<select id="getDeptPayInfo" resultMap="deptItemMap">
SELECT
i.item_id,
i.item_name,
i.bill_id,
<if test="type == 1">
s.class_name AS dept_name,
</if>
<if test="type == 2">
s.grade_name AS dept_name,
</if>
SUM( i.item_price ) AS item_price,
SUM( i.reduction_price ) AS reduction_price,
COUNT( s.student_id ) AS pay_num,
${deptId} AS dept_id,
${type} AS dept_type
FROM
edu_bill_order_item i
LEFT JOIN edu_bill_order o ON i.order_id = o.order_id
LEFT JOIN edu_bill_order_student s ON o.order_id = s.order_id
WHERE
o.pay_status = '1'
AND o.bill_id = #{billId}
<if test="type == 1">
AND s.class_id = #{deptId}
</if>
<if test="type == 2">
AND s.grade_id = #{deptId}
</if>
GROUP BY
i.item_id,
i.item_name,
i.bill_id,
dept_name
</select>
<!-- 账单部门缴费子选项信息统计 -->
<select id="getDeptSubItemPayInfo"
resultType="com.yida.data.mall.vo.h5.H5BillItemSubVO">
SELECT
s.sub_item_id,
s.sub_item_name,
SUM( s.sub_item_price ) AS sub_item_price,
COUNT( s.student_id ) AS pay_num
FROM
edu_bill_order_item_sub s
LEFT JOIN edu_bill_order o ON s.order_id = o.order_id
LEFT JOIN edu_bill_order_student bs ON o.order_id = bs.order_id
WHERE
o.pay_status = '1'
AND o.bill_id = #{billId}
AND s.item_id = #{itemId}
<if test="deptType == 1">
AND bs.class_id = #{deptId}
</if>
<if test="deptType == 2">
AND bs.grade_id = #{deptId}
</if>
GROUP BY
s.sub_item_id,
s.sub_item_name
</select>
<resultMap id="exportItemMap" type="com.yida.data.mall.vo.BillPayVO">
<result column="item_id" property="itemId"/>
<result column="sub_item_id" property="subItemId"/>
<association property="payNum" javaType="long"
select="getPayNum"
column="{itemId=item_id,subItemId=sub_item_id,billId=bill_id}">
</association>
<collection property="billPayPriceVO" ofType="com.yida.data.mall.vo.BillPayPriceVO"
select="getPayPrice"
column="{itemId=item_id,subItemId=sub_item_id,billId=bill_id}">
</collection>
</resultMap>
<!-- 查询账单总缴费信息 -->
<select id="listTotalItemPayInfo" resultMap="exportItemMap">
SELECT
i.id AS item_id,
s.id AS sub_item_id,
i.bill_id
FROM
edu_bill_item i
LEFT JOIN ( SELECT id, item_id FROM edu_bill_item_sub WHERE del_flag = 0 AND bill_id = #{billId} ) s ON i.id = s.item_id
WHERE
i.del_flag = 0
AND i.bill_id = #{billId}
ORDER BY i.id
</select>
<!-- 查询项目或选项缴费金额 -->
<select id="getPayPrice" resultType="com.yida.data.mall.vo.BillPayPriceVO">
<choose>
<when test="subItemId == null">
SELECT
SUM( i.item_price ) AS item_price,
SUM( i.reduction_price ) AS reduction_price
FROM
edu_bill_order_item i
LEFT JOIN edu_bill_order o ON i.order_id = o.order_id
WHERE
o.del_flag = 0
AND i.del_flag = 0
AND i.item_id = #{itemId}
AND o.bill_id = #{billId}
AND o.pay_status = '1'
</when>
<otherwise>
SELECT
SUM( s.sub_item_price ) AS item_price,
SUM( i.reduction_price ) AS reduction_price
FROM
edu_bill_order_item_sub s
LEFT JOIN edu_bill_order_item i ON s.order_item_id = i.id
LEFT JOIN edu_bill_order o ON i.order_id = o.order_id
WHERE
s.del_flag = 0
AND o.del_flag = 0
AND i.del_flag = 0
AND s.sub_item_id = #{subItemId}
AND s.item_id = #{itemId}
AND o.bill_id = #{billId}
AND o.pay_status = '1'
</otherwise>
</choose>
</select>
<!-- 查询项目或选项缴费人数 -->
<select id="getPayNum" resultType="long">
<choose>
<when test="subItemId == null">
SELECT
COUNT(DISTINCT s.student_id) AS num
FROM
edu_bill_order_item i
LEFT JOIN edu_bill_order o ON i.order_id = o.order_id
LEFT JOIN edu_bill_order_student s ON o.order_id = s.order_id
WHERE
o.del_flag = 0
AND i.del_flag = 0
AND i.item_id = #{itemId}
AND o.bill_id = #{billId}
AND o.pay_status = '1'
</when>
<otherwise>
SELECT
COUNT(DISTINCT os.student_id) AS num
FROM
edu_bill_order_item_sub s
LEFT JOIN edu_bill_order_item i ON s.order_item_id = i.id
LEFT JOIN edu_bill_order o ON i.order_id = o.order_id
LEFT JOIN edu_bill_order_student os ON o.order_id = os.order_id
WHERE
s.del_flag = 0
AND o.del_flag = 0
AND i.del_flag = 0
AND s.sub_item_id = #{subItemId}
AND s.item_id = #{itemId}
AND o.bill_id = #{billId}
AND o.pay_status = '1'
</otherwise>
</choose>
</select>
<resultMap id="exportDeptItemMap" type="com.yida.data.mall.vo.BillPayVO">
<result column="item_id" property="itemId"/>
<result column="sub_item_id" property="subItemId"/>
<association property="payNum" javaType="long"
select="getDeptPayNum"
column="{itemId=item_id,subItemId=sub_item_id,billId=bill_id,deptId=dept_id,type=type}">
</association>
<collection property="billPayPriceVO" ofType="com.yida.data.mall.vo.BillPayPriceVO"
select="getDeptPayPrice"
column="{itemId=item_id,subItemId=sub_item_id,billId=bill_id,deptId=dept_id,type=type}">
</collection>
</resultMap>
<!-- 账单部门缴费信息统计 -->
<select id="listDeptItemPayInfo" resultMap="exportDeptItemMap">
SELECT
i.id AS item_id,
s.id AS sub_item_id,
i.bill_id,
${deptId} AS dept_id,
${type} AS type
FROM
edu_bill_item i
LEFT JOIN ( SELECT id, item_id FROM edu_bill_item_sub WHERE del_flag = 0 AND bill_id = #{billId} ) s ON i.id = s.item_id
WHERE
i.del_flag = 0
AND i.bill_id = #{billId}
ORDER BY i.id
</select>
<!-- 查询部门项目或选项缴费金额 -->
<select id="getDeptPayPrice" resultType="com.yida.data.mall.vo.BillPayPriceVO">
<choose>
<when test="subItemId == null">
SELECT
SUM( i.item_price ) AS item_price,
SUM( i.reduction_price ) AS reduction_price,
<if test="type == 1">
s.class_name AS dept_name
</if>
<if test="type == 2">
s.grade_name AS dept_name
</if>
FROM
edu_bill_order_item i
LEFT JOIN edu_bill_order o ON i.order_id = o.order_id
LEFT JOIN edu_bill_order_student s ON o.order_id = s.order_id
WHERE
o.del_flag = 0
AND i.del_flag = 0
AND i.item_id = #{itemId}
AND o.bill_id = #{billId}
<if test="type == 1">
AND s.class_id = #{deptId}
</if>
<if test="type == 2">
AND s.grade_id = #{deptId}
</if>
AND o.pay_status = '1'
GROUP BY
dept_name
</when>
<otherwise>
SELECT
SUM( s.sub_item_price ) AS item_price,
SUM( i.reduction_price ) AS reduction_price,
<if test="type == 1">
os.class_name AS dept_name
</if>
<if test="type == 2">
os.grade_name AS dept_name
</if>
FROM
edu_bill_order_item_sub s
LEFT JOIN edu_bill_order_item i ON s.order_item_id = i.id
LEFT JOIN edu_bill_order o ON i.order_id = o.order_id
LEFT JOIN edu_bill_order_student os ON o.order_id = os.order_id
WHERE
s.del_flag = 0
AND o.del_flag = 0
AND i.del_flag = 0
AND s.sub_item_id = #{subItemId}
AND s.item_id = #{itemId}
AND o.bill_id = #{billId}
<if test="type == 1">
AND os.class_id = #{deptId}
</if>
<if test="type == 2">
AND os.grade_id = #{deptId}
</if>
AND o.pay_status = '1'
GROUP BY
dept_name
</otherwise>
</choose>
</select>
<!-- 查询项目或选项缴费人数 -->
<select id="getDeptPayNum" resultType="long">
<choose>
<when test="subItemId == null">
SELECT
COUNT(DISTINCT s.student_id) AS num
FROM
edu_bill_order_item i
LEFT JOIN edu_bill_order o ON i.order_id = o.order_id
LEFT JOIN edu_bill_order_student s ON o.order_id = s.order_id
WHERE
o.del_flag = 0
AND i.del_flag = 0
AND i.item_id = #{itemId}
AND o.bill_id = #{billId}
<if test="type == 1">
AND s.class_id = #{deptId}
</if>
<if test="type == 2">
AND s.grade_id = #{deptId}
</if>
AND o.pay_status = '1'
</when>
<otherwise>
SELECT
COUNT(DISTINCT os.student_id) AS num
FROM
edu_bill_order_item_sub s
LEFT JOIN edu_bill_order_item i ON s.order_item_id = i.id
LEFT JOIN edu_bill_order o ON i.order_id = o.order_id
LEFT JOIN edu_bill_order_student os ON o.order_id = os.order_id
WHERE
s.del_flag = 0
AND o.del_flag = 0
AND i.del_flag = 0
AND s.sub_item_id = #{subItemId}
AND s.item_id = #{itemId}
AND o.bill_id = #{billId}
<if test="type == 1">
AND os.class_id = #{deptId}
</if>
<if test="type == 2">
AND os.grade_id = #{deptId}
</if>
AND o.pay_status = '1'
</otherwise>
</choose>
</select>
</mapper>
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yida.data.mall.mapper.EduBillStudentMapper">
<!-- 查询账单人员列表 -->
<select id="listBillUserPage"
resultType="com.yida.data.mall.vo.BillStudentInfoVO">
SELECT
id as bill_student_id,
student_id,
pay_status
FROM
edu_bill_student
WHERE
del_flag = 0
AND bill_id = #{dto.billId}
AND student_id in
<foreach collection="studentList" open="(" close=")" separator="," item="student">
#{student.id}
</foreach>
order by
create_date desc
</select>
</mapper>