六厂扣费系统

This commit is contained in:
hejiayang
2025-09-29 16:41:23 +08:00
commit 23166b08db
434 changed files with 47001 additions and 0 deletions
@@ -0,0 +1,4 @@
*.js linguist-language=Java
*.css linguist-language=Java
*.html linguist-language=Java
*.vue linguist-language=Java
@@ -0,0 +1,89 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-module-system</artifactId>
<version>3.4.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-system-biz</artifactId>
<dependencies>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-system-local-api</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</dependency>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>hibernate-re</artifactId>
</dependency>
<dependency>
<groupId>com.arcsoft</groupId>
<artifactId>arcsoft-sdk-face</artifactId>
<version>4.1.1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/arcsoft-sdk-face-4.1.1.0.jar</systemPath>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<!--消息队列连接池-->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
<version>5.16.7</version>
</dependency>
<!--加载hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.28</version>
</dependency>
<!-- 企业微信/钉钉 api -->
<dependency>
<groupId>org.jeecgframework</groupId>
<artifactId>jeewx-api</artifactId>
</dependency>
<!-- 积木报表 -->
<dependency>
<groupId>org.jeecgframework.jimureport</groupId>
<artifactId>jimureport-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>net.sf.barcode4j</groupId>
<artifactId>barcode4j-light</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.62</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.pulsar</groupId>
<artifactId>pulsar-client</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>com.yixiong.tools</groupId>
<artifactId>yixiong</artifactId>
<version>1.0.3</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,71 @@
package org.jeecg.activemq;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.activemq.command.ActiveMQMessage;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.ActiveMqEntityVO;
import org.jeecg.equipment.entity.StEquipment;
import org.jeecg.equipment.service.IStEquipmentService;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.jms.JMSException;
import javax.jms.Session;
import javax.jms.TextMessage;
@Component
@Slf4j
public class QueueConsumerListener {
@Resource
private IStEquipmentService iStEquipmentService;
/**
* 接受设备服务 投递给本服务的 设备数据同步 主题消息
*/
@JmsListener(destination="queue_msg_equipment_finance", containerFactory="equipmentQueueListener")
public void receiveQueueStEquipment(ActiveMQMessage message, Session session) throws JMSException {
log.info("receive topic_msg:1");
try {
String text = null;
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
text = textMessage.getText();
// log.info("topic_msg接收到消息:{}", text);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
ActiveMqEntityVO activeMqEntityVO = objectMapper.readValue(text, ActiveMqEntityVO.class);
if (activeMqEntityVO.getEntityReference().contains("entity.StEquipment")) {
StEquipment stEquipment = objectMapper.readValue(activeMqEntityVO.getDataJsonString(), StEquipment.class);
// log.info("接受某服务 投递给 zhst服务 的 消息 queue_msg_equipment_zhst 接收到 StEquipment {}", JSONObject.toJSONString(stEquipment));
if(StringUtils.isNotBlank(stEquipment.getId()) && null == stEquipment.getCreateTime()){//表示删除
boolean flag = iStEquipmentService.removeById(stEquipment.getId());
// if(flag){
// log.info("queue_msg_equipment_zhst 接收到消息,删除设备:{} 成功", stEquipment.getId());
// }
} else {
boolean flag = iStEquipmentService.saveOrUpdate(stEquipment);
if(!flag) {
throw new Exception("执行 StEquipment 保存数据异常");
}
}
}
// 确认消息。只要被确认后 就会出队,接受失败没有确认成功,会在原队列里面
message.acknowledge();
// log.info("手动ACK确认ok");
}
} catch (Exception e) {
log.error("出现异常,消费失败,放弃消费"+e.getMessage());
// 此不可省略 重发信息使用,如果不写此方法,将不会实现重发操作。失败的消息将会一直在队列中,因为没有进行消息确认。6次异常消息会放入死信队列ActiveMQ.DLQ
session.recover();
}
}
}
@@ -0,0 +1,34 @@
package org.jeecg.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Component
public class AspectUtil {
/**
*
* 功能描述:通过JoinPoint获取注解MyOperationLog
*
* 访问目标方法参数,有三种方法(实际有四种):
* 1.joinpoint.getargs():获取带参方法的参数
* 2.joinpoint.getTarget():.获取他们的目标对象信息
* 3.joinpoint.getSignature():(signature是信号,标识的意思):获取被增强的方法相关信息
*
*/
public SendNotification getMyOperationLogByJoinPoint(JoinPoint joinPoint) {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (null == method) {
return null;
}
return method.getAnnotation(SendNotification.class);
}
}
@@ -0,0 +1,17 @@
package org.jeecg.aspect;
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SendNotification {
// 方法名称
String methodName() default "";
// 当前操作人
String currentUser() default "";
// 操作
String operate() default "";
}
@@ -0,0 +1,230 @@
package org.jeecg.emp.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.emp.entity.CqBaseEmployee;
import org.jeecg.emp.service.ICqBaseEmployeeService;
import org.jeecg.emp.vo.CqBaseEmpVo;
import org.jeecg.system.service.ISwUserFaceimgService;
import org.jeecg.system.service.ISwUserFaceimgSubService;
import org.jeecg.system.service.ISysUserSubService;
import org.jeecg.user.entity.SwUserFaceimgSub;
import org.jeecg.user.entity.SysUserSub;
import org.jeecg.user.vo.SysUserSubVo;
import org.jeecg.user.vo.UserFaceInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Description: 子员工信息表
* @Author: jeecg-boot
* @Date: 2021-12-31
* @Version: V1.0
*/
@Tag(name = "员工信息表")
@RestController
@RequestMapping("/emp/cqBaseEmployee/sub")
@Slf4j
public class CqBaseEmployeePayController extends JeecgController<CqBaseEmployee, ICqBaseEmployeeService> {
@Autowired
private ICqBaseEmployeeService cqBaseEmployeeService;
@Resource
private ISysUserSubService sysUserSubService;
@Autowired
private ISwUserFaceimgSubService iSwUserFaceimgSubService;
@Autowired
private ISwUserFaceimgService swUserFaceimgService;
/**
* 分页列表查询
*
* @param baseEmpVo
* @param pageNo
* @param pageSize
* @param req
* @return
*/
@AutoLog(value = "员工信息表-分页列表查询")
@Operation(summary = "员工信息表-分页列表查询", description = "员工信息表-分页列表查询")
@GetMapping(value = "/list")
public Result<?> queryPageList(CqBaseEmpVo baseEmpVo,
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest req) {
Page<CqBaseEmpVo> pageList = new Page<CqBaseEmpVo>(pageNo, pageSize);
pageList = cqBaseEmployeeService.queryListV2(pageList, baseEmpVo);
return Result.OK(pageList);
}
/**
* 分页列表查询
*
* @param baseEmpVo
* @param pageNo
* @param pageSize
* @param req
* @return
*/
@AutoLog(value = "员工信息表-分页列表查询")
@Operation(summary = "员工信息表-分页列表查询", description = "员工信息表-分页列表查询")
@GetMapping(value = "/list/V3")
public Result<?> queryPageListV3(CqBaseEmpVo baseEmpVo,
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest req) {
Page<CqBaseEmpVo> pageList = new Page<CqBaseEmpVo>(pageNo, pageSize);
pageList = cqBaseEmployeeService.queryListV3(pageList, baseEmpVo);
return Result.OK(pageList);
}
/**
* 非正式、家庭用户添加
*
* @return
*/
@AutoLog(value = "非正式、家庭用户添加-添加")
@Operation(summary = "非正式、家庭用户添加-添加", description = "非正式、家庭用户添加-添加")
@PostMapping(value = "/add")
public Result<?> add(@RequestBody SysUserSub sysUserSub) {
if(StringUtils.isBlank(sysUserSub.getRealname())){
return Result.error("用户名不能为空");
}
//家庭用户
if(StringUtils.isNotBlank(sysUserSub.getMainUserId()) && StringUtils.isBlank(sysUserSub.getMainUserRelation())){
return Result.error("与主账户关系不能为空");
}
//非正式员工
if(StringUtils.isBlank(sysUserSub.getMainUserId()) && StringUtils.isBlank(sysUserSub.getPhone())){
return Result.error("手机号不能为空");
}
return cqBaseEmployeeService.saveEmpSub(sysUserSub);
}
/**
* 非正式、家庭用户编辑
*
* @return
*/
@AutoLog(value = "非正式、家庭用户编辑-编辑")
@Operation(summary = "非正式、家庭用户编辑-编辑", description = "非正式、家庭用户编辑-编辑")
@PutMapping(value = "/edit")
public Result<?> edit(@RequestBody SysUserSub sysUserSub) {
if(StringUtils.isBlank(sysUserSub.getId())){
return Result.error("用户ID不能为空");
}
Result<?> result = cqBaseEmployeeService.updateEmpSub(sysUserSub);
Map<String, Object> stringMap = new HashMap<>();
stringMap.put("userId", sysUserSub.getId());
return result;
}
/**
* 查询用户
* @return
*/
@AutoLog(value = "查询用户")
@Operation(summary = "查询用户", description = "查询用户")
@GetMapping(value = "/getByIdSub")
public Result<SysUserSub> getByIdSub(@RequestParam(name = "userId") String userId) {
if(StringUtils.isBlank(userId)){
return Result.error("用户ID不能为空");
}
return Result.OK(sysUserSubService.getById(userId));
}
/**
* 用户作废与恢复
* //用户类型(0: 正式员工 1:非正式员工,2:家庭用户)
* //当前用户是正式员工:停用钱包状态 钱包状态(1-禁用,0-正常)'
* //当前用户是非正式员工:停用钱包状态 钱包状态(1-禁用,0-正常)'
* //当前用户是家庭用户:停用用户状态(状态(1:正常 2:冻结 ))
* @return
*/
@AutoLog(value = "用户作废与恢复")
@Operation(summary = "用户作废与恢复", description = "用户作废与恢复")
@PostMapping(value = "/cancelOrRecovery")
public Result<?> cancellationAndRecovery(@RequestBody SysUserSubVo sysUserSub) {
if(StringUtils.isBlank(sysUserSub.getUserId())){
return Result.error("用户ID不能为空");
}
if(null == sysUserSub.getStatus()){
return Result.error("操作状态不能为空");
}
Result result = cqBaseEmployeeService.cancellationAndRecovery(sysUserSub);
return result;
}
/**
* 通过id删除
*
* @param id
* @return
*/
@AutoLog(value = "员工信息表-通过id删除")
@Operation(summary = "员工信息表-通过id删除", description = "员工信息表-通过id删除")
@DeleteMapping(value = "/delete")
public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
//2025-05-07 余:逻辑删除用户 扣费人员,油田员工逻辑删除不动人脸,非正式员工逻辑删除,人脸逻辑删除)
SysUserSub sysUserSub = sysUserSubService.getById(id);
if(null == sysUserSub){
return Result.error("用户不存在");
}
// 2025-05-09 ,如果主用户下面有子用户,删除主用户时是否关联删除子用户?余:做简单点,有子用户的主用户不能删除,要删逐级删除。
// 判断删除的是主用户,当前用户下存在子用户不能直接删除
if(StringUtils.isBlank(sysUserSub.getMainUserId())){
LambdaQueryWrapper<SysUserSub> subLambdaQueryWrapper = new LambdaQueryWrapper<>();
subLambdaQueryWrapper.eq(SysUserSub::getMainUserId, id);
subLambdaQueryWrapper.eq(SysUserSub::getDelFlag, 0);
//查询所有子用户
List<SysUserSub> sysUserSubs = sysUserSubService.list(subLambdaQueryWrapper);
if(CollectionUtils.isNotEmpty(sysUserSubs)){
return Result.error("当前用户下存在子用户不能直接删除");
}
}
if(0 != sysUserSub.getUserType()){
sysUserSubService.deleteUserSub(id);
//删除用户信息时删除人脸数据
List<SwUserFaceimgSub> slUserFaceimgList = iSwUserFaceimgSubService.lambdaQuery().eq(SwUserFaceimgSub::getUserId, id).
eq(SwUserFaceimgSub::getDelFlag, 0).list();//人脸图片和特征
if(CollectionUtils.isNotEmpty(slUserFaceimgList)){
slUserFaceimgList.forEach(swUserFaceimgSub->{
swUserFaceimgSub.setDelFlag(1);
//2025-05-07 余:逻辑删除用户特征
iSwUserFaceimgSubService.updateById(swUserFaceimgSub);
//发送删除扣费闸机人脸特征数据
UserFaceInfo userInfo = new UserFaceInfo();
userInfo.setUserId(swUserFaceimgSub.getUserId());
swUserFaceimgService.sendPaymentGateUserInfo(userInfo,0,false,null);
});
}
} else {
//正式员工-逻辑删除serSub表
sysUserSubService.deleteUserSub(id);
//正式员工--发送删除扣费闸机人脸特征数据
UserFaceInfo userInfo = new UserFaceInfo();
userInfo.setUserId(sysUserSub.getId());
swUserFaceimgService.sendPaymentGateUserInfo(userInfo,0,false,sysUserSub.getId());
}
return Result.OK("删除成功!");
}
}
@@ -0,0 +1,112 @@
package org.jeecg.emp.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.jeecg.emp.entity.CqBaseEmployee;
import org.jeecg.emp.vo.CqBaseEmpVo;
import org.jeecg.emp.vo.DepartVo;
import org.jeecg.emp.vo.EmpInfoVo;
import org.jeecg.emp.vo.UserInfoVo;
import org.jeecg.user.entity.SysUser;
import java.util.List;
import java.util.Map;
/**
* @Description: 员工信息表
* @Author: jeecg-boot
* @Date: 2021-12-31
* @Version: V1.0
*/
public interface CqBaseEmployeeMapper extends BaseMapper<CqBaseEmployee> {
List<CqBaseEmpVo> queryList(Page<CqBaseEmpVo> page, @Param("vo") CqBaseEmpVo baseEmpVo);
List<CqBaseEmpVo> queryListV2(Page<CqBaseEmpVo> page, @Param("vo") CqBaseEmpVo baseEmpVo);
/**
* 查询用户树形结构(支持分页和搜索)
* @param page 分页参数
* @return 分页结果
*/
List<CqBaseEmpVo> selectUserTreePage(Page<?> page,@Param("vo") CqBaseEmpVo baseEmpVo);
void updateIsStatusByMemberId(Map map);
void updateStatusById(Map map);
List<CqBaseEmpVo> queryListSubUser(@Param("list") List<String> userIdList);
List<CqBaseEmpVo> queryList(@Param("vo") CqBaseEmpVo baseEmpVo);
public EmpInfoVo getEmpInfo(String idcard);
public EmpInfoVo getEmpInfoByUsername(String username);
public EmpInfoVo getEmpInfoByUserId(String userId);
@Select("select id,depart_name,org_code from sys_depart where org_code like 'A01%' and length(org_code) = 6 and del_flag = 0 order by depart_order asc")
public List<DepartVo> getSecondDepartList();
/**
*
* @return
*/
@Select("select id,depart_name,org_code from sys_depart where org_code like concat((select left(org_code,6) from sys_depart where FIND_IN_SET(id,#{departIds})limit 1),'%') and length(org_code) = 6 AND del_flag = 0 order by depart_order asc")
public List<DepartVo> getChargeSecondDepartList(String departIds);
/**
*
* @return
*/
@Select("select id,depart_name,org_code from sys_depart where org_code = #{orgCode} and length(org_code) = 6 AND del_flag = 0 order by depart_order asc")
public List<DepartVo> getChargeSecondDepartListV2(String orgCode);
@Select("select id,depart_name,org_code from sys_depart where FIND_IN_SET(id,#{departIds}) and length(org_code) = 9 AND del_flag = 0 order by depart_order asc")
public List<DepartVo> getChargeThirdDepartList(String departIds);
@Select("select id,depart_name,org_code from sys_depart where parent_id = (SELECT id FROM sys_depart WHERE org_code = #{orgCode} ) and length(org_code) = 9 AND del_flag = 0 order by depart_order asc")
public List<DepartVo> getChargeThirdDepartListV2(String departIds);
@Select("select id,depart_name,org_code from sys_depart where org_code like 'A01%' and length(org_code) = 9 and parent_id = #{parentId} AND del_flag = 0 order by depart_order asc")
public List<DepartVo> getThirdDepartList(String parentId);
@Select("select id,username,avatar,phone,realname from sys_user where FIND_IN_SET(id,#{userIds}) AND del_flag = 0 ")
public List<UserInfoVo> geUserNameByIdList(String userIds);
/**
* 获取用户明文手机号
* @param userId 用户id
* @return 手机号
*/
String getPhoneByUserId(@Param("userId") String userId);
/**
* 获取用户明文手机号
* @param userId 用户id
* @return 手机号
*/
String getIdCardByUserId(@Param("userId") String userId);
/**
* 根据身份证号 获取用户信息
* @param idCardList 身份证列表
* @return 用户列表
*/
List<SysUser> getUserList(@Param("list") List<String> idCardList);
public EmpInfoVo getEmpInfoByJobNumberLimit1(@Param("workNo") String workNo);
public List<EmpInfoVo> getEmpInfoByUsernameList(@Param("username") String username);
EmpInfoVo getEmpInfoVoByUserId(String userId);
}
@@ -0,0 +1,464 @@
<?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="org.jeecg.emp.mapper.CqBaseEmployeeMapper">
<select id="queryList" parameterType="String" resultType="org.jeecg.emp.vo.CqBaseEmpVo">
SELECT
cbe.id,
cbe.emp_sysno,
cbe.emp_birthday,
CONCAT(LEFT ( cbe.emp_idcard, 3 ),'*************',RIGHT ( cbe.emp_idcard, 2 )) AS emp_idcard,
cbe.emp_job,
cbe.emp_group,
cbe.emp_position,
cbe.emp_level,
cbe.emp_status,
cbe.emp_political,
cbe.emp_nation,
cbe.emp_degree,
cbe.emp_nativeplace,
cbe.emp_jk_state,
cbe.emp_worktype,
cbe.emp_type,
cbe.work_space,
cbe.live_space,
cbe.emp_remark,
cbe.person_type,
cbe.sex,
cbe.height,
cbe.weight,
cbe.work_strength,
cbe.del_flag,
cbe.is_sync,
dd.depart_name secondDepartName,
ddd.depart_name thirdDepartName,
sud.dep_id,
sd.depart_name,
su.username,
su.realname,
su.avatar,
su.sex,
CONCAT(LEFT(su.phone,3),'****',RIGHT(su.phone,4)) as phone,
su.create_time
FROM
cq_base_employee cbe
LEFT JOIN sys_user su ON cbe.id = su.id AND su.del_flag = 0
LEFT JOIN sys_user_depart sud ON sud.user_id = su.id AND sud.del_flag = 0
LEFT JOIN sys_depart sd ON sud.dep_id = sd.id AND sd.del_flag = 0
LEFT JOIN sys_depart dd ON LEFT ( sd.org_code, 6 ) = dd.org_code AND dd.del_flag = 0
LEFT JOIN sys_depart ddd ON LEFT ( sd.org_code, 9 ) = ddd.org_code AND ddd.del_flag = 0
where 1=1
and su.user_identity = 6
AND cbe.del_flag = 0
<if test="vo.empSysno != null and vo.empSysno != ''">
and cbe.emp_sysno like CONCAT('%', #{vo.empSysno},'%')
</if>
<if test="vo.empIdcard != null and vo.empIdcard != ''">
and cbe.emp_idcard like CONCAT('%', #{vo.empIdcard},'%')
</if>
<if test="vo.realname != null and vo.realname != ''">
and su.realname like CONCAT('%', #{vo.realname},'%')
</if>
<if test="vo.username != null and vo.username != ''">
and su.username like CONCAT('%', #{vo.username},'%')
</if>
<if test="vo.secondDepartId != null and vo.secondDepartId != ''">
and dd.id = #{vo.secondDepartId}
</if>
<if test="vo.orgCode != null and vo.orgCode != ''">
and dd.org_code = #{vo.orgCode}
</if>
<if test="vo.thirdDepartId != null and vo.thirdDepartId != ''">
and ddd.id = #{vo.thirdDepartId}
</if>
<if test="vo.empWorktype != null and vo.empWorktype != ''">
and cbe.emp_worktype = #{vo.empWorktype}
</if>
<if test="vo.phone != null and vo.phone != ''">
and su.phone = #{vo.phone}
</if>
<if test="vo.selections != null and vo.selections != ''">
and find_in_set(cbe.id,#{vo.selections})
</if>
<if test="vo.workNo != null and vo.workNo != ''">
and su.work_no = #{vo.workNo}
</if>
order by su.create_time desc
</select>
<select id="queryListV2" parameterType="String" resultType="org.jeecg.emp.vo.CqBaseEmpVo">
SELECT
sus.id,
NULL AS emp_sysno, -- 对应字段在 sys_user_sub 中不存在,填 NULL
sus.birthday AS emp_birthday,
CONCAT(LEFT(sus.card_no, 3), '*************', RIGHT(sus.card_no, 2)) AS emp_idcard,
NULL AS emp_job, -- 对应字段在 sys_user_sub 中不存在,填 NULL
NULL AS emp_group,
NULL AS emp_position,
NULL AS emp_level,
NULL AS emp_status,
NULL AS emp_political,
NULL AS emp_nation,
NULL AS emp_degree,
NULL AS emp_nativeplace,
NULL AS emp_jk_state,
NULL AS emp_worktype,
NULL AS emp_type,
NULL AS work_space,
NULL AS live_space,
NULL AS emp_remark,
NULL AS person_type,
NULL AS height, -- 对应字段在 sys_user_sub 中不存在,填 NULL
NULL AS weight,
NULL AS work_strength,
sus.del_flag,
sus.is_sync,
NULL AS secondDepartName, -- 对应字段在 sys_user_sub 中不存在,填 NULL
NULL AS thirdDepartName,
NULL AS dep_id,
NULL AS depart_name,
sus.username,
sus.realname,
sus.avatar,
sus.work_no,
sus.sex,
CONCAT(LEFT(sus.phone, 3), '****', RIGHT(sus.phone, 4)) AS phone,
sus.create_time,
sus.user_type,
sus.main_user_id,
sus.main_user_relation,
sus.canteen_id,
sus.status,
sus.remark
FROM
sys_user_sub sus
WHERE 1 = 1
AND sus.user_identity = 6 -- 根据需求过滤条件
AND sus.del_flag = 0
<if test="(vo.realname == null or vo.realname == '') and (vo.phone == null or vo.phone == '')">
and sus.main_user_id is null -- 默认只查询正式员工+非正式员工,搜索姓名或者手机号查询全部用户
</if>
<if test="vo.realname != null and vo.realname != ''">
and sus.realname like CONCAT('%', #{vo.realname},'%')
</if>
<if test="vo.phone != null and vo.phone != ''">
and sus.phone = #{vo.phone}
</if>
<if test="vo.mainUserRelation != null and vo.mainUserRelation != ''">
and sus.main_ser_relation = #{vo.mainUserRelation}
</if>
<if test="vo.userType != null and vo.userType != ''">
and sus.user_type = #{vo.userType}
</if>
ORDER BY sus.create_time DESC; -- 使用统一的排序字段
</select>
<select id="queryListSubUser" resultType="org.jeecg.emp.vo.CqBaseEmpVo">
SELECT
sus.id,
NULL AS emp_sysno, -- 对应字段在 sys_user_sub 中不存在,填 NULL
sus.birthday AS emp_birthday,
CONCAT(LEFT(sus.card_no, 3), '*************', RIGHT(sus.card_no, 2)) AS emp_idcard,
NULL AS emp_job, -- 对应字段在 sys_user_sub 中不存在,填 NULL
NULL AS emp_group,
NULL AS emp_position,
NULL AS emp_level,
NULL AS emp_status,
NULL AS emp_political,
NULL AS emp_nation,
NULL AS emp_degree,
NULL AS emp_nativeplace,
NULL AS emp_jk_state,
NULL AS emp_worktype,
NULL AS emp_type,
NULL AS work_space,
NULL AS live_space,
NULL AS emp_remark,
NULL AS person_type,
NULL AS height, -- 对应字段在 sys_user_sub 中不存在,填 NULL
NULL AS weight,
NULL AS work_strength,
sus.del_flag,
sus.is_sync,
NULL AS secondDepartName, -- 对应字段在 sys_user_sub 中不存在,填 NULL
NULL AS thirdDepartName,
NULL AS dep_id,
NULL AS depart_name,
sus.username,
sus.realname,
sus.avatar,
sus.sex,
CONCAT(LEFT(sus.phone, 3), '****', RIGHT(sus.phone, 4)) AS phone,
sus.create_time,
sus.user_type,
sus.main_user_id,
sus.main_user_relation,
sus.canteen_id,
sus.status
FROM
sys_user_sub sus
WHERE 1 = 1
AND sus.user_identity = 6 -- 根据需求过滤条件
AND sus.del_flag = 0
and sus.main_user_id in
<foreach collection="list" item="mainUserId" separator="," open="(" close=")" >
#{mainUserId}
</foreach>
</select>
<!-- 定义 ResultMap,用于处理嵌套的父子关系 -->
<resultMap id="userTreeResultMap" type="org.jeecg.emp.vo.CqBaseEmpVo">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="realname" column="realname"/>
<result property="phone" column="phone"/>
<result property="mainUserId" column="main_user_id"/>
<result property="createTime" column="create_time"/>
<result property="userType" column="user_type"/>
<result property="mainUserRelation" column="main_user_relation"/>
<result property="status" column="status"/>
<!-- 嵌套查询子用户 -->
<collection property="subUserList" ofType="org.jeecg.emp.vo.CqBaseEmpVo"
select="selectChildrenByParentId"
column="{parentId=id, realname=vo.realname, phone=vo.phone, mainUserRelation=vo.mainUserRelation, userType=vo.userType}"/>
</resultMap>
<!-- 查询所有用户(支持分页和搜索) -->
<select id="selectUserTreePage" resultMap="userTreeResultMap">
SELECT *
FROM sys_user_sub
WHERE 1=1
and user_type in (0,1)
and del_flag = 0
<if test="vo.realname != null and vo.realname != ''">
AND realname LIKE CONCAT('%', #{vo.realname}, '%')
</if>
<if test="vo.phone != null and vo.phone != ''">
AND phone LIKE CONCAT('%', #{vo.phone}, '%')
</if>
<if test="vo.mainUserRelation != null and vo.mainUserRelation != ''">
and main_ser_relation = #{vo.mainUserRelation}
</if>
<if test="vo.userType != null and vo.userType != ''">
and user_type = #{vo.userType}
</if>
</select>
<update id="updateIsStatusByMemberId" parameterType="map">
UPDATE st_client_member_balance
<set>
<if test="isStatus != null">
is_status = #{isStatus}
</if>
</set>
WHERE member_id = #{memberId}
</update>
<update id="updateStatusById" parameterType="map">
UPDATE sys_user_sub
<set>
<if test="status != null">
status = #{status} ,
</if>
<if test="remark != null and remark != ''">
remark = #{remark}
</if>
</set>
WHERE id = #{id}
</update>
<select id="getEmpInfoByUserId" parameterType="String" resultType="org.jeecg.emp.vo.EmpInfoVo">
SELECT
u.avatar avatar,
emp.id userId,
dd.id secondDepartId,
dd.depart_name secondDepartName,
ddd.id thirdDepartId,
ddd.depart_name thirdDepartName,
u.username,
u.realname,
u.work_no workNo,
emp.emp_idcard empIdcard,
u.phone mobilePhone,
u.create_time createTime,
u.user_identity level,
emp.sex,
TIMESTAMPDIFF(YEAR, STR_TO_DATE(SUBSTRING(emp.emp_idcard, 7, 8), '%Y%m%d'), CURDATE()) AS age
FROM
cq_base_employee emp
LEFT JOIN sys_user u ON emp.id = u.id
LEFT JOIN sys_user_depart ud ON emp.id = ud.user_id
LEFT JOIN sys_depart d ON ud.dep_id = d.id
LEFT JOIN sys_depart dd ON LEFT ( d.org_code, 6 ) = dd.org_code
LEFT JOIN sys_depart ddd ON LEFT ( d.org_code, 9 ) = ddd.org_code
WHERE
emp.id = #{userId}
AND emp.del_flag = 0
LIMIT 1
</select>
<select id="getEmpInfo" resultType="org.jeecg.emp.vo.EmpInfoVo">
SELECT
emp.id userId,
dd.id secondDepartId,
dd.depart_name secondDepartName,
ddd.id thirdDepartId,
ddd.depart_name thirdDepartName,
u.realname,
emp.emp_idcard empIdcard,
u.phone mobilePhone,
u.work_no workNo,
emp.sex,
TIMESTAMPDIFF(YEAR, STR_TO_DATE(SUBSTRING(emp.emp_idcard, 7, 8), '%Y%m%d'), CURDATE()) AS age
FROM
cq_base_employee emp
LEFT JOIN sys_user u ON emp.id = u.id AND u.del_flag = 0
LEFT JOIN sys_user_depart ud ON emp.id = ud.user_id AND ud.del_flag = 0
LEFT JOIN sys_depart d ON ud.dep_id = d.id AND d.del_flag = 0
LEFT JOIN sys_depart dd ON LEFT ( d.org_code, 6 ) = dd.org_code AND dd.del_flag = 0
LEFT JOIN sys_depart ddd ON LEFT ( d.org_code, 9 ) = ddd.org_code AND ddd.del_flag = 0
WHERE
emp.del_flag = 0
AND emp.emp_idcard = #{idcard}
LIMIT 1
</select>
<select id="getEmpInfoByUsername" resultType="org.jeecg.emp.vo.EmpInfoVo">
SELECT
u.id userId,
u.depart_ids as departIds,
dd.id secondDepartId,
dd.depart_name secondDepartName,
ddd.id thirdDepartId,
ddd.depart_name thirdDepartName,
u.realname,
emp.emp_idcard empIdcard,
u.phone mobilePhone,
u.work_no workNo,
u.PASSWORD,
u.salt,
s.screen_id AS canteenId,
u.user_identity AS LEVEL
FROM
sys_user u
LEFT JOIN cq_base_employee emp ON emp.id = u.id AND emp.del_flag = 0
LEFT JOIN sys_user_depart ud ON emp.id = ud.user_id AND ud.del_flag = 0
LEFT JOIN sys_depart d ON ud.dep_id = d.id AND d.del_flag = 0
LEFT JOIN sys_depart dd ON LEFT ( d.org_code, 6 ) = dd.org_code AND dd.del_flag = 0
LEFT JOIN sys_depart ddd ON LEFT ( d.org_code, 9 ) = ddd.org_code AND ddd.del_flag = 0
LEFT JOIN sys_user_screen s ON s.user_id = u.id
WHERE
u.username = #{username}
AND u.del_flag = 0
limit 1
</select>
<select id="getPhoneByUserId" resultType="java.lang.String">
select phone from sys_user where id = #{userId}
</select>
<select id="getIdCardByUserId" resultType="java.lang.String">
select emp_idcard from cq_base_employee where id = #{userId}
</select>
<select id="getUserList" resultType="org.jeecg.user.entity.SysUser">
select *
from sys_user
where
1 = 1
<if test="list != null and list.size != 0 ">
and card_no in
<foreach collection="list" item="idCard" separator="," open="(" close=")" >
#{idCard}
</foreach>
</if>
</select>
<select id="getEmpInfoByJobNumberLimit1" resultType="org.jeecg.emp.vo.EmpInfoVo">
SELECT
u.id userId,
u.depart_ids as departIds,
dd.id secondDepartId,
dd.depart_name secondDepartName,
ddd.id thirdDepartId,
ddd.depart_name thirdDepartName,
u.realname,
emp.emp_idcard empIdcard,
u.phone mobilePhone,
u.work_no workNo,
u.PASSWORD,
u.salt,
u.user_identity AS LEVEL
FROM
sys_user u
LEFT JOIN cq_base_employee emp ON emp.id = u.id AND emp.del_flag = 0
LEFT JOIN sys_user_depart ud ON emp.id = ud.user_id AND ud.del_flag = 0
LEFT JOIN sys_depart d ON ud.dep_id = d.id AND d.del_flag = 0
LEFT JOIN sys_depart dd ON LEFT ( d.org_code, 6 ) = dd.org_code AND d.del_flag = 0
LEFT JOIN sys_depart ddd ON LEFT ( d.org_code, 9 ) = ddd.org_code AND ddd.del_flag = 0
WHERE
u.work_no = #{workNo}
AND u.del_flag = 0
limit 1
</select>
<select id="getEmpInfoByUsernameList" resultType="org.jeecg.emp.vo.EmpInfoVo">
SELECT
u.id userId,
u.depart_ids as departIds,
dd.id secondDepartId,
dd.depart_name secondDepartName,
ddd.id thirdDepartId,
ddd.depart_name thirdDepartName,
u.realname,
emp.emp_idcard empIdcard,
u.phone mobilePhone,
u.work_no workNo,
u.PASSWORD,
u.salt,
u.user_identity AS LEVEL
FROM
sys_user u
LEFT JOIN cq_base_employee emp ON emp.id = u.id AND emp.del_flag = 0
LEFT JOIN sys_user_depart ud ON emp.id = ud.user_id AND ud.del_flag = 0
LEFT JOIN sys_depart d ON ud.dep_id = d.id AND d.del_flag = 0
LEFT JOIN sys_depart dd ON LEFT ( d.org_code, 6 ) = dd.org_code AND d.del_flag = 0
LEFT JOIN sys_depart ddd ON LEFT ( d.org_code, 9 ) = ddd.org_code AND ddd.del_flag = 0
WHERE
u.username = #{username}
AND u.del_flag = 0
</select>
<select id="getEmpInfoVoByUserId" resultType="org.jeecg.emp.vo.EmpInfoVo">
SELECT
u.id userId,
dd.id secondDepartId,
dd.depart_name secondDepartName,
ddd.id thirdDepartId,
ddd.depart_name thirdDepartName,
u.realname,
emp.emp_idcard empIdcard,
u.phone mobilePhone,
u.work_no workNo,
u.PASSWORD,
u.salt,
u.user_identity AS LEVEL
FROM
sys_user u
LEFT JOIN cq_base_employee emp ON emp.id = u.id AND emp.del_flag = 0
LEFT JOIN sys_user_depart ud ON emp.id = ud.user_id AND ud.del_flag = 0
LEFT JOIN sys_depart d ON ud.dep_id = d.id AND d.del_flag = 0
LEFT JOIN sys_depart dd ON LEFT ( d.org_code, 6 ) = dd.org_code AND d.del_flag = 0
LEFT JOIN sys_depart ddd ON LEFT ( d.org_code, 9 ) = ddd.org_code AND ddd.del_flag = 0
WHERE
u.id = #{userId}
AND u.del_flag = 0
limit 1
</select>
</mapper>
@@ -0,0 +1,41 @@
package org.jeecg.emp.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.common.api.vo.Result;
import org.jeecg.emp.entity.CqBaseEmployee;
import org.jeecg.emp.vo.CqBaseEmpVo;
import org.jeecg.emp.vo.DepartVo;
import org.jeecg.user.entity.SysUser;
import org.jeecg.user.entity.SysUserSub;
import org.jeecg.user.vo.SysUserSubVo;
import java.util.List;
/**
* @Description: 员工信息表
* @Author: jeecg-boot
* @Date: 2021-12-31
* @Version: V1.0
*/
public interface ICqBaseEmployeeService extends IService<CqBaseEmployee> {
public Result<?> saveEmpSub(SysUserSub jsonObject);
Page<CqBaseEmpVo> queryListV2(Page<CqBaseEmpVo> pageList, CqBaseEmpVo baseEmpVo);
Page<CqBaseEmpVo> queryListV3(Page<CqBaseEmpVo> pageList, CqBaseEmpVo baseEmpVo);
Result<?> updateEmpSub(SysUserSub jsonObject);
Result<?> cancellationAndRecovery(SysUserSubVo sysUserSub);
/**
* 获取二级部门列表
*
* @return
*/
public List<DepartVo> getSecondDepartList();
List<SysUser> getUserList(List<String> idCardList);
}
@@ -0,0 +1,176 @@
package org.jeecg.emp.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.util.*;
import org.jeecg.emp.entity.CqBaseEmployee;
import org.jeecg.emp.mapper.CqBaseEmployeeMapper;
import org.jeecg.emp.service.ICqBaseEmployeeService;
import org.jeecg.emp.vo.CqBaseEmpVo;
import org.jeecg.emp.vo.DepartVo;
import org.jeecg.system.service.ISysPayDepartService;
import org.jeecg.system.service.ISysUserService;
import org.jeecg.system.service.ISysUserSubService;
import org.jeecg.user.entity.SysUser;
import org.jeecg.user.entity.SysUserSub;
import org.jeecg.user.vo.SysUserSubVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @Description: 员工信息表
* @Author: jeecg-boot
* @Date: 2021-12-31
* @Version: V1.0
*/
@Service
@Slf4j
public class CqBaseEmployeeServiceImpl extends ServiceImpl<CqBaseEmployeeMapper, CqBaseEmployee> implements ICqBaseEmployeeService {
@Resource
private CqBaseEmployeeMapper employeeMapper;
@Autowired
private ICqBaseEmployeeService cqBaseEmployeeService;
@Resource
private ISysUserSubService sysUserSubService;
@Resource
private ISysUserService sysUserService;
@Resource
private ISysPayDepartService iSysPayDepartService;
@Override
public Result<?> saveEmpSub(SysUserSub user) {
Result<?> result = new Result<>();
try {
//设置创建时间
user.setCreateTime(new Date());
user.setStatus(1);
user.setDelFlag(CommonConstant.DEL_FLAG_0);
user.setSysOrgCode("A01A54");//20250411 余:同一放采气六厂的,orgCode A01A54
user.setUserIdentity(6);
if(StringUtils.isBlank(user.getMainUserId())){
user.setMainUserId(null);
user.setUserType(1);//非正式员工
} else {
user.setUserType(2);//家庭用户
}
Result result1 = sysUserService.saveUserSub(user);
if(result1.getCode() != 200){
return result1;
}
result.success("添加成功!");
result.setMessage("添加成功!");
} catch (Exception e) {
log.error(e.getMessage(), e);
result.error500("操作失败");
}
return result;
}
@Override
public Page<CqBaseEmpVo> queryListV2(Page<CqBaseEmpVo> page, CqBaseEmpVo baseEmpVo) {
//SQL注入:MyBatis-高危解决
if(StringUtils.isNotBlank(baseEmpVo.getDepartId())){
List<String> allCascadeDeptIds = iSysPayDepartService.getAllCascadeDeptIds(baseEmpVo.getDepartId());
if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(allCascadeDeptIds)){
baseEmpVo.setList(allCascadeDeptIds);
}
}
List<CqBaseEmpVo> list = employeeMapper.queryListV2(page, baseEmpVo);
if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(list)){
List<String> stringList = list.stream().map(CqBaseEmpVo::getId).collect(Collectors.toList());
List<CqBaseEmpVo> subList = employeeMapper.queryListSubUser(stringList);
list.forEach(user->{
List<CqBaseEmpVo> subUserList = subList.stream().filter(emp -> emp.getMainUserId().equals(user.getId())).collect(Collectors.toList());
user.setSubUserList(subUserList);
});
}
return page.setRecords(list);
}
@Override
public Page<CqBaseEmpVo> queryListV3(Page<CqBaseEmpVo> page, CqBaseEmpVo baseEmpVo) {
//SQL注入:MyBatis-高危解决
List<CqBaseEmpVo> list = employeeMapper.selectUserTreePage(page, baseEmpVo);
return page.setRecords(list);
}
@Override
public Result<?> updateEmpSub(SysUserSub jsonObject) {
Result<?> result = new Result<SysUserSub>();
try {
//更新用户表
SysUserSub sysUser = sysUserSubService.getById(jsonObject.getId());
BeanUtils.copyProperties(jsonObject, sysUser);
sysUser.setUpdateTime(new Date());//设置创建时间
sysUserService.editUserSub(sysUser);
result.success("编辑成功!");
} catch (Exception e) {
log.error(e.getMessage(), e);
result.error500("操作失败");
}
return result;
}
@Override
public Result<?> cancellationAndRecovery(SysUserSubVo sysUserSub){
//用户类型(0: 正式员工 1:非正式员工,2:家庭用户)
//当前用户是正式员工:停用用户+钱包状态 钱包状态(1-禁用,0-正常)'
//当前用户是非正式员工:停用用户+钱包状态 钱包状态(1-禁用,0-正常)'
//当前用户是家庭用户:停用用户状态(状态(1:正常 2:冻结 ))
SysUserSub sysUserSub1 = sysUserSubService.getById(sysUserSub.getUserId());
if(null == sysUserSub1){
return Result.error("用户不存在");
}
if(0 == sysUserSub1.getUserType() || 1 == sysUserSub1.getUserType()){
Map<String, Object> params = new HashMap<>();
params.put("memberId", sysUserSub.getUserId());
//状态(1:正常 2:作废
if(1 == sysUserSub.getStatus()){
params.put("isStatus", 0); // 钱包状态(1-禁用,0-正常)'
}
if(2 == sysUserSub.getStatus()){
params.put("isStatus", 1); // 钱包状态(1-禁用,0-正常)'
}
employeeMapper.updateIsStatusByMemberId(params);
}
Map<String, Object> params = new HashMap<>();
params.put("id", sysUserSub.getUserId());
params.put("status", sysUserSub.getStatus()); // 停用用户状态(状态(1:正常 2:冻结 ))
String name = sysUserSub.getStatus() == 1 ? "恢复正常" : "冻结";
String msg = DateUtils.formatDateTime() + "用户【"+sysUserSub1.getRealname()+"】被"+name;
params.put("remark", sysUserSub1.getRemark()+","+msg);
employeeMapper.updateStatusById(params);
return Result.OK("操作成功");
}
@Override
public List<DepartVo> getSecondDepartList() {
return employeeMapper.getSecondDepartList();
}
@Override
public List<SysUser> getUserList(List<String> idCardList) {
return baseMapper.getUserList(idCardList);
}
}
@@ -0,0 +1,24 @@
package org.jeecg.equipment.controller;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.equipment.entity.StEquipment;
import org.jeecg.equipment.service.IStEquipmentService;
import org.springframework.web.bind.annotation.*;
/**
* @Description: 设备管理表
* @Author: jeecg-boot
* @Date: 2022-08-30
* @Version: V1.0
*/
@Tag(name="设备管理表")
@RestController
@RequestMapping("/equipment/stEquipment")
@Slf4j
public class StEquipmentController extends JeecgController<StEquipment, IStEquipmentService> {
}
@@ -0,0 +1,55 @@
package org.jeecg.equipment.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.equipment.entity.StEquipment;
import org.jeecg.equipment.service.IStEquipmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @Description: 设备管理表
* @Author: jeecg-boot
* @Date: 2022-08-30
* @Version: V1.0
*/
@Tag(name="设备管理表")
@RestController
@RequestMapping("/restaurant/equipment/stEquipment")
@Slf4j
public class StRestaurantEquipmentController extends JeecgController<StEquipment, IStEquipmentService> {
@Autowired
private IStEquipmentService stEquipmentService;
/**
* 食堂直连外网设备统一根据设备号获取token(配比秤)
*/
@Operation(summary = "食堂直连外网设备统一根据设备号获取token", description = "食堂直连外网设备统一根据设备号获取token")
@GetMapping("/getEquipmentToken")
@AutoLog(value = "食堂直连外网设备统一根据设备号获取token")
public Result getEquipmentToken(@RequestParam String qrcodeId) {
if(StringUtils.isBlank(qrcodeId)){
return Result.error("设备编号不能为空");
}
LambdaQueryWrapper<StEquipment> stEquipmentLambdaQueryWrapper = new LambdaQueryWrapper<>();
stEquipmentLambdaQueryWrapper.eq(StEquipment::getEquipmentCode, qrcodeId);
stEquipmentLambdaQueryWrapper.orderByDesc(StEquipment::getCreateTime);
List<StEquipment> stEquipmentList = stEquipmentService.list(stEquipmentLambdaQueryWrapper);
if(org.apache.commons.collections4.CollectionUtils.isEmpty(stEquipmentList)){
log.error("根据设备号获取token,异常:设备编号不存在,qrcodeId="+qrcodeId);
return Result.error("设备编号不存在");
}
String token = JwtUtil.signUserId("0000000000000000001", qrcodeId, qrcodeId,"4");
return Result.OK(token);
}
}
@@ -0,0 +1,14 @@
package org.jeecg.equipment.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.equipment.entity.StEquipment;
/**
* @Description: 设备管理表
* @Author: jeecg-boot
* @Date: 2022-08-30
* @Version: V1.0
*/
public interface StEquipmentMapper extends BaseMapper<StEquipment> {
}
@@ -0,0 +1,15 @@
package org.jeecg.equipment.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.equipment.entity.StWeighSacleOrgCode;
/**
* @Description: 体重秤设备二级部门关系表
* @Author: jeecg-boot
* @Date: 2022-09-16
* @Version: V1.0
*/
public interface StWeighSacleOrgCodeMapper extends BaseMapper<StWeighSacleOrgCode> {
}
@@ -0,0 +1,5 @@
<?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="org.jeecg.equipment.mapper.StEquipmentMapper">
</mapper>
@@ -0,0 +1,5 @@
<?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="org.jeecg.equipment.mapper.StWeighSacleOrgCodeMapper">
</mapper>
@@ -0,0 +1,14 @@
package org.jeecg.equipment.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.equipment.entity.StEquipment;
/**
* @Description: 设备管理表
* @Author: jeecg-boot
* @Date: 2022-08-30
* @Version: V1.0
*/
public interface IStEquipmentService extends IService<StEquipment> {
}
@@ -0,0 +1,14 @@
package org.jeecg.equipment.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.equipment.entity.StWeighSacleOrgCode;
/**
* @Description: 体重秤设备二级部门关系表
* @Author: jeecg-boot
* @Version: V1.0
*/
public interface IStWeighSacleOrgCodeService extends IService<StWeighSacleOrgCode> {
}
@@ -0,0 +1,19 @@
package org.jeecg.equipment.service.impl;
import org.jeecg.equipment.entity.StEquipment;
import org.jeecg.equipment.mapper.StEquipmentMapper;
import org.jeecg.equipment.service.IStEquipmentService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
/**
* @Description: 设备管理表
* @Author: jeecg-boot
* @Date: 2022-08-30
* @Version: V1.0
*/
@Service
public class StEquipmentServiceImpl extends ServiceImpl<StEquipmentMapper, StEquipment> implements IStEquipmentService {
}
@@ -0,0 +1,18 @@
package org.jeecg.equipment.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.equipment.entity.StWeighSacleOrgCode;
import org.jeecg.equipment.mapper.StWeighSacleOrgCodeMapper;
import org.jeecg.equipment.service.IStWeighSacleOrgCodeService;
import org.springframework.stereotype.Service;
/**
* @Description: 体重秤设备二级部门关系表
* @Author: jeecg-boot
* @Date: 2022-09-16
* @Version: V1.0
*/
@Service
public class StWeighSacleOrgCodeServiceImpl extends ServiceImpl<StWeighSacleOrgCodeMapper, StWeighSacleOrgCode> implements IStWeighSacleOrgCodeService {
}
@@ -0,0 +1,61 @@
package org.jeecg.face.factory;
import com.arcsoft.face.EngineConfiguration;
import com.arcsoft.face.FaceEngine;
import com.arcsoft.face.enums.ErrorInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
@Slf4j
public class FaceEngineFactory extends BasePooledObjectFactory<FaceEngine> {
private String libPath;
private String appId;
private String sdkKey;
private String activeKey;
private EngineConfiguration engineConfiguration;
public FaceEngineFactory(String libPath, String appId, String sdkKey, String activeKey, EngineConfiguration engineConfiguration) {
this.appId = appId;
this.sdkKey = sdkKey;
this.activeKey = activeKey;
this.libPath = libPath;
this.engineConfiguration = engineConfiguration;
}
@Override
public FaceEngine create() {
FaceEngine faceEngine = new FaceEngine(libPath);
int activeCode = faceEngine.activeOnline(appId, sdkKey, activeKey);
if (activeCode != ErrorInfo.MOK.getValue() && activeCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) {
log.error("引擎激活失败" + activeCode);
// throw new BusinessException("引擎激活失败" + activeCode);
}
int initCode = faceEngine.init(engineConfiguration);
if (initCode != ErrorInfo.MOK.getValue()) {
log.error("引擎初始化失败" + initCode);
// throw new BusinessException(ErrorCodeEnum.FAIL, "引擎初始化失败" + initCode);
}
return faceEngine;
}
@Override
public PooledObject<FaceEngine> wrap(FaceEngine faceEngine) {
return new DefaultPooledObject<>(faceEngine);
}
@Override
public void destroyObject(PooledObject<FaceEngine> p) throws Exception {
FaceEngine faceEngine = p.getObject();
int result = faceEngine.unInit();
super.destroyObject(p);
}
}
@@ -0,0 +1,25 @@
package org.jeecg.face.service;
import com.arcsoft.face.FaceInfo;
import com.arcsoft.face.toolkit.ImageInfo;
import org.jeecg.user.vo.UserCompareInfo;
import org.jeecg.user.vo.UserFaceInfo;
import java.util.List;
public interface FaceEngineService {
// 人脸数据键名
String FACE_CACHE = "FACE_CACHE";
// 食堂支付人脸数据键名
String FACE_CACHE_PAY = "FACE_CACHE_PAY";
List<FaceInfo> detectFaces(ImageInfo imageInfo);
byte[] extractFaceFeature(ImageInfo imageInfo, FaceInfo faceInfo);
List<UserCompareInfo> faceRecognition(byte[] faceFeature, List<UserFaceInfo> userInfoList, float passRate);
}
@@ -0,0 +1,250 @@
package org.jeecg.face.service.impl;
import com.arcsoft.face.*;
import com.arcsoft.face.enums.DetectMode;
import com.arcsoft.face.enums.DetectOrient;
import com.arcsoft.face.enums.ExtractType;
import com.arcsoft.face.toolkit.ImageInfo;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.jeecg.common.executor.CustomExecutors;
import org.jeecg.face.factory.FaceEngineFactory;
import org.jeecg.face.service.FaceEngineService;
import org.jeecg.system.service.UserFaceCacheService;
import org.jeecg.user.vo.UserCompareInfo;
import org.jeecg.user.vo.UserFaceInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
@Service("faceEngineService")
@Slf4j
public class FaceEngineServiceImpl implements FaceEngineService {
@Value(value = "${face.appId}")
private String appId;
@Value(value = "${face.sdkKey}")
private String sdkKey;
@Value(value = "${face.activeKey}")
private String activeKey;
@Value(value = "${face.libPath}")
private String libPath;
@Value(value = "${detect.pool.size}")
public Integer detectPooSize;
@Value(value = "${compare.pool.size}")
public Integer comparePooSize;
private ExecutorService compareExecutorService;
//通用人脸识别引擎池
private GenericObjectPool<FaceEngine> faceEngineGeneralPool;
//人脸比对引擎池
private GenericObjectPool<FaceEngine> faceEngineComparePool;
@Autowired
private UserFaceCacheService userFaceCacheService;
//初始化注册人脸,注册到本地内存
@PostConstruct
public void initFace() {
//查询所有人脸信息
CustomExecutors.execute(() -> {
//存放到redis
userFaceCacheService.init();
});
log.info("正在初始化人脸数据中~");
}
@PostConstruct
public void init() {
log.info("初始化人脸特征比较线程池及人脸引擎---开始");
GenericObjectPoolConfig detectPoolConfig = new GenericObjectPoolConfig();
detectPoolConfig.setMaxIdle(detectPooSize);
detectPoolConfig.setMaxTotal(detectPooSize);
detectPoolConfig.setMinIdle(detectPooSize);
detectPoolConfig.setLifo(false);
//引擎配置
EngineConfiguration detectCfg = new EngineConfiguration();
detectCfg.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);//图片检测模式,如果是连续帧的视频流图片,那么改成VIDEO模式
detectCfg.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);//人脸旋转角度
detectCfg.setDetectFaceMaxNum(10);
// 功能配置
FunctionConfiguration detectFunctionCfg = new FunctionConfiguration();
detectFunctionCfg.setSupportFaceDetect(true);//开启人脸检测功能
detectFunctionCfg.setSupportFaceRecognition(true);//开启人脸识别功能
detectFunctionCfg.setSupportAge(true);//开启年龄检测功能
detectFunctionCfg.setSupportGender(true);//开启性别检测功能
detectFunctionCfg.setSupportLiveness(true);//开启活体检测功能
detectFunctionCfg.setSupportIRLiveness(true);
detectFunctionCfg.setSupportImageQuality(true);
detectFunctionCfg.setSupportMaskDetect(true);
detectFunctionCfg.setSupportUpdateFaceData(true);
detectCfg.setFunctionConfiguration(detectFunctionCfg);
faceEngineGeneralPool = new GenericObjectPool(new FaceEngineFactory(System.getProperty("user.dir")+ File.separator+libPath, appId, sdkKey, activeKey, detectCfg), detectPoolConfig);//底层库算法对象池
//初始化特征比较线程池
GenericObjectPoolConfig comparePoolConfig = new GenericObjectPoolConfig();
comparePoolConfig.setMaxIdle(comparePooSize);
comparePoolConfig.setMaxTotal(comparePooSize);
comparePoolConfig.setMinIdle(comparePooSize);
comparePoolConfig.setLifo(false);
EngineConfiguration compareCfg = new EngineConfiguration();
FunctionConfiguration compareFunctionCfg = new FunctionConfiguration();
compareFunctionCfg.setSupportFaceRecognition(true);//开启人脸识别功能
compareCfg.setFunctionConfiguration(compareFunctionCfg);
compareCfg.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);//图片检测模式,如果是连续帧的视频流图片,那么改成VIDEO模式
compareCfg.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);//人脸旋转角度
compareExecutorService = Executors.newFixedThreadPool(comparePooSize);
faceEngineComparePool = new GenericObjectPool(new FaceEngineFactory(System.getProperty("user.dir")+ File.separator+libPath, appId, sdkKey, activeKey, compareCfg), comparePoolConfig);
log.info("初始化人脸特征比较线程池及人脸引擎---完成");
}
private class CompareFaceTask implements Callable<List<UserCompareInfo>> {
private List<UserFaceInfo> userInfoList;
private FaceFeature targetFaceFeature;
private float passRate;
public CompareFaceTask(List<UserFaceInfo> userInfoList, FaceFeature targetFaceFeature, float passRate) {
this.userInfoList = userInfoList;
this.targetFaceFeature = targetFaceFeature;
this.passRate = passRate;
}
@Override
public List<UserCompareInfo> call() throws Exception {
FaceEngine faceEngine = null;
List<UserCompareInfo> resultUserInfoList = Lists.newLinkedList();//识别到的人脸列表
try {
faceEngine = faceEngineComparePool.borrowObject();
for (UserFaceInfo userInfo : userInfoList) {
FaceFeature sourceFaceFeature = new FaceFeature();
sourceFaceFeature.setFeatureData(userInfo.getFaceFeature());
FaceSimilar faceSimilar = new FaceSimilar();
faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);
if (faceSimilar.getScore() > passRate) {//相似值大于配置预期,加入到识别到人脸的列表
UserCompareInfo info = new UserCompareInfo();
info.setUserId(userInfo.getUserId());
info.setSimilar(faceSimilar.getScore());
resultUserInfoList.add(info);
}
}
} catch (Exception e) {
log.error("", e);
} finally {
if (faceEngine != null) {
faceEngineComparePool.returnObject(faceEngine);
}
}
return resultUserInfoList;
}
}
@Override
public List<UserCompareInfo> faceRecognition(byte[] faceFeature, List<UserFaceInfo> userInfoList, float passRate) {
List<UserCompareInfo> resultUserInfoList = Lists.newLinkedList();//识别到的人脸列表
FaceFeature targetFaceFeature = new FaceFeature();
targetFaceFeature.setFeatureData(faceFeature);
List<List<UserFaceInfo>> faceUserInfoPartList = Lists.partition(userInfoList, 1000);//分成1000一组,多线程处理
CompletionService<List<UserCompareInfo>> completionService = new ExecutorCompletionService(compareExecutorService);
for (List<UserFaceInfo> part : faceUserInfoPartList) {
completionService.submit(new CompareFaceTask(part, targetFaceFeature, passRate));
}
for (int i = 0; i < faceUserInfoPartList.size(); i++) {
List<UserCompareInfo> faceUserInfoList = null;
try {
faceUserInfoList = completionService.take().get();
} catch (InterruptedException | ExecutionException e) {
}
if (CollectionUtils.isNotEmpty(userInfoList)) {
resultUserInfoList.addAll(faceUserInfoList);
}
}
resultUserInfoList.sort((h1, h2) -> h2.getSimilar().compareTo(h1.getSimilar()));//从大到小排序
return resultUserInfoList;
}
/**
* 人脸特征
*
* @param imageInfo
* @return
*/
@Override
public byte[] extractFaceFeature(ImageInfo imageInfo, FaceInfo faceInfo) {
FaceEngine faceEngine = null;
try {
faceEngine = faceEngineGeneralPool.borrowObject();
if (faceEngine == null) {
log.error("获取引擎失败");
return null;
}
FaceFeature faceFeature = new FaceFeature();
//提取人脸特征
int errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfo, ExtractType.REGISTER, 0,faceFeature);
if (errorCode == 0) {
return faceFeature.getFeatureData();
} else {
log.error("特征提取失败,errorCode" + errorCode);
}
} catch (Exception e) {
log.error("", e);
} finally {
if (faceEngine != null) {
//释放引擎对象
faceEngineGeneralPool.returnObject(faceEngine);
}
}
return null;
}
@Override
public List<FaceInfo> detectFaces(ImageInfo imageInfo) {
FaceEngine faceEngine = null;
try {
faceEngine = faceEngineGeneralPool.borrowObject();
if (faceEngine == null) {
log.error("获取引擎失败");
return null;
}
//人脸检测得到人脸列表
List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
//人脸检测
int errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
if (errorCode == 0) {
return faceInfoList;
} else {
log.error("人脸检测失败,errorCode" + errorCode);
}
} catch (Exception e) {
log.error("", e);
} finally {
if (faceEngine != null) {
//释放引擎对象
faceEngineGeneralPool.returnObject(faceEngine);
}
}
return null;
}
}
@@ -0,0 +1,429 @@
package org.jeecg.pay.controller;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.equipment.entity.StEquipment;
import org.jeecg.equipment.service.IStEquipmentService;
import org.jeecg.payment.entity.StBbzxOrderInfo;
import org.jeecg.payment.listUtils.MapUtil;
import org.jeecg.payment.service.IStBbzxOrderInfoService;
import org.jeecg.payment.service.IStClientMemberBalanceService;
import org.jeecg.payment.service.IStClientMemberLevelDeductRuleService;
import org.jeecg.payment.vo.*;
import org.jeecg.restaurant.entity.SlBaseDinnerTime;
import org.jeecg.restaurant.entity.SlBaseRestaurant;
import org.jeecg.restaurant.service.ISlBaseDinnerTimeService;
import org.jeecg.restaurant.service.ISlBaseRestaurantService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
/**
食堂API接口支付相关
* @throws
* @since
*/
@Tag(name = "0.食堂API接口支付相关 ")
@RestController
@RequestMapping("/zhstapi/pay/")
@Slf4j
public class StPayController {
// @Autowired
// private IStBaseService stBaseService;
@Autowired
private ISlBaseRestaurantService slBaseRestaurantService;
@Autowired
private RedisUtil redisUtil;
@Resource
private IStClientMemberBalanceService iStClientMemberBalanceService;
@Resource
private IStBbzxOrderInfoService iStBbzxOrderInfoService;
@Resource
private IStClientMemberLevelDeductRuleService iStClientMemberLevelDeductRuleService;
@Autowired
private IStEquipmentService iStEquipmentService;
@Resource
private ISlBaseDinnerTimeService slBaseDinnerTimeService;
/**
* 根据设备号获取token
*/
@Operation(summary = "根据设备号获取token", description = "根据设备号获取token")
@GetMapping("/getEquipmentToken")
@AutoLog(value = "根据设备号获取token")
public Result getEquipmentToken(@RequestParam String qrcodeId) {
if(StringUtils.isNotBlank(qrcodeId)){
LambdaQueryWrapper<StEquipment> stEquipmentLambdaQueryWrapper = new LambdaQueryWrapper<>();
stEquipmentLambdaQueryWrapper.eq(StEquipment::getEquipmentCode, qrcodeId);
stEquipmentLambdaQueryWrapper.orderByDesc(StEquipment::getCreateTime);
List<StEquipment> stEquipmentList = iStEquipmentService.list(stEquipmentLambdaQueryWrapper);
if(CollectionUtils.isEmpty(stEquipmentList)){
log.error("根据设备号获取token,异常:设备编号不存在,qrcodeId="+qrcodeId);
return Result.error("设备编号不存在");
} else {
// try {
// //查询设备编码
// StEquipment stEquipment = stEquipmentList.get(0);
// String canteenId = slBaseRestaurantService.getCanteenId(stEquipment.getCanteenId());
// SlBaseDinnerTime slBaseDinnerTime = stBaseService.getCanteenDinnerType(canteenId);
// if(null != slBaseDinnerTime && StringUtils.isNotBlank(slBaseDinnerTime.getDinnerType())){
// String timesName = slBaseDinnerTime.getDinnerType();
// //异步上传设备统计信息
// iStRfidDeviceLogService.syncUploadDeviceInfo(qrcodeId,canteenId,timesName,null,slBaseDinnerTime,null);
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
}
}
String token = JwtUtil.signUserId("0000000000000000001", qrcodeId, qrcodeId,"4");
return Result.OK(token);
}
@Operation(summary = "", description = "提供根据食堂ID获取食堂配置信息")
@GetMapping(value = "/getDinnerType/byCanteenId")
@AutoLog(value = "提供根据食堂ID获取食堂配置信息")
public Result<?> getCanteenInfoByCanteenId(@RequestParam(name = "restId", required = true) String restId) {
SlBaseRestaurant slBaseRestaurant = slBaseRestaurantService.getById(restId);
if(null == slBaseRestaurant){
return Result.error("食堂未找到,请检查参数");
}
//扣费规则(1:固定扣费,2:固定+补贴扣费,3:按量扣费)
StClientMemberLevelDeductRuleVo levelDeductRuleVo = iStClientMemberLevelDeductRuleService.getDeductRuleByCanteenId(restId);
if(null == levelDeductRuleVo || null == levelDeductRuleVo.getDeductionType()){
return Result.error("食堂未设置扣费规则");
}
levelDeductRuleVo.setIsOverdraftDine(slBaseRestaurant.getIsOverdraftDine());
levelDeductRuleVo.setIsExternalDineFlag(slBaseRestaurant.getIsExternalDine());
return Result.OK(levelDeductRuleVo);
}
@Operation(summary = "获取用户余额信息", description = "获取用户余额信息")
@AutoLog(value = "获取用户余额信息")
@PostMapping(value = "/getUserBalance")
public Result<StMiniMineBalanceVo> getUserBalance(@RequestBody StRfidVo stRfidVo){
Result<StMiniMineBalanceVo> stMiniMineBalanceVoResult = iStClientMemberBalanceService.getUserBalance(stRfidVo.getUserId());
StMiniMineBalanceVo stMiniMineBalanceVo = new StMiniMineBalanceVo();
if(stMiniMineBalanceVoResult.isSuccess()){
stMiniMineBalanceVo = stMiniMineBalanceVoResult.getResult();
}else {
return Result.error(stMiniMineBalanceVoResult.getMessage());
}
if(null == stMiniMineBalanceVo){
return Result.error("用户账户数据异常");
}
//根据时间判断当前餐次
SlBaseDinnerTime slBaseDinnerTime = slBaseDinnerTimeService.getCanteenDinnerType(stRfidVo.getRestId());
String timesName = slBaseDinnerTime.getDinnerType();
//从redis查询用户本餐次是否已经扣款(第一次扣款模式下扣费节点会根据,根据用户ID+日期+餐次为key,保存用户已扣费标记)
String key = stMiniMineBalanceVo.getMemberId()+ "_" + DateUtil.today() + "_" + timesName;
Object flag = redisUtil.hget(MapUtil.USER_ORDER_FLAG, key);
if(null != flag){
stMiniMineBalanceVo.setSecondReminder(true);
} else {
stMiniMineBalanceVo.setSecondReminder(false);
}
stMiniMineBalanceVo.setUserId(stRfidVo.getUserId());
stMiniMineBalanceVoResult.setResult(stMiniMineBalanceVo);
return stMiniMineBalanceVoResult;
}
@Operation(summary = "获取指定食堂的当前餐次", description = "获取指定食堂的当前餐次")
@GetMapping(value = "/getCanteenDinnerType")
@AutoLog(value = "获取指定食堂的当前餐次")
public Result<?> getCanteenDinnerType(@RequestParam(name = "restId", required = true) String restId) {
log.error("/getCanteenDinnerType 获取指定食堂的当前餐次,canteenId={}",restId);
Map<String, Object> map = new HashMap<>();
map.put("dinnerType", slBaseDinnerTimeService.getCanteenDinnerType(restId));
log.error("/getCanteenDinnerType 获取指定食堂的当前餐次,canteenId={},返回值{}",restId,JSONObject.toJSONString(map));
return Result.OK(map);
}
@Operation(summary = "离线人脸扣费v2", description = "离线人脸扣费v2")
@PostMapping(value = "/payUser/offline")
@AutoLog(value = "离线人脸扣费v2")
public Result<StClientMemberSpendVO> bindUserOfflineV2(@RequestBody StRfidoffLineVo stRfidoffLineVo) {
String deviceCode = stRfidoffLineVo.getDeviceCode();
String restId = stRfidoffLineVo.getRestId();
List<StRfidVo> voListAll = stRfidoffLineVo.getVoList();
if(CollectionUtils.isNotEmpty(voListAll)){
//扣费规则(1:固定扣费,2:固定+补贴扣费,3:按量扣费)
StClientMemberLevelDeductRuleVo levelDeductRuleVo = iStClientMemberLevelDeductRuleService.getDeductRuleByCanteenId(restId);
if(null == levelDeductRuleVo){
log.error("食堂扣费规则未设置"+restId);
return Result.error("食堂扣费规则未设置"+restId);
}
//加异步处理
CompletableFuture.runAsync(() -> {
//将扣费信息按照餐次分组
Map<String, List<StRfidVo>> stringListMap = iStClientMemberLevelDeductRuleService.groupByMeal(voListAll,restId);
for (Map.Entry<String, List<StRfidVo>> entry : stringListMap.entrySet()) {
System.out.println("餐次: " + entry.getKey() + ", 数量: " + entry.getValue().size());
List<StRfidVo> voList = entry.getValue();
voList.forEach(stRfidVo->{
stRfidVo.setDeviceCode(deviceCode);
stRfidVo.setRestId(restId);
log.error("/payUser/offline 离线人脸扣费,bindUser={}", JSONObject.toJSONString(stRfidVo));
if(StringUtils.isNotBlank(stRfidVo.getPayId())){
StBbzxOrderInfo stBbzxOrderInfo = iStBbzxOrderInfoService.getSwBbzxOrderInfoByPayId(stRfidVo.getPayId());
if(null != stBbzxOrderInfo){
log.error("闸机记录的支付唯一id已经有支付信息,stRfidVo.getPayId()={},已经存在的数据订单编号={}",stRfidVo.getPayId(),stBbzxOrderInfo.getOrderNo());
//跳过本次循环执行下次循环
return;
}
}
//当前餐次
String timesName = entry.getKey();
//实际扣减额
BigDecimal spendMoney = BigDecimal.ZERO;//用户实际扣费金额
BigDecimal rewardDeduction = BigDecimal.ZERO;//用户扣费补贴金额
BigDecimal totalDeduction = BigDecimal.ZERO;//原订单总金额
//毫秒级时间戳
Date dateTime = new Date(Long.parseLong(stRfidVo.getDateTime()));
String userId = stRfidVo.getUserId();
Result<StMiniMineBalanceVo> userBalanceResult = iStClientMemberBalanceService.getUserBalance(userId);
StMiniMineBalanceVo stMiniMineBalanceVo = new StMiniMineBalanceVo();
if(userBalanceResult.isSuccess()){
stMiniMineBalanceVo = userBalanceResult.getResult();
} else {
log.error("离线人脸扣费v2,根据userId"+userId+"查询用户钱包数据"+userBalanceResult.getMessage());
// StClientMemberSpendDataVO stClientMemberSpendDataVO = iStClientMemberBalanceService.fixedFee(levelDeductRuleVo,timesName,totalDeduction,spendMoney,rewardDeduction,stMiniMineBalanceVo.getUserInnerType());
// spendMoney = stClientMemberSpendDataVO.getSpendMoney();
// stRfidVo.setSpendMoney(spendMoney);
iStBbzxOrderInfoService.buildOrderInfoNew(dateTime,stRfidVo.getRestId(),timesName,deviceCode,stRfidVo.getUserId(),null,null,
1,levelDeductRuleVo,"离线人脸扣费v2订单支付异常,根据userId:"+userId+",查询用户钱包数据:"+userBalanceResult.getMessage(),stRfidVo);
return;
}
//计算本次扣费金额(一次扣费模式返回实际扣费金额,按量扣费直接返回0)
StClientMemberSpendDataVO stClientMemberSpendDataVO = iStClientMemberBalanceService.fixedFee(levelDeductRuleVo,timesName,totalDeduction,spendMoney,rewardDeduction,stMiniMineBalanceVo.getUserInnerType());
spendMoney = stClientMemberSpendDataVO.getSpendMoney();
stMiniMineBalanceVo.setAmountThis(spendMoney);
String data = iStClientMemberLevelDeductRuleService.syncMemberSpendOffLine(dateTime,restId,userId,stRfidVo,timesName, stMiniMineBalanceVo,levelDeductRuleVo);
if(StringUtils.isNotBlank(data)) {
log.error("扣费操作失败: {}", data);
return;
}
});
}
});
}
return Result.OK("扣费成功");
}
/**
* 离线人脸扣费v3 ,加自定义金额、卡号扣款
* @param stRfidoffLineVo
* @return
*/
@Operation(summary = "离线人脸扣费v3", description = "离线人脸扣费v2")
@PostMapping(value = "/payUser/offline/v3")
@AutoLog(value = "离线人脸扣费v3")
public Result<StClientMemberSpendVO> bindUserOfflineV3(@RequestBody StRfidoffLineVo stRfidoffLineVo) {
return iStClientMemberLevelDeductRuleService.bindUserOfflineCardCode(stRfidoffLineVo);
}
/**
* 在线扣费
* @return
*/
@Operation(summary = "在线扣费", description = "在线扣费")
@PostMapping(value = "/payUser/online")
@AutoLog(value = "在线扣费")
public Result<StClientMemberSpendVO> bindUserOnline(@RequestBody StRfidVo stRfidVo) {
StRfidoffLineVo stRfidoffLineVo = new StRfidoffLineVo();
stRfidoffLineVo.setDeviceCode(stRfidVo.getDeviceCode());
stRfidoffLineVo.setVoList(Collections.singletonList(stRfidVo));
stRfidoffLineVo.setRestId(stRfidVo.getRestId());
return iStClientMemberLevelDeductRuleService.bindUserOfflineCardCode(stRfidoffLineVo);
}
/**
* 补偿人脸扣费闸机离线扣费方法(只考虑透支消费版本)
* @param list
* @return
*/
@Operation(summary = "补偿人脸扣费闸机离线扣费方法(只考虑透支消费版本)", description = "补偿人脸扣费闸机离线扣费方法(只考虑透支消费版本)")
@PostMapping(value = "/payUser/memberSpendOfflineCompensate")
@AutoLog(value = "补偿人脸扣费闸机离线扣费方法(只考虑透支消费版本)")
public Result<List<StClientMemberSpendVO>> memberSpendOfflineCompensate(@RequestBody List<String> list) {
return Result.OK(iStClientMemberBalanceService.memberSpendOfflineCompensate(list));
}
//============================================弃用接口========================
@Operation(summary = "获取用户二次扣费提示性-弃用前端本地保存二次扣费标记扣费数据批量提交", description = "获取用户二次扣费提示性-弃用前端本地保存二次扣费标记扣费数据批量提交")
@AutoLog(value = "获取用户二次扣费提示性-弃用前端本地保存二次扣费标记扣费数据批量提交")
@PostMapping(value = "/getUserBalance/second")
public Result<Boolean> getUserBalanceSecond(@RequestBody StRfidVo stRfidVo){
//根据时间判断当前餐次
SlBaseDinnerTime slBaseDinnerTime = slBaseDinnerTimeService.getCanteenDinnerType(stRfidVo.getRestId());
String timesName = slBaseDinnerTime.getDinnerType();
String userId = stRfidVo.getUserId();
Result<StMiniMineBalanceVo> userBalanceResult = iStClientMemberBalanceService.getUserBalance(userId);
StMiniMineBalanceVo stMiniMineBalanceVo = new StMiniMineBalanceVo();
if(userBalanceResult.isSuccess()){
stMiniMineBalanceVo = userBalanceResult.getResult();
}else {
return Result.error(userBalanceResult.getMessage());
}
if(null == stMiniMineBalanceVo){
return Result.error("用户账户数据异常");
}
//从redis查询用户本餐次是否已经扣款(第一次扣款模式下扣费节点会根据,根据用户ID+日期+餐次为key,保存用户已扣费标记)
String key = stMiniMineBalanceVo.getMemberId()+ "_" + DateUtil.today() + "_" + timesName;
Object flag = redisUtil.hget(MapUtil.USER_ORDER_FLAG, key);
if(null != flag){
return Result.OK(true);
}
return Result.OK(false);
}
@Operation(summary = "人脸扣费-弃用前端本地进行扣费批量提交扣费数据", description = "人脸扣费-弃用前端本地进行扣费批量提交扣费数据")
@PostMapping(value = "/payUser")
@AutoLog(value = "人脸扣费-弃用前端本地进行扣费批量提交扣费数据")
public Result<StClientMemberSpendVO> bindUser(@RequestBody StRfidVo stRfidVo) {
log.error("/payUser 人脸扣费,bindUser={}", JSONObject.toJSONString(stRfidVo));
if(StringUtils.isNotBlank(stRfidVo.getPayId())){
StBbzxOrderInfo stBbzxOrderInfo = iStBbzxOrderInfoService.getSwBbzxOrderInfoByPayId(stRfidVo.getPayId());
if(null != stBbzxOrderInfo){
log.error("闸机记录的支付唯一id已经有支付信息,stRfidVo.getPayId()={},已经存在的数据订单编号={}",stRfidVo.getPayId(),stBbzxOrderInfo.getOrderNo());
return Result.error("本次已支付,请勿重复支付!");
}
}
//根据时间判断当前餐次
SlBaseDinnerTime slBaseDinnerTime = slBaseDinnerTimeService.getCanteenDinnerType(stRfidVo.getRestId());
String timesName = slBaseDinnerTime.getDinnerType();
String userId = stRfidVo.getUserId();
String restId = stRfidVo.getRestId();
StClientMemberSpendVO stClientMemberSpendVO = new StClientMemberSpendVO();
//扣费规则(1:固定扣费,2:固定+补贴扣费,3:按量扣费)
StClientMemberLevelDeductRuleVo levelDeductRuleVo = iStClientMemberLevelDeductRuleService.getDeductRuleByCanteenId(restId);
if(null == levelDeductRuleVo){
log.error("食堂扣费规则未设置"+restId);
iStBbzxOrderInfoService.buildOrderInfoNew(null,restId,timesName,stRfidVo.getDeviceCode(),stRfidVo.getUserId(),null,
null,1,null,"食堂扣费规则未设置:"+restId,stRfidVo);
return Result.error("食堂扣费规则设置异常,请检查!");
}
Result<StMiniMineBalanceVo> userBalanceResult = iStClientMemberBalanceService.getUserBalance(userId);
StMiniMineBalanceVo stMiniMineBalanceVo = new StMiniMineBalanceVo();
if(userBalanceResult.isSuccess()){
stMiniMineBalanceVo = userBalanceResult.getResult();
} else {
iStBbzxOrderInfoService.buildOrderInfoNew(null,restId,timesName,stRfidVo.getDeviceCode(),stRfidVo.getUserId(),null,
null,1,null,"用户钱包异常:"+userBalanceResult.getMessage(),stRfidVo);
return Result.error(userBalanceResult.getMessage());
}
stClientMemberSpendVO.setRealname(stMiniMineBalanceVo.getRealname());
stClientMemberSpendVO.setWorkNo(stMiniMineBalanceVo.getWorkNo());
stClientMemberSpendVO.setPayRealname(stMiniMineBalanceVo.getPayRealname());
stClientMemberSpendVO.setPayWorkNo(stMiniMineBalanceVo.getPayWorkNo());
SlBaseRestaurant slBaseRestaurant = slBaseRestaurantService.getById(restId);
if (null == slBaseRestaurant) {
iStBbzxOrderInfoService.buildOrderInfoNew(null,restId,timesName,stRfidVo.getDeviceCode(),stRfidVo.getUserId(),null,
null,1,null,"食堂不存在:"+restId,stRfidVo);
return Result.error("食堂不存在");
}
//"是否支持透支消费(0:不支持,1:支持)"
Integer isOverdraftDine = slBaseRestaurant.getIsOverdraftDine();
//实际扣减额
BigDecimal spendMoney = BigDecimal.ZERO;//用户实际扣费金额
BigDecimal rewardDeduction = BigDecimal.ZERO;//用户扣费补贴金额
BigDecimal totalDeduction = BigDecimal.ZERO;//原订单总金额
//计算本次扣费金额(一次扣费模式返回实际扣费金额,按量扣费直接返回0)
StClientMemberSpendDataVO stClientMemberSpendDataVO = iStClientMemberBalanceService.fixedFee(levelDeductRuleVo,timesName,totalDeduction,spendMoney,rewardDeduction,stMiniMineBalanceVo.getUserInnerType());
spendMoney = stClientMemberSpendDataVO.getSpendMoney();
rewardDeduction = stClientMemberSpendDataVO.getRewardDeduction();
//判断食堂是否支持透支消费(此处的金额需要经过扣费规则计算实际扣费金额)
BigDecimal total = new BigDecimal(stMiniMineBalanceVo.getBalance());
// if(levelDeductRuleVo.getDeductionType() != 3){//一次扣费模式,1进行预扣费计算 + 2余额不足校验
if (spendMoney.compareTo(total) > -1 && isOverdraftDine == 0) {
return Result.error("用户余额不足!");
}
//2:进行预扣费计算
total = total.subtract(spendMoney).setScale(2, BigDecimal.ROUND_HALF_UP);
stClientMemberSpendVO.setSuccess(true);
stClientMemberSpendVO.setPreferentialPrice(rewardDeduction);
stClientMemberSpendVO.setSpendMoney(spendMoney);
stClientMemberSpendVO.setBalance(total);
//==============================================异步异步生成订单和进行实际扣费流程操作=========================================================
StMiniMineBalanceVo finalStMiniMineBalanceVo = stMiniMineBalanceVo;
finalStMiniMineBalanceVo.setAmountThis(spendMoney);
// CompletableFuture.runAsync(() -> {
String data = syncMemberSpend(null,restId,userId,stRfidVo,timesName, finalStMiniMineBalanceVo);
if(StringUtils.isNotBlank(data)) {
return Result.error(data,stClientMemberSpendVO);
}
// });
//==============================================异步异步生成订单和进行实际扣费流程操作=========================================================
return Result.OK("扣费成功",stClientMemberSpendVO);
}
/**
* 异步生成订单和进行实际扣费流程
* @param dateTime 订单时间
* @param restId
* @param userId
* @param stRfidVo
* @param timesName
*/
private String syncMemberSpend(Date dateTime,String restId,String userId,StRfidVo stRfidVo,String timesName,StMiniMineBalanceVo miniMineBalanceVo){
//统一生成订单
StBbzxOrderInfo stBbzxOrderInfo = iStBbzxOrderInfoService.crateOrderInfo(dateTime,restId,userId,stRfidVo.getDeviceCode(),timesName, stRfidVo);
if(null == stBbzxOrderInfo) {
log.error("食堂扣费规则设置异常,请检查!");
return "食堂扣费规则设置异常,请检查!";
}
StClientMemberSpendDTO stClientMemberSpendDTO = new StClientMemberSpendDTO();
stClientMemberSpendDTO.setCanteenId(stRfidVo.getRestId());
stClientMemberSpendDTO.setOrderNo(stBbzxOrderInfo.getOrderNo());
stClientMemberSpendDTO.setId(miniMineBalanceVo.getMemberId());//钱包用户id
stClientMemberSpendDTO.setMiniMineBalanceVo(miniMineBalanceVo);//钱包用户
StClientMemberSpendVO stClientMemberSpendVO = iStClientMemberBalanceService.memberSpendV3(stClientMemberSpendDTO);
if(null != stClientMemberSpendVO && !stClientMemberSpendVO.getSuccess()){
return stClientMemberSpendVO.getMsg();
} else {
return null;
}
}
}
@@ -0,0 +1,394 @@
package org.jeecg.payment.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.payment.dto.StAmountSpentEveryMemberDTO;
import org.jeecg.payment.dto.StClientMemberTransactionRecordDTO;
import org.jeecg.payment.service.IStBbzxOrderInfoService;
import org.jeecg.payment.service.IStClientMemberTransactionRecordService;
import org.jeecg.payment.utils.ExcelUtils;
import org.jeecg.payment.utils.GenericSumUtil;
import org.jeecg.payment.vo.StClientMemberTransactionRecordVO;
import org.jeecg.payment.vo.StatisticsTheAmountSpentVo;
import org.jeecg.restaurant.vo.StatisticsBusinessVo;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
* 订单 控制器
*/
@RestController
@RequestMapping("/payment/swbbzxorderinfo")
@Tag(name = "报表中心-店内订单")
@Slf4j
public class StBbzxOrderInfoController {
@Resource
private IStBbzxOrderInfoService iStBbzxOrderInfoService;
@Resource
private IStClientMemberTransactionRecordService iStClientMemberTransactionRecordService;
/**
* 食堂消费记录统计
* @return 个人消费记录统计
*/
@PostMapping("/statisticsTheAmountSpentList")
@Operation(summary = "食堂消费记录统计")
public Result<?> getStatisticsTheAmountSpentList(@RequestBody StAmountSpentEveryMemberDTO dto) {
//处理时间
if(CollectionUtils.isNotEmpty(dto.getDates())){
dto.setStartDate(dto.getDates().get(0));
dto.setEndDate(dto.getDates().get(1));
}
return Result.OK(iStBbzxOrderInfoService.getStatisticsTheAmountSpentList(dto.getCanteenId(), dto.getStartDate(), dto.getEndDate(), dto.getPageNo(), dto.getPageSize()));
}
/**
* 食堂消费记录统计总计
* @param startDate 开始时间
* @param endDate 结束时间
* @return 食堂消费记录统计总计
*/
@GetMapping("/statisticsTheAmountSpentList/sum")
@Operation(summary = "食堂消费记录统计总计")
public Result<?> getStatisticsTheAmountSpentListSum(@RequestParam(value = "canteenId", required = false) String canteenId,
@RequestParam(value = "startDate", required = false) String startDate,
@RequestParam(value = "endDate", required = false) String endDate) {
List<StatisticsTheAmountSpentVo> dataList = iStBbzxOrderInfoService.getStatisticsTheAmountSpentList(canteenId, startDate, endDate);
StatisticsTheAmountSpentVo sumResult = GenericSumUtil.sumList(dataList, StatisticsTheAmountSpentVo.class);
sumResult.setRestName("总计");
sumResult.setEatDay(startDate+"~"+endDate);
return Result.OK(sumResult);
}
/**
* 食堂消费记录统计-导出
*/
@GetMapping("/statisticsTheAmountSpentList/export")
public void statisticsTheAmountSpentListExport(HttpServletResponse response, @RequestParam(value = "canteenId", required = false) String canteenId,
@RequestParam(value = "startDate", required = false) String startDate,
@RequestParam(value = "endDate", required = false) String endDate) {
List<StatisticsTheAmountSpentVo> statisticsTheAmountSpentList = iStBbzxOrderInfoService.getStatisticsTheAmountSpentList(canteenId, startDate, endDate);
if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(statisticsTheAmountSpentList)){
StatisticsTheAmountSpentVo sumResult = GenericSumUtil.sumList(statisticsTheAmountSpentList, StatisticsTheAmountSpentVo.class);
sumResult.setRestName("总计");
sumResult.setEatDay(startDate+"~"+endDate);
statisticsTheAmountSpentList.add(sumResult);
String exportFields = "restName|食堂名称,customerPrice|消费总额(元),totalCount|消费人次,totalNum|消费人数," +
"breakfastAmount|早餐消费金额(元),breakfastPerson|早餐消费次数,lunchAmount|午餐消费金额(元),lunchPerson|午餐消费次数,dinnerAmount|晚餐消费金额(元),dinnerPerson|晚餐消费次数" +
",otherAmount|其他消费金额(元),otherPerson|其他消费次数,orderPrice|结算金额(元),eatDay|消费日期";
ExcelUtils.export(response, "食堂消费统计", statisticsTheAmountSpentList, exportFields, "yyyy-MM-dd HH:mm",true);
}
}
/**
* 个人消费记录统计
* @return 个人消费记录统计
*/
@PostMapping("/statisticsTheAmountSpentEveryMember")
@Operation(summary = "个人消费金额统计")
public Result<?> getStatisticsTheAmountSpentEveryMember(@RequestBody StAmountSpentEveryMemberDTO dto) {
String secondDepartId = null;
String thirdDepartId = null;
if(StringUtils.isNotEmpty(dto.getSecondThirdDepartIds())){
String[] split = dto.getSecondThirdDepartIds().split(",");
secondDepartId = split[0];
if(split.length > 1){
thirdDepartId = split[1];
}
}
//处理时间
if(CollectionUtils.isNotEmpty(dto.getDates())){
dto.setStartDate(dto.getDates().get(0));
dto.setEndDate(dto.getDates().get(1));
}
return Result.OK(iStBbzxOrderInfoService.statisticsTheAmountSpentEveryMember(dto.getCanteenId(),dto.getName(),dto.getPayName(),dto.getStartDate(),dto.getEndDate(),secondDepartId,thirdDepartId,dto.getPageNo(),dto.getPageSize()));
}
/**
* 个人消费记录统计总计
* @param startDate 开始时间
* @param endDate 结束时间
* @param secondThirdDepartIds 二/三级部门id
* @return 个人消费记录统计总计
*/
@GetMapping("/statisticsTheAmountSpentEveryMember/sum")
@Operation(summary = "个人消费记录统计总计")
public Result<?> getStatisticsTheAmountSpentEveryMemberSum(@RequestParam(value = "canteenId", required = false) String canteenId,
@RequestParam(value = "secondThirdDepartIds", required = false) String secondThirdDepartIds,
@RequestParam(value = "startDate", required = false) String startDate,
@RequestParam(value = "endDate", required = false) String endDate,
@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "payName", required = false) String payName) {
String secondDepartId = null;
String thirdDepartId = null;
if(StringUtils.isNotEmpty(secondThirdDepartIds)){
String[] split = secondThirdDepartIds.split(",");
secondDepartId = split[0];
if(split.length > 1){
thirdDepartId = split[1];
}
}
List<StatisticsTheAmountSpentVo> statisticsTheAmountSpentList = iStBbzxOrderInfoService.statisticsTheAmountSpentEveryMember(canteenId,name,payName,startDate, endDate,secondDepartId, thirdDepartId);
StatisticsTheAmountSpentVo sumResult = GenericSumUtil.sumList(statisticsTheAmountSpentList, StatisticsTheAmountSpentVo.class);
sumResult.setRestName("总计");
sumResult.setEatDay(startDate+"~"+endDate);
return Result.OK(sumResult);
}
/**
* 个人消费记录统计-导出
*/
@GetMapping("/statisticsTheAmountSpentEveryMember/export")
public void statisticsTheAmountSpentListExport(HttpServletResponse response,
@RequestParam(value = "canteenId", required = false) String canteenId,
@RequestParam(value = "secondThirdDepartIds", required = false) String secondThirdDepartIds,
@RequestParam(value = "startDate", required = false) String startDate,
@RequestParam(value = "endDate", required = false) String endDate,
@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "payName", required = false) String payName) {
String secondDepartId = null;
String thirdDepartId = null;
if(StringUtils.isNotEmpty(secondThirdDepartIds)){
String[] split = secondThirdDepartIds.split(",");
secondDepartId = split[0];
if(split.length > 1){
thirdDepartId = split[1];
}
}
List<StatisticsTheAmountSpentVo> statisticsTheAmountSpentList = iStBbzxOrderInfoService.statisticsTheAmountSpentEveryMember(canteenId,name,payName,startDate, endDate,secondDepartId, thirdDepartId);
if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(statisticsTheAmountSpentList)){
StatisticsTheAmountSpentVo sumResult = GenericSumUtil.sumList(statisticsTheAmountSpentList, StatisticsTheAmountSpentVo.class);
sumResult.setRealname("总计");
sumResult.setWorkNo(null);
sumResult.setDepartName(null);
sumResult.setEatDay(startDate+"~"+endDate);
statisticsTheAmountSpentList.add(sumResult);
String exportFields = "realname|姓名,customerPrice|消费总额(元),workNo|工号,departName|部门,totalCount|消费次数,totalNum|消费天数," +
"breakfastAmount|早餐消费金额(元),breakfastPerson|早餐消费次数,lunchAmount|午餐消费金额(元),lunchPerson|午餐消费次数,dinnerAmount|晚餐消费金额(元),dinnerPerson|晚餐消费次数" +
",otherAmount|其他消费金额(元),otherPerson|其他消费次数,orderPrice|结算金额(元),eatDay|消费日期";
ExcelUtils.export(response, "个人消费统计", statisticsTheAmountSpentList, exportFields, "yyyy-MM-dd HH:mm",true);
}
}
/**
* 食堂营业查询报表
* @return 食堂营业查询报表
*/
@PostMapping("/statisticsCanteenBusiness")
@Operation(summary = "食堂营业查询报表")
public Result<?> statisticsCanteenBusiness(@RequestBody StAmountSpentEveryMemberDTO dto) {
String secondDepartId = null;
String thirdDepartId = null;
if(StringUtils.isNotEmpty(dto.getSecondThirdDepartIds())){
String[] split = dto.getSecondThirdDepartIds().split(",");
secondDepartId = split[0];
if(split.length > 1){
thirdDepartId = split[1];
}
}
//处理时间
if(CollectionUtils.isNotEmpty(dto.getDates())){
dto.setStartDate(dto.getDates().get(0));
dto.setEndDate(dto.getDates().get(1));
}
return Result.OK(iStBbzxOrderInfoService.statisticsCanteenBusiness(dto.getCanteenId(), dto.getStartDate(), dto.getEndDate(), secondDepartId, thirdDepartId, dto.getPageNo(), dto.getPageSize()));
}
/**
* 食堂营业查询报表总计
* @param startDate 开始时间
* @param endDate 结束时间
* @return 食堂营业查询报表
*/
@GetMapping("/statisticsCanteenBusiness/sum")
@Operation(summary = "食堂营业查询报表总计")
public Result<?> statisticsCanteenBusiness(@RequestParam(value = "secondThirdDepartIds", required = false) String secondThirdDepartIds,
@RequestParam(value = "startDate", required = false) String startDate,
@RequestParam(value = "endDate", required = false) String endDate,
@RequestParam(value = "canteenId", required = false) String canteenId) {
String secondDepartId = null;
String thirdDepartId = null;
if(StringUtils.isNotEmpty(secondThirdDepartIds)){
String[] split = secondThirdDepartIds.split(",");
secondDepartId = split[0];
if(split.length > 1){
thirdDepartId = split[1];
}
}
List<StatisticsBusinessVo> statisticsCanteenBusiness = iStBbzxOrderInfoService.statisticsCanteenBusiness(canteenId, startDate, endDate, secondDepartId, thirdDepartId);
StatisticsBusinessVo sumResult = GenericSumUtil.sumList(statisticsCanteenBusiness, StatisticsBusinessVo.class);
sumResult.setRestName("总计");
sumResult.setPayTime(null);
return Result.OK(sumResult);
}
/**
* 食堂营业查询报表-导出
*/
@GetMapping("/statisticsCanteenBusiness/export")
public void statisticsCanteenBusinessExport(HttpServletResponse response,
@RequestParam(value = "secondThirdDepartIds", required = false) String secondThirdDepartIds,
@RequestParam(value = "startDate", required = false) String startDate,
@RequestParam(value = "endDate", required = false) String endDate,
@RequestParam(value = "canteenId", required = false) String canteenId) {
String secondDepartId = null;
String thirdDepartId = null;
if(StringUtils.isNotEmpty(secondThirdDepartIds)){
String[] split = secondThirdDepartIds.split(",");
secondDepartId = split[0];
if(split.length > 1){
thirdDepartId = split[1];
}
}
List<StatisticsBusinessVo> statisticsCanteenBusiness = iStBbzxOrderInfoService.statisticsCanteenBusiness(canteenId, startDate, endDate, secondDepartId, thirdDepartId);
if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(statisticsCanteenBusiness)){
StatisticsBusinessVo sumResult = GenericSumUtil.sumList(statisticsCanteenBusiness, StatisticsBusinessVo.class);
sumResult.setRestName("总计");
sumResult.setPayTime(null);
statisticsCanteenBusiness.add(sumResult);
String exportFields = "restName|食堂名称,payTime|日期,rechargeAmount|充值合计,totalRefund|退款合计,totalCount|消费次数合计,customerPrice|消费合计";
ExcelUtils.export(response, "食堂营业统计", statisticsCanteenBusiness, exportFields, "yyyy-MM-dd HH:mm",true);
}
}
/**
* 充值表
* @param query
* @return
*/
@PostMapping("/rechargeTransactionRecord")
@Operation(summary = "充值流水列表分页查询", description = "传入条件")
public Result<IPage<StClientMemberTransactionRecordVO>> rechargeTransactionRecord(@RequestBody StClientMemberTransactionRecordDTO query) {
if(StringUtils.isNotBlank(query.getMainTimeDay()) && query.getMainTimeDay().contains(",")){
String[] split = query.getMainTimeDay().split(",");
query.setStartTime(split[0]);
query.setEndTime(split[1]);
}
//处理时间
if(CollectionUtils.isNotEmpty(query.getDates())){
query.setStartTime(query.getDates().get(0));
query.setEndTime(query.getDates().get(1));
}
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
//餐品总库只查询内置食堂
if(sysUser.getUserIdentity().equals(CommonConstant.USER_IDENTITY_0) || sysUser.getUserIdentity().equals(CommonConstant.USER_IDENTITY_1)){
// 后期分数据权限时在解开注释,此处管理员账户能看到所有食堂数据
// ScreenVo screenVo = new ScreenVo();
// screenVo.setId(CommonConstant.INLAY_CANTEEN_ID);
// canteenIdList.add(screenVo);
} else if (sysUser.getUserIdentity().equals(CommonConstant.USER_IDENTITY_4)) {
//查询当前登录用户的食堂列表
String canteenId = sysUser.getCanteenId();
query.setCanteenId(canteenId);
} else {
return Result.OK();
}
query.setStatus(3);//(充值=102
return Result.OK(iStClientMemberTransactionRecordService.pageQuery(query));
}
/**
* 充值表汇总
* @param query
* @return
*/
@GetMapping("/rechargeTransactionRecord/sum")
@Operation(summary = "充值流水列表分页查询汇总", description = "传入条件")
public Result<?> rechargeTransactionRecordSum(StClientMemberTransactionRecordDTO query) {
if(StringUtils.isNotBlank(query.getMainTimeDay()) && query.getMainTimeDay().contains(",")){
String[] split = query.getMainTimeDay().split(",");
query.setStartTime(split[0]);
query.setEndTime(split[1]);
}
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
//餐品总库只查询内置食堂
if(sysUser.getUserIdentity().equals(CommonConstant.USER_IDENTITY_0) || sysUser.getUserIdentity().equals(CommonConstant.USER_IDENTITY_1)){
// 后期分数据权限时在解开注释,此处管理员账户能看到所有食堂数据
// ScreenVo screenVo = new ScreenVo();
// screenVo.setId(CommonConstant.INLAY_CANTEEN_ID);
// canteenIdList.add(screenVo);
} else if (sysUser.getUserIdentity().equals(CommonConstant.USER_IDENTITY_4)) {
//查询当前登录用户的食堂列表
String canteenId = sysUser.getCanteenId();
query.setCanteenId(canteenId);
} else {
return Result.OK();
}
query.setStatus(3);//(充值=102
List<StClientMemberTransactionRecordVO> statisticsCanteenBusiness = iStClientMemberTransactionRecordService.queryList(query);
StClientMemberTransactionRecordVO sumResult = GenericSumUtil.sumList(statisticsCanteenBusiness, StClientMemberTransactionRecordVO.class);
StClientMemberTransactionRecordVO stClientMemberTransactionRecordVO = new StClientMemberTransactionRecordVO();//只汇总交易金额
stClientMemberTransactionRecordVO.setSerialNo("总计");
stClientMemberTransactionRecordVO.setTransactionAmount(sumResult.getTransactionAmount());
return Result.OK(stClientMemberTransactionRecordVO);
}
/**
* 充值流水报表-导出
*/
@GetMapping("/rechargeTransactionRecord/export")
public void rechargeTransactionRecordExport(HttpServletResponse response,StClientMemberTransactionRecordDTO query) {
if(StringUtils.isNotBlank(query.getMainTimeDay()) && query.getMainTimeDay().contains(",")){
String[] split = query.getMainTimeDay().split(",");
query.setStartTime(split[0]);
query.setEndTime(split[1]);
}
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
//餐品总库只查询内置食堂
if(sysUser.getUserIdentity().equals(CommonConstant.USER_IDENTITY_0) || sysUser.getUserIdentity().equals(CommonConstant.USER_IDENTITY_1)){
// 后期分数据权限时在解开注释,此处管理员账户能看到所有食堂数据
// ScreenVo screenVo = new ScreenVo();
// screenVo.setId(CommonConstant.INLAY_CANTEEN_ID);
// canteenIdList.add(screenVo);
} else if (sysUser.getUserIdentity().equals(CommonConstant.USER_IDENTITY_4)) {
//查询当前登录用户的食堂列表
String canteenId = sysUser.getCanteenId();
query.setCanteenId(canteenId);
} else {
return;
}
query.setStatus(3);//(充值=102
List<StClientMemberTransactionRecordVO> statisticsCanteenBusiness = iStClientMemberTransactionRecordService.queryList(query);
if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(statisticsCanteenBusiness)){
StClientMemberTransactionRecordVO sumResult = GenericSumUtil.sumList(statisticsCanteenBusiness, StClientMemberTransactionRecordVO.class);
StClientMemberTransactionRecordVO stClientMemberTransactionRecordVO = new StClientMemberTransactionRecordVO();//只汇总交易金额
stClientMemberTransactionRecordVO.setSerialNo("总计");
stClientMemberTransactionRecordVO.setTransactionAmount(sumResult.getTransactionAmount());
statisticsCanteenBusiness.add(stClientMemberTransactionRecordVO);
// String exportFields = "serialNo|交易流水号,orderNo|交易单号,userName|姓名,phone|手机号,workNo|工号," +
// "statusName|操作类型,transactionAmount|交易金额,paymentMethodName|结账方式,storedBalance|储值金额变动(元),rewardBalance|赠送金额变动(元),availableBalance|余额," +
// "integralBalance|积分变动,createTime|交易时间,payTime|结账时间,updateStatusName|操作端,createOne|操作人";
String exportFields = "serialNo|交易流水号,orderNo|交易单号,userName|姓名,phone|手机号,workNo|工号," +
"transactionAmount|交易金额,statusName|操作类型,paymentMethodName|充值方式,availableBalance|现金余额," +
"createTime|充值时间,createOne|操作人";
ExcelUtils.export(response, "充值记录", statisticsCanteenBusiness, exportFields, "yyyy-MM-dd HH:mm",true);
}
}
}
@@ -0,0 +1,722 @@
package org.jeecg.payment.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.Operation;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.aspect.SendNotification;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.payment.dto.StClientMemberChangeBalanceDTO;
import org.jeecg.payment.dto.StClientMemberTopUpDTO;
import org.jeecg.payment.dto.StClientMemberTransactionRecordDTO;
import org.jeecg.payment.entity.StClientMemberBalance;
import org.jeecg.payment.entity.StClientMemberLevelDemotionTime;
import org.jeecg.payment.entity.StClientMemberTransactionRecord;
import org.jeecg.payment.enums.MemberTransactionTypeEnum;
import org.jeecg.payment.service.IStClientMemberBalanceService;
import org.jeecg.payment.service.IStClientMemberLevelDemotionTimeService;
import org.jeecg.payment.service.IStClientMemberTransactionRecordService;
import org.jeecg.payment.utils.ExcelResultGenerator;
import org.jeecg.payment.utils.ExcelUtils;
import org.jeecg.payment.utils.GenericSumUtil;
import org.jeecg.payment.vo.*;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
/**
充值管理
*/
@RestController
@RequestMapping("/payment/swClientMemberBalance")
public class StClientMemberBalanceController {
@Resource
private IStClientMemberBalanceService iStClientMemberBalanceService;
@Resource
private IStClientMemberTransactionRecordService iStClientMemberTransactionRecordService;
@Resource
private IStClientMemberLevelDemotionTimeService iStClientMemberLevelDemotionTimeService;
//==============================用户充值==================================================
/**
* 后台用户充值列表
* @param
* @return
*/
@Operation(summary = "用户充值-后台用户充值列表", description = "后台用户充值列表-列表")
@PostMapping(value = "/getSpendingOrRechargeInfoList")
public Result<IPage<StClientMemberBalanceListVO>> getSpendingOrRechargeInfoList(@RequestBody StClientMemberTransactionRecordDTO stClientUserInfoShopPageDTO){
if(StringUtils.isBlank(stClientUserInfoShopPageDTO.getCanteenId())){
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
stClientUserInfoShopPageDTO.setCanteenId(sysUser.getCanteenId());
}
//处理时间
if(org.apache.commons.collections.CollectionUtils.isNotEmpty(stClientUserInfoShopPageDTO.getDates())){
stClientUserInfoShopPageDTO.setStartTime(stClientUserInfoShopPageDTO.getDates().get(0));
stClientUserInfoShopPageDTO.setEndTime(stClientUserInfoShopPageDTO.getDates().get(1));
}
Page<StClientMemberBalanceListVO> recordListVoPage = new Page<>(stClientUserInfoShopPageDTO.getPageNo(), stClientUserInfoShopPageDTO.getPageSize());
IPage<StClientMemberBalanceListVO> stRecordListVoIPage = iStClientMemberBalanceService.memberClientMemberBalanceService(recordListVoPage,stClientUserInfoShopPageDTO);
return Result.OK(stRecordListVoIPage);
}
/**
* 用户充值-导出
*/
@GetMapping("/getSpendingOrRechargeInfoList/export")
public void getSpendingOrRechargeInfoListExport(HttpServletResponse response, StClientMemberTransactionRecordDTO stClientUserInfoShopPageDTO) {
if(StringUtils.isBlank(stClientUserInfoShopPageDTO.getCanteenId())){
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
stClientUserInfoShopPageDTO.setCanteenId(sysUser.getCanteenId());
}
List<StClientMemberBalanceListVO> statisticsTheAmountSpentList = iStClientMemberBalanceService.getSpendingOrRechargeInfoListExport(stClientUserInfoShopPageDTO);
if(CollectionUtils.isNotEmpty(statisticsTheAmountSpentList)){
String exportFields = "workNo|工号,userName|姓名,phone|联系方式,topUpBalanceTotal|总余额(元),topUpBalance|储值金额(元),rewardBalance|赠送金额(元)," +
"consumptionCount|消费次数,consumptionTotal|累计消费(元),topUpCount|充值次数,lastConsumptionTime|最后一次消费时间,firstTopUpTime|首充时间";
ExcelUtils.export(response, "用户充值", statisticsTheAmountSpentList, exportFields, "yyyy-MM-dd HH:mm",true);
}
}
@GetMapping("/memberTopUp")
@Operation(summary = "用户充值-充值(线下)", description = "传入条件")
public Result<?> memberTopUp(@RequestParam(name = "canteenId",required = false) String canteenId,@RequestParam String userId, @RequestParam BigDecimal value, @RequestParam int paymentMethod) {
if(StringUtils.isBlank(canteenId)){
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
canteenId = sysUser.getCanteenId();
}
LambdaQueryWrapper<StClientMemberBalance> clientMemberWrapper = new LambdaQueryWrapper<>();
clientMemberWrapper.eq(StClientMemberBalance::getMemberId, userId);
StClientMemberBalance balance = iStClientMemberBalanceService.getOne(clientMemberWrapper);
// Map<String, Object> map = iStClientMemberLevelDemotionTimeService.topUpAwardService(null, value.floatValue(),canteenId);
BigDecimal rewardBalance = new BigDecimal(0);
int integralBalance = 0;
StClientMemberTopUpDTO query = new StClientMemberTopUpDTO();
query.setId(balance.getId());
query.setCanteenId(canteenId);
// if(null != map){
// rewardBalance = BigDecimal.valueOf(Float.parseFloat(map.get("amount").toString()));
// integralBalance = Integer.parseInt(map.get("integral").toString());
// }
query.setTopUpBalance(value);
query.setRewardBalance(rewardBalance);
query.setIntegralBalance(integralBalance);
query.setPaymentMethod(paymentMethod);
boolean b = iStClientMemberBalanceService.memberTopUp(query);
if(b){
return Result.OK("操作成功!");
}
return Result.error("操作失败");
}
/**
* 导入充值数据
* @param file 文件
* @param canteenId 所属食堂
*/
@AutoLog(value = "导入充值数据")
@PostMapping("/importRechargeData")
public Result<?> importRechargeData(@RequestParam(name ="file", required = true) MultipartFile file,
@RequestParam(name = "canteenId",required = false) String canteenId) {
try {
// 1. 处理食堂ID
if (StringUtils.isBlank(canteenId)) {
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
canteenId = sysUser.getCanteenId();
}
// 2. 解析原始Excel
List<StClientMemberTopUpDTO> originalDtoList = iStClientMemberBalanceService.parseExcel(file, canteenId);
if (originalDtoList.isEmpty()) {
throw new RuntimeException("Excel文件中无有效数据,请检查文件内容");
}
// 3. 执行充值并获取结果
Map<String, List<StClientMemberTopUpDTO>> rechargeResultMap =
iStClientMemberBalanceService.importRechargeDataV2(originalDtoList);
// 4. 全部成功时返回指定JSON格式
if (rechargeResultMap.containsKey("allSuccess") &&
CollectionUtils.isNotEmpty(rechargeResultMap.getOrDefault("allSuccess", Collections.emptyList()))) {
return Result.OK("导入成功");
} else {
// 4. 提取各类结果列表
List<StClientMemberTopUpDTO> successList = rechargeResultMap.getOrDefault("newListSuccess", Collections.emptyList());
List<StClientMemberTopUpDTO> failList = rechargeResultMap.getOrDefault("newListFailure", Collections.emptyList());
List<StClientMemberTopUpDTO> duplicateSerialList = rechargeResultMap.getOrDefault("oldList", Collections.emptyList());
List<StClientMemberTopUpDTO> multiUserList = rechargeResultMap.getOrDefault("userListMoreFailure", Collections.emptyList());
List<StClientMemberTopUpDTO> missingUserList = rechargeResultMap.getOrDefault("userListMissingFailure", Collections.emptyList());
List<String> successCardNos = successList.stream()
.map(StClientMemberTopUpDTO::getCardNo)
.collect(Collectors.toList());
List<String> failCardNos = failList.stream()//充值执行失败
.map(StClientMemberTopUpDTO::getCardNo)
.collect(Collectors.toList());
List<String> duplicateSerialCardNos = duplicateSerialList.stream()//缴费单号历史已导入
.map(StClientMemberTopUpDTO::getSerialNo)
.collect(Collectors.toList());
List<String> multiUserCardNos = multiUserList.stream()//用户/钱包信息重复
.map(StClientMemberTopUpDTO::getCardNo)
.collect(Collectors.toList());
List<String> missingUserCardNos = missingUserList.stream()//用户/钱包信息缺失
.map(StClientMemberTopUpDTO::getCardNo)
.collect(Collectors.toList());
// 构建失败信息字符串
StringBuilder errorMsg = new StringBuilder();
// 充值执行失败(非空才添加)
if (!failCardNos.isEmpty()) {
errorMsg.append("充值执行失败:").append(failCardNos.size())
.append("条: ").append(failCardNos).append("; ");
}
// 缴费单号历史已导入(非空才添加)
if (!duplicateSerialCardNos.isEmpty()) {
errorMsg.append("缴费单号历史已导入:").append(duplicateSerialCardNos.size())
.append("条: ").append(duplicateSerialCardNos).append("; ");
}
// 用户/钱包信息重复(非空才添加)
if (!multiUserCardNos.isEmpty()) {
errorMsg.append("用户/钱包信息重复:").append(multiUserCardNos.size())
.append("条: ").append(multiUserCardNos).append("; ");
}
// 用户/钱包信息缺失(非空才添加)
if (!missingUserCardNos.isEmpty()) {
errorMsg.append("用户/钱包信息缺失:").append(missingUserCardNos.size())
.append("条: ").append(missingUserCardNos).append("; ");
}
// 去除末尾可能多余的分号和空格
if (errorMsg.length() > 0) {
errorMsg.setLength(errorMsg.length() - 2); // 移除最后的 "; "
}
return Result.error(errorMsg.toString());
}
} catch (Exception e) {
// 异常处理
return Result.error("导入异常");
}
}
/**
* 导入充值数据(改造后:返回带标记的Excel文件+导入统计)
* @param file 上传的Excel文件
* @param canteenId 所属食堂(为空时取当前登录用户的食堂ID)
* @return ResponseEntity<Resource> 带Excel文件的响应,响应头附带统计信息
*/
@AutoLog(value = "导入充值数据")
@PostMapping("/importRechargeData/v2")
public ResponseEntity<?> importRechargeDataV2(
@RequestParam(name = "file", required = true) MultipartFile file,
@RequestParam(name = "canteenId", required = false) String canteenId) throws IOException {
try {
// 1. 处理食堂ID
if (StringUtils.isBlank(canteenId)) {
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
canteenId = sysUser.getCanteenId();
}
// 2. 解析原始Excel
List<StClientMemberTopUpDTO> originalDtoList = iStClientMemberBalanceService.parseExcel(file, canteenId);
if (originalDtoList.isEmpty()) {
throw new RuntimeException("Excel文件中无有效数据,请检查文件内容");
}
// 3. 执行充值并获取结果
Map<String, List<StClientMemberTopUpDTO>> rechargeResultMap =
iStClientMemberBalanceService.importRechargeDataV2(originalDtoList);
// 4. 全部成功时返回指定JSON格式
if (rechargeResultMap.containsKey("allSuccess") &&
CollectionUtils.isNotEmpty(rechargeResultMap.getOrDefault("allSuccess", Collections.emptyList()))) {
// 构建统一响应JSON
Map<String, Object> successResponse = new HashMap<>();
successResponse.put("success", true);
successResponse.put("message", "操作成功");
successResponse.put("code", 200);
successResponse.put("result", "操作成功");
successResponse.put("timestamp", System.currentTimeMillis());
// 设置响应头为JSON类型
HttpHeaders jsonHeaders = new HttpHeaders();
jsonHeaders.setContentType(MediaType.APPLICATION_JSON);
return new ResponseEntity<>(successResponse, jsonHeaders, HttpStatus.OK);
}
// 4. 提取各类结果列表
List<StClientMemberTopUpDTO> successList = rechargeResultMap.getOrDefault("newListSuccess", Collections.emptyList());
List<StClientMemberTopUpDTO> failList = rechargeResultMap.getOrDefault("newListFailure", Collections.emptyList());
List<StClientMemberTopUpDTO> duplicateSerialList = rechargeResultMap.getOrDefault("oldList", Collections.emptyList());
List<StClientMemberTopUpDTO> multiUserList = rechargeResultMap.getOrDefault("userListMoreFailure", Collections.emptyList());
List<StClientMemberTopUpDTO> missingUserList = rechargeResultMap.getOrDefault("userListMissingFailure", Collections.emptyList());
// 5. 生成结果Excel流
InputStream resultExcelStream = ExcelResultGenerator.generateResultExcel(
file, successList, failList, duplicateSerialList, multiUserList, missingUserList);
//将 InputStream 转为字节数组
byte[] excelBytes = inputStreamToByteArray(resultExcelStream);
//用 ByteArrayResource 包装字节数组(Spring 支持的资源类型)
ByteArrayResource resource = new ByteArrayResource(excelBytes) {
// 重写 getFilename 方法,确保下载时能正确识别文件名(部分浏览器依赖)
@Override
public String getFilename() {
try {
String originalFileName = file.getOriginalFilename();
String suffix = originalFileName.endsWith(".xls") ? ".xls" : ".xlsx";
return URLEncoder.encode("充值导入结果_" + System.currentTimeMillis() + suffix, StandardCharsets.UTF_8.name())
.replaceAll("\\+", "%20");
} catch (Exception e) {
return "充值导入结果.xlsx"; // 兜底文件名
}
}
};
// 6. 封装响应头
HttpHeaders headers = new HttpHeaders();
String originalFileName = file.getOriginalFilename();
String downloadFileName = "充值导入结果_" + System.currentTimeMillis() +
(originalFileName.endsWith(".xls") ? ".xls" : ".xlsx");
String encodedFileName = URLEncoder.encode(downloadFileName, StandardCharsets.UTF_8.name())
.replaceAll("\\+", "%20");
// 设置文件下载头(Content-Disposition 必须正确配置)
headers.setContentDispositionFormData("attachment", encodedFileName);
// 明确设置内容类型(避免浏览器识别错误)
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
// 设置内容长度
headers.setContentLength(excelBytes.length);
// 7. 附带导入统计信息
headers.add("Import-Success-Count", String.valueOf(successList.size()));
headers.add("Import-Fail-Count", String.valueOf(failList.size()));
headers.add("Import-Duplicate-Serial-Count", String.valueOf(duplicateSerialList.size()));
headers.add("Import-Multi-User-Count", String.valueOf(multiUserList.size()));
headers.add("Import-Missing-User-Count", String.valueOf(missingUserList.size()));
headers.add("Import-Total-Count", String.valueOf(originalDtoList.size()));
// 8. 返回响应
return new ResponseEntity<>(resource, headers, HttpStatus.OK);
} catch (Exception e) {
// 异常处理
HttpHeaders errorHeaders = new HttpHeaders();
String errorMsg = URLEncoder.encode(e.getMessage(), StandardCharsets.UTF_8.name())
.replaceAll("\\+", "%20");
errorHeaders.add("Error-Message", errorMsg);
// 返回空资源+500状态码
return new ResponseEntity<>(null, errorHeaders, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
/**
* 工具方法:将 InputStream 转为字节数组
* @param inputStream 输入流
* @return 字节数组
* @throws IOException 流读取异常
*/
private byte[] inputStreamToByteArray(InputStream inputStream) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
// 循环读取流内容到字节数组输出流
while ((len = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
// 关闭流(避免内存泄漏)
inputStream.close();
outputStream.flush();
outputStream.close();
return outputStream.toByteArray();
}
/**
* 自定义金额获取奖励
* @param price 金额
* @return
*/
@GetMapping("/getTopUpAward")
@Operation(summary = "用户充值-充值(线下)-自定义金额获取奖励", description = "用户充值-充值(线下)-自定义金额获取奖励")
public Result<?> getTopUpAward(@RequestParam(name = "canteenId",required = false) String canteenId,@RequestParam String price){
if(StringUtils.isBlank(canteenId)){
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
canteenId = sysUser.getCanteenId();
}
StClientMemberLevelDemotionTime ruleSource = iStClientMemberLevelDemotionTimeService.getOne(new LambdaQueryWrapper<StClientMemberLevelDemotionTime>()
.eq(StClientMemberLevelDemotionTime::getCanteenId, canteenId));
Map<String, Object> result = new HashMap<>();
if (ruleSource == null) {//未设置规则返回null,前端判断跳转到设置规则页面
result.put("amount", null);
result.put("integral", null);
return Result.OK(result);
}
Map<String, Object> map = iStClientMemberLevelDemotionTimeService.topUpAwardService(null, Float.parseFloat(price),canteenId);
return Result.OK(map);
}
@PostMapping("/backOutTopUpList")
@Operation(summary = "用户充值-撤销充值列表查询(线下)", description = "传入条件")
public Result<StClientMemberBackOutVO> backOutTopUpList(@RequestBody StClientMemberBackOutTopUpDTO query) {
if(StringUtils.isBlank(query.getCanteenId())){//当前食堂管理员只能查询到充值到该食堂的充值记录
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
query.setCanteenId(sysUser.getCanteenId());
}
return Result.OK(iStClientMemberBalanceService.backOutTopUpList(query));
}
@PostMapping("/backOutTopUpAll")
@Operation(summary = "用户充值-撤销充值(线下线下二合一)", description = "流水表主键id")
public Result<?> backOutTopUpAll(@RequestBody StClientMemberBackTopUpQueryDto query) throws Exception {
if(StringUtils.isBlank(query.getCanteenId())){//当前食堂管理员撤销充值该食堂的充值记录
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
query.setCanteenId(sysUser.getCanteenId());
}
StClientMemberTransactionRecord transactionRecord = iStClientMemberTransactionRecordService.getById(query.getId());
if(null == transactionRecord || StringUtils.isBlank(transactionRecord.getId())){
return Result.error("订单未找到");
}
// List<Integer> onLine = Arrays.asList(MemberEnum.PAYMENT_METHOD_BY_ALI.getCode(),
// MemberEnum.PAYMENT_METHOD_BY_WX.getCode());
// if(!onLine.contains(transactionRecord.getPaymentMethod()) && onLine.contains(query.getPaymentMethod())){
// //原充值方式不是线上,但是撤销充值时是线上提示,不支持线上退款请选择其他退回
// return Result.error("原订单非线上充值,不支持原路退回,请选择其他方式");
// }
// if(onLine.contains(transactionRecord.getPaymentMethod())){//线上退款
// RefundDTO refundDTO = new RefundDTO();
// refundDTO.setPayOrderNo(query.getPayOrderNo());
// refundDTO.setTotalFee(query.getTotalFee());
// refundDTO.setPaymentMethod(query.getPaymentMethod());
// refundDTO.setRemark(query.getRemark());
// if(StringUtils.isBlank(query.getPayOrderNo())){
// return Result.error("商户订单号不能为空");
// }
// return stBbzxOrderInfoService.returnPayInfoTopUpOnline(refundDTO);
// } else {
//线下退款
return iStClientMemberBalanceService.backOutTopUpOffLine(query);
// }
}
@PostMapping("/changeBalanceAndIntegral")
@Operation(summary = "用户充值-余额调整", description = "传入条件")
@SendNotification()
public Result<?> changeBalanceAndIntegral(@RequestBody StClientMemberChangeBalanceDTO query) {
if(StringUtils.isBlank(query.getCanteenId())){//当前食堂管理员撤销充值该食堂的充值记录
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
query.setCanteenId(sysUser.getCanteenId());
}
return iStClientMemberBalanceService.changeBalanceAndIntegral(query);
}
//=================================流水明细==========================================
@PostMapping("/pageQuery")
@Operation(summary = "流水明细-流水列表分页查询", description = "传入条件")
public Result<IPage<StClientMemberTransactionRecordVO>> pageQuery(@RequestBody StClientMemberTransactionRecordDTO query) {
if(StringUtils.isNotBlank(query.getMainTimeDay()) && query.getMainTimeDay().contains(",")){
String[] split = query.getMainTimeDay().split(",");
query.setStartTime(split[0]);
query.setEndTime(split[1]);
}
//处理时间
if(CollectionUtils.isNotEmpty(query.getDates())){
query.setStartTime(query.getDates().get(0));
query.setEndTime(query.getDates().get(1));
}
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
String canteenId = sysUser.getCanteenId();
query.setCanteenId(canteenId);
query.setStatus(1);//消费=101
return Result.OK(iStClientMemberTransactionRecordService.pageQuery(query));
}
/**
* 消费明细汇总
* @param query
* @return
*/
@GetMapping("/pageQuery/sum")
@Operation(summary = "消费明细列表分页查询汇总", description = "传入条件")
public Result<?> rechargeTransactionRecordSum(StClientMemberTransactionRecordDTO query) {
if(StringUtils.isNotBlank(query.getMainTimeDay()) && query.getMainTimeDay().contains(",")){
String[] split = query.getMainTimeDay().split(",");
query.setStartTime(split[0]);
query.setEndTime(split[1]);
}
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
//餐品总库只查询内置食堂
if(sysUser.getUserIdentity().equals(CommonConstant.USER_IDENTITY_0) || sysUser.getUserIdentity().equals(CommonConstant.USER_IDENTITY_1)){
// 后期分数据权限时在解开注释,此处管理员账户能看到所有食堂数据
// ScreenVo screenVo = new ScreenVo();
// screenVo.setId(CommonConstant.INLAY_CANTEEN_ID);
// canteenIdList.add(screenVo);
} else if (sysUser.getUserIdentity().equals(CommonConstant.USER_IDENTITY_4)) {
//查询当前登录用户的食堂列表
String canteenId = sysUser.getCanteenId();
query.setCanteenId(canteenId);
} else {
return Result.OK();
}
query.setStatus(1);//消费=101
List<StClientMemberTransactionRecordVO> statisticsCanteenBusiness = iStClientMemberTransactionRecordService.queryList(query);
StClientMemberTransactionRecordVO sumResult = GenericSumUtil.sumList(statisticsCanteenBusiness, StClientMemberTransactionRecordVO.class);
StClientMemberTransactionRecordVO stClientMemberTransactionRecordVO = new StClientMemberTransactionRecordVO();//只汇总交易金额
stClientMemberTransactionRecordVO.setSerialNo("总计");
stClientMemberTransactionRecordVO.setTransactionAmount(sumResult.getTransactionAmount());
return Result.OK(stClientMemberTransactionRecordVO);
}
/**
* 消费明细报表-导出
*/
@GetMapping("/pageQuery/export")
public void rechargeTransactionRecordExport(HttpServletResponse response, StClientMemberTransactionRecordDTO query) {
if(StringUtils.isNotBlank(query.getMainTimeDay()) && query.getMainTimeDay().contains(",")){
String[] split = query.getMainTimeDay().split(",");
query.setStartTime(split[0]);
query.setEndTime(split[1]);
}
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
//餐品总库只查询内置食堂
if(sysUser.getUserIdentity().equals(CommonConstant.USER_IDENTITY_0) || sysUser.getUserIdentity().equals(CommonConstant.USER_IDENTITY_1)){
// 后期分数据权限时在解开注释,此处管理员账户能看到所有食堂数据
// ScreenVo screenVo = new ScreenVo();
// screenVo.setId(CommonConstant.INLAY_CANTEEN_ID);
// canteenIdList.add(screenVo);
} else if (sysUser.getUserIdentity().equals(CommonConstant.USER_IDENTITY_4)) {
//查询当前登录用户的食堂列表
String canteenId = sysUser.getCanteenId();
query.setCanteenId(canteenId);
} else {
return;
}
query.setStatus(1);//消费=101
List<StClientMemberTransactionRecordVO> statisticsCanteenBusiness = iStClientMemberTransactionRecordService.queryList(query);
StClientMemberTransactionRecordVO sumResult = GenericSumUtil.sumList(statisticsCanteenBusiness, StClientMemberTransactionRecordVO.class);
StClientMemberTransactionRecordVO stClientMemberTransactionRecordVO = new StClientMemberTransactionRecordVO();//只汇总交易金额
stClientMemberTransactionRecordVO.setSerialNo("总计");
stClientMemberTransactionRecordVO.setTransactionAmount(sumResult.getTransactionAmount());
statisticsCanteenBusiness.add(stClientMemberTransactionRecordVO);
String exportFields = "serialNo|交易流水号,orderNo|交易单号,userName|姓名,phone|手机号,workNo|工号,cardCode|卡号," +
"statusName|操作类型,transactionAmount|交易金额,paymentMethodName|结账方式,businessModelName|消费类型,availableBalance|余额," +
"payTime|结账时间,updateStatusName|操作端,createOne|操作人";
// "dinnerType|餐次名称,restName|食堂名称,createTime|交易时间,payTime|结账时间,updateStatusName|操作端,createOne|操作人";
ExcelUtils.export(response, "消费明细", statisticsCanteenBusiness, exportFields, "yyyy-MM-dd HH:mm",true);
}
//==============================用户退费==================================================
/**
* 余额退款后台审核分页列表查询
*
* @param stClientMemberTransactionRecord
* @param pageNo
* @param pageSize
* @param req
* @return
*/
@Operation(summary="用户退费-余额退款后台审核分页列表查询", description="余额退款后台审核-分页列表查询")
@GetMapping(value = "/btoc/refund/list")
public Result<IPage<StClientMemberTransactionRecordVO>> queryPageList(StClientMemberTransactionRecordDTO stClientMemberTransactionRecord,
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
if(StringUtils.isNotBlank(stClientMemberTransactionRecord.getMainTimeDay()) && stClientMemberTransactionRecord.getMainTimeDay().contains(",")){
String[] split = stClientMemberTransactionRecord.getMainTimeDay().split(",");
stClientMemberTransactionRecord.setStartTime(split[0]);
stClientMemberTransactionRecord.setEndTime(split[1]);
}
stClientMemberTransactionRecord.setStatus(2);
stClientMemberTransactionRecord.setPayTimeStatus(2);
Page<StClientMemberTransactionRecordVO> page = new Page<>(pageNo, pageSize);
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
String canteenId = sysUser.getCanteenId();
stClientMemberTransactionRecord.setCanteenId(canteenId);
IPage<StClientMemberTransactionRecordVO> pageList = iStClientMemberTransactionRecordService.pageBalanceRefundList(page, stClientMemberTransactionRecord);
return Result.OK(pageList);
}
// /**
// * 企业付款到个人微信余额退款后台审核接口
// * @param orderNo
// * @return
// */
// @GetMapping("/btoc/refund/check")
// @Operation(summary= "用户退费-企业付款到个人微信余额退款后台审核接口")
// @SendNotification()
// public Result<?> btocRefund(@RequestParam String orderNo) {
// String auditorId = JwtUtil.getUserId();
// LambdaQueryWrapper<StClientMemberTransactionRecord> queryWrapper = new LambdaQueryWrapper<>();
// queryWrapper.eq(StClientMemberTransactionRecord::getOrderNo, orderNo);
// StClientMemberTransactionRecord one = iStClientMemberTransactionRecordService.getOne(queryWrapper);
// if(null == one){
// return Result.error("申请订单不存在");
// }
// if(one.getStatus().equals(MemberTransactionTypeEnum.B_TO_C_REFUND_301.getCode())){
// return Result.error("订单已经退款成功!");
// }
// TransfersDto transfersDto = new TransfersDto();
// transfersDto.setAmount(one.getTransactionAmount().multiply(BigDecimal.valueOf(100)).intValue());
// SysUser sysUser = feignSystemService.getById(one.getMemberId());
// if(null == sysUser){
// return Result.error("用户不存在");
// }
// if(StringUtils.isBlank(sysUser.getThirdId())){
// return Result.error("用户微信标识为空,请先绑定微信后再试");
// }
// transfersDto.setOpenid(sysUser.getThirdId());
// transfersDto.setCheck_name("FORCE_CHECK");
// transfersDto.setRe_user_name(sysUser.getRealname());
// transfersDto.setDesc("企业付款到个人微信余额退款");
// transfersDto.setPartner_trade_no(StMemberUtil.getOrderNoTransfer(orderNo));
// Result<Boolean> result = iPayInfo.btocRefund(transfersDto);
// one.setCreateBy(auditorId);//审核人ID
// one.setPayTime(new Date());//审核人时间
// one.setIsSync(0);
// iStClientMemberTransactionRecordService.updateById(one);
// if(null != result && result.getCode() == HttpServletResponse.SC_OK && result.getResult()){
// LambdaQueryWrapper<StClientMemberBalance> wrapper = new LambdaQueryWrapper<>();
// wrapper.eq(StClientMemberBalance::getMemberId, one.getMemberId());
// StClientMemberBalance swClientMemberBalance = iStClientMemberBalanceService.getBaseMapper().selectOne(wrapper);
// if (swClientMemberBalance != null) {
// swClientMemberBalance.setTopUpBalance(new BigDecimal(0));
// swClientMemberBalance.setRewardBalance(new BigDecimal(0));
// swClientMemberBalance.setIntegralBalance(0);
// swClientMemberBalance.setUpdateTime(new Date());
// swClientMemberBalance.setCreateBy(one.getCreateBy());
// swClientMemberBalance.setUpdateBy(one.getUpdateBy());
// swClientMemberBalance.setCanteenId(one.getCanteenId());
// swClientMemberBalance.setIsSync(0);
// boolean flag = iStClientMemberBalanceService.saveOrUpdate(swClientMemberBalance);
// if(flag){
// one.setStatus(MemberTransactionTypeEnum.B_TO_C_REFUND_301.getCode());
// one.setIsSync(0);
// iStClientMemberTransactionRecordService.updateById(one);
// }
// }
// return Result.OK("退款成功");
// } else {
// return Result.error("退款失败");
// }
//
// }
//=====================================================================================
/**
* 根据订单号获取 充值订单记录信息
* @param payOrderNo 小程序充值成功后微信订单号
* @return 订单记录信息
*/
@GetMapping("/getRecordInfoAboutRechargeByPayOrderNo")
public StClientMemberTransactionRecord getRecordInfoAboutRechargeByPayOrderNo(String payOrderNo){
return iStClientMemberBalanceService.getRecordInfoAboutRechargeByPayOrderNo(payOrderNo,null,null);
}
/**
* 充值退款后逻辑
* 通过充值记录 生成退款记录 , 计算balance表数据
* @param czRecord 充值记录
*/
@GetMapping("/backOrder")
@SendNotification()
public void backOrder(StClientMemberTransactionRecord czRecord){
iStClientMemberBalanceService.backOrder(czRecord);
}
//======================pay服务feign接口
@GetMapping("/getBalantceInfoFeign")
@Operation(summary= "会员余额feign")
public StClientMemberBalance memberBalanceInfoFeign(@RequestParam String memberId) {
return iStClientMemberBalanceService.getOne(new LambdaQueryWrapper<StClientMemberBalance>()
.eq(StClientMemberBalance::getMemberId, memberId));
}
// @PostMapping("/updateFeign")
// @Operation(summary = "会员余额更新feign")
// public void memberBalanceUpdateFeign(@RequestBody StClientMemberSpendDTO balance) throws Exception {
// balance.setInvoice(false);
//// iStClientMemberBalanceService.memberSpend(balance); 迁移至client服务更新余额
// }
@PostMapping("/returnSpendFeign")
@Operation(summary="会员余额退款")
@SendNotification()
public void returnSpendFeign(@RequestParam String orderNo) {
//
LambdaQueryWrapper<StClientMemberTransactionRecord> queryWrapper = new LambdaQueryWrapper<>();
if(orderNo.length()>19){
orderNo= orderNo.substring(0, orderNo.length() - 3);
}
//特殊处理会员订单号
queryWrapper.eq(StClientMemberTransactionRecord::getOrderNo, orderNo);
queryWrapper.eq(StClientMemberTransactionRecord::getStatus, MemberTransactionTypeEnum.EXPENDITURE.getCode());
queryWrapper.orderByDesc(StClientMemberTransactionRecord::getPayTime);
List<StClientMemberTransactionRecord> ones = iStClientMemberTransactionRecordService.list(queryWrapper);
if (ones != null && ones.size() > 0) {
StClientMemberTransactionRecord one = ones.get(0);
LambdaQueryWrapper<StClientMemberBalance> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(StClientMemberBalance::getMemberId, one.getMemberId());
StClientMemberBalance swClientMemberBalance = iStClientMemberBalanceService.getBaseMapper().selectOne(wrapper);
if (swClientMemberBalance != null) {
BigDecimal yue = swClientMemberBalance.getTopUpBalance().add(one.getStoredBalance());
swClientMemberBalance.setTopUpBalance(yue);
BigDecimal zsye = swClientMemberBalance.getRewardBalance().add(one.getRewardBalance());
swClientMemberBalance.setRewardBalance(zsye);
int jf = swClientMemberBalance.getIntegralBalance() + one.getIntegralBalance();
swClientMemberBalance.setIntegralBalance(jf);
swClientMemberBalance.setUpdateTime(new Date());
swClientMemberBalance.setCreateBy(one.getCreateBy());
swClientMemberBalance.setUpdateBy(one.getUpdateBy());
swClientMemberBalance.setCanteenId(one.getCanteenId());
swClientMemberBalance.setIsSync(0);
iStClientMemberBalanceService.saveOrUpdate(swClientMemberBalance);
}
}
}
}
@@ -0,0 +1,146 @@
package org.jeecg.payment.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.aspect.SendNotification;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.payment.entity.StClientMemberBalance;
import org.jeecg.payment.entity.StClientMemberTransactionRecord;
import org.jeecg.payment.enums.MemberTransactionTypeEnum;
import org.jeecg.payment.service.IStClientMemberBalanceService;
import org.jeecg.payment.service.IStClientMemberTransactionRecordService;
import org.jeecg.payment.vo.StClientMemberSpendDTO;
import org.jeecg.system.service.ISysUserService;
import org.jeecg.user.entity.SysUser;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
会员卡余额
*/
@RestController
@RequestMapping("/zhstapi/swClientMemberBalance")
@Tag(name = "会员卡余额列表接口")
@Slf4j
public class StClientMemberBalanceFeignController {
@Resource
private IStClientMemberBalanceService iStClientMemberBalanceService;
@Resource
private IStClientMemberTransactionRecordService iStClientMemberTransactionRecordService;
@Resource
private ISysUserService feignSystemService;
//======================pay服务feign接口
@GetMapping("/getBalantceInfoFeign")
@Operation(summary = "会员余额feign")
@SendNotification()
public StClientMemberBalance memberBalanceInfoFeign(@RequestParam String memberId) {
return iStClientMemberBalanceService.getOne(new LambdaQueryWrapper<StClientMemberBalance>()
.eq(StClientMemberBalance::getMemberId, memberId));
}
@PostMapping("/updateFeign")
@Operation(summary = "会员余额更新feign")
@SendNotification()
public void memberBalanceUpdateFeign(@RequestBody StClientMemberSpendDTO balance) throws Exception {
balance.setInvoice(false);
iStClientMemberBalanceService.memberSpend(balance);
}
@PostMapping("/returnSpendFeign")
@Operation(summary = "会员余额退款")
@SendNotification()
public void returnSpendFeign(@RequestParam String orderNo) {
//
LambdaQueryWrapper<StClientMemberTransactionRecord> queryWrapper = new LambdaQueryWrapper<>();
if(orderNo.length()>19){
orderNo= orderNo.substring(0, orderNo.length() - 3);
}
//特殊处理会员订单号
queryWrapper.eq(StClientMemberTransactionRecord::getOrderNo, orderNo);
queryWrapper.eq(StClientMemberTransactionRecord::getStatus, MemberTransactionTypeEnum.EXPENDITURE.getCode());
queryWrapper.orderByDesc(StClientMemberTransactionRecord::getPayTime);
List<StClientMemberTransactionRecord> ones = iStClientMemberTransactionRecordService.list(queryWrapper);
if (ones != null && ones.size() > 0) {
StClientMemberTransactionRecord one = ones.get(0);
LambdaQueryWrapper<StClientMemberBalance> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(StClientMemberBalance::getMemberId, one.getMemberId());
StClientMemberBalance swClientMemberBalance = iStClientMemberBalanceService.getBaseMapper().selectOne(wrapper);
if (swClientMemberBalance != null) {
BigDecimal yue = swClientMemberBalance.getTopUpBalance().add(one.getStoredBalance());
swClientMemberBalance.setTopUpBalance(yue);
BigDecimal zsye = swClientMemberBalance.getRewardBalance().add(one.getRewardBalance());
swClientMemberBalance.setRewardBalance(zsye);
int jf = swClientMemberBalance.getIntegralBalance() + one.getIntegralBalance();
swClientMemberBalance.setIntegralBalance(jf);
swClientMemberBalance.setUpdateTime(new Date());
swClientMemberBalance.setCreateBy(one.getCreateBy());
swClientMemberBalance.setUpdateBy(one.getUpdateBy());
swClientMemberBalance.setCanteenId(one.getCanteenId());
swClientMemberBalance.setIsSync(0);
iStClientMemberBalanceService.saveOrUpdate(swClientMemberBalance);
}
}
}
/**
* 添加
*
* @param stClientMemberBalance
* @return
*/
@AutoLog(value = "用户钱包初始数据添加")
@Operation(summary = "用户钱包初始数据添加", description = "用户钱包初始数据添加")
@PostMapping(value = "/add")
// @SendNotification()
public Result<?> add(@RequestBody StClientMemberBalance stClientMemberBalance) {
if(StringUtils.isBlank(stClientMemberBalance.getMemberId())){
log.error("用户钱包初始数据添加,用户不存在{}",stClientMemberBalance.getMemberId());
return Result.OK("用户id为空!");
}
SysUser sysUser = feignSystemService.getById(stClientMemberBalance.getMemberId());
if(null == sysUser){
log.error("用户钱包初始数据添加,用户不存在{}",stClientMemberBalance.getMemberId());
return Result.error("用户不存在");
}
LambdaQueryWrapper<StClientMemberBalance> stClientMemberBalanceLambdaQueryWrapper = new LambdaQueryWrapper<>();
stClientMemberBalanceLambdaQueryWrapper.eq(StClientMemberBalance::getMemberId, stClientMemberBalance.getMemberId());
StClientMemberBalance stClientMemberBalance1 = iStClientMemberBalanceService.getOne(stClientMemberBalanceLambdaQueryWrapper);
if(null != stClientMemberBalance1){
log.error("用户钱包初始数据添加,用户不存在{}",stClientMemberBalance.getMemberId());
return Result.error("用户钱包已存在");
}
stClientMemberBalance.setTopUpTotal(BigDecimal.ZERO);
stClientMemberBalance.setTopUpBalance(BigDecimal.ZERO);
stClientMemberBalance.setRewardBalance(BigDecimal.ZERO);
stClientMemberBalance.setIntegralBalance(0);
stClientMemberBalance.setConsumptionCount(0);
stClientMemberBalance.setConsumptionTotal(BigDecimal.ZERO);
stClientMemberBalance.setIsDel(0);
stClientMemberBalance.setCreateTime(new Date());
stClientMemberBalance.setCanteenId(stClientMemberBalance.getCanteenId());
stClientMemberBalance.setIsSync(0);
iStClientMemberBalanceService.save(stClientMemberBalance);
return Result.OK("添加成功!");
}
}
@@ -0,0 +1,255 @@
/**
* use shuwei code generator created
*/
package org.jeecg.payment.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.aspect.SendNotification;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.payment.entity.StClientMemberLevelDeductRule;
import org.jeecg.payment.service.IStClientMemberLevelDeductRuleService;
import org.jeecg.payment.vo.*;
import org.jeecg.restaurant.entity.SlBaseRestaurant;
import org.jeecg.restaurant.mapper.SlBaseRestaurantMapper;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
/**
* 扣费规则管理
*/
@RestController
@AllArgsConstructor
@RequestMapping("/payment/memberLevelDeductRule")
@Tag(name="扣费规则管理")
public class StClientMemberLevelDeductRuleController {
@Resource
private IStClientMemberLevelDeductRuleService iStClientMemberLevelDeductRuleService;
@Resource
private SlBaseRestaurantMapper slBaseRestaurantMapper;
/**
* 详情
*/
@GetMapping("/detail")
@Operation(summary = "详情", description = "传入StClientMemberLevelDemotionTime")
public Result<StClientMemberLevelDeductRuleVo> detail(StClientMemberLevelDeductRuleVo StClientMemberLevelDemotionTime) {
return Result.ok(iStClientMemberLevelDeductRuleService.getOneService(StClientMemberLevelDemotionTime));
}
/**
* 启用停用
*/
@GetMapping("/support/anableAndDisable")
@Operation(summary = "启用停用", description = "传入isEnable启用=1,禁用=0")
@SendNotification()
public Result<Integer> anableAndDisable(@RequestParam(name = "canteenId",required = false) String canteenId,
@RequestParam(name = "isEnable") Integer isEnable,
@RequestParam(name = "id") String id) {
if(StringUtils.isBlank(canteenId)){
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
canteenId = sysUser.getCanteenId();
}
StClientMemberLevelDeductRule stClientMemberLevelDeductRule = iStClientMemberLevelDeductRuleService.getById(id);
if(null == stClientMemberLevelDeductRule){
return Result.error("未查询到数据");
}
if(!stClientMemberLevelDeductRule.getIsEnable().equals(isEnable)){
stClientMemberLevelDeductRule.setIsEnable(isEnable);
stClientMemberLevelDeductRule.setIsSync(0);
boolean flag = iStClientMemberLevelDeductRuleService.updateById(stClientMemberLevelDeductRule);
if(flag && isEnable == 1){
LambdaQueryWrapper<StClientMemberLevelDeductRule> levelDeductRuleLambdaQueryWrapper = new LambdaQueryWrapper<>();
levelDeductRuleLambdaQueryWrapper.ne(StClientMemberLevelDeductRule::getId,id);
levelDeductRuleLambdaQueryWrapper.eq(StClientMemberLevelDeductRule::getIsEnable,isEnable);
levelDeductRuleLambdaQueryWrapper.eq(StClientMemberLevelDeductRule::getCanteenId,canteenId);
List<StClientMemberLevelDeductRule> levelDeductRuleList = iStClientMemberLevelDeductRuleService.list(levelDeductRuleLambdaQueryWrapper);
//关闭其他开着的规则
if(CollectionUtils.isNotEmpty(levelDeductRuleList)){
levelDeductRuleList.forEach(rule->{
rule.setIsEnable(0);
rule.setIsSync(0);
});
iStClientMemberLevelDeductRuleService.updateBatchById(levelDeductRuleList);
}
}
}
return Result.ok("操作成功");
}
/**
* 查询是否支持外部人员就餐标记
*/
@GetMapping("/support/external/personnel")
@Operation(summary = "查询是否支持外部人员就餐标记,是否使用支持外部人员就餐(0:不支持,1:支持)")
public Result<Integer> supportExternalPersonnel(@RequestParam(name = "canteenId",required = false) String canteenId) {
if(StringUtils.isBlank(canteenId)){
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
canteenId = sysUser.getCanteenId();
}
SlBaseRestaurant slBaseRestaurant = slBaseRestaurantMapper.selectById(canteenId);
if(null == slBaseRestaurant){
return Result.error("未查询到食堂数据");
}
return Result.ok(slBaseRestaurant.getIsExternalDine());
}
@GetMapping("/page")
@Operation(summary = "扣费规则列表分页查询")
public Result<IPage<StClientMemberLevelDeductRuleVo>> pageQuery(StClientMemberLevelDemotionTimeVO query) {
if(StringUtils.isBlank(query.getCanteenId())){
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
query.setCanteenId(sysUser.getCanteenId());
}
return Result.OK(iStClientMemberLevelDeductRuleService.selectStClientMemberLevelDemotionTimePage(query));
}
/**
* 新增
*/
@PostMapping("/saveOrUpdate")
@Operation(summary = "新增/更新")
@SendNotification()
public Result<?> save(@Valid @RequestBody StClientMemberLevelDeductRuleVo stClientMemberLevelDeductRuleVo) {
if(StringUtils.isBlank(stClientMemberLevelDeductRuleVo.getCanteenId())){
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
stClientMemberLevelDeductRuleVo.setCanteenId(sysUser.getCanteenId());
}
Result<?> result = verificationRule(stClientMemberLevelDeductRuleVo);
if(!result.isSuccess()){
return result;
}
return Result.OK("操作成功",iStClientMemberLevelDeductRuleService.saveOrUpdateService(stClientMemberLevelDeductRuleVo));
}
/**
* 删除
*/
@DeleteMapping("/remove")
@Operation(summary = "删除")
@SendNotification()
public Result<?> remove( @RequestParam String id) {
StClientMemberLevelDeductRule stClientMemberLevelDeductRule = iStClientMemberLevelDeductRuleService.getById(id);
if(stClientMemberLevelDeductRule.getIsEnable() == 1){
return Result.error("启用状态不能删除");
}
boolean flag = iStClientMemberLevelDeductRuleService.removeById(id);
return Result.OK("操作成功");
}
private Result<?> verificationRule(StClientMemberLevelDeductRuleVo stClientMemberLevelDeductRuleVo){
if(null == stClientMemberLevelDeductRuleVo.getDeductionType()){
return Result.error("请选择扣费类型");
}
Integer deductionType = stClientMemberLevelDeductRuleVo.getDeductionType();
if(3 != deductionType){
StMemberDeductRuleVO stMemberDeductRuleVO = stClientMemberLevelDeductRuleVo.getStMemberDeductRuleVO();
StMemberDeductUserTypeRuleVO breakfast = stMemberDeductRuleVO.getBreakfast();
if(null == breakfast){
return Result.error("请设置早餐扣费规则");
}
StMemberDeductUserTypeRuleVO lunch = stMemberDeductRuleVO.getLunch();
if(null == lunch){
return Result.error("请设置午餐扣费规则");
}
StMemberDeductUserTypeRuleVO dinner = stMemberDeductRuleVO.getDinner();
if(null == dinner){
return Result.error("请设置晚餐扣费规则");
}
//===========================
SlBaseRestaurant slBaseRestaurant = slBaseRestaurantMapper.selectById(stClientMemberLevelDeductRuleVo.getCanteenId());
if(null == slBaseRestaurant){
return Result.error("未查询到食堂数据");
}
StMemberDeductTypeOfAuditorRuleVO breakfast1 = breakfast.getInner();
if(null == breakfast1){
return Result.error("请设置内部人员早餐相关扣费规则");
}
StMemberDeductTypeOfAuditorRuleVO lunch1 = lunch.getInner();
if(null == lunch1){
return Result.error("请设置内部人员午餐相关扣费规则");
}
StMemberDeductTypeOfAuditorRuleVO dinner1 = dinner.getInner();
if(null == dinner1){
return Result.error("请设置内部人员晚餐相关扣费规则");
}
if(breakfast1.getFixedDeduction() == null){
return Result.error("请设置内部人员早餐【固定扣除】");
}
if(lunch1.getFixedDeduction() == null){
return Result.error("请设置内部人员午餐【固定扣除】");
}
if(dinner1.getFixedDeduction() == null){
return Result.error("请设置内部人员晚餐【固定扣除】");
}
//2:固定+补贴扣费
if(deductionType == 2){
if(breakfast1.getRatioDeduction() == null && breakfast1.getRewardDeduction() == null){
return Result.error("请设置内部人员早餐【比例扣减】或【补贴减扣】");
}
if(lunch1.getRatioDeduction() == null && lunch1.getRewardDeduction() == null){
return Result.error("请设置内部人员午餐【比例扣减】或【补贴减扣】");
}
if(dinner1.getRatioDeduction() == null && dinner1.getRewardDeduction() == null){
return Result.error("请设置内部人员晚餐【比例扣减】或【补贴减扣】");
}
}
//是否使用支持外部人员就餐(0:不支持,1:支持)
Integer isExternalDine = slBaseRestaurant.getIsExternalDine();
if(isExternalDine == 1){
StMemberDeductTypeOfAuditorRuleVO breakfast2 = breakfast.getExternal();
if(null == breakfast2){
return Result.error("请设置外部人员早餐相关扣费规则");
}
StMemberDeductTypeOfAuditorRuleVO lunch2 = lunch.getExternal();
if(null == lunch2){
return Result.error("请设置外部人员午餐相关扣费规则");
}
StMemberDeductTypeOfAuditorRuleVO dinner2 = dinner.getExternal();
if(null == dinner2){
return Result.error("请设置外部人员晚餐相关扣费规则");
}
if(breakfast2.getFixedDeduction() == null){
return Result.error("请设置外部人员早餐【固定扣除】");
}
if(lunch2.getFixedDeduction() == null){
return Result.error("请设置外部人员午餐【固定扣除】");
}
if(dinner2.getFixedDeduction() == null){
return Result.error("请设置外部人员晚餐【固定扣除】");
}
//2:固定+补贴扣费
if(deductionType == 2){
if(breakfast2.getRatioDeduction() == null && breakfast2.getRewardDeduction() == null){
return Result.error("请设置外部人员早餐【比例扣减】或【补贴减扣】");
}
if(lunch2.getRatioDeduction() == null && lunch2.getRewardDeduction() == null){
return Result.error("请设置外部人员午餐【比例扣减】或【补贴减扣】");
}
if(dinner2.getRatioDeduction() == null && dinner2.getRewardDeduction() == null){
return Result.error("请设置外部人员晚餐【比例扣减】或【补贴减扣】");
}
}
}
}
return Result.OK();
}
}
@@ -0,0 +1,130 @@
/**
* use shuwei code generator created
*/
package org.jeecg.payment.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.aspect.SendNotification;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.payment.entity.StClientMemberLevelDemotionTime;
import org.jeecg.payment.service.IStClientMemberLevelDemotionTimeService;
import org.jeecg.payment.vo.StClientMemberLevelDemotionTimeVO;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
/**
* 充值规则管理
*/
@RestController
@AllArgsConstructor
@RequestMapping("/payment/StClientMemberLevelDemotionTime")
@Tag(name= "充值规则管理")
public class StClientMemberLevelDemotionTimeController {
@Resource
private IStClientMemberLevelDemotionTimeService stClientMemberLevelDemotionTimeService;
/**
* 详情
*/
@GetMapping("/detail")
@Operation(summary = "详情", description = "传入StClientMemberLevelDemotionTime")
public Result<StClientMemberLevelDemotionTimeVO> detail(StClientMemberLevelDemotionTime StClientMemberLevelDemotionTime) {
return Result.ok(stClientMemberLevelDemotionTimeService.getOneService(StClientMemberLevelDemotionTime));
}
/**
* 启用停用
*/
@GetMapping("/support/anableAndDisable")
@Operation(summary = "启用停用", description = "传入isEnable启用=1,禁用=0")
@SendNotification()
public Result<Integer> anableAndDisable( @RequestParam(name = "canteenId",required = false) String canteenId,
@RequestParam(name = "isEnable") Integer isEnable,
@RequestParam(name = "id") String id) {
if(StringUtils.isBlank(canteenId)){
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
canteenId = sysUser.getCanteenId();
}
StClientMemberLevelDemotionTime stClientMemberLevelDemotionTime = stClientMemberLevelDemotionTimeService.getById(id);
if(null == stClientMemberLevelDemotionTime){
return Result.error("未查询到数据");
}
if(!stClientMemberLevelDemotionTime.getIsEnable().equals(isEnable)){
stClientMemberLevelDemotionTime.setIsEnable(isEnable);
stClientMemberLevelDemotionTime.setIsSync(0);
boolean flag = stClientMemberLevelDemotionTimeService.updateById(stClientMemberLevelDemotionTime);
if(flag && isEnable == 1){
LambdaQueryWrapper<StClientMemberLevelDemotionTime> clientMemberLevelDemotionTimeLambdaQueryWrapper = new LambdaQueryWrapper<>();
clientMemberLevelDemotionTimeLambdaQueryWrapper.ne(StClientMemberLevelDemotionTime::getId,id);
clientMemberLevelDemotionTimeLambdaQueryWrapper.eq(StClientMemberLevelDemotionTime::getIsEnable,isEnable);
clientMemberLevelDemotionTimeLambdaQueryWrapper.eq(StClientMemberLevelDemotionTime::getCanteenId,canteenId);
List<StClientMemberLevelDemotionTime> memberLevelDemotionTimes = stClientMemberLevelDemotionTimeService.list(clientMemberLevelDemotionTimeLambdaQueryWrapper);
//关闭其他开着的规则
if(CollectionUtils.isNotEmpty(memberLevelDemotionTimes)){
memberLevelDemotionTimes.forEach(rule->{
rule.setIsEnable(0);
rule.setIsSync(0);
});
stClientMemberLevelDemotionTimeService.updateBatchById(memberLevelDemotionTimes);
}
}
}
return Result.ok("操作成功");
}
@GetMapping("/page")
@Operation(summary = "储值规则列表分页查询", description = "传入条件")
public Result<IPage<StClientMemberLevelDemotionTimeVO>> pageQuery(StClientMemberLevelDemotionTimeVO query) {
if(StringUtils.isBlank(query.getCanteenId())){
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
query.setCanteenId(sysUser.getCanteenId());
}
return Result.OK(stClientMemberLevelDemotionTimeService.selectStClientMemberLevelDemotionTimePage(query));
}
/**
* 新增
*/
@PostMapping("/saveOrUpdate")
@Operation(summary = "新增/更新", description = "传入StClientMemberLevelDemotionTime")
@SendNotification()
public Result<?> save(@Valid @RequestBody StClientMemberLevelDemotionTimeVO stClientMemberLevelDemotionTimeVO) {
if(StringUtils.isBlank(stClientMemberLevelDemotionTimeVO.getCanteenId())){
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
stClientMemberLevelDemotionTimeVO.setCanteenId(sysUser.getCanteenId());
}
return Result.OK("操作成功",stClientMemberLevelDemotionTimeService.saveOrUpdateService(stClientMemberLevelDemotionTimeVO));
}
/**
* 删除
*/
@DeleteMapping("/remove")
@Operation(summary = "删除", description = "传入id")
@SendNotification()
public Result<?> remove(@RequestParam String id) {
StClientMemberLevelDemotionTime stClientMemberLevelDemotionTime = stClientMemberLevelDemotionTimeService.getById(id);
if(stClientMemberLevelDemotionTime.getIsEnable() == 1){
return Result.error("启用状态不能删除");
}
boolean flag = stClientMemberLevelDemotionTimeService.removeById(id);
return Result.OK();
}
}
@@ -0,0 +1,126 @@
package org.jeecg.payment.listUtils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.lang.reflect.Field;
import java.util.*;
public class ListUtil {
/**
* list 集合分页
* @param list list
* @param pageNum 页数
* @param pageSize 每页条数
* @return IPage
*/
public static IPage listToPage(List<?> list, int pageNum, int pageSize){
List pageList = new ArrayList<>();
int curIdx = pageNum > 1 ? (pageNum - 1) * pageSize : 0;
for (int i = 0; i < pageSize && curIdx + i < list.size(); i++) {
pageList.add(list.get(curIdx + i));
}
IPage page = new Page<>(pageNum, pageSize);
page.setRecords(pageList);
page.setTotal(list.size());
return page;
}
/**
* object转list对象
* @param obj object对象
* @param clazz 需要转换的集合
* @param <T> 泛型
* @return list <T>
*/
public static <T> List<T> changeList(Object obj,Class<T> clazz){
try{
List<T> result = new ArrayList<>();
if (obj instanceof List<?>){
for (Object o : (List<?>)obj){
String s = JSONObject.toJSONString(o);
T t = JSONObject.parseObject(s,clazz);
result.add(t);
}
return result;
}
return null;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
/**
* 对象 转 map
*/
public static Map beanToMap(Object obj) {
Map<String, Object> map = new HashMap<>();
Field[] fields = obj.getClass().getDeclaredFields();
try {
for (Field field : fields) {
field.setAccessible(true);
map.put(field.getName(), field.get(obj));
}
return map;
} catch (IllegalAccessException i) {
return null;
}
}
//String转换成map
public Map<String,Object> parseJsonMap(String str){
Map<String,Object> map = new HashMap<>();
JSONObject jsonObject = JSONObject.parseObject(str);
for (Object k : jsonObject.keySet()){
Object v = jsonObject.get(k);
if(v instanceof JSONArray){
List<Map<String,Object>> list = new ArrayList<>();
Iterator it = ((JSONArray) v).iterator();
while (it.hasNext()){
Object json2 = it.hasNext();
list.add(parseJsonMap(json2.toString()));
}
map.put(k.toString(),list);
}else {
map.put(k.toString(),v);
}
}
return map;
}
/**
* 对Map中的键进行排序通常需要先将键提取出来,排序后再根据排序后的键重新构建一个有序的Map。如果你想对键进行“指定位置排序”,这可能意味着你有一个特定的顺序要求,而不是简单的自然排序或比较器排序。
* @param map
* @param keyOrder
* @param <K>
* @param <V>
* @return
*/
public static <K, V> Map<K, V> sortMapByKeyOrder(Map<K, V> map, List<K> keyOrder) {
// 使用LinkedHashMap来保持插入顺序
Map<K, V> sortedMap = new LinkedHashMap<>();
// 遍历keyOrder列表,将map中的键值对按顺序放入sortedMap
for (K key : keyOrder) {
if (map.containsKey(key)) {
sortedMap.put(key, map.get(key));
}
}
// 如果keyOrder列表中没有包含map中的所有键,将剩余的键添加到sortedMap末尾
for (Map.Entry<K, V> entry : map.entrySet()) {
if (!sortedMap.containsKey(entry.getKey())) {
sortedMap.put(entry.getKey(), entry.getValue());
}
}
return sortedMap;
}
}
@@ -0,0 +1,133 @@
package org.jeecg.payment.listUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import java.util.*;
/**
* @author fans
* @date 2024/04/29 9:39
*/
public class MapUtil {
//第一次扣款节点,根据用户ID+日期+餐次为key,保存redis中12小时
public static final String USER_ORDER_FLAG = "USER_ORDER_FLAG";
//保存扣费规则实体类
public static final String DeductRule = "DeductRule";
/**
* Map拆分 (指定分组大小)
* @param map Map
* @param chunkSize 每个分组的大小 (>=1)
* @param <K> Key
* @param <V> Value
* @return 子Map列表
*/
public static <K,V> List<Map<K,V>> splitByChunkSize(Map<K,V> map, int chunkSize){
if(Objects.isNull(map) || map.isEmpty() || chunkSize<1){
//空map或者分组大小<1,无法拆分
return Collections.emptyList();
}
int mapSize = map.size(); //键值对总数
int groupSize = mapSize/chunkSize + (mapSize%chunkSize==0?0:1); //计算分组个数
List<Map<K,V>> list = Lists.newArrayListWithCapacity(groupSize); //子Map列表
if(chunkSize >= mapSize){ //只能分1组的情况
list.add(map);
return list;
}
int count = 0; //每个分组的组内计数
Map<K,V> subMap = Maps.newHashMapWithExpectedSize(chunkSize); //子Map
for (Map.Entry<K, V> entry : map.entrySet()) {
if (count < chunkSize) {
//给每个分组放chunkSize个键值对,最后一个分组可能会装不满
subMap.put(entry.getKey(), entry.getValue());
count++; //组内计数+1
} else {
//结束上一个分组
list.add(subMap); //当前分组装满了->加入列表
//开始下一个分组
subMap = Maps.newHashMapWithExpectedSize(chunkSize); //新的分组
subMap.put(entry.getKey(), entry.getValue()); //添加当前键值对
count = 1; //组内计数重置为1
}
}
list.add(subMap); //添加最后一个分组
return list;
}
/**
* Map拆分(指定分组个数)
* @param map Map
* @param groupSize 分组个数 (>=1)
* @param <K> Key
* @param <V> Value
* @return 子Map列表
*/
public static <K,V> List<Map<K,V>> splitByGroupSize(Map<K,V> map, int groupSize){
if(Objects.isNull(map) || map.isEmpty() || groupSize<1){
//空map或者分组数<1,无法拆分
return Collections.emptyList();
}
List<Map<K,V>> list = Lists.newArrayListWithCapacity(groupSize);
if(groupSize == 1){ //只有1个分组的情况
list.add(map);
return list;
}
int mapSize = map.size(); //键值对总数
int chunkIndex = 0; //当前分组的下标,[0, groupSize-1]
int restCount = mapSize % groupSize; //平均后剩余的键值对数
int chunkSize0 = mapSize / groupSize; //每个分组键值对数量
int chunkSize1 = chunkSize0 + 1; //多分一个
int chunkSize = chunkIndex<restCount ? chunkSize1 : chunkSize0; //实际每组的大小(前面的部分分组可能会多分1个)
int count = 0; //每个分组的组内计数
Map<K,V> subMap = Maps.newHashMapWithExpectedSize(chunkSize);//子Map
for (Map.Entry<K, V> entry : map.entrySet()) {
if(count < chunkSize){
//每个分组按实际分组大小(chunkSize)加入键值对
subMap.put(entry.getKey(), entry.getValue());
count ++; //组内计数+1
}else{
//结束上一个分组
list.add(subMap); //当前分组装满了->加入列表
chunkIndex ++; //分组个数+1
//开始下一个分组
chunkSize = chunkIndex<restCount ? chunkSize1 : chunkSize0; //重新计算分组大小
subMap = Maps.newHashMapWithExpectedSize(chunkSize); //新的分组
subMap.put(entry.getKey(), entry.getValue()); //添加当前键值对
count = 1; //组内计数重置为1
}
}
list.add(subMap); //添加最后一个分组
return list;
}
//测试
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("a", "1");
map.put("b", "2");
map.put("c", "3");
map.put("d", "4");
map.put("e", "5");
map.put("f", "6");
map.put("g", "7");
System.out.println("splitByChunkSize: " + splitByChunkSize(map, 3));
System.out.println("splitByGroupSize: " + splitByGroupSize(map, 3));
//splitByChunkSize: [{a=1, b=2, c=3}, {d=4, e=5, f=6}, {g=7}]
//splitByGroupSize: [{a=1, b=2, c=3}, {d=4, e=5}, {f=6, g=7}]
}
}
@@ -0,0 +1,132 @@
package org.jeecg.payment.listUtils;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
/**
* * 订单编码码生成器,生成32位数字编码,
* * @生成规则 1位单号类型+17位时间戳+14位(用户id加密&随机数)
*/
public class OrderUtils {
/**
* 订单类别头
*/
private static final String ORDER_CODE = "";
/**
* 退货类别头
*/
private static final String RETURN_ORDER = "";
/**
* 退款类别头
*/
private static final String REFUND_ORDER = "";
/**
* 随即编码
*/
private static final int[] r = new int[]{7, 9, 6, 2, 8, 1, 3, 0, 5, 4};
/**
* 用户id和随机数总长度
*/
private static final int maxLength = 14;
/**
* 根据id进行加密+加随机数组成固定长度编码
*/
private static String toCode(Integer userId) {
String idStr = userId.toString();
StringBuilder idsbs = new StringBuilder();
for (int i = idStr.length() - 1; i >= 0; i--) {
idsbs.append(r[idStr.charAt(i) - '0']);
}
return idsbs.append(getRandom(maxLength - idStr.length())).toString();
}
/**
* 生成时间戳
*/
private static String getDateTime() {
DateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
return sdf.format(new Date());
}
/**
* 生成时间戳
*/
private static String getDateTimeV2() {
DateFormat sdf = new SimpleDateFormat("yyMMddHHmmss");
return sdf.format(new Date());
}
/**
* 生成固定长度随机码
*
* @param n 长度
*/
private static long getRandom(long n) {
long min = 1, max = 9;
for (int i = 1; i < n; i++) {
min *= 10;
max *= 10;
}
long rangeLong = (((long) (new Random().nextDouble() * (max - min)))) + min;
return rangeLong;
}
/**
* 生成不带类别标头的编码
*
* @param userId
*/
private static synchronized String getCode(Integer userId) {
userId = userId == null ? 10000 : userId;
return getDateTime()+ userId;//+ toCode(userId);
}
/**
* 生成订单单号编码(调用方法)
* @param userId 网站中该用户唯一ID 防止重复
*/
public static String getOrderCode(Integer userId) {
return ORDER_CODE + getCode(userId);
}
/**
* 生成订单单号编码(调用方法)
*/
public static String getOrderCodeV2() {
return ORDER_CODE + getDateTimeV2();
}
/**
* 生成退货单号编码(调用方法)
* @param userId 网站中该用户唯一ID 防止重复
*/
public static String getReturnCode(Integer userId) {
return RETURN_ORDER + getCode(userId);
}
/**
* 生成退款单号编码(调用方法)
* @param userId 网站中该用户唯一ID 防止重复
*/
public static String getRefundCode(Integer userId) {
return REFUND_ORDER + getCode(userId);
}
}
@@ -0,0 +1,78 @@
/**
* use shuwei code generator created
*/
package org.jeecg.payment.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.jeecg.common.system.vo.ScreenVo;
import org.jeecg.payment.entity.StBbzxOrderInfo;
import org.jeecg.payment.vo.OrderShow;
import org.jeecg.payment.vo.StatisticsTheAmountSpentVo;
import org.jeecg.restaurant.vo.StatisticsBusinessVo;
import org.jeecg.statistics.vo.StEatFoodInfoVo;
import java.util.List;
/**
* 报表中心-店内订单 Mapper 接口
*/
public interface StBbzxOrderInfoMapper extends BaseMapper<StBbzxOrderInfo> {
/**
* 自定义分页
*
* @return
*/
// List<SwBbzxOrderInfoVO> selectSwBbzxOrderInfoPage(SwBbzxOrderInfoDTO swBbzxOrderInfo);
List<OrderShow> selectSwOrderInfoPage(@Param("memberId") String memberId, @Param("openId") String open_id, @Param("orderType")Integer orderType, @Param("startDate")String startDate, @Param("endDate")String endDate, @Param("unionId") String unionId);
/**
* 支付宝小程序订单列表
*
* @param memberId
* @param open_id
* @return
*/
List<OrderShow> selectSwOrderInfoPage_zfb(String memberId,
@Param("openId") String open_id);
List<StBbzxOrderInfo> getAllByOpenId(@Param("openId") String openId);
List<StEatFoodInfoVo> getFoodInfoByOrderIdList(@Param("orderIds") List<Integer> orderIds);
/**
* 消费金额统计
* @param canteenIds 食堂id
* @param startDate 开始时间
* @param endDate 结束时间
* @return 消费金额统计
*/
List<StatisticsTheAmountSpentVo> statisticsTheAmountSpent(@Param("list") List<String> canteenIds, @Param("startDate") String startDate, @Param("endDate") String endDate);
/**
* 个人消费记录统计
* @param startDate 开始时间
* @param endDate 结束时间
* @param secondDepartId 二级单位id
* @param thirdDepartId 三级部门id
* @return 个人消费记录统计
*/
List<StatisticsTheAmountSpentVo> statisticsTheAmountSpentEveryMember(@Param("list") List<String> canteenIds, @Param("name") String name,@Param("payName") String payName,@Param("startDate") String startDate, @Param("endDate") String endDate,
@Param("secondDepartId") String secondDepartId,
@Param("thirdDepartId") String thirdDepartId);
/**
* 食堂营业表
* @param startDate 开始时间
* @param endDate 结束时间
* @param canteenIdList 二级单位id
* @return 食堂营业表
*/
List<StatisticsBusinessVo> statisticsCanteenBusiness(@Param("list") List<ScreenVo> canteenIdList, @Param("startDate") String startDate, @Param("endDate") String endDate);
}
@@ -0,0 +1,17 @@
/**
* use shuwei code generator created
*/
package org.jeecg.payment.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.payment.entity.StBbzxOrderInfoPay;
/**
* 支付信息 Mapper 接口
*/
public interface StBbzxOrderInfoPayMapper extends BaseMapper<StBbzxOrderInfoPay> {
}
@@ -0,0 +1,119 @@
package org.jeecg.payment.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.jeecg.payment.dto.*;
import org.jeecg.payment.entity.StClientMemberBalance;
import org.jeecg.payment.entity.StClientMemberTransactionRecord;
import org.jeecg.payment.vo.*;
import org.jeecg.user.entity.SysUserSub;
import org.jeecg.user.vo.SysUserSubInfo;
import java.util.List;
/**
* @author Ls.
* @date 2021/6/16.
*/
public interface StClientMemberBalanceMapper extends BaseMapper<StClientMemberBalance> {
/**
* 后台列表查询
*
* @return
*/
List<StClientMemberBalanceListVO> pageList(Page<StClientMemberBalanceListVO> page, @Param("vo") StClientMemberTransactionRecordDTO query);
/**
* 后台列表查询
*
* @return
*/
List<StClientMemberBalanceListVO> pageList(@Param("vo") StClientMemberTransactionRecordDTO query);
/**
* 余额/积分调整
*
* @param query
* @return
*/
int changeBalanceAndIntegral(StClientMemberChangeBalanceDTO query);
/**
* 会员充值
*
* @return
*/
int memberTopUp(StClientMemberTopUpDTO query);
/**
* 撤销充值用户vo
*
* @param memberId
* @return
*/
StClientMemberBackOutUserVO selectBackOutUser(@Param("memberId") String memberId,
@Param("eaId") String eaId);
/**
* 撤销充值的交易流水查询
*
* @param memberId
* @param status 撤销状态码
* @return
*/
List<StClientMemberBackOutPayVO> selectRunningTabAsBackOut(@Param("memberId") String memberId,
@Param("list") List<Integer> list,
@Param("status") Integer status,
@Param("canteenId") String canteenId);
/**
* 查询最新的一条数据
*
* @param memberId
* @param list status状态集合
* @return
*/
StClientMemberBalance selectLastMsgByTime(@Param("memberId") String memberId,
@Param("list") List<Integer> list);
StClientMemberBalance selectLastMsgByPayTime(@Param("memberId") String memberId,
@Param("status") Integer status);
/**
* 撤销充值
*
* @param query
* @return
*/
int backOutTopUp(StClientMemberBackTopUpDto query);
/**
* 会员消费
*
* @param param
* @return
*/
int memberSpend(StClientMemberSpendMapperDTO param);
/**
* @param userId 用户唯一标识
* @return 会员消费记录
*/
List<StClientMemberTransactionRecord> memberTranRecordMapper(Page<StClientMemberTransactionRecord> page, @Param("userId") String userId, @Param("status") String status);
StMiniMineBalanceVo getBalanceInfo(@Param("userId") String userId);
SysUserSub getOneByUserId(@Param("userId") String userId);
SysUserSub getOneByCardCode(@Param("cardCode") String cardCode);
/**
* 批量根据身份证号查询用户钱包(用户表和钱包都有数据才能查询到记录)
* @param list
* @return
*/
List<SysUserSubInfo> getSubUserListByCardNoList(@Param("list") List<String> list);
StMiniMineBalanceVo getBalanceByUserId(@Param("userId") String userId);
}
@@ -0,0 +1,27 @@
/**
* use shuwei code generator created
*/
package org.jeecg.payment.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.jeecg.payment.entity.StClientMemberLevelDeductRule;
import org.jeecg.payment.entity.StClientMemberLevelDemotionTime;
import org.jeecg.payment.vo.StClientMemberLevelDeductRuleVo;
import org.jeecg.payment.vo.StClientMemberLevelDemotionTimeVO;
import java.util.List;
/**
* 扣费规则Mapper 接口
*/
public interface StClientMemberLevelDeductRuleMapper extends BaseMapper<StClientMemberLevelDeductRule> {
/**
* 自定义分页
* @return
*/
List<StClientMemberLevelDeductRuleVo> selectStClientMemberLevelDeductRulePage(Page<StClientMemberLevelDeductRuleVo> page, @Param("vo") StClientMemberLevelDemotionTimeVO stClientMemberLevelDeductRule);
}
@@ -0,0 +1,27 @@
/**
* use shuwei code generator created
*/
package org.jeecg.payment.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.jeecg.payment.entity.StClientMemberLevelDemotionTime;
import org.jeecg.payment.vo.StClientMemberLevelDemotionTimeVO;
import java.util.List;
/**
* 储值规则Mapper 接口
*/
public interface StClientMemberLevelDemotionTimeMapper extends BaseMapper<StClientMemberLevelDemotionTime> {
/**
* 自定义分页
*
* @param stClientMemberLevelDemotionTime
* @return
*/
List<StClientMemberLevelDemotionTimeVO> selectSwClientMemberLevelDemotionTimePage(Page<StClientMemberLevelDemotionTimeVO> page,@Param("vo") StClientMemberLevelDemotionTimeVO stClientMemberLevelDemotionTime);
}
@@ -0,0 +1,38 @@
package org.jeecg.payment.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.jeecg.payment.dto.StClientMemberTransactionRecordDTO;
import org.jeecg.payment.entity.StClientMemberTransactionRecord;
import org.jeecg.payment.vo.InOutRecordInfoVo;
import org.jeecg.payment.vo.StClientMemberTransactionRecordVO;
import java.util.List;
/**
交易记录
*/
public interface StClientMemberTransactionRecordMapper extends BaseMapper<StClientMemberTransactionRecord> {
/**
* 列表查询
* @return
*/
List<StClientMemberTransactionRecordVO> pageList(Page<StClientMemberTransactionRecordVO> page, @Param("vo") StClientMemberTransactionRecordDTO query);
/**
* 列表查询
* @return
*/
List<StClientMemberTransactionRecordVO> pageList(@Param("vo") StClientMemberTransactionRecordDTO query);
/**
* 列表查询
* @return
*/
List<StClientMemberTransactionRecordVO> pageBalanceRefundList(Page<StClientMemberTransactionRecordVO> page, @Param("vo") StClientMemberTransactionRecordDTO query);
InOutRecordInfoVo getOneInOutInfo(@Param("recordId") String recordId);
}
@@ -0,0 +1,383 @@
<?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="org.jeecg.payment.mapper.StBbzxOrderInfoMapper">
<!-- 通用查询映射结果 -->
<!-- <resultMap id="swBbzxOrderInfoResultMap" type="com.shuwei.zhct.vo.SwBbzxOrderInfoVO">
<id column="id" property="id"/>
<result column="order_type" property="orderType"></result>
<result column="ea_id" property="eaId"/>
<result column="create_user_no" property="createUserNo"/>
<result column="create_time" property="createTime"/>
<result column="update_user_no" property="updateUserNo"/>
<result column="update_time" property="updateTime"/>
<result column="is_del" property="isDel"/>
<result column="order_no" property="orderNo"/>
<result column="serial_no" property="serialNo"></result>
<result column="business_model" property="businessModel"/>
<result column="order_from" property="orderFrom"/>
<result column="order_from_sign" property="orderFromSign"></result>
<result column="dining_way" property="diningWay"/>
<result column="business_date" property="businessDate"/>
<result column="order_date" property="orderDate"/>
<result column="pay_order_date" property="payOrderDate"/>
<result column="withdrawals_date" property="withdrawalsDate"/>
<result column="desk_id" property="deskId"/>
<result column="desk_no" property="deskNo"></result>
<result column="desk_name" property="deskName"></result>
<result column="user_num" property="userNum"/>
<result column="order_price" property="orderPrice"/>
<result column="customer_price" property="customerPrice"/>
<result column="pay_total" property="payTotal"/>
<result column="preferential_price" property="preferentialPrice"/>
<result column="income" property="income"/>
<result column="pay_type" property="payType"/>
<result column="status" property="status"/>
<result column="food_price" property="foodPrice"/>
<result column="service_price" property="servicePrice"/>
<result column="service_discounts_price" property="serviceDiscountsPrice"/>
<result column="service_income" property="serviceIncome"/>
<result column="change_zero" property="changeZero"></result>
<result column="auto_change_zero" property="autoChangeZero"></result>
<result column="reserve_date" property="reserveDate"/>
<result column="reserve_user" property="reserveUser"></result>
<result column="reserve_phone" property="reservePhone"></result>
<result column="member_id" property="memberId"/>
<result column="member_name" property="memberName"></result>
<result column="member_phone" property="memberPhone"></result>
<result column="commission_id" property="commissionId"/>
<result column="order_remark" property="orderRemark"/>
<result column="remark" property="remark"></result>
<result column="order_discount" property="orderDiscount"></result>
<result column="order_derate" property="orderDerate"></result>
<result column="order_text" property="orderText"></result>
<result column="area_name" property="areaName"></result>
</resultMap>
<select id="selectSwBbzxOrderInfoPage" resultMap="swBbzxOrderInfoResultMap">
SELECT
area.area_name,
b.*
FROM
st_bbzx_order_info b
LEFT JOIN sw_desk_info desk ON b.desk_id = desk.id
AND desk.is_del = 0
LEFT JOIN sw_desk_area area ON desk.area_id = area.id
AND area.is_del = 0
WHERE
b.is_del = 0
AND b.ea_id = #{eaId}
<if test="orderFrom!=null and orderFrom!=0">
AND b.order_from = #{orderFrom}
</if>
<if test="payType!=null and payType!=0">
AND b.pay_type = #{payType}
</if>
<if test="status!=null and status!=4">
AND b.status = #{status}
</if>
<if test="status!=null and status==4">
AND (b.status = 4 or b.status = 0)
</if>
<if test="timeType!=null and timeType==1">
AND (b.order_date &gt;= #{timeStart} AND b.order_date &lt;= #{timeEnd})
</if>
<if test="timeType!=null and timeType==2">
AND (b.pay_order_date &gt;= #{timeStart} AND b.pay_order_date &lt;= #{timeEnd})
</if>
<if test="timeType!=null and timeType==3">
AND (b.business_date &gt;= #{timeStart} AND b.business_date &lt;= #{timeEnd})
</if>
ORDER BY b.create_time DESC
</select>-->
<!-- <select id="getFoodPriceByOrderIdMapper" resultType="com.shuwei.zhct.entity.SwFoodInfoPrice">-->
<!-- SELECT-->
<!-- fp.sell_price,-->
<!-- fp.vip_price-->
<!-- FROM-->
<!-- st_bbzx_order_info_food o-->
<!-- LEFT JOIN sw_food_info_price fp ON o.specification_id = fp.id-->
<!-- WHERE-->
<!-- o.is_del = 0-->
<!-- AND fp.is_del = 0 AND o.order_id = #{id}-->
<!-- </select>-->
<select id="selectSwOrderInfoPage" resultType="org.jeecg.payment.vo.OrderShow">
select o.id as orderId,o.order_no,o.`status`,o.remark,o.create_time,o.pay_total as originalPrice,o.ea_id,o.remark as orderName,o.order_remark as remark
,o.order_from,
o.order_type
FROM
st_bbzx_order_info o
WHERE
o.is_del = 0
and (o.order_from_sign = #{openId} or o.order_from_sign = #{memberId}
<if test="unionId!= null and unionId != ''">
OR o.union_id = #{unionId}
</if>
)
<if test="orderType!= null and orderType != 0">
and o.order_type = #{orderType}
</if>
<if test="startDate != null and startDate != '' and endDate != null and endDate != ''">
and o.create_time between #{startDate} and #{endDate}
</if>
order by o.create_time desc
</select>
<select id="selectSwOrderInfoPage_zfb" resultType="org.jeecg.payment.vo.OrderShow">
SELECT
o.id AS orderId,
o.order_no,
o.`status`,
o.remark,
o.create_time,
o.order_price AS originalPrice,
o.ea_id,
o.remark AS orderName,
o.order_remark AS remark
FROM
st_bbzx_order_info o
WHERE
o.is_del = 0
<choose>
<when test="memberId!=null and memberId!=''">
AND ( o.order_from = 5 OR o.order_from = 4 )
AND member_id = #{memberId}
</when>
<otherwise>
AND o.order_from = 5
AND o.order_from_sign = #{openId}
</otherwise>
</choose>
ORDER BY
create_time DESC
</select>
<select id="getAllByOpenId" resultType="org.jeecg.payment.entity.StBbzxOrderInfo">
SELECT
*
FROM
st_bbzx_order_info
WHERE
order_from_sign = #{openId}
AND member_id IS NULL
AND is_del = 0
</select>
<select id="getFoodInfoByOrderIdList" resultType="org.jeecg.statistics.vo.StEatFoodInfoVo">
SELECT
ufi.order_id,
ufi.food_id,
fi.food_name,
file.relative_url
FROM
st_bbzx_order_info_food ufi
JOIN st_bbzx_order_info oi ON ufi.order_id = oi.id
JOIN sw_food_info fi ON ufi.food_id = fi.id AND fi.is_del = 0
join sw_food_info_orderclient orderclient ON orderclient.food_id = ufi.food_id AND orderclient.is_del = 0
JOIN sw_file_info file ON file.id = orderclient.file_id AND file.is_del = 0
WHERE ufi.order_id in
<foreach collection="orderIds" separator="," open="(" close=")" item="orderId">
#{orderId}
</foreach>
AND fi.food_or_combo = 1
AND ufi.is_del = 0
-- 套餐
UNION ALL
SELECT
ufi.order_id,
groupFood.food_id,
groupFood.food_name,
file.relative_url
FROM
st_bbzx_order_info_food ufi
JOIN st_bbzx_order_info oi ON ufi.order_id = oi.id
JOIN sw_combo_info_group infoGroup ON ufi.food_id = infoGroup.combo_id AND infoGroup.is_del = 0
JOIN sw_food_info fi ON fi.id = ufi.food_id AND fi.is_del = 0
JOIN sw_combo_info_group_food groupFood ON infoGroup.id = groupFood.group_id
JOIN sw_food_info_sell sell ON groupFood.food_id = sell.food_id AND sell.is_del = 0
join sw_food_info_orderclient orderclient ON orderclient.food_id = groupFood.food_id AND orderclient.is_del = 0
JOIN sw_file_info file ON file.id = orderclient.file_id AND file.is_del = 0
WHERE ufi.order_id in
<foreach collection="orderIds" separator="," open="(" close=")" item="orderId">
#{orderId}
</foreach>
AND fi.food_or_combo = 2
AND ufi.is_del = 0
</select>
<select id="statisticsTheAmountSpent" resultType="org.jeecg.payment.vo.StatisticsTheAmountSpentVo">
SELECT
oi.canteen_id,
r.rest_name,
-- COUNT(DISTINCT CASE WHEN oi.dinner_type = '早餐' THEN oi.member_id END) AS breakfastPerson,
COUNT(CASE WHEN oi.dinner_type = '早餐' THEN oi.member_id END) AS breakfastPerson,
SUM(CASE WHEN oi.dinner_type = '早餐' THEN oi.customer_price ELSE 0 END) AS breakfastAmount,
-- COUNT(DISTINCT CASE WHEN oi.dinner_type = '午餐' THEN oi.member_id END) AS lunchPerson,
COUNT(CASE WHEN oi.dinner_type = '午餐' THEN oi.member_id END) AS lunchPerson,
SUM(CASE WHEN oi.dinner_type = '午餐' THEN oi.customer_price ELSE 0 END) AS lunchAmount,
-- COUNT(DISTINCT CASE WHEN oi.dinner_type = '晚餐' THEN oi.member_id END) AS dinnerPerson,
COUNT(CASE WHEN oi.dinner_type = '晚餐' THEN oi.member_id END) AS dinnerPerson,
SUM(CASE WHEN oi.dinner_type = '晚餐' THEN oi.customer_price ELSE 0 END) AS dinnerAmount,
-- COUNT(DISTINCT CASE WHEN oi.dinner_type = '加餐' THEN oi.member_id END) AS otherPerson,
COUNT(CASE WHEN oi.dinner_type = '加餐' THEN oi.member_id END) AS otherPerson,
SUM(CASE WHEN oi.dinner_type = '加餐' THEN oi.customer_price ELSE 0 END) AS otherAmount,
oi.eat_day,
SUM(oi.customer_price) customerPrice,
SUM(oi.order_price) orderPrice,
(SELECT COUNT(DISTINCT member_id) FROM st_bbzx_order_info WHERE eat_day = oi.eat_day and `status` = 5
and order_type = 3
<if test="list != null and list.size() > 0">
and canteen_id IN
<foreach collection="list" item="canteenId" separator="," open="(" close=")" >
#{canteenId}
</foreach>
</if>
<if test="startDate != '' and startDate != null ">
and eat_day between #{startDate} and #{endDate}
</if>
) AS totalNum
FROM
st_bbzx_order_info oi
JOIN st_base_restaurant r ON oi.canteen_id = r.id
WHERE
oi.`status` = 5
and oi.order_type = 3
<if test="list != null and list.size() > 0">
and oi.canteen_id IN
<foreach collection="list" item="canteenId" separator="," open="(" close=")" >
#{canteenId}
</foreach>
</if>
<if test="startDate != '' and startDate != null ">
and oi.eat_day between #{startDate} and #{endDate}
</if>
GROUP BY
oi.canteen_id,
oi.eat_day
order by oi.eat_day desc
</select>
<select id="statisticsTheAmountSpentEveryMember"
resultType="org.jeecg.payment.vo.StatisticsTheAmountSpentVo">
SELECT
u.realname,
pay.realname as payRealname,
u.work_no,
CONCAT(
IFNULL(parent_depart.depart_name, ''),
IF(parent_depart.depart_name IS NOT NULL AND direct_depart.depart_name IS NOT NULL, '->', ''),
IFNULL(direct_depart.depart_name, '')
) as departName,
oi.member_id,
oi.canteen_id,
-- COUNT( DISTINCT CASE WHEN oi.dinner_type = '早餐' THEN oi.eat_day END ) AS breakfastPerson,
COUNT( CASE WHEN oi.dinner_type = '早餐' THEN oi.eat_day END ) AS breakfastPerson,
SUM( CASE WHEN oi.dinner_type = '早餐' THEN oi.customer_price ELSE 0 END ) AS breakfastAmount,
-- COUNT( DISTINCT CASE WHEN oi.dinner_type = '午餐' THEN oi.eat_day END ) AS lunchPerson,
COUNT( CASE WHEN oi.dinner_type = '午餐' THEN oi.eat_day END ) AS lunchPerson,
SUM( CASE WHEN oi.dinner_type = '午餐' THEN oi.customer_price ELSE 0 END ) AS lunchAmount,
-- COUNT( DISTINCT CASE WHEN oi.dinner_type = '晚餐' THEN oi.eat_day END ) AS dinnerPerson,
COUNT( CASE WHEN oi.dinner_type = '晚餐' THEN oi.eat_day END ) AS dinnerPerson,
SUM( CASE WHEN oi.dinner_type = '晚餐' THEN oi.customer_price ELSE 0 END ) AS dinnerAmount,
-- COUNT( DISTINCT CASE WHEN oi.dinner_type = '加餐' THEN oi.eat_day END ) AS otherPerson,
COUNT( CASE WHEN oi.dinner_type = '加餐' THEN oi.eat_day END ) AS otherPerson,
SUM( CASE WHEN oi.dinner_type = '加餐' THEN oi.customer_price ELSE 0 END ) AS otherAmount,
SUM( oi.customer_price ) customerPrice,
SUM( oi.order_price ) orderPrice,
( SELECT COUNT( DISTINCT eat_day ) FROM st_bbzx_order_info WHERE member_id = oi.member_id and `status` = 5
and order_type = 3
<if test="list != null and list.size() > 0">
and canteen_id IN
<foreach collection="list" item="canteenId" separator="," open="(" close=")" >
#{canteenId}
</foreach>
</if>
<if test="startDate != '' and startDate != null ">
and eat_day between #{startDate} and #{endDate}
</if>
) AS totalNum
FROM
st_bbzx_order_info oi
JOIN sys_user_sub u ON oi.member_id = u.id
JOIN sys_user_sub pay ON oi.pay_member_id = pay.id
LEFT JOIN sys_pay_depart direct_depart ON pay.depart_ids = direct_depart.id AND direct_depart.del_flag = '0'
LEFT JOIN sys_pay_depart parent_depart ON direct_depart.parent_id = parent_depart.id AND parent_depart.del_flag = '0'
WHERE
oi.`status` = 5
and oi.order_type = 3
<if test="startDate != '' and startDate != null ">
and oi.eat_day between #{startDate} and #{endDate}
</if>
<if test="list != null and list.size() > 0">
and oi.canteen_id IN
<foreach collection="list" item="canteenId" separator="," open="(" close=")" >
#{canteenId}
</foreach>
</if>
<if test="name != '' and name != null ">
and (u.realname LIKE CONCAT('%',#{name},'%') OR u.username LIKE CONCAT('%', #{name},'%') or u.work_no LIKE CONCAT('%', #{name},'%') )
</if>
<if test="payName != '' and payName != null ">
and (pay.realname LIKE CONCAT('%',#{payName},'%') OR pay.username LIKE CONCAT('%', #{payName},'%') or pay.work_no LIKE CONCAT('%', #{payName},'%') )
</if>
<if test="secondDepartId != '' and secondDepartId != null ">
and dd.id = #{secondDepartId}
</if>
<if test="thirdDepartId != '' and thirdDepartId != null ">
and ddd.id = #{thirdDepartId}
</if>
GROUP BY
oi.member_id
ORDER BY
MAX(oi.eat_day) DESC
</select>
<select id="statisticsCanteenBusiness"
resultType="org.jeecg.restaurant.vo.StatisticsBusinessVo">
SELECT
ct.canteen_id,
r.rest_name AS restName,
-- 交易日期(按pay_time的日期维度分组,统一统计粒度)
DATE(ct.pay_time) AS payTime,
-- 1. 充值合计:status=102(充值),排除已删除记录,金额求和(无数据显示0)
IFNULL(SUM(CASE WHEN ct.`status` = 102 AND ct.is_del = 0 THEN ct.transaction_amount ELSE 0 END), 0) AS rechargeAmount,
-- 2. 退款合计:status=103(撤销充值),排除已删除记录,金额求和(无数据显示0)
IFNULL(SUM(CASE WHEN ct.`status` = 103 AND ct.is_del = 0 THEN ct.transaction_amount ELSE 0 END), 0) AS totalRefund,
-- 3. 消费次数合计:status=101(消费),排除已删除记录,统计有效交易次数
IFNULL(COUNT(CASE WHEN ct.`status` = 101 AND ct.is_del = 0 THEN 1 END), 0) AS totalCount,
-- 4. 消费金额合计:status=101(消费),排除已删除记录,金额求和(无数据显示0)
IFNULL(SUM(CASE WHEN ct.`status` = 101 AND ct.is_del = 0 THEN ct.transaction_amount ELSE 0 END), 0) AS customerPrice
FROM
st_client_member_transaction_record ct
LEFT JOIN st_base_restaurant r
ON ct.canteen_id = r.id
WHERE 1=1
<if test="startDate != '' and startDate != null ">
and DATE_FORMAT(ct.pay_time,'%Y-%m-%d') between #{startDate} and #{endDate}
</if>
<if test="list != null and list.size != 0 ">
and r.id IN
<foreach collection="list" item="screenVo" separator="," open="(" close=")">
#{screenVo.id}
</foreach>
</if>
GROUP BY
ct.canteen_id,
r.rest_name,
DATE(ct.pay_time)
ORDER BY
ct.canteen_id ASC,
DATE(ct.pay_time) desc
</select>
</mapper>
@@ -0,0 +1,6 @@
<?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="org.jeecg.payment.mapper.StBbzxOrderInfoPayMapper">
</mapper>
@@ -0,0 +1,352 @@
<?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="org.jeecg.payment.mapper.StClientMemberBalanceMapper">
<resultMap id="BaseResultMap" type="org.jeecg.payment.entity.StClientMemberBalance">
<!--@mbg.generated-->
<!--@Table st_client_member_balance-->
<id column="id" jdbcType="INTEGER" property="id"/>
<result column="member_id" jdbcType="VARCHAR" property="memberId"/>
<result column="top_up_balance" jdbcType="DECIMAL" property="topUpBalance"/>
<result column="top_up_total" jdbcType="DECIMAL" property="topUpTotal"/>
<result column="reward_balance" jdbcType="DECIMAL" property="rewardBalance"/>
<result column="integral_balance" jdbcType="INTEGER" property="integralBalance"/>
<result column="consumption_count" jdbcType="INTEGER" property="consumptionCount"/>
<result column="consumption_total" jdbcType="DECIMAL" property="consumptionTotal"/>
<result column="last_consumption_time" jdbcType="TIMESTAMP" property="lastConsumptionTime"/>
<result column="first_top_up_time" jdbcType="TIMESTAMP" property="firstTopUpTime"/>
<result column="invoice_total" jdbcType="DECIMAL" property="invoiceTotal"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
<result column="is_del" jdbcType="INTEGER" property="isDel"/>
</resultMap>
<sql id="Base_Column_List">
<!--@mbg.generated-->
id, member_id, top_up_balance, reward_balance, integral_balance, consumption_count,
consumption_total, last_consumption_time, first_top_up_time, create_user_no, create_time,
update_user_no, update_time, is_del, canteen_id
</sql>
<select id="pageList" resultType="org.jeecg.payment.vo.StClientMemberBalanceListVO">
SELECT
a.id,
b.id as userId,
b.realname as userName,
CONCAT(
IFNULL(parent_depart.depart_name, ''),
IF(parent_depart.depart_name IS NOT NULL AND direct_depart.depart_name IS NOT NULL, '->', ''),
IFNULL(direct_depart.depart_name, '')
) as deptName,
b.phone,
b.work_no as workNo,
b.card_code,
b.card_code_status,
a.is_status,
a.top_up_balance+a.reward_balance topUpBalanceTotal,
a.top_up_balance as topUpBalance,
a.consumption_count as consumptionCount,
a.consumption_total as consumptionTotal,
(select count(1) from st_client_member_transaction_record where member_id = a.member_id and status = 102 and is_del = 0) AS topUpCount,
a.reward_balance as rewardBalance,
a.last_consumption_time as lastConsumptionTime,
a.first_top_up_time as firstTopUpTime,
a.integral_balance as integralBalance,
a.top_up_total as topUpTotal
FROM
st_client_member_balance AS a
JOIN sys_user_sub AS b ON a.member_id = b.id
LEFT JOIN sys_pay_depart direct_depart ON b.depart_ids = direct_depart.id AND direct_depart.del_flag = '0'
LEFT JOIN sys_pay_depart parent_depart ON direct_depart.parent_id = parent_depart.id AND parent_depart.del_flag = '0'
WHERE
a.is_del = 0 and b.del_flag = 0
and b.user_type in (0,1) -- 用户类型(0:正式员工, 1:非正式员工,2:家庭用户)
<if test="vo.isStatus != null and vo.isStatus != ''">
and a.is_status = #{vo.isStatus}
</if>
<if test="vo.phone != null and vo.phone != ''">
and b.phone like CONCAT('%',#{vo.phone,jdbcType=VARCHAR},'%')
</if>
<if test="vo.cardCode != null and vo.cardCode != ''">
and b.card_code like CONCAT('%',#{vo.cardCode,jdbcType=VARCHAR},'%')
</if>
<if test="vo.cardCodeStatus != null and vo.cardCodeStatus != ''">
and b.card_code_status = #{vo.cardCodeStatus}
</if>
<if test="vo.userName != null and vo.userName != ''">
and b.realname like CONCAT('%',#{vo.userName,jdbcType=VARCHAR},'%')
</if>
<if test="vo.workNo != null and vo.workNo != ''">
and b.work_no like CONCAT('%',#{vo.workNo,jdbcType=VARCHAR},'%')
</if>
<if test="vo.startTime != null and vo.startTime != '' and vo.endTime != null and vo.endTime != ''">
and DATE_FORMAT(a.first_top_up_time,'%Y-%m-%d') between #{vo.startTime} and #{vo.endTime}
</if>
<if test="vo.list != null">
and b.depart_ids in
<foreach item="departId" collection="vo.list" open="(" separator="," close=")">
#{departId}
</foreach>
</if>
</select>
<!--余额/积分调整-->
<update id="changeBalanceAndIntegral">
UPDATE st_client_member_balance
<if test="status != null">
<set>
<choose>
<!--余额补录影响累计余额-->
<when test="status == 1">
<if test="topUpBalance != null">
top_up_balance = top_up_balance + #{topUpBalance,jdbcType=DECIMAL},
top_up_total = top_up_total + #{topUpBalance,jdbcType=DECIMAL}
</if>
<if test="rewardBalance != null">
reward_balance = reward_balance + #{rewardBalance,jdbcType=DECIMAL}
</if>
<if test="integralBalance != null">
integral_balance = integral_balance + #{integralBalance,jdbcType=DECIMAL}
</if>
</when>
<!--扣减不影响累计余额-->
<when test="status == 2">
<if test="topUpBalance != null">
top_up_balance = top_up_balance - #{topUpBalance,jdbcType=DECIMAL}
</if>
<if test="rewardBalance != null">
reward_balance = reward_balance - #{rewardBalance,jdbcType=DECIMAL}
</if>
<if test="integralBalance != null">
integral_balance = integral_balance - #{integralBalance,jdbcType=DECIMAL}
</if>
</when>
</choose>
</set>
</if>
WHERE id = #{id,jdbcType=INTEGER}
<!--扣减需要余额大于扣减数额-->
<if test="status == 2">
<if test="topUpBalance != null">
AND top_up_balance >= #{topUpBalance,jdbcType=DECIMAL}
</if>
<if test="rewardBalance != null">
AND reward_balance >= #{rewardBalance,jdbcType=DECIMAL}
</if>
<if test="integralBalance != null">
AND integral_balance >= #{integralBalance,jdbcType=DECIMAL}
</if>
</if>
</update>
<!--充值-->
<update id="memberTopUp">
UPDATE st_client_member_balance
<set>
<if test="topUpBalance != null">
top_up_balance = top_up_balance + #{topUpBalance,jdbcType=DECIMAL},
top_up_total = top_up_total + #{topUpBalance,jdbcType=DECIMAL},
</if>
<if test="rewardBalance != null">
reward_balance = reward_balance + #{rewardBalance,jdbcType=DECIMAL},
</if>
<if test="integralBalance != null">
integral_balance = integral_balance + #{integralBalance,jdbcType=DECIMAL},
</if>
<if test="invoiceBalance != null">
invoice_total = invoice_total + #{invoiceBalance,jdbcType=DECIMAL},
</if>
is_sync = 0
</set>
where id = #{id}
</update>
<!--撤销充值用户vo-->
<select id="selectBackOutUser" resultType="org.jeecg.payment.vo.StClientMemberBackOutUserVO">
SELECT
a.realname AS userName,
a.phone,
'' AS cardCode,
'' as eaName,
'' as cardLevelName,
a.work_no as workNo,
'' as deptName
FROM
sys_user_sub AS a
JOIN st_client_member_balance AS b ON b.member_id = a.id
where a.id = #{memberId}
</select>
<!--撤销充值的交易流水查询-->
<select id="selectRunningTabAsBackOut" resultType="org.jeecg.payment.vo.StClientMemberBackOutPayVO">
select IFNULL(B.operationStatus,1) as operationStatus,
A.*
from (
select
b.id,
b.serial_no as serialNo,
b.order_no as orderNo,
b.pay_order_no as payOrderNo,
b.status,
b.payment_method as paymentMethod,
b.update_status as updateStatus,
c.realname as createOne,
b.remark,
b.stored_balance as storedBalance,
b.reward_balance as rewardBalance,
b.create_time as createTime
from st_client_member_transaction_record as b
left join sys_user_sub as c on b.create_by = c.id
where b.member_id = #{memberId}
<if test="canteenId != null and canteenId != '' ">
and b.canteen_id = #{canteenId}
</if>
AND b.status in
<foreach collection="list" separator="," open="(" close=")" item="statusList">
#{statusList}
</foreach>
) AS A
left join (
select order_no,0 as operationstatus
from st_client_member_transaction_record where member_id = #{memberId} and status =
#{status,jdbcType=INTEGER}
) AS B on A.orderNo = B.order_no
order by A.createTime desc
</select>
<!--查询最新的一条数据-->
<select id="selectLastMsgByTime" resultMap="BaseResultMap">
select * from st_client_member_transaction_record
where member_id = #{memberId,jdbcType=VARCHAR}
AND status in
<foreach collection="list" separator="," open="(" close=")" item="statusList">
#{statusList}
</foreach>
order by create_time desc limit 0,1;
</select>
<select id="selectLastMsgByPayTime" resultMap="BaseResultMap">
SELECT
*
FROM
st_client_member_transaction_record
WHERE
member_id = #{memberId,jdbcType=VARCHAR} and status = #{status,jdbcType=INTEGER}
AND order_no not in ( SELECT c.order_no FROM st_client_member_transaction_record c where c.member_id = #{memberId,jdbcType=VARCHAR} GROUP BY c.order_no HAVING count( c.order_no ) > 1 )
order by create_time desc
limit 0,1
</select>
<!--撤销充值-->
<update id="backOutTopUp">
UPDATE st_client_member_balance SET
top_up_balance = top_up_balance - #{topUpSubtractBalance,jdbcType=DECIMAL},
top_up_total = top_up_total - #{topUpSubtractBalance,jdbcType=DECIMAL},
reward_balance = reward_balance - #{rewardSubtractBalance,jdbcType=DECIMAL},
integral_balance = integral_balance - #{integralSubtractBalance,jdbcType=INTEGER},
is_sync = 0
WHERE id = #{id,jdbcType=INTEGER}
AND top_up_balance = #{oldTopUpBalance,jdbcType=DECIMAL}
AND reward_balance = #{oldRewardBalance,jdbcType=DECIMAL}
</update>
<!--会员消费-->
<update id="memberSpend">
update st_client_member_balance set
<if test="topUpBalance != null">
top_up_balance = top_up_balance - #{topUpBalance,jdbcType=DECIMAL},
</if>
<if test="rewardBalance != null">
reward_balance = reward_balance - #{rewardBalance,jdbcType=DECIMAL},
</if>
consumption_count = consumption_count + 1,
consumption_total = consumption_total + #{consumptionTotal,jdbcType=DECIMAL},
is_sync = 0,
last_consumption_time = now()
where id = #{id,jdbcType=INTEGER}
</update>
<select id="memberTranRecordMapper" resultType="org.jeecg.payment.entity.StClientMemberTransactionRecord">
SELECT
r.id,
r.STATUS,
r.create_time,
r.pay_time,
r.transaction_amount,
r.available_balance,
r.reward_balance,
r.order_no
FROM
st_client_member_transaction_record r
WHERE
r.member_id = #{userId}
AND r.is_del = 0
<if test="status == null">
and r.STATUS in (101,102,103)
</if>
<if test="status != null and status == 0 ">
and r.STATUS in (102,103)
</if>
<if test="status != null and status == 1 ">
and r.STATUS = 101
</if>
ORDER BY
r.create_time DESC
</select>
<select id="getBalanceInfo" resultType="org.jeecg.payment.vo.StMiniMineBalanceVo">
SELECT
(mb.top_up_balance + mb.reward_balance) balance,
'' as levelId,
mb.integral_balance AS integralBalance,
mb.user_inner_type as userInnerType
FROM
sys_user_sub u
LEFT JOIN st_client_member_balance mb ON mb.member_id = u.id
WHERE
u.id = #{userId}
</select>
<select id="getOneByUserId" resultType="org.jeecg.user.entity.SysUserSub">
SELECT id,main_user_id,status,del_flag,realname,work_no,user_type FROM sys_user_sub WHERE id = #{userId}
-- and del_flag = 0
</select>
<select id="getBalanceByUserId" resultType="org.jeecg.payment.vo.StMiniMineBalanceVo">
SELECT
mb.id,
( mb.top_up_balance + mb.reward_balance ) balance,
mb.integral_balance AS integralBalance,
mb.user_inner_type AS userInnerType ,
u.`status` userStatus,
mb.member_id,
u.realname as payRealname,
u.work_no as payWorkNo,
u.del_flag as pay_del_flag
FROM
sys_user_sub u
LEFT JOIN st_client_member_balance mb ON u.id = mb.member_id
WHERE
u.id = #{userId}
</select>
<select id="getOneByCardCode" resultType="org.jeecg.user.entity.SysUserSub">
SELECT id,main_user_id,status,del_flag,realname,work_no,user_type,card_code,card_code_status FROM sys_user_sub WHERE card_code = #{cardCode}
</select>
<select id="getSubUserListByCardNoList" resultType="org.jeecg.user.vo.SysUserSubInfo">
SELECT
scmb.id AS balanceId,
sus.*
FROM
sys_user_sub sus
INNER JOIN st_client_member_balance scmb ON sus.id = scmb.member_id
WHERE
sus.card_no
in
<foreach collection="list" separator="," open="(" close=")" item="cardNo">
#{cardNo}
</foreach>
AND scmb.is_del = 0
AND sus.del_flag = 0
</select>
</mapper>
@@ -0,0 +1,21 @@
<?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="org.jeecg.payment.mapper.StClientMemberLevelDeductRuleMapper">
<select id="selectStClientMemberLevelDeductRulePage" resultType="org.jeecg.payment.vo.StClientMemberLevelDeductRuleVo">
select * from st_client_member_level_deduct_rule
where 1=1
<if test="vo.canteenId != null and vo.canteenId != ''">
and canteen_id = #{vo.canteenId}
</if>
<if test="vo.ruleName != null and vo.ruleName != ''">
and rule_name like CONCAT('%',#{vo.ruleName},'%')
</if>
<if test="vo.isEnable != null and vo.isEnable != ''">
and is_enable = #{vo.isEnable}
</if>
order by is_enable desc, create_time desc
</select>
</mapper>
@@ -0,0 +1,21 @@
<?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="org.jeecg.payment.mapper.StClientMemberLevelDemotionTimeMapper">
<select id="selectSwClientMemberLevelDemotionTimePage" resultType="org.jeecg.payment.vo.StClientMemberLevelDemotionTimeVO">
select * from st_client_member_level_demotion_time
where 1=1
<if test="vo.canteenId != null and vo.canteenId != ''">
and canteen_id = #{vo.canteenId}
</if>
<if test="vo.ruleName != null and vo.ruleName != ''">
and rule_name like CONCAT('%',#{vo.ruleName},'%')
</if>
<if test="vo.isEnable != null">
and is_enable = #{vo.isEnable}
</if>
order by is_enable desc, create_time desc
</select>
</mapper>
@@ -0,0 +1,212 @@
<?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="org.jeecg.payment.mapper.StClientMemberTransactionRecordMapper">
<resultMap id="BaseResultMap" type="org.jeecg.payment.entity.StClientMemberTransactionRecord">
<!--@mbg.generated-->
<!--@Table st_client_member_transaction_record-->
<id column="id" jdbcType="VARCHAR" property="id"/>
<result column="member_id" jdbcType="VARCHAR" property="memberId"/>
<result column="serial_no" jdbcType="VARCHAR" property="serialNo"/>
<result column="order_no" jdbcType="VARCHAR" property="orderNo"/>
<result column="status" jdbcType="INTEGER" property="status"/>
<result column="transaction_amount" jdbcType="DECIMAL" property="transactionAmount"/>
<result column="payment_method" jdbcType="INTEGER" property="paymentMethod"/>
<result column="stored_balance" jdbcType="DECIMAL" property="storedBalance"/>
<result column="reward_balance" jdbcType="DECIMAL" property="rewardBalance"/>
<result column="integral_balance" jdbcType="INTEGER" property="integralBalance"/>
<result column="available_balance" jdbcType="DECIMAL" property="availableBalance"/>
<result column="pay_time" jdbcType="TIMESTAMP" property="payTime"/>
<result column="update_status" jdbcType="INTEGER" property="updateStatus"/>
<result column="remark" jdbcType="VARCHAR" property="remark"/>
<result column="is_invoice" jdbcType="INTEGER" property="isInvoice"/>
<result column="reward_user_no" jdbcType="VARCHAR" property="rewardUserNo"/>
<result column="create_by" jdbcType="VARCHAR" property="createBy"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
<result column="update_by" jdbcType="VARCHAR" property="updateBy"/>
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
<result column="is_del" jdbcType="INTEGER" property="isDel"/>
<result column="canteen_id" jdbcType="VARCHAR" property="canteenId"/>
</resultMap>
<sql id="Base_Column_List">
<!--@mbg.generated-->
id, member_id, serial_no, order_no, `status`, transaction_amount, payment_method,
stored_balance, reward_balance, integral_balance, pay_time, update_status, create_by,
create_time, update_by, update_time, is_del, canteen_id
</sql>
<select id="pageList" resultType="org.jeecg.payment.vo.StClientMemberTransactionRecordVO">
SELECT
a.id,
a.serial_no as serialNo,
a.order_no as orderNo,
c.realname as userName,
sboi.serial_no as cardCode,
sboi.business_model AS businessModel,
pay.realname as payUserName,
CONCAT(
IFNULL(parent_depart.depart_name, ''),
IF(parent_depart.depart_name IS NOT NULL AND direct_depart.depart_name IS NOT NULL, '->', ''),
IFNULL(direct_depart.depart_name, '')
) as deptName,
c.phone,
c.work_no as workNo,
a.status,
a.transaction_amount as transactionAmount,
a.payment_method as paymentMethod,
a.available_balance as availableBalance,
a.reward_balance as rewardBalance,
a.stored_balance as storedBalance,
a.integral_balance as integralBalance,
b.consumption_total as monetary,
a.create_time as createTime,
a.pay_time as payTime,
a.update_status as updateStatus,
br.rest_name as restName,
sboi.dinner_type AS dinnerType
FROM
st_client_member_transaction_record as a
LEFT JOIN st_client_member_balance AS b ON a.member_id = b.member_id
LEFT JOIN st_bbzx_order_info AS sboi ON sboi.order_no = a.order_no
LEFT JOIN st_base_restaurant AS br ON br.id = a.canteen_id
LEFT JOIN sys_user_sub AS c ON a.member_id = c.id
LEFT JOIN sys_user_sub AS pay ON a.pay_member_id = pay.id
LEFT JOIN sys_pay_depart direct_depart ON pay.depart_ids = direct_depart.id AND direct_depart.del_flag = '0'
LEFT JOIN sys_pay_depart parent_depart ON direct_depart.parent_id = parent_depart.id AND parent_depart.del_flag = '0'
WHERE a.is_del = 0
<if test="vo.startTime != null and vo.endTime !=''">
<choose>
<when test="vo.payTimeStatus == 1">
and DATE_FORMAT(a.pay_time,'%Y-%m-%d') &gt;= DATE_FORMAT(#{vo.startTime},'%Y-%m-%d')
and DATE_FORMAT(a.pay_time,'%Y-%m-%d') &lt;= DATE_FORMAT(#{vo.endTime},'%Y-%m-%d')
</when>
<when test="vo.payTimeStatus == 2">
and DATE_FORMAT(a.create_time,'%Y-%m-%d') &gt;= DATE_FORMAT(#{vo.startTime},'%Y-%m-%d')
and DATE_FORMAT(a.create_time,'%Y-%m-%d') &lt;= DATE_FORMAT(#{vo.endTime},'%Y-%m-%d')
</when>
</choose>
</if>
<if test="vo.status == null">
and a.STATUS in (101,102,103)
</if>
<if test="vo.status != null and vo.status == 0 ">
and a.STATUS in (102,103)
</if>
<if test="vo.status != null and vo.status == 1 ">
and a.STATUS = 101
</if>
<if test="vo.status != null and vo.status == 2 ">
and a.STATUS in (301,302)
</if>
<if test="vo.status != null and vo.status == 3 ">
and a.STATUS = 102
</if>
<if test="vo.phone != null and vo.phone != ''">
and c.phone like CONCAT('%',#{vo.phone,jdbcType=VARCHAR},'%')
</if>
<if test="vo.cardCode != null and vo.cardCode != ''">
and sboi.serial_no like CONCAT('%',#{vo.cardCode,jdbcType=VARCHAR},'%')
</if>
<if test="vo.businessModel != null and vo.businessModel != ''">
and sboi.business_model = #{vo.businessModel}
</if>
<if test="vo.paymentMethod != null and vo.paymentMethod != ''">
and a.payment_method = #{vo.paymentMethod}
</if>
<if test="vo.workNo != null and vo.workNo != ''">
and c.work_no like CONCAT('%',#{vo.workNo,jdbcType=VARCHAR},'%')
</if>
<if test="vo.userName != null and vo.userName != ''">
and c.realname like CONCAT('%',#{vo.userName,jdbcType=VARCHAR},'%')
</if>
<if test="vo.canteenId != null and vo.canteenId != ''">
and a.canteen_id = #{vo.canteenId}
</if>
<if test="vo.list != null">
and pay.depart_ids in
<foreach item="departId" collection="vo.list" open="(" separator="," close=")">
#{departId}
</foreach>
</if>
order by a.create_time desc
</select>
<select id="pageBalanceRefundList" resultType="org.jeecg.payment.vo.StClientMemberTransactionRecordVO">
SELECT
a.id,
a.serial_no as serialNo,
a.order_no as orderNo,
c.realname as userName,
c.phone,
c.work_no as workNo,
a.status,
a.available_balance as availableBalance,
a.reward_balance as rewardBalance,
a.stored_balance as storedBalance,
a.transaction_amount as transactionAmount,
b.consumption_total as monetary,
a.payment_method as paymentMethod,
a.integral_balance as integralBalance,
a.create_time as createTime,
a.pay_time as payTime,
a.update_status as updateStatus,
d.realname as createOne
FROM
st_client_member_transaction_record as a
LEFT JOIN st_client_member_balance AS b ON a.member_id = b.member_id
LEFT JOIN sys_user AS d ON a.create_by = d.id
LEFT JOIN sys_user AS c ON a.member_id = c.id
WHERE a.is_del = 0
<if test="vo.canteenId != null and vo.canteenId != '' ">
and a.canteen_id = #{vo.canteenId}
</if>
<if test="vo.startTime != null and vo.endTime !=''">
<choose>
<when test="vo.payTimeStatus == 1">
and DATE_FORMAT(a.pay_time,'%Y-%m-%d') &gt;= DATE_FORMAT(#{vo.startTime},'%Y-%m-%d')
and DATE_FORMAT(a.pay_time,'%Y-%m-%d') &lt;= DATE_FORMAT(#{vo.endTime},'%Y-%m-%d')
</when>
<when test="vo.payTimeStatus == 2">
and DATE_FORMAT(a.create_time,'%Y-%m-%d') &gt;= DATE_FORMAT(#{vo.startTime},'%Y-%m-%d')
and DATE_FORMAT(a.create_time,'%Y-%m-%d') &lt;= DATE_FORMAT(#{vo.endTime},'%Y-%m-%d')
</when>
</choose>
</if>
<if test="vo.status == null">
and a.STATUS in (101,102,103)
</if>
<if test="vo.status != null and vo.status == 0 ">
and a.STATUS in (102,103)
</if>
<if test="vo.status != null and vo.status == 1 ">
and a.STATUS = 101
</if>
<if test="vo.status != null and vo.status == 2 ">
and a.STATUS in (301,302)
</if>
<if test="vo.phone != null and vo.phone != ''">
and c.phone like CONCAT('%',#{vo.phone,jdbcType=VARCHAR},'%')
</if>
<if test="vo.workNo != null and vo.workNo != ''">
and c.work_no like CONCAT('%',#{vo.workNo,jdbcType=VARCHAR},'%')
</if>
<if test="vo.userName != null and vo.userName != ''">
and c.realname like CONCAT('%',#{vo.userName,jdbcType=VARCHAR},'%')
</if>
order by a.create_time,a.pay_time desc
</select>
<select id="getOneInOutInfo" resultType="org.jeecg.payment.vo.InOutRecordInfoVo">
SELECT
record.`status`,
record.transaction_amount,
record.pay_time,
record.order_no,
record.payment_method,
IFNULL(record.remark,'-') remark,
ea.rest_name as ea_name
FROM
st_client_member_transaction_record record
LEFT JOIN st_base_restaurant ea ON ea.id = record.canteen_id
WHERE
record.id = #{recordId}
</select>
</mapper>
@@ -0,0 +1,16 @@
/**
* use shuwei code generator created
*/
package org.jeecg.payment.service;
import org.jeecg.common.system.base.service.JeecgService;
import org.jeecg.payment.entity.StBbzxOrderInfoPay;
/**
* 支付信息 服务类
*/
public interface IStBbzxOrderInfoPayService extends JeecgService<StBbzxOrderInfoPay> {
}
@@ -0,0 +1,217 @@
/**
* use shuwei code generator created
*/
package org.jeecg.payment.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.jeecg.common.system.base.service.JeecgService;
import org.jeecg.payment.vo.*;
import org.jeecg.payment.OrderInfo;
import org.jeecg.payment.entity.StBbzxOrderInfo;
import org.jeecg.restaurant.vo.StatisticsBusinessVo;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* 订单 服务类
*/
public interface IStBbzxOrderInfoService extends JeecgService<StBbzxOrderInfo> {
// /***
// * 微信小程序充值
// * @param orderInfo
// * @return
// */
// JSONObject saveXCXorderInfoTopUp(OrderInfo orderInfo);
//获取余额信息+充值规则模板
StMiniMineBalanceVo mineBalanceInfo(String userId, String canteenId);
/**
* 用户支出/充值记录列表
* @param userId 用户标识
*/
IPage<StRecordListInfo> getSpendingOrRechargeInfoListV2(String userId, Integer pageNum, Integer pageSize);
/**
* 根据订单号 获取订单信息
*
* @param orderCode
* @return
*/
StBbzxOrderInfo getSwBbzxOrderInfo(String orderCode);
/**
* 根据payId查询支付订单
*
* @param payId
* @return
*/
StBbzxOrderInfo getSwBbzxOrderInfoByPayId(String payId);
// /**
// * 退单
// *
// * @param orderNo
// * @return
// */
// boolean returnOrder(String orderNo);
//
// /**
// * 线上消费退款
// *
// * @param payDto
// * @return
// */
// Result<?> returnPayInfo(RefundDTO payDto);
//
//
// /**
// * 线上充值退款
// *
// * @param payDto
// * @return
// */
// Result<?> returnPayInfoTopUpOnline(RefundDTO payDto);
void updateMemberIdByOpenId(String openId,String memberId,String memberName);
/**
*
* @param orderId 订单主表id
* @param orderFrom 订单来源(1平板端 、2收银端、3自助点餐机、4小程序、5自助餐)
* @param payCode 小程序 支付编码
* @param payType 支付类型: 1是支付宝 2微信 3现金 4会员 5混合
* @param orderFromSign 支付用户id(微信支付 = openid、支付宝支付 = 支付宝id)
* @param bh 混合支付时,会员支付的金额
* @param tradeOrderNo 渠道支付返回的三方交易订单号
* @param tarnsCode 混合支付时 经过随机数3位拼接的自定义余额支付订单号
*/
void updateOrderFeign(String orderId, int orderFrom, String payCode, Integer payType, String orderFromSign,
StBbzxOrderInfo orderInfo, BigDecimal bh, String tradeOrderNo, String tarnsCode);
/**
* 消费金额统计
* @param canteenId 食堂id
* @param startDate 开始时间
* @param endDate 结束时间
* @param pageNo 页数
* @param pageSize 条数
* @return 消费金额统计
*/
IPage<?> getStatisticsTheAmountSpentList(String canteenId, String startDate, String endDate, Integer pageNo, Integer pageSize);
/**
* 消费金额统计
* @param canteenId 食堂id
* @param startDate 开始时间
* @param endDate 结束时间
* @return 消费金额统计
*/
List<StatisticsTheAmountSpentVo> getStatisticsTheAmountSpentList(String canteenId, String startDate, String endDate);
/**
* 个人消费记录统计
* @param startDate 开始时间
* @param endDate 结束时间
* @param secondDepartId 二级单位id
* @param thirdDepartId 三级部门id
* @param pageNo 页数
* @param pageSize 条数
* @return 个人消费记录统计
*/
IPage<?> statisticsTheAmountSpentEveryMember(String canteenId,String name,String payName,String startDate, String endDate, String secondDepartId,String thirdDepartId,Integer pageNo, Integer pageSize);
/**
* 个人消费记录统计导出
* @param startDate 开始时间
* @param endDate 结束时间
* @param secondDepartId 二级单位id
* @param thirdDepartId 三级部门id
* @return 个人消费记录统计
*/
List<StatisticsTheAmountSpentVo> statisticsTheAmountSpentEveryMember(String canteenId,String name,String payName,String startDate, String endDate, String secondDepartId,String thirdDepartId);
/**
* 食堂营业查询报表
* @param startDate 开始时间
* @param endDate 结束时间
* @param pageNo 页数
* @param pageSize 条数
* @return 食堂营业查询报表
*/
IPage<?> statisticsCanteenBusiness(String canteenId,String startDate, String endDate, String secondDepartId,String thirdDepartId,Integer pageNo, Integer pageSize);
/**
* 食堂营业查询报表-导出
* @param startDate 开始时间
* @param endDate 结束时间
* @return 食堂营业查询报表
*/
List<StatisticsBusinessVo> statisticsCanteenBusiness(String canteenId, String startDate, String endDate, String secondDepartId, String thirdDepartId);
/**
* 统一生成订单
* @param restId
* @param userId
* @param plateNumber
* @return
*/
StBbzxOrderInfo crateOrderInfo(Date dateTime, String restId, String userId, String plateNumber, String timesName,StRfidVo stRfidVo);
StBbzxOrderInfo buildOrderInfoNew(Date dateTime, String restId, String dinnerType, String plateNumber, String userId, String memberName,
String memberPhone, Integer deductionType, StClientMemberLevelDeductRuleVo levelDeductRuleVo, String remark,StRfidVo stRfidVo);
/**
* 离线订单
* @param dateTime
* @param restId
* @param dinnerType
* @param plateNumber
* @param userId
* @param memberName
* @param memberPhone
* @param deductionType
* @param levelDeductRuleVo
* @param remark
* @param stRfidVo
* @param miniMineBalanceVo
* @return
*/
StBbzxOrderInfo buildOrderInfoNewOffLine(Date dateTime, String restId, String dinnerType, String plateNumber, String userId, String memberName,
String memberPhone, Integer deductionType, StClientMemberLevelDeductRuleVo levelDeductRuleVo, String remark,StRfidVo stRfidVo,StMiniMineBalanceVo miniMineBalanceVo);
/**
* 根据userId + 日期 + 餐次 + 订单状态,获取订单信息
* @param userId
* @param eatDay
* @param dinnerType
* @param orderStatus
* @param businessModel 经营模式、扣费类型(1:固定扣费,2:固定+补贴扣费,3:按量扣费)
* @return
*/
StBbzxOrderInfo getSwBbzxOrderInfoByUserId(String userId,String eatDay,String dinnerType,Integer orderStatus,String restId,
Integer businessModel );
/**
* 定时任务 根据userId + 日期 + 订单状态,获取未支付的订单信息
* @param userId
* @param eatDay
* @param orderStatus
* @param businessModel 经营模式、扣费类型(1:固定扣费,2:固定+补贴扣费,3:按量扣费)
* @return
*/
List<StBbzxOrderInfo> getSwBbzxOrderInfoListByUserId(String userId, String eatDay, String dinnerType, Integer orderStatus, String restId,
Integer businessModel);
}
@@ -0,0 +1,196 @@
package org.jeecg.payment.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.base.service.JeecgService;
import org.jeecg.payment.dto.StClientMemberChangeBalanceDTO;
import org.jeecg.payment.dto.StClientMemberTopUpDTO;
import org.jeecg.payment.dto.StClientMemberTransactionRecordDTO;
import org.jeecg.payment.dto.StClientUserInfoShopPageDTO;
import org.jeecg.payment.entity.StBbzxOrderInfo;
import org.jeecg.payment.entity.StClientMemberBalance;
import org.jeecg.payment.entity.StClientMemberTransactionRecord;
import org.jeecg.payment.vo.*;
import org.springframework.web.multipart.MultipartFile;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
/**
* @author Ls.
* @date 2021/6/16.
*/
public interface IStClientMemberBalanceService extends JeecgService<StClientMemberBalance> {
/**
* 后台用户充值列表
* @param
* @return
*/
IPage<StClientMemberBalanceListVO> memberClientMemberBalanceService(Page<StClientMemberBalanceListVO> page, StClientMemberTransactionRecordDTO stClientUserInfoShopPageDTO);
List<StClientMemberBalanceListVO> getSpendingOrRechargeInfoListExport(StClientMemberTransactionRecordDTO stClientUserInfoShopPageDTO);
/**
* 小程序 会员卡充值
* @param memberId memberId
* @param topUpBalance 交易金额
* @param paymentMethod 支付方式
* @return 赠送金额+赠送积分
*/
Map memberTopUpXcx(String memberId,
BigDecimal topUpBalance,
int paymentMethod,String orderNo);
/**
* 会员交易记录
* @param userId
* @return 会员交易记录
*/
IPage<StClientMemberTransactionRecord> memberTranRecordService(Page<StClientMemberTransactionRecord> page,String userId,String status);
/**
* 会员充值
*
* @param canteenId
* @param userId
* @param value
* @param paymentMethod
* @return
*/
Map memberTopUp_new_yc(String canteenId, String userId, BigDecimal value, int paymentMethod);
/**
* 主键id
* 撤销充值列表查询
*/
StClientMemberBackOutVO backOutTopUpList(StClientMemberBackOutTopUpDTO query);
/**
* 撤销充值
*
* @return
*/
Result<?> backOutTopUpOffLine(StClientMemberBackTopUpQueryDto queryDto);
/**
* 根据订单号获取 充值订单记录信息
*
* @param payOrderNo 小程序充值成功后微信订单号
* @return 订单记录信息
*/
StClientMemberTransactionRecord getRecordInfoAboutRechargeByPayOrderNo(String payOrderNo, String orderNo, List<Integer> integerList);
/**
* 充值退款后逻辑
* 通过充值记录 生成退款记录 , 计算balance表数据
* @param czRecord 充值记录
*/
void backOrder( StClientMemberTransactionRecord czRecord);
/**
* 会员消费
*
* @param query
*/
StClientMemberSpendVO memberSpend(StClientMemberSpendDTO query) throws Exception;
/**
* 会员消费
*
* @param query
*/
StClientMemberSpendVO memberSpendV2(StClientMemberSpendDTO query) throws Exception;
/**
* 用户余额消费统一扣费方法
* query.id 必填:用户id
* query.orderNo 必填:订单号
*
* @return StClientMemberSpendVO
* @throws Exception
*/
StClientMemberSpendVO memberSpendV3(StClientMemberSpendDTO query);
/**
* 用户余额消费统一扣费方法
* query.id 必填:用户id
* query.orderNo 必填:订单号
*
* @return StClientMemberSpendVO
* @throws Exception
*/
StClientMemberSpendVO memberSpendOffline(StClientMemberSpendDTO query, StBbzxOrderInfo stBbzxOrderInfo);
/**
* 补偿人脸扣费闸机离线扣费方法(只考虑透支消费版本)
* StClientMemberSpendDTO 支付信息
*
* @return StClientMemberSpendVO
* @throws Exception
*/
List<StClientMemberSpendVO> memberSpendOfflineCompensate(List<String> orderIds);
/**
* 积分/余额调整
*
* @param query
* @return
*/
Result<?> changeBalanceAndIntegral(StClientMemberChangeBalanceDTO query);
/**
* 后台员卡充值
*
* @return
*/
boolean memberTopUp(StClientMemberTopUpDTO query);
/**
* 充值明细导入
* @param snList
*/
Map<String, List<StClientMemberTopUpDTO>> importRechargeData(List<StClientMemberTopUpDTO> snList);
/**
* 充值明细导入(全量校验通过后才执行真实充值)
*
* @param orgList 待导入的充值明细列表
*/
Map<String, List<StClientMemberTopUpDTO>> importRechargeDataV2(List<StClientMemberTopUpDTO> orgList);
public List<StClientMemberTopUpDTO> parseExcel(MultipartFile file, String canteenId);
/**
* 计算本次扣费金额(一次扣费模式返回实际扣费金额,按量扣费直接返回0)
* @param levelDeductRuleVo 扣费规则
* @param dinnerType 餐次
* @param totalDeduction 费用总计(一次扣费模式=固定/固定+补贴,按量扣费模式=实际金额)
* @param spendMoney 消费金额
* @param rewardDeduction 补贴金额
* @param userInnerType 用户类型(内部用户=0,外部用户=1)
*/
StClientMemberSpendDataVO fixedFee(StClientMemberLevelDeductRuleVo levelDeductRuleVo, String dinnerType,
BigDecimal totalDeduction, BigDecimal spendMoney, BigDecimal rewardDeduction, Integer userInnerType);
Result<StMiniMineBalanceVo> getUserBalance(String userId);
/**
* 根据卡号查询用户钱包
* @param cardCode
* @return
*/
Result<StMiniMineBalanceVo> getUserBalanceByCardCode(String cardCode);
}
@@ -0,0 +1,66 @@
package org.jeecg.payment.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.base.service.JeecgService;
import org.jeecg.payment.entity.StClientMemberLevelDeductRule;
import org.jeecg.payment.entity.StClientMemberLevelDemotionTime;
import org.jeecg.payment.vo.*;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* 扣费规则 服务类
*/
public interface IStClientMemberLevelDeductRuleService extends JeecgService<StClientMemberLevelDeductRule> {
/**
* 列表查询
*
* @param query
* @return
*/
IPage<StClientMemberLevelDeductRuleVo> selectStClientMemberLevelDemotionTimePage(StClientMemberLevelDemotionTimeVO query);
Boolean saveOrUpdateService(StClientMemberLevelDeductRuleVo vo);
StClientMemberLevelDeductRuleVo getOneService(StClientMemberLevelDeductRuleVo stClientMemberLevelDeductRuleVo);
StClientMemberLevelDeductRuleVo getDeductRuleByCanteenId(String canteenId);
/**
* 组装扣费规则vo
*
* @param vo
* @param memberLevel
* @return
*/
StClientMemberLevelDeductRuleVo bulidStClientMemberLevelDeductRule(StClientMemberLevelDeductRuleVo vo, StClientMemberLevelDeductRule memberLevel);
Result<StClientMemberSpendVO> bindUserOfflineCardCode(@RequestBody StRfidoffLineVo stRfidoffLineVo);
/**
* 异步生成订单和进行实际扣费流程
* @param dateTime 订单时间
* @param restId
* @param userId
* @param stRfidVo
* @param timesName
*/
public String syncMemberSpendOffLine(Date dateTime, String restId, String userId, StRfidVo stRfidVo, String timesName, StMiniMineBalanceVo miniMineBalanceVo, StClientMemberLevelDeductRuleVo levelDeductRuleVo);
public Map<String, List<StRfidVo>> groupByMeal(List<StRfidVo> rfidVos, String restId);
}
@@ -0,0 +1,52 @@
package org.jeecg.payment.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.base.service.JeecgService;
import org.jeecg.payment.dto.StClientMemberTransactionRecordDTO;
import org.jeecg.payment.entity.StClientMemberLevelDemotionTime;
import org.jeecg.payment.vo.StClientMemberLevelDemotionTimeVO;
import org.jeecg.payment.vo.StClientMemberTransactionRecordVO;
import org.jeecg.payment.vo.StMemberLevelStoredVO;
import java.util.List;
import java.util.Map;
/**
* 储值规则 服务类
*/
public interface IStClientMemberLevelDemotionTimeService extends JeecgService<StClientMemberLevelDemotionTime> {
/**
* 会员充值奖励后台接口
* levelId:关系表id
* topUpPrice:充值金额
*/
Map<String, Object> topUpAwardService(Integer levelId, Float topUpPrice,String canteenId);
/**
* 列表查询
*
* @param query
* @return
*/
IPage<StClientMemberLevelDemotionTimeVO> selectStClientMemberLevelDemotionTimePage(StClientMemberLevelDemotionTimeVO query);
Boolean saveOrUpdateService(StClientMemberLevelDemotionTimeVO swClientMemberLevelDemotionTime);
StClientMemberLevelDemotionTimeVO getOneService(StClientMemberLevelDemotionTime swClientMemberLevelDemotionTime);
/**
*
* @return 店铺会员卡权益规则信息
*/
List<StMemberLevelStoredVO> appMemberLevelStoredService();
Result<?> memberLevelDemotionTimeByCanteenId(String canteenId);
}
@@ -0,0 +1,39 @@
package org.jeecg.payment.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.jeecg.common.system.base.service.JeecgService;
import org.jeecg.payment.dto.StClientMemberTransactionRecordDTO;
import org.jeecg.payment.entity.StClientMemberTransactionRecord;
import org.jeecg.payment.vo.InOutRecordInfoVo;
import org.jeecg.payment.vo.StClientMemberTransactionRecordVO;
import org.jeecg.restaurant.vo.SlBaseRestaurantVo;
import java.util.List;
/**
* 会员卡交易记录
*/
public interface IStClientMemberTransactionRecordService extends JeecgService<StClientMemberTransactionRecord> {
/**
* 列表查询
*
* @param query
* @return
*/
IPage<StClientMemberTransactionRecordVO> pageQuery(StClientMemberTransactionRecordDTO query);
/**
* 列表查询导出
*
* @param query
* @return
*/
List<StClientMemberTransactionRecordVO> queryList(StClientMemberTransactionRecordDTO query);
IPage<StClientMemberTransactionRecordVO> pageBalanceRefundList(Page<StClientMemberTransactionRecordVO> page, StClientMemberTransactionRecordDTO query);
InOutRecordInfoVo getOneInOutInfo(String recordId);
}
@@ -0,0 +1,20 @@
/**
* use shuwei code generator created
*/
package org.jeecg.payment.service.impl;
import org.jeecg.common.system.base.service.impl.JeecgServiceImpl;
import org.jeecg.payment.entity.StBbzxOrderInfoPay;
import org.jeecg.payment.mapper.StBbzxOrderInfoPayMapper;
import org.jeecg.payment.service.IStBbzxOrderInfoPayService;
import org.springframework.stereotype.Service;
/**
* 支付信息 服务实现类
*/
@Service
public class StBbzxOrderInfoPayServiceImpl extends JeecgServiceImpl<StBbzxOrderInfoPayMapper, StBbzxOrderInfoPay> implements IStBbzxOrderInfoPayService {
}
@@ -0,0 +1,954 @@
/**
* use shuwei code generator created
*/
package org.jeecg.payment.service.impl;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xkcoding.http.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.system.base.service.impl.JeecgServiceImpl;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.ScreenVo;
import org.jeecg.common.util.DateUtils;
import org.jeecg.payment.entity.StBbzxOrderInfo;
import org.jeecg.payment.entity.StBbzxOrderInfoPay;
import org.jeecg.payment.entity.StClientMemberLevelDemotionTime;
import org.jeecg.payment.entity.StClientMemberTransactionRecord;
import org.jeecg.payment.enums.OrderStatus;
import org.jeecg.payment.enums.UserTypeEnum;
import org.jeecg.payment.listUtils.ListUtil;
import org.jeecg.payment.listUtils.OrderUtils;
import org.jeecg.payment.mapper.StBbzxOrderInfoMapper;
import org.jeecg.payment.mapper.StBbzxOrderInfoPayMapper;
import org.jeecg.payment.mapper.StClientMemberBalanceMapper;
import org.jeecg.payment.service.*;
import org.jeecg.payment.vo.*;
import org.jeecg.restaurant.vo.StatisticsBusinessVo;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
/**
* 报表中心-店内订单 服务实现类
*/
@Slf4j
@Service
public class StBbzxOrderInfoServiceImpl extends JeecgServiceImpl<StBbzxOrderInfoMapper, StBbzxOrderInfo> implements IStBbzxOrderInfoService {
//
// @Resource
// private IPayInfo payInfo;
@Resource
private IStClientMemberBalanceService stClientMemberBalanceService;
@Resource
private IStClientMemberLevelDeductRuleService iStClientMemberLevelDeductRuleService;
@Resource
private StClientMemberBalanceMapper stClientMemberBalanceMapper;
@Resource
private IStClientMemberLevelDemotionTimeService swClientMemberLevelDemotionTimeService;
@Resource
private IStBbzxOrderInfoPayService swBbzxOrderInfoPayService;
@Resource
private RedisTemplate redisTemplate;
// /***
// * 微信小程序充值
// * @param orderInfo
// * @return
// */
// @Override
// public JSONObject saveXCXorderInfoTopUp(OrderInfo orderInfo) {
// String userId = JwtUtil.getUserId();
// String openId = JwtUtil.getOpenId();
// String orderNoTopUp = userId+"-"+OrderUtils.getOrderCodeV2();
// //拉起微信支付
// BigDecimal b = BigDecimal.valueOf(orderInfo.getOriginalPrice()).setScale(2, BigDecimal.ROUND_HALF_UP);
// Result<?> r = payInfo.wxXcxDoPay(orderNoTopUp, "", "1", "小程序充值" + orderNoTopUp, b, openId,userId);
// String result = r.getResult().toString();
// JSONObject orderCode = JSONObject.parseObject(result);
// orderCode.put("orderCode", orderNoTopUp);
// return orderCode;
// }
/**
*
* 获取余额信息+充值规则模板
* @param userId 小程序标识
*/
@Override
public StMiniMineBalanceVo mineBalanceInfo(String userId, String canteenId){
//获取
LambdaQueryWrapper<StClientMemberLevelDemotionTime> lambdaQueryWrapper = new LambdaQueryWrapper<StClientMemberLevelDemotionTime>();
lambdaQueryWrapper.eq(StClientMemberLevelDemotionTime::getIsEnable, 1);
if(StringUtils.isNotBlank(canteenId)){
lambdaQueryWrapper.eq(StClientMemberLevelDemotionTime::getCanteenId, canteenId);
}
StClientMemberLevelDemotionTime memberLevel = swClientMemberLevelDemotionTimeService.getOne(lambdaQueryWrapper);
StMiniMineBalanceVo balanceInfo = stClientMemberBalanceMapper.getBalanceInfo(userId);
List<StMemberLevelStoredVO> storedVOS = new ArrayList<>();
if(memberLevel != null){
if(StringUtil.isNotEmpty(memberLevel.getStoredRule())){
storedVOS = com.alibaba.fastjson.JSON.parseArray(memberLevel.getStoredRule(), StMemberLevelStoredVO.class);
}
}
balanceInfo.setStoredVOS(storedVOS);
return balanceInfo;
}
/**
* 用户支出/充值记录列表
* @param userId 用户标识
*/
@Override
public IPage<StRecordListInfo> getSpendingOrRechargeInfoListV2(String userId,Integer pageNum, Integer pageSize) {
Page<StRecordListInfo> page = new Page<>(pageNum, pageSize);
Page<StClientMemberTransactionRecord> recordListVoPage = new Page<>(pageNum, pageSize);
IPage<StClientMemberTransactionRecord> memberTransactionRecord = stClientMemberBalanceService.memberTranRecordService(recordListVoPage,userId,null);
List<StClientMemberTransactionRecord> list = memberTransactionRecord.getRecords();
if(CollectionUtils.isEmpty(list)){
return new Page<>(pageNum, pageSize, 0);
}
List<StRecordListInfo> infos = new ArrayList<>();
list.forEach(v->{
String statusName = "";
//根据获取类型
if(102 == v.getStatus()){
statusName = "充值";
}else if (103 == v.getStatus()){
statusName = "撤销充值";
}else {
statusName = "支出";
}
StRecordListInfo info = new StRecordListInfo();
info.setName(statusName);
info.setStatus(v.getStatus());
info.setOrderNo(v.getOrderNo());
info.setRewardBalance(v.getRewardBalance());
info.setAvailableBalance(v.getAvailableBalance());
info.setTransactionAmount(v.getTransactionAmount());
info.setPayTime(DateUtil.format(v.getPayTime(),"yyyy-MM-dd HH:mm"));
infos.add(info);
});
page.setTotal(recordListVoPage.getTotal());
page.setPages(recordListVoPage.getPages());
page.setSize(recordListVoPage.getSize());
page.setCurrent(recordListVoPage.getCurrent());
return page.setRecords(infos);
}
@Override
public StBbzxOrderInfo getSwBbzxOrderInfo(String orderCode) {
LambdaQueryWrapper<StBbzxOrderInfo> wrapperorder = new LambdaQueryWrapper<>();
wrapperorder.eq(StBbzxOrderInfo::getOrderNo, orderCode);
StBbzxOrderInfo orderInfo1 = this.getBaseMapper().selectOne(wrapperorder);
return orderInfo1;
}
/**
* 根据payId查询支付订单
* @param payId
* @return
*/
@Override
public StBbzxOrderInfo getSwBbzxOrderInfoByPayId(String payId) {
LambdaQueryWrapper<StBbzxOrderInfo> wrapperorder = new LambdaQueryWrapper<>();
wrapperorder.eq(StBbzxOrderInfo::getPayId, payId);
StBbzxOrderInfo orderInfo1 = this.getBaseMapper().selectOne(wrapperorder);
return orderInfo1;
}
//
// @Override
// public boolean returnOrder(String orderNo) {
// StBbzxOrderInfo orderInfo = this.getSwBbzxOrderInfo(orderNo);
// //支付方式
// LambdaQueryWrapper<StBbzxOrderInfoPay> queryDayWrapper = new LambdaQueryWrapper<>();
// queryDayWrapper.in(StBbzxOrderInfoPay::getOrderId, orderInfo.getId());
// queryDayWrapper.eq(StBbzxOrderInfoPay::getIsDel, 0);
// List<StBbzxOrderInfoPay> payInfos = swBbzxOrderInfoPayService.getBaseMapper().selectList(queryDayWrapper);
// boolean r = true;
// try {
// if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(payInfos)) {
// for (StBbzxOrderInfoPay pay : payInfos) {
// RefundDTO refundDTO = new RefundDTO();
// refundDTO.setTotalFee(pay.getPayPrice());
// refundDTO.setPayOrderNo(pay.getPayCode());
// if (pay.getPayType() == 1) {//支付宝
//
// payInfo.refund(refundDTO);
// } else if (pay.getPayType() == 2) {//微信
//
// payInfo.refund(refundDTO);
// } else if (pay.getPayType() == 4) {//vip
// payInfo.refund(refundDTO);
// }
// }
// }
//
// } catch (Exception e) {
// e.printStackTrace();
// r = false;
// }
//
// return r;
// }
// /**
// * 线上消费退款
// * @param refundDTO
// * @return
// */
// @Override
// public Result<?> returnPayInfo(RefundDTO refundDTO) {
// return payInfo.refund(refundDTO);
// }
//
// /**
// * 线上充值退款
// * @param refundDTO
// * @return
// */
// @Override
// public Result<?> returnPayInfoTopUpOnline(RefundDTO refundDTO) {
// StClientMemberTransactionRecord recordInfoAboutRechargeByPayOrderNo = new StClientMemberTransactionRecord();
//// if(null == refundDTO.getTotalFee() || refundDTO.getTotalFee().compareTo(BigDecimal.ZERO)<=0){
// // 微信充值退款之前调用he获取微信退款实际金额接口
// recordInfoAboutRechargeByPayOrderNo = stClientMemberBalanceService.getRecordInfoAboutRechargeByPayOrderNo(refundDTO.getPayOrderNo(),null,null);
// if(recordInfoAboutRechargeByPayOrderNo == null){
// return Result.error("查询不到此订单信息!");
// }
// BigDecimal money = recordInfoAboutRechargeByPayOrderNo.getStoredBalance();
// if(money.compareTo(BigDecimal.ZERO)<=0){
// return Result.error("此订单无可退金额!");
// }
// StClientMemberTransactionRecord stClientMemberTransactionRecord = stClientMemberBalanceService.getRecordInfoAboutRechargeByPayOrderNo(null,recordInfoAboutRechargeByPayOrderNo.getOrderNo(),Arrays.asList(MemberTransactionTypeEnum.BACK_PAY.getCode()));
// if(null != stClientMemberTransactionRecord){
// return Result.error("此订单已退款");
// }
// refundDTO.setTotalFee(money);
//// }
// Result<PayResultVO> r = payInfo.refund(refundDTO);
// if(null != r && r.getCode() == HttpServletResponse.SC_OK && null!=r.getResult()){
// if(r.getResult().getIsSuccess()){
// recordInfoAboutRechargeByPayOrderNo.setRemark(refundDTO.getRemark());
// recordInfoAboutRechargeByPayOrderNo.setPaymentMethod(refundDTO.getPaymentMethod());
// // 微信充值退款成功之后调用he处理会员余额和退款记录相关逻辑接口
// stClientMemberBalanceService.backOrder(recordInfoAboutRechargeByPayOrderNo);
// return Result.OK("退款成功");
// } else {
// return Result.error(r.getResult().getMsg());
// }
// } else {
// return Result.error("退款失败");
// }
// }
@Override
public void updateMemberIdByOpenId(String openId,String memberId,String memberName){
List<StBbzxOrderInfo> allByOpenId = baseMapper.getAllByOpenId(openId);
if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(allByOpenId)){
for (StBbzxOrderInfo orderInfo : allByOpenId) {
orderInfo.setMemberName(memberName);
orderInfo.setMemberId(memberId);
}
this.saveOrUpdateBatch(allByOpenId);
}
}
/**
*
* @param orderId 订单主表id
* @param orderFrom 订单来源(1平板端 、2收银端、3自助点餐机、4小程序、5自助餐)
* @param payCode 小程序 支付编码
* @param payType 支付类型: 1是支付宝 2微信 3现金 4会员 5混合
* @param orderFromSign 支付用户id(微信支付 = openid、支付宝支付 = 支付宝id)
* @param bh 混合支付时,会员支付的金额
* @param tradeOrderNo 渠道支付返回的三方交易订单号
* @param tarnsCode 混合支付时 经过随机数3位拼接的自定义余额支付订单号
*/
@Override
public void updateOrderFeign(String orderId,int orderFrom,String payCode,Integer payType,String orderFromSign,StBbzxOrderInfo order,
BigDecimal bh,String tradeOrderNo,String tarnsCode) {
boolean mixedPayment = false ;//自助餐,混合支付时渠道的支付方式
if(null == bh){
bh = new BigDecimal("0");
} else if(bh.compareTo(BigDecimal.ZERO)>0){//余额支付大于0,表示混合支付
mixedPayment = true;
}
String unionId = null;
// if(!StringUtil.isEmpty(tradeOrderNo)){
// unionId = dbyWechatExtService.getUnionId(orderFromSign,tradeOrderNo);
// }
LambdaUpdateWrapper<StBbzxOrderInfo> orderLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
orderLambdaUpdateWrapper
.eq(StBbzxOrderInfo::getId, orderId)
.set(StBbzxOrderInfo::getStatus, OrderStatus.ORDER_STATUS_HAS_CHECK_OUT.getCode())
.set(StBbzxOrderInfo::getPayOrderDate, new Date())
.set(StBbzxOrderInfo::getPayType, mixedPayment ? 5 : payType)//对应订单 1是支付宝 2微信 3现金 4会员 5混合
.set(StBbzxOrderInfo::getOrderFromSign, (null != order && null != order.getMemberId()) ? order.getMemberId() : orderFromSign)
.set(StBbzxOrderInfo::getUnionId, unionId)
.set(StBbzxOrderInfo::getMemberId, (null != order && null != order.getMemberId()) ? order.getMemberId() : null)
.set(StBbzxOrderInfo::getMemberName, null != order && StringUtils.isNotBlank(order.getMemberName()) ? order.getMemberName() : null)
.set(StBbzxOrderInfo::getMemberPhone, null != order && StringUtils.isNotBlank(order.getMemberPhone()) ? order.getMemberPhone() : null)
.set(StBbzxOrderInfo::getIsSync, 0);
boolean flag = this.update(null, orderLambdaUpdateWrapper);
// if(flag){
// //支付完成后,如果是自助餐订单,置空plate_number餐盘编号,更新userId字段(userId,memberId,openId,支付宝id 和 userIdType
// StBbzxOrderInfo swBbzxOrderInfo = this.getById(orderId);
// if(null != swBbzxOrderInfo && swBbzxOrderInfo.getOrderType() == 3){ //1:桌台点餐 2预点餐 3.自助餐
// LambdaQueryWrapper<StUserFoodInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
// lambdaQueryWrapper.eq(StUserFoodInfo::getOrderId,orderId);
// List<StUserFoodInfo> stUserFoodInfoList = stUserFoodInfoMapper.selectList(lambdaQueryWrapper);
// stUserFoodInfoList.forEach(stUserFoodInfo -> {
// stUserFoodInfo.setPlateNumber("-");
// if(swBbzxOrderInfo.getPayType() == 1){//结账方式 * /对应订单 1是支付宝 2微信 3现金 4会员 5混合
// stUserFoodInfo.setUserId(swBbzxOrderInfo.getOrderFromSign());
// stUserFoodInfo.setUserIdType("4");//用户id类型(4:支付宝id
// } else if(swBbzxOrderInfo.getPayType() == 2){
// stUserFoodInfo.setUserId(swBbzxOrderInfo.getOrderFromSign());
// stUserFoodInfo.setUserIdType("3");//用户id类型(3:openId
// } else if(swBbzxOrderInfo.getPayType() == 3 && null != swBbzxOrderInfo.getMemberId()){//现金支付-现金支付绑定会员
// stUserFoodInfo.setUserId(swBbzxOrderInfo.getMemberId()+"");
// stUserFoodInfo.setUserIdType("2");//用户id类型(2:memberIdd
// }else if(swBbzxOrderInfo.getPayType() == 4 || swBbzxOrderInfo.getPayType() == 5){
// stUserFoodInfo.setUserId(swBbzxOrderInfo.getMemberId()+"");
// stUserFoodInfo.setUserIdType("2");//用户id类型(2:memberId
// }
// stUserFoodInfoMapper.updateById(stUserFoodInfo);
// });
// //纯会员支付 :自助餐推送给收银台设备支付消息(此处只推送纯会员支付消息)
// if(payType == 4){
// // 微信支付宝的混合支付在com.shuwei.zhct.controller.SwBbzxOrderInfoController.updateOrderPayStatus 中进行消息推送
// //开启线程发送推送信息
// Map<String, Object> mapPush = JSONObject.parseObject(JSONObject.toJSONString(swBbzxOrderInfo));
// mapPush.put("mqType", "1");//支付
// mapPush.put("payStatus", 1);//支付状态-1系统异常,请重试 0 支付失败 1支付成功 2退款成功 3订单不存在 4支付失败,请撤销订单 5 用户支付中 6交易创建,等待买家付款
//// Thread t = new Thread(() -> {
//// //发送推送信息
//// String tp = "sw_test";
//// Topic t1 = () -> tp;
//// producer.sendMessage(t1, JSON.toJSONString(mapPush));
//// });
//// t.start();
// //推送消息给收银台进行订单同步信息
//// this.sendCashierDeskOrderMsg(swBbzxOrderInfo);
// } else {// 支付类型: 1是支付宝 / 2微信 / mixedPayment = true 混合
// // 1sw_pay_trans_details + sw_bbzx_order_info_pay 保存记录,混合渠道和会员支付各保存一条金额分开
// if(mixedPayment){//混合支付
// //渠道的一笔
// StBbzxOrderInfoPay infoPay = new StBbzxOrderInfoPay();
// infoPay.setOrderId(swBbzxOrderInfo.getId());
// if(swBbzxOrderInfo.getMemberId() != null){//混合支付 渠道的金额 = 订单总金额 - 会员支付金额
// infoPay.setPayIncome(swBbzxOrderInfo.getCustomerPrice().subtract(bh).setScale(2, BigDecimal.ROUND_HALF_UP));
// infoPay.setPayPrice(swBbzxOrderInfo.getCustomerPrice().subtract(bh).setScale(2, BigDecimal.ROUND_HALF_UP));
// } else {
// infoPay.setPayIncome(swBbzxOrderInfo.getOrderPrice().subtract(bh).setScale(2, BigDecimal.ROUND_HALF_UP));
// infoPay.setPayPrice(swBbzxOrderInfo.getOrderPrice().subtract(bh).setScale(2, BigDecimal.ROUND_HALF_UP));
// }
// infoPay.setPayType(payType);
// infoPay.setStatus(1);
// // infoPay.setPayDiscount(p.getPayCode());
// infoPay.setPayCode(tradeOrderNo);
// infoPay.setRemark("混合渠道支付成功");
// infoPay.setIsDel(0);
// infoPay.setCreateBy("0");
// infoPay.setCreateTime(new Date());
// infoPay.setCanteenId(order.getCanteenId());
// infoPay.setIsSync(0);
// stBbzxOrderInfoPayMapper.insert(infoPay);
//
// //会员的一笔
// StBbzxOrderInfoPay stBbzxOrderInfoPay = new StBbzxOrderInfoPay();
// stBbzxOrderInfoPay.setOrderId(swBbzxOrderInfo.getId());
// //ALI_PAY = "1" WX_PAY = "2" ASH_PAY = "3";
// stBbzxOrderInfoPay.setPayType(4);
// stBbzxOrderInfoPay.setPayIncome(bh);
// stBbzxOrderInfoPay.setPayPrice(bh);
// stBbzxOrderInfoPay.setStatus(1);
// // infoPay.setPayDiscount(p.getPayCode());
// stBbzxOrderInfoPay.setPayCode(tarnsCode);
// stBbzxOrderInfoPay.setRemark("混合余额支付成功");
// stBbzxOrderInfoPay.setCreateBy("0");
// stBbzxOrderInfoPay.setCreateTime(new Date());
// stBbzxOrderInfoPay.setCanteenId(order.getCanteenId());
// stBbzxOrderInfoPay.setIsSync(0);
// swBbzxOrderInfoPayService.saveOrUpdate(stBbzxOrderInfoPay);
// } else {//单渠道支付 : 1是支付宝 2微信
// //渠道的一笔
// StBbzxOrderInfoPay infoPay = new StBbzxOrderInfoPay();
// infoPay.setOrderId(swBbzxOrderInfo.getId());
// if(swBbzxOrderInfo.getMemberId() != null){
// infoPay.setPayIncome(swBbzxOrderInfo.getCustomerPrice().setScale(2, BigDecimal.ROUND_HALF_UP));
// infoPay.setPayPrice(swBbzxOrderInfo.getCustomerPrice().setScale(2, BigDecimal.ROUND_HALF_UP));
// } else {
// infoPay.setPayIncome(swBbzxOrderInfo.getOrderPrice().setScale(2, BigDecimal.ROUND_HALF_UP));
// infoPay.setPayPrice(swBbzxOrderInfo.getOrderPrice().setScale(2, BigDecimal.ROUND_HALF_UP));
// }
// infoPay.setPayType(payType);
// infoPay.setStatus(1);
// // infoPay.setPayDiscount(p.getPayCode());
// infoPay.setPayCode(tradeOrderNo);
// infoPay.setRemark("");
// infoPay.setIsDel(0);
// infoPay.setCreateBy("0");
// infoPay.setCreateTime(new Date());
// infoPay.setCanteenId(order.getCanteenId());
// infoPay.setIsSync(0);
// stBbzxOrderInfoPayMapper.insert(infoPay);
// }
// }
//
// }
// }
if (orderFrom == 4) {//小程序
LambdaUpdateWrapper<StBbzxOrderInfoPay> payLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
payLambdaUpdateWrapper
.eq(StBbzxOrderInfoPay::getOrderId, orderId)
.eq(StBbzxOrderInfoPay::getPayType, 2)
.set(StBbzxOrderInfoPay::getPayCode, payCode)
.set(StBbzxOrderInfoPay::getIsSync, 0);
swBbzxOrderInfoPayService.update(null, payLambdaUpdateWrapper);
}
}
@Override
public IPage<?> getStatisticsTheAmountSpentList(String canteenId, String startDate, String endDate, Integer pageNo, Integer pageSize){
if(StringUtils.isEmpty(startDate)){
startDate = DateUtil.format(new Date(),"yyyy-MM-dd");
endDate = DateUtil.format(new Date(),"yyyy-MM-dd");
}
//权限校验
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
List<String> canteenIds = new ArrayList<>();
if(StringUtils.isEmpty(canteenId)){
if(sysUser != null){
canteenIds = sysUser.getCanteenIdList().stream().map(ScreenVo::getId).collect(Collectors.toList());
}
}else {
canteenIds = Collections.singletonList(canteenId);
}
//获取数据列表
List<StatisticsTheAmountSpentVo> statisticsTheAmountSpentVos = baseMapper.statisticsTheAmountSpent(canteenIds, startDate, endDate);
if(CollectionUtils.isEmpty(statisticsTheAmountSpentVos)){
return new Page<>();
}
statisticsTheAmountSpentVos.forEach(vo->{
vo.setTotalCount(vo.getBreakfastPerson().add(vo.getLunchPerson().add(vo.getDinnerPerson()).add(vo.getOtherPerson())));
vo.setCorrectionValue(BigDecimal.ZERO);
vo.setCorrectionCount(BigDecimal.ZERO);
});
if(startDate.equals(endDate)){
return ListUtil.listToPage(statisticsTheAmountSpentVos,pageNo,pageSize);
}else {
//如果是时间返回之内的数据 , 直接求每天的和
//根据食堂分组
Map<String, List<StatisticsTheAmountSpentVo>> canteenListMaps = statisticsTheAmountSpentVos.stream().collect(Collectors.groupingBy(StatisticsTheAmountSpentVo::getCanteenId));
List<StatisticsTheAmountSpentVo> statisticsTheAmountSpentVoList = new ArrayList<>();
for (Map.Entry<String, List<StatisticsTheAmountSpentVo>> canteenListMap : canteenListMaps.entrySet()) {
StatisticsTheAmountSpentVo spentVo = new StatisticsTheAmountSpentVo();
spentVo.setEatDay(startDate+"~"+endDate);
spentVo.setCanteenId(canteenListMap.getKey());
spentVo.setRestName(canteenListMap.getValue().get(0).getRestName());
spentVo.setTotalNum(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getTotalNum).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setTotalCount(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getTotalCount).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setCustomerPrice(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getCustomerPrice).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setCorrectionCount(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getCorrectionCount).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setCorrectionValue(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getCorrectionValue).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setBreakfastAmount(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getBreakfastAmount).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setBreakfastPerson(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getBreakfastPerson).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setLunchAmount(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getLunchAmount).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setLunchPerson(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getLunchPerson).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setDinnerAmount(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getDinnerAmount).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setDinnerPerson(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getDinnerPerson).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setOtherAmount(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getOtherAmount).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setOtherPerson(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getOtherPerson).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setOrderPrice(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getOrderPrice).reduce(BigDecimal.ZERO,BigDecimal::add));
statisticsTheAmountSpentVoList.add(spentVo);
}
return ListUtil.listToPage(statisticsTheAmountSpentVoList,pageNo,pageSize);
}
}
@Override
public List<StatisticsTheAmountSpentVo> getStatisticsTheAmountSpentList(String canteenId, String startDate, String endDate){
if(StringUtils.isEmpty(startDate)){
startDate = DateUtil.format(new Date(),"yyyy-MM-dd");
endDate = DateUtil.format(new Date(),"yyyy-MM-dd");
}
//权限校验
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
List<String> canteenIds = new ArrayList<>();
if(StringUtils.isEmpty(canteenId)){
if(sysUser != null){
canteenIds = sysUser.getCanteenIdList().stream().map(ScreenVo::getId).collect(Collectors.toList());
}
}else {
canteenIds = Collections.singletonList(canteenId);
}
//获取数据列表
List<StatisticsTheAmountSpentVo> statisticsTheAmountSpentVos = baseMapper.statisticsTheAmountSpent(canteenIds, startDate, endDate);
if(CollectionUtils.isEmpty(statisticsTheAmountSpentVos)){
return new ArrayList<>();
}
statisticsTheAmountSpentVos.forEach(vo->{
vo.setTotalCount(vo.getBreakfastPerson().add(vo.getLunchPerson().add(vo.getDinnerPerson()).add(vo.getOtherPerson())));
vo.setCorrectionValue(BigDecimal.ZERO);
vo.setCorrectionCount(BigDecimal.ZERO);
});
if(startDate.equals(endDate)){
return statisticsTheAmountSpentVos;
}else {
//如果是时间返回之内的数据 , 直接求每天的和
//根据食堂分组
Map<String, List<StatisticsTheAmountSpentVo>> canteenListMaps = statisticsTheAmountSpentVos.stream().collect(Collectors.groupingBy(StatisticsTheAmountSpentVo::getCanteenId));
List<StatisticsTheAmountSpentVo> statisticsTheAmountSpentVoList = new ArrayList<>();
for (Map.Entry<String, List<StatisticsTheAmountSpentVo>> canteenListMap : canteenListMaps.entrySet()) {
StatisticsTheAmountSpentVo spentVo = new StatisticsTheAmountSpentVo();
spentVo.setEatDay(startDate+"~"+endDate);
spentVo.setCanteenId(canteenListMap.getKey());
spentVo.setRestName(canteenListMap.getValue().get(0).getRestName());
spentVo.setTotalNum(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getTotalNum).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setTotalCount(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getTotalCount).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setCustomerPrice(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getCustomerPrice).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setCorrectionCount(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getCorrectionCount).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setCorrectionValue(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getCorrectionValue).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setBreakfastAmount(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getBreakfastAmount).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setBreakfastPerson(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getBreakfastPerson).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setLunchAmount(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getLunchAmount).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setLunchPerson(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getLunchPerson).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setDinnerAmount(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getDinnerAmount).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setDinnerPerson(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getDinnerPerson).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setOtherAmount(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getOtherAmount).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setOtherPerson(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getOtherPerson).reduce(BigDecimal.ZERO,BigDecimal::add));
spentVo.setOrderPrice(canteenListMap.getValue().stream().map(StatisticsTheAmountSpentVo::getOrderPrice).reduce(BigDecimal.ZERO,BigDecimal::add));
statisticsTheAmountSpentVoList.add(spentVo);
}
return statisticsTheAmountSpentVoList;
}
}
/**
* 个人消费记录统计
* @param startDate 开始时间
* @param endDate 结束时间
* @param secondDepartId 二级单位id
* @param thirdDepartId 三级部门id
* @param pageNo 页数
* @param pageSize 条数
* @return 个人消费记录统计
*/
@Override
public IPage<?> statisticsTheAmountSpentEveryMember(String canteenId,String name,String payName,String startDate, String endDate, String secondDepartId,String thirdDepartId,Integer pageNo, Integer pageSize){
String eatDay = "";
if(StringUtils.isEmpty(startDate)){
startDate = DateUtil.format(new Date(),"yyyy-MM-dd");
endDate = DateUtil.format(new Date(),"yyyy-MM-dd");
eatDay = startDate;
}else {
eatDay = startDate + "~" + endDate;
}
//权限校验
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
List<String> canteenIds = new ArrayList<>();
if(StringUtils.isEmpty(canteenId)){
if(sysUser != null){
canteenIds = sysUser.getCanteenIdList().stream().map(ScreenVo::getId).collect(Collectors.toList());
}
}else {
canteenIds = Collections.singletonList(canteenId);
}
List<StatisticsTheAmountSpentVo> statisticsTheAmountSpentVos = baseMapper.statisticsTheAmountSpentEveryMember(canteenIds,name,payName,startDate, endDate, secondDepartId, thirdDepartId);
if(CollectionUtils.isEmpty(statisticsTheAmountSpentVos)){
return new Page<>();
}
String finalEatDay = eatDay;
statisticsTheAmountSpentVos.forEach(vo->{
//计算消费次数
vo.setTotalCount(vo.getBreakfastPerson().add(vo.getLunchPerson().add(vo.getDinnerPerson()).add(vo.getOtherPerson())));
vo.setEatDay(finalEatDay);
});
return ListUtil.listToPage(statisticsTheAmountSpentVos,pageNo,pageSize);
}
/**
* 个人消费记录统计导出
* @param startDate 开始时间
* @param endDate 结束时间
* @param secondDepartId 二级单位id
* @param thirdDepartId 三级部门id
* @return 个人消费记录统计导出
*/
@Override
public List<StatisticsTheAmountSpentVo> statisticsTheAmountSpentEveryMember(String canteenId,String name,String payName,String startDate, String endDate, String secondDepartId,String thirdDepartId){
String eatDay = "";
if(StringUtils.isEmpty(startDate)){
startDate = DateUtil.format(new Date(),"yyyy-MM-dd");
endDate = DateUtil.format(new Date(),"yyyy-MM-dd");
eatDay = startDate;
}else {
eatDay = startDate + "~" + endDate;
}
//权限校验
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
List<String> canteenIds = new ArrayList<>();
if(StringUtils.isEmpty(canteenId)){
if(sysUser != null){
canteenIds = sysUser.getCanteenIdList().stream().map(ScreenVo::getId).collect(Collectors.toList());
}
}else {
canteenIds = Collections.singletonList(canteenId);
}
List<StatisticsTheAmountSpentVo> statisticsTheAmountSpentVos = baseMapper.statisticsTheAmountSpentEveryMember(canteenIds,name,payName,startDate, endDate, secondDepartId, thirdDepartId);
if(CollectionUtils.isEmpty(statisticsTheAmountSpentVos)){
return Collections.emptyList();
}
String finalEatDay = eatDay;
statisticsTheAmountSpentVos.forEach(vo->{
//计算消费次数
vo.setTotalCount(vo.getBreakfastPerson().add(vo.getLunchPerson().add(vo.getDinnerPerson()).add(vo.getOtherPerson())));
vo.setEatDay(finalEatDay);
});
return statisticsTheAmountSpentVos;
}
/**
* 食堂营业查询报表
* @param startDate 开始时间
* @param endDate 结束时间
* @param secondDepartId 二级单位id
* @param thirdDepartId 三级部门id
* @param pageNo 页数
* @param pageSize 条数
* @return 食堂营业查询报表
*/
@Override
public IPage<?> statisticsCanteenBusiness(String canteenId,String startDate, String endDate, String secondDepartId,String thirdDepartId,Integer pageNo, Integer pageSize){
List<ScreenVo> canteenIdList = new ArrayList<>();
if(StringUtils.isNotBlank(canteenId)){
ScreenVo screenVo = new ScreenVo();
screenVo.setId(canteenId);
canteenIdList.add(screenVo);
} else {
//权限校验
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
List<String> canteenIds = new ArrayList<>();
if(sysUser != null){
canteenIds = sysUser.getCanteenIdList().stream().map(ScreenVo::getId).collect(Collectors.toList());
canteenIds.forEach(id->{
ScreenVo screenVo = new ScreenVo();
screenVo.setId(id);
canteenIdList.add(screenVo);
});
}
}
List<StatisticsBusinessVo> statisticsTheAmountSpentVos = baseMapper.statisticsCanteenBusiness(canteenIdList,startDate, endDate);
if(CollectionUtils.isEmpty(statisticsTheAmountSpentVos)){
return new Page<>();
}
return ListUtil.listToPage(statisticsTheAmountSpentVos,pageNo,pageSize);
}
/**
* 食堂营业查询报表
* @param startDate 开始时间
* @param endDate 结束时间
* @param secondDepartId 二级单位id
* @param thirdDepartId 三级部门id
* @return 食堂营业查询报表
*/
@Override
public List<StatisticsBusinessVo> statisticsCanteenBusiness(String canteenId,String startDate, String endDate, String secondDepartId,String thirdDepartId){
List<ScreenVo> canteenIdList = new ArrayList<>();
if(StringUtils.isNotBlank(canteenId)){
ScreenVo screenVo = new ScreenVo();
screenVo.setId(canteenId);
canteenIdList.add(screenVo);
} else {
//权限校验
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
List<String> canteenIds = new ArrayList<>();
if(sysUser != null){
canteenIds = sysUser.getCanteenIdList().stream().map(ScreenVo::getId).collect(Collectors.toList());
canteenIds.forEach(id->{
ScreenVo screenVo = new ScreenVo();
screenVo.setId(id);
canteenIdList.add(screenVo);
});
}
}
List<StatisticsBusinessVo> statisticsTheAmountSpentVos = baseMapper.statisticsCanteenBusiness(canteenIdList,startDate, endDate);
if(CollectionUtils.isEmpty(statisticsTheAmountSpentVos)){
return new ArrayList<>();
}
return statisticsTheAmountSpentVos;
}
/**
* 统一生成订单
* @param restId
* @param userId
* @param plateNumber
* @return
*/
@Override
public StBbzxOrderInfo crateOrderInfo(Date dateTime, String restId, String userId, String plateNumber, String timesName, StRfidVo stRfidVo){
//扣费规则(1:固定扣费,2:固定+补贴扣费,3:按量扣费)
StClientMemberLevelDeductRuleVo levelDeductRuleVo = iStClientMemberLevelDeductRuleService.getDeductRuleByCanteenId(restId);
if(null == levelDeductRuleVo){
return null;
}
// 生成新订单
return buildOrderInfoNew(dateTime,restId, timesName, plateNumber, userId, "", "", levelDeductRuleVo.getDeductionType(),levelDeductRuleVo,null, stRfidVo);
}
/**
* 生成新订单
* @param restId
* @param dinnerType
* @param plateNumber
* @param userId
* @param memberName
* @param memberPhone
* @param deductionType
* @return
*/
@Override
public StBbzxOrderInfo buildOrderInfoNew(Date dateTime,String restId,String dinnerType,String plateNumber,String userId,String memberName,String memberPhone,Integer deductionType,StClientMemberLevelDeductRuleVo levelDeductRuleVo , String remark,StRfidVo stRfidVo){
StBbzxOrderInfo stBbzxOrderInfo = new StBbzxOrderInfo();
stBbzxOrderInfo.setOrderType(3);
String orderNo = OrderUtils.getOrderCode(10);
stBbzxOrderInfo.setOrderNo(orderNo);
stBbzxOrderInfo.setSerialNo(stRfidVo.getCardCode());
stBbzxOrderInfo.setDinnerType(dinnerType);
stBbzxOrderInfo.setMemberId(userId);
stBbzxOrderInfo.setMemberName(memberName);
stBbzxOrderInfo.setMemberPhone(memberPhone);
stBbzxOrderInfo.setPlateNumber(plateNumber);
stBbzxOrderInfo.setOrderFrom(5);
stBbzxOrderInfo.setDiningWay(2);
stBbzxOrderInfo.setEatDay(DateUtil.today());
stBbzxOrderInfo.setBusinessDate(new Date());
stBbzxOrderInfo.setOrderDate(new Date());
if(null != dateTime){
stBbzxOrderInfo.setBusinessDate(dateTime);
stBbzxOrderInfo.setOrderDate(dateTime);
String eatDay = DateUtils.formatDate(dateTime,"yyyy-MM-dd");
stBbzxOrderInfo.setEatDay(eatDay);
}
if (null != stRfidVo && null != stRfidVo.getSpendMoney()) {
stBbzxOrderInfo.setOrderPrice(stRfidVo.getSpendMoney());
stBbzxOrderInfo.setCustomerPrice(stRfidVo.getSpendMoney());
}
stBbzxOrderInfo.setStatus(OrderStatus.ORDER_STATUS_WAIT_CHECK_OUT.getCode());//待结账
stBbzxOrderInfo.setCanteenId(restId);
stBbzxOrderInfo.setBusinessModel(deductionType);
stBbzxOrderInfo.setIsSync(0);
stBbzxOrderInfo.setIsDel(0);
if(4 == deductionType){//自定义扣费
StClientMemberLevelDeductRuleVo stClientMemberLevelDeductRuleVoCustom = new StClientMemberLevelDeductRuleVo();
stClientMemberLevelDeductRuleVoCustom.setRuleName("自定义扣费");
stClientMemberLevelDeductRuleVoCustom.setDeductionType(4);
stBbzxOrderInfo.setOrderText(JSONObject.toJSONString(stClientMemberLevelDeductRuleVoCustom));
} else {
if(null != levelDeductRuleVo){
stBbzxOrderInfo.setOrderText(JSONObject.toJSONString(levelDeductRuleVo));
}
}
stBbzxOrderInfo.setRemark(remark);
stBbzxOrderInfo.setPayId(stRfidVo.getPayId());
this.save(stBbzxOrderInfo);
return stBbzxOrderInfo;
}
/**
* 生成新订单
* @param restId
* @param dinnerType
* @param plateNumber
* @param userId
* @param memberName
* @param memberPhone
* @param deductionType
* @return
*/
@Override
public StBbzxOrderInfo buildOrderInfoNewOffLine(Date dateTime,String restId,String dinnerType,String plateNumber,String userId,String memberName,
String memberPhone,Integer deductionType,StClientMemberLevelDeductRuleVo levelDeductRuleVo ,
String remark,StRfidVo stRfidVo,StMiniMineBalanceVo miniMineBalanceVo){
StBbzxOrderInfo stBbzxOrderInfo = new StBbzxOrderInfo();
stBbzxOrderInfo.setOrderType(3);
String orderNo = OrderUtils.getOrderCode(10);
stBbzxOrderInfo.setOrderNo(orderNo);
stBbzxOrderInfo.setSerialNo(miniMineBalanceVo.getCardCode());
stBbzxOrderInfo.setDinnerType(dinnerType);
stBbzxOrderInfo.setMemberId(userId);
stBbzxOrderInfo.setMemberName(memberName);
stBbzxOrderInfo.setMemberPhone(memberPhone);
stBbzxOrderInfo.setPlateNumber(plateNumber);
stBbzxOrderInfo.setOrderFrom(5);
stBbzxOrderInfo.setDiningWay(2);
stBbzxOrderInfo.setEatDay(DateUtil.today());
stBbzxOrderInfo.setBusinessDate(new Date());
stBbzxOrderInfo.setOrderDate(new Date());
if(null != dateTime){
stBbzxOrderInfo.setBusinessDate(dateTime);
stBbzxOrderInfo.setOrderDate(dateTime);
String eatDay = DateUtils.formatDate(dateTime,"yyyy-MM-dd");
stBbzxOrderInfo.setEatDay(eatDay);
}
stBbzxOrderInfo.setStatus(OrderStatus.ORDER_STATUS_WAIT_CHECK_OUT.getCode());//待结账
stBbzxOrderInfo.setCanteenId(restId);
stBbzxOrderInfo.setBusinessModel(deductionType);
stBbzxOrderInfo.setIsSync(0);
stBbzxOrderInfo.setIsDel(0);
stBbzxOrderInfo.setOrderText(JSONObject.toJSONString(levelDeductRuleVo));
String result = MessageFormat.format("【识别用户名称:{6},识别用户当前类型:{0},识别用户当前删除状态:{1},识别用户当前停用状态:{2}," +
"支付用户名称:{7},支付用户当前类型:{3},支付用户当前删除状态:{4},支付用户当前停用状态:{5}】",
UserTypeEnum.getByCode(miniMineBalanceVo.getUserType()).getDesc(),
miniMineBalanceVo.getDelFlag() == 1 ? "删除" : "正常", miniMineBalanceVo.getStatus() == 1 ? "正常" : "禁用",
miniMineBalanceVo.getUserInnerType() == 1 ? "外部用户" : "内部用户",
miniMineBalanceVo.getPayDelFlag() == 1 ? "删除" : "正常",
miniMineBalanceVo.getUserStatus()== 1 ? "正常" : "禁用",
miniMineBalanceVo.getRealname(),miniMineBalanceVo.getPayRealname());
stBbzxOrderInfo.setRemark(result+remark);
stBbzxOrderInfo.setPayId(stRfidVo.getPayId());
stBbzxOrderInfo.setOrderPrice(miniMineBalanceVo.getAmountThis());
stBbzxOrderInfo.setCustomerPrice(miniMineBalanceVo.getAmountThis());
this.save(stBbzxOrderInfo);
return stBbzxOrderInfo;
}
/**
* 生成订单流水号
*/
public String generateSerialNumber_tool(String eaId) {
String container = "ORDER_SERIAL_NUMBER:" + eaId + ":";
LocalDateTime sameDay = LocalDateTime.now();
String day = sameDay.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
//获取缓存日期
HashOperations<String, Object, Object> hashOperations = redisTemplate.opsForHash();
String redisDay = (String) hashOperations.get(container.concat(day), "SERIAL_NUMBER");
String result = "";
if (!org.springframework.util.StringUtils.isEmpty(redisDay)) {
int newSerialNumber = Integer.valueOf(redisDay) + 1;
switch (String.valueOf(newSerialNumber).length()) {
case 1:
result = "000" + newSerialNumber;
break;
case 2:
result = "00" + newSerialNumber;
break;
case 3:
result = "0" + newSerialNumber;
break;
case 4:
result = newSerialNumber + "";
break;
}
} else {
result = "0001";
}
//重新写入
hashOperations.put(container.concat(day), "SERIAL_NUMBER", result);
return result;
}
/**
* 根据userId + 日期 + 餐次 + 订单状态,获取订单信息
* @param userId
* @param eatDay
* @param dinnerType
* @param orderStatus
* @return
*/
@Override
public StBbzxOrderInfo getSwBbzxOrderInfoByUserId(String userId,String eatDay,String dinnerType,Integer orderStatus,String restId,
Integer businessModel ){
LambdaQueryWrapper<StBbzxOrderInfo> wrapperorder = new LambdaQueryWrapper<>();
wrapperorder.eq(StBbzxOrderInfo::getMemberId, userId);
if(StringUtils.isNotBlank(eatDay)){
wrapperorder.eq(StBbzxOrderInfo::getEatDay, eatDay);
}
if(StringUtils.isNotBlank(dinnerType)){
wrapperorder.eq(StBbzxOrderInfo::getDinnerType, dinnerType);
}
if(null != orderStatus){
wrapperorder.eq(StBbzxOrderInfo::getStatus, orderStatus);
}
if(null != businessModel){
wrapperorder.eq(StBbzxOrderInfo::getBusinessModel, businessModel);
}
wrapperorder.eq(StBbzxOrderInfo::getCanteenId, restId);
wrapperorder.eq(StBbzxOrderInfo::getIsDel, 0);
StBbzxOrderInfo orderInfo1 = this.getBaseMapper().selectOne(wrapperorder);
return orderInfo1;
}
/**
* 根据userId + 日期 + 餐次 + 订单状态,获取订单信息
* @param userId
* @param eatDay
* @param orderStatus
* @return
*/
@Override
public List<StBbzxOrderInfo> getSwBbzxOrderInfoListByUserId(String userId,String eatDay,String dinnerType,Integer orderStatus,String restId,
Integer businessModel ){
LambdaQueryWrapper<StBbzxOrderInfo> wrapperorder = new LambdaQueryWrapper<>();
wrapperorder.eq(StBbzxOrderInfo::getMemberId, userId);
if(StringUtils.isNotBlank(eatDay)){
wrapperorder.eq(StBbzxOrderInfo::getEatDay, eatDay);
}
if(StringUtils.isNotBlank(dinnerType)){
wrapperorder.eq(StBbzxOrderInfo::getDinnerType, dinnerType);
}
if(null != orderStatus){
wrapperorder.eq(StBbzxOrderInfo::getStatus, orderStatus);
}
if(null != businessModel){
wrapperorder.eq(StBbzxOrderInfo::getBusinessModel, businessModel);
}
wrapperorder.eq(StBbzxOrderInfo::getCanteenId, restId);
wrapperorder.eq(StBbzxOrderInfo::getIsDel, 0);
List<StBbzxOrderInfo> orderInfo1 = this.getBaseMapper().selectList(wrapperorder);
return orderInfo1;
}
}
@@ -0,0 +1,571 @@
/**
* use shuwei code generator created
*/
package org.jeecg.payment.service.impl;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.base.service.impl.JeecgServiceImpl;
import org.jeecg.common.util.DateUtils;
import org.jeecg.payment.entity.StBbzxOrderInfo;
import org.jeecg.payment.entity.StClientMemberLevelDeductRule;
import org.jeecg.payment.enums.DeductionTypeEnum;
import org.jeecg.payment.mapper.StClientMemberLevelDeductRuleMapper;
import org.jeecg.payment.service.IStBbzxOrderInfoService;
import org.jeecg.payment.service.IStClientMemberBalanceService;
import org.jeecg.payment.service.IStClientMemberLevelDeductRuleService;
import org.jeecg.payment.utils.MealGroupingUtil;
import org.jeecg.payment.vo.*;
import org.jeecg.restaurant.entity.SlBaseDinnerTime;
import org.jeecg.restaurant.entity.SlBaseRestaurant;
import org.jeecg.restaurant.mapper.SlBaseRestaurantMapper;
import org.jeecg.restaurant.service.ISlBaseDinnerTimeService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
/**
* 扣费规则服务实现类
*/
@Service
@Slf4j
public class StClientMemberLevelDeductRuleServiceImpl extends JeecgServiceImpl<StClientMemberLevelDeductRuleMapper, StClientMemberLevelDeductRule> implements IStClientMemberLevelDeductRuleService {
@Resource
private SlBaseRestaurantMapper slBaseRestaurantMapper;
@Resource
private IStBbzxOrderInfoService iStBbzxOrderInfoService;
@Resource
private IStClientMemberBalanceService iStClientMemberBalanceService;
@Autowired
private ISlBaseDinnerTimeService stBaseDinnerTimeService;
@Override
public IPage<StClientMemberLevelDeductRuleVo> selectStClientMemberLevelDemotionTimePage(StClientMemberLevelDemotionTimeVO query){
Page<StClientMemberLevelDeductRuleVo> page = new Page<>(query.getPageNo(), query.getPageSize());
List<StClientMemberLevelDeductRuleVo> pageList = baseMapper.selectStClientMemberLevelDeductRulePage(page,query);
SlBaseRestaurant slBaseRestaurant = slBaseRestaurantMapper.selectById(query.getCanteenId());
pageList.forEach(p->{
p.setIsExternalDine(null !=slBaseRestaurant?slBaseRestaurant.getIsExternalDine():0);
});
return page.setRecords(pageList);
}
@Override
public Boolean saveOrUpdateService(StClientMemberLevelDeductRuleVo vo) {
//规则
StClientMemberLevelDeductRule demotionTime = new StClientMemberLevelDeductRule();
demotionTime.setId(vo.getId());
demotionTime.setRuleName(DeductionTypeEnum.getName(vo.getDeductionType()));
StMemberDeductRuleVO resetVO = vo.getStMemberDeductRuleVO();
//2:固定+补贴扣费
if(vo.getDeductionType().equals(2)){
//=============================早餐=================================
StMemberDeductUserTypeRuleVO breakfast = resetVO.getBreakfast();
StMemberDeductTypeOfAuditorRuleVO externalBreakfast = breakfast.getExternal();
this.buildMemberDeductTypeOfAuditorRule(externalBreakfast);
breakfast.setExternal(externalBreakfast);
StMemberDeductTypeOfAuditorRuleVO innerBreakfast = breakfast.getInner();
this.buildMemberDeductTypeOfAuditorRule(innerBreakfast);
breakfast.setInner(innerBreakfast);
resetVO.setBreakfast(breakfast);
//=============================午餐=================================
StMemberDeductUserTypeRuleVO lunch = resetVO.getLunch();
StMemberDeductTypeOfAuditorRuleVO externalLunch = lunch.getExternal();
this.buildMemberDeductTypeOfAuditorRule(externalLunch);
lunch.setExternal(externalLunch);
StMemberDeductTypeOfAuditorRuleVO innerLunch = lunch.getInner();
this.buildMemberDeductTypeOfAuditorRule(innerLunch);
lunch.setInner(innerLunch);
resetVO.setLunch(lunch);
//=============================晚餐=================================
StMemberDeductUserTypeRuleVO dinner = resetVO.getDinner();
StMemberDeductTypeOfAuditorRuleVO externalDinner= dinner.getExternal();
this.buildMemberDeductTypeOfAuditorRule(externalDinner);
dinner.setExternal(externalDinner);
StMemberDeductTypeOfAuditorRuleVO innerDinner = dinner.getInner();
this.buildMemberDeductTypeOfAuditorRule(innerDinner);
dinner.setInner(innerDinner);
resetVO.setDinner(dinner);
}
String reStr = JSON.toJSONString(resetVO);
demotionTime.setDeductionRule(reStr);
demotionTime.setDeductionType(vo.getDeductionType());
demotionTime.setCanteenId(vo.getCanteenId());
demotionTime.setIsSync(0);
return this.saveOrUpdate(demotionTime);
}
/**
* 扣费类型:固定+补贴扣费,选择按照比例扣减,计算赠送金额和总金额
* @param typeOfAuditorRule
*/
private void buildMemberDeductTypeOfAuditorRule(StMemberDeductTypeOfAuditorRuleVO typeOfAuditorRule){
//选择按照比例扣减
if(typeOfAuditorRule.getRatioDeduction() !=null){
//四舍五入到两位小数
BigDecimal rewardDeduction = BigDecimal.valueOf(typeOfAuditorRule.getFixedDeduction())
.multiply(BigDecimal.valueOf(typeOfAuditorRule.getRatioDeduction() / 100)).setScale(2, RoundingMode.HALF_UP);
typeOfAuditorRule.setRewardDeduction(rewardDeduction.floatValue());
typeOfAuditorRule.setTotalDeduction(rewardDeduction.add(BigDecimal.valueOf(typeOfAuditorRule.getFixedDeduction())).floatValue());
} else {
//固定扣除
typeOfAuditorRule.setTotalDeduction(BigDecimal.valueOf(typeOfAuditorRule.getFixedDeduction())
.add(BigDecimal.valueOf(typeOfAuditorRule.getRewardDeduction())).setScale(2, RoundingMode.HALF_UP).floatValue());
}
}
@Override
public StClientMemberLevelDeductRuleVo getOneService(StClientMemberLevelDeductRuleVo stClientMemberLevelDeductRuleVo) {
StClientMemberLevelDeductRuleVo vo = new StClientMemberLevelDeductRuleVo();
StClientMemberLevelDeductRule memberLevel = null;
if(StringUtils.isNotBlank(stClientMemberLevelDeductRuleVo.getId())){
memberLevel = getOne(new LambdaQueryWrapper<StClientMemberLevelDeductRule>()
.eq(StClientMemberLevelDeductRule::getId, stClientMemberLevelDeductRuleVo.getId()));
}
if(StringUtils.isNotBlank(stClientMemberLevelDeductRuleVo.getCanteenId())){
memberLevel = getOne(new LambdaQueryWrapper<StClientMemberLevelDeductRule>()
.eq(StClientMemberLevelDeductRule::getCanteenId, stClientMemberLevelDeductRuleVo.getCanteenId())
.eq(StClientMemberLevelDeductRule::getIsEnable,1));
}
if (memberLevel == null) {
return null;
}
BeanUtils.copyProperties(memberLevel, vo);
if (vo.getDeductionType() == null) {
vo.setDeductionType(1);
}
/**
* 规则
*/
String deductionRule = memberLevel.getDeductionRule();
StMemberDeductRuleVO stMemberDeductRuleVO;
if (!org.springframework.util.StringUtils.isEmpty(deductionRule)) {
stMemberDeductRuleVO = JSON.parseObject(deductionRule, StMemberDeductRuleVO.class);
} else {
stMemberDeductRuleVO = new StMemberDeductRuleVO();
}
vo.setStMemberDeductRuleVO(stMemberDeductRuleVO);
return vo;
}
/**
* 根据食堂ID获取商户扣费规则
* @param canteenId
* @return
*/
@Override
public StClientMemberLevelDeductRuleVo getDeductRuleByCanteenId(String canteenId) {
// Object deductRule = redisUtil.hget(MapUtil.DeductRule, canteenId);
// if (ObjectUtils.isNotEmpty(deductRule)){
// return (StClientMemberLevelDeductRuleVo)deductRule;
//// return JSONObject.parseObject(deductRule, StClientMemberLevelDeductRuleVo.class);
// }
StClientMemberLevelDeductRuleVo vo = new StClientMemberLevelDeductRuleVo();
StClientMemberLevelDeductRule memberLevel = null;
if(StringUtils.isNotBlank(canteenId)){
memberLevel = getOne(new LambdaQueryWrapper<StClientMemberLevelDeductRule>()
.eq(StClientMemberLevelDeductRule::getCanteenId, canteenId)
.eq(StClientMemberLevelDeductRule::getIsEnable,1));
}
if (memberLevel == null) {
return null;
}
vo = bulidStClientMemberLevelDeductRule(vo,memberLevel);
// redisUtil.hset(MapUtil.DeductRule, canteenId, vo);
return vo;
}
/**
* 组装扣费规则vo
* @param vo
* @param memberLevel
* @return
*/
@Override
public StClientMemberLevelDeductRuleVo bulidStClientMemberLevelDeductRule(StClientMemberLevelDeductRuleVo vo, StClientMemberLevelDeductRule memberLevel){
BeanUtils.copyProperties(memberLevel, vo);
if (vo.getDeductionType() == null) {
vo.setDeductionType(1);
}
/**
* 规则
*/
String deductionRule = memberLevel.getDeductionRule();
StMemberDeductRuleVO stMemberDeductRuleVO;
if (!org.springframework.util.StringUtils.isEmpty(deductionRule)) {
stMemberDeductRuleVO = JSON.parseObject(deductionRule, StMemberDeductRuleVO.class);
} else {
stMemberDeductRuleVO = new StMemberDeductRuleVO();
}
vo.setStMemberDeductRuleVO(stMemberDeductRuleVO);
return vo;
}
@Override
public Result<StClientMemberSpendVO> bindUserOfflineCardCode(@RequestBody StRfidoffLineVo stRfidoffLineVo){
String deviceCode = stRfidoffLineVo.getDeviceCode();
String restId = stRfidoffLineVo.getRestId();
List<StRfidVo> voListAll = stRfidoffLineVo.getVoList();
if(CollectionUtils.isEmpty(voListAll)){
return Result.error("扣费信息不能为空");
}
//扣费规则(扣费类型(1:固定扣费,2:固定+补贴扣费,3:按量扣费,4:自定义金额))
StClientMemberLevelDeductRuleVo levelDeductRuleVo = this.getDeductRuleByCanteenId(restId);
if(voListAll.size() > 1){//离线扣费
//加异步处理
CompletableFuture.runAsync(() -> {
unifiedDeductionInterface(voListAll,restId,deviceCode,levelDeductRuleVo,false);
});
} else {//在线扣费
return unifiedDeductionInterface(voListAll,restId,deviceCode,levelDeductRuleVo,true);
}
return Result.OK("扣费成功");
}
/**
* 统一扣费方法
* @param voListAll
* @param restId
* @param deviceCode
* @param levelDeductRuleVo
* @return
*/
private Result<StClientMemberSpendVO> unifiedDeductionInterface(List<StRfidVo> voListAll, String restId, String deviceCode,
StClientMemberLevelDeductRuleVo levelDeductRuleVo, Boolean online) {
long start = System.currentTimeMillis();
//声明在线扣费余额信息
StClientMemberSpendVO stClientMemberSpendVO = new StClientMemberSpendVO();
BigDecimal totalOnline = BigDecimal.ZERO;
BigDecimal spendMoneyOnline = BigDecimal.ZERO;
// 存储错误信息
String errorMessages = null;
// 将扣费信息按照餐次分组
Map<String, List<StRfidVo>> stringListMap = groupByMeal(voListAll, restId);
StMiniMineBalanceVo stMiniMineBalanceVoOnline = new StMiniMineBalanceVo();
for (Map.Entry<String, List<StRfidVo>> entry : stringListMap.entrySet()) {
List<StRfidVo> voList = entry.getValue();
for (StRfidVo stRfidVo : voList) { // 改用普通for循环,方便控制流程
stRfidVo.setDeviceCode(deviceCode);
stRfidVo.setRestId(restId);
if(!online){
log.error("/payUser/offline/v3 离线人脸扣费v3,bindUser={}", JSONObject.toJSONString(stRfidVo));
} else {
log.error("/payUser/online 在线人脸扣费,bindUser={}", JSONObject.toJSONString(stRfidVo));
}
// 检查支付ID是否已存在
if (StringUtils.isNotBlank(stRfidVo.getPayId())) {
// StBbzxOrderInfo stBbzxOrderInfo = iStBbzxOrderInfoService.getSwBbzxOrderInfoByPayId(stRfidVo.getPayId());
StBbzxOrderInfo stBbzxOrderInfo = iStBbzxOrderInfoService.lambdaQuery()
.select(StBbzxOrderInfo::getOrderNo)
.eq(StBbzxOrderInfo::getPayId, stRfidVo.getPayId())
.one();
if (null != stBbzxOrderInfo) {
String errorMsg = "闸机记录的支付唯一id已经有支付信息, payId=" + stRfidVo.getPayId() +
", 已存在的订单编号=" + stBbzxOrderInfo.getOrderNo();
log.error(errorMsg);
errorMessages = "重复支付"; // 添加错误信息
continue; // 跳过当前循环,处理下一个
}
}
// 当前餐次
String timesName = entry.getKey();
BigDecimal rewardDeduction = BigDecimal.ZERO;
BigDecimal totalDeduction = BigDecimal.ZERO;
Date dateTime = new Date(Long.parseLong(stRfidVo.getDateTime()));
// 预算本次扣费金额
BigDecimal spendMoneyBudgeted = BigDecimal.ZERO;
BigDecimal moneyCustom = stRfidVo.getSpendMoney();
Integer deductionType;
if (moneyCustom != null && moneyCustom.compareTo(BigDecimal.ZERO) > 0) {
// 自定义金额方式
spendMoneyBudgeted = moneyCustom;
deductionType = 4;
} else {
deductionType = 1;
if (null == levelDeductRuleVo) {
String errorMsg = "食堂扣费规则未设置, restId=" + restId;
log.error(errorMsg);
errorMessages = "食堂扣费规则未设置";
if(!online) {//离线
CompletableFuture.runAsync(()-> iStBbzxOrderInfoService.buildOrderInfoNew(dateTime, stRfidVo.getRestId(), timesName, deviceCode,
stRfidVo.getUserId(), null, null, 1, levelDeductRuleVo,
errorMsg, stRfidVo));
}
continue;
}
// 扣费规则模式计算
try {
StClientMemberSpendDataVO stClientMemberSpendDataVO =
iStClientMemberBalanceService.fixedFee(levelDeductRuleVo, timesName, totalDeduction,
spendMoneyBudgeted, rewardDeduction, 1);
spendMoneyBudgeted = stClientMemberSpendDataVO.getSpendMoney();
} catch (Exception e) {
String errorMsg = "计算预算扣费金额失败, userId=" + stRfidVo.getUserId() + ", 餐次=" + timesName;
log.error(errorMsg, e);
errorMessages = "计算预算扣费金额失败";
continue;
}
}
// 获取用户钱包数据
String userId = stRfidVo.getUserId();
StMiniMineBalanceVo stMiniMineBalanceVo = new StMiniMineBalanceVo();
if (StringUtils.isNotBlank(userId)) {
// 人脸识别方式
Result<StMiniMineBalanceVo> userBalanceResult = iStClientMemberBalanceService.getUserBalance(userId);
if (!userBalanceResult.isSuccess()) {
stRfidVo.setSpendMoney(spendMoneyBudgeted);
String errorMsg = "离线人脸扣费v3,根据userId=" + userId + "查询用户钱包数据失败: " + userBalanceResult.getMessage();
log.error(errorMsg);
errorMessages = "根据人脸查询用户钱包数据失败: " + userBalanceResult.getMessage();
if(!online){//离线
CompletableFuture.runAsync(()->iStBbzxOrderInfoService.buildOrderInfoNew(dateTime, stRfidVo.getRestId(), timesName, deviceCode,
stRfidVo.getUserId(), null, null, deductionType,
levelDeductRuleVo, errorMsg, stRfidVo));
}
continue;
}
stMiniMineBalanceVo = userBalanceResult.getResult();
} else {
// 刷卡方式
if (StringUtils.isBlank(stRfidVo.getCardCode())) {
stRfidVo.setSpendMoney(spendMoneyBudgeted);
String errorMsg = "离线人脸扣费v3,判断为刷卡方式,卡号为空, payId=" + stRfidVo.getPayId();
log.error(errorMsg);
errorMessages = "刷卡卡号为空";
if(!online) {//离线
CompletableFuture.runAsync(()->iStBbzxOrderInfoService.buildOrderInfoNew(dateTime, stRfidVo.getRestId(), timesName, deviceCode,
stRfidVo.getUserId(), null, null, deductionType,
levelDeductRuleVo, errorMsg, stRfidVo));
}
continue;
}
String cardCode = stRfidVo.getCardCode();
Result<StMiniMineBalanceVo> userBalanceResult = iStClientMemberBalanceService.getUserBalanceByCardCode(cardCode);
if (!userBalanceResult.isSuccess()) {
stRfidVo.setSpendMoney(spendMoneyBudgeted);
String errorMsg = "离线人脸扣费v3,刷卡方式根据卡号=" + cardCode + "查询用户钱包数据失败: " + userBalanceResult.getMessage();
log.error(errorMsg);
errorMessages = "根据卡号查询用户钱包数据: " + userBalanceResult.getMessage();
if(!online) {//离线
CompletableFuture.runAsync(()->iStBbzxOrderInfoService.buildOrderInfoNew(dateTime, stRfidVo.getRestId(), timesName, deviceCode,
stRfidVo.getUserId(), null, null, deductionType, levelDeductRuleVo,
errorMsg, stRfidVo));
}
continue;
}
if(StringUtils.isNotBlank(stMiniMineBalanceVo.getCardCode()) && stMiniMineBalanceVo.getCardCodeStatus() != 1){
errorMessages = "此卡已挂失";
if(!online) {//离线
String finalErrorMessages = errorMessages;
StMiniMineBalanceVo finalStMiniMineBalanceVo = stMiniMineBalanceVo;
CompletableFuture.runAsync(()->iStBbzxOrderInfoService.buildOrderInfoNew(dateTime, stRfidVo.getRestId(), timesName, deviceCode,
stRfidVo.getUserId(), null, null, deductionType, levelDeductRuleVo,
finalErrorMessages +",卡号:"+ finalStMiniMineBalanceVo.getCardCode(), stRfidVo));
}
continue;
}
stMiniMineBalanceVo = userBalanceResult.getResult();
stMiniMineBalanceVo.setCardCode(stRfidVo.getCardCode());
stRfidVo.setUserId(stMiniMineBalanceVo.getMemberId());
userId = stMiniMineBalanceVo.getMemberId();
}
//在线场景判断用户和钱包状态
if(online){
if(stMiniMineBalanceVo.getUserStatus() != 1){
errorMessages = "主用户已停用";
continue;
}
if(stMiniMineBalanceVo.getStatus()!= 1){
errorMessages = "当前用户已停用";
continue;
}
}
// 计算本次实际扣费金额并处理
BigDecimal spendMoney = BigDecimal.ZERO;
BigDecimal money = stRfidVo.getSpendMoney();
try {
if (money != null && money.compareTo(BigDecimal.ZERO) > 0) {
// 自定义金额方式
spendMoney = money;
StClientMemberLevelDeductRuleVo stClientMemberLevelDeductRuleVo = new StClientMemberLevelDeductRuleVo();
stClientMemberLevelDeductRuleVo.setRuleName("自定义扣费");
stClientMemberLevelDeductRuleVo.setDeductionType(4);
stMiniMineBalanceVo.setAmountThis(spendMoney);
String data = syncMemberSpendOffLine(dateTime, restId, userId, stRfidVo, timesName,
stMiniMineBalanceVo, stClientMemberLevelDeductRuleVo);
if (StringUtils.isNotBlank(data)) {
String errorMsg = "自定义金额扣费操作失败, userId=" + userId + ", 错误信息: " + data;
log.error(errorMsg);
errorMessages = "自定义金额扣费操作失败: " + data;
continue;
}
} else {
// 扣费规则模式
StClientMemberSpendDataVO stClientMemberSpendDataVO =
iStClientMemberBalanceService.fixedFee(levelDeductRuleVo, timesName, totalDeduction,
spendMoney, rewardDeduction, stMiniMineBalanceVo.getUserInnerType());
spendMoney = stClientMemberSpendDataVO.getSpendMoney();
stMiniMineBalanceVo.setAmountThis(spendMoney);
String data = syncMemberSpendOffLine(dateTime, restId, userId, stRfidVo, timesName,
stMiniMineBalanceVo, levelDeductRuleVo);
if (StringUtils.isNotBlank(data)) {
String errorMsg = "规则模式扣费操作失败, userId=" + userId + ", 错误信息: " + data;
log.error(errorMsg);
errorMessages = "规则模式扣费操作失败:" + data;
continue;
}
}
} catch (Exception e) {
String errorMsg = "扣费处理过程中发生异常, userId=" + userId + ", 异常信息: " + e.getMessage();
log.error(errorMsg, e);
errorMessages = "扣费处理过程中发生异常: " + e.getMessage();
continue;
}
if(online){//在线扣费
stMiniMineBalanceVoOnline = stMiniMineBalanceVo;
spendMoneyOnline = spendMoney;
BigDecimal total = new BigDecimal(stMiniMineBalanceVo.getBalance());
//扣费后余额
totalOnline = total.subtract(spendMoney).setScale(2, BigDecimal.ROUND_HALF_UP);
}
}
}
if(online){//在线
// 根据错误信息返回不同结果
if (StringUtils.isBlank(errorMessages)) {
BigDecimal rewardDeduction = BigDecimal.ZERO;//用户扣费补贴金额
stClientMemberSpendVO.setRealname(stMiniMineBalanceVoOnline.getRealname());
stClientMemberSpendVO.setWorkNo(stMiniMineBalanceVoOnline.getWorkNo());
stClientMemberSpendVO.setPayRealname(stMiniMineBalanceVoOnline.getPayRealname());
stClientMemberSpendVO.setPayWorkNo(stMiniMineBalanceVoOnline.getPayWorkNo());
stClientMemberSpendVO.setSuccess(true);
stClientMemberSpendVO.setPreferentialPrice(rewardDeduction);
stClientMemberSpendVO.setSpendMoney(spendMoneyOnline);
stClientMemberSpendVO.setBalance(totalOnline);
log.info("在线扣费耗时,success{}",System.currentTimeMillis() - start);
return Result.OK("扣费成功",stClientMemberSpendVO);
} else {
log.info("在线扣费耗时,error{}",System.currentTimeMillis() - start);
return Result.error(errorMessages);
}
}
return Result.OK("扣费成功");
}
/**
* 扣费只有三餐,加餐怎么算?20250916余,加餐不算,后面让马老师那边加设置,不在三餐时间不能刷脸就扣费
* @param rfidVos
* @param restId
* @return
*/
@Override
public Map<String, List<StRfidVo>> groupByMeal(List<StRfidVo> rfidVos,String restId) {
List<SlBaseDinnerTime> list = stBaseDinnerTimeService.list(new LambdaQueryWrapper<SlBaseDinnerTime>()
.eq(SlBaseDinnerTime::getRestId, restId)
.orderByAsc(SlBaseDinnerTime::getEndTime));
return rfidVos.stream()
.collect(Collectors.groupingBy(rfidVo -> {
long timestamp = Long.parseLong(rfidVo.getDateTime());
Date date = new Date(timestamp);
SlBaseDinnerTime dinnerTime = getCanteenDinnerType(list, date);
if(null != dinnerTime){
return dinnerTime.getDinnerType();
} else {
return MealGroupingUtil.getDefaultMealType(date);
}
}));
}
private SlBaseDinnerTime getCanteenDinnerType(List<SlBaseDinnerTime> list, Date dataTime) {
if (org.apache.commons.collections.CollectionUtils.isNotEmpty(list)) {
for (SlBaseDinnerTime slBaseDinnerTime : list) {
DateTime endTime = DateUtil.parse(DateUtil.today() + " " + slBaseDinnerTime.getEndTime());
Date date = new Date();
if(null != dataTime){
endTime = DateUtil.parse(DateUtils.formatDate(dataTime,"yyyy-MM-dd") + " " + slBaseDinnerTime.getEndTime());
date = dataTime;
}
if (DateUtil.compare(date, endTime) <= 0) {
return slBaseDinnerTime;
}
}
return list.get(list.size() - 1);
}
return null;
}
/**
* 异步生成订单和进行实际扣费流程
* @param dateTime 订单时间
* @param restId
* @param userId
* @param stRfidVo
* @param timesName
*/
@Override
public String syncMemberSpendOffLine(Date dateTime, String restId, String userId, StRfidVo stRfidVo, String timesName, StMiniMineBalanceVo miniMineBalanceVo, StClientMemberLevelDeductRuleVo levelDeductRuleVo){
// 生成新订单
StBbzxOrderInfo stBbzxOrderInfo = iStBbzxOrderInfoService.buildOrderInfoNewOffLine(dateTime,restId, timesName, stRfidVo.getDeviceCode(), userId,
"", "", levelDeductRuleVo.getDeductionType(),levelDeductRuleVo,null, stRfidVo,miniMineBalanceVo);
StClientMemberSpendDTO stClientMemberSpendDTO = new StClientMemberSpendDTO();
stClientMemberSpendDTO.setCanteenId(stRfidVo.getRestId());
stClientMemberSpendDTO.setOrderNo(stBbzxOrderInfo.getOrderNo());
stClientMemberSpendDTO.setId(miniMineBalanceVo.getMemberId());//钱包用户id
stClientMemberSpendDTO.setMiniMineBalanceVo(miniMineBalanceVo);//钱包用户
StClientMemberSpendVO stClientMemberSpendVO = iStClientMemberBalanceService.memberSpendOffline(stClientMemberSpendDTO,stBbzxOrderInfo);
if(null != stClientMemberSpendVO && !stClientMemberSpendVO.getSuccess()){
return stClientMemberSpendVO.getMsg();
} else {
return null;
}
}
}
@@ -0,0 +1,316 @@
/**
* use shuwei code generator created
*/
package org.jeecg.payment.service.impl;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.base.service.impl.JeecgServiceImpl;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.payment.entity.StClientMemberLevelDemotionTime;
import org.jeecg.payment.mapper.StClientMemberLevelDemotionTimeMapper;
import org.jeecg.payment.service.IStClientMemberLevelDemotionTimeService;
import org.jeecg.payment.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 储值规则服务实现类
*/
@Service
public class StClientMemberLevelDemotionTimeServiceImpl extends JeecgServiceImpl<StClientMemberLevelDemotionTimeMapper, StClientMemberLevelDemotionTime> implements IStClientMemberLevelDemotionTimeService {
@Override
public Map<String, Object> topUpAwardService(Integer levelId, Float topUpPrice, String canteenId) {
Map<String, Object> result = new HashMap<>();
try {
//赠送的金额
float reChargeAmount = 0;
//赠送的积分
int reChargePIntegral = 0;
LambdaQueryWrapper<StClientMemberLevelDemotionTime> lambdaQueryWrapper = new LambdaQueryWrapper<StClientMemberLevelDemotionTime>();
lambdaQueryWrapper.eq(StClientMemberLevelDemotionTime::getIsEnable, 1);
if(StringUtils.isNotBlank(canteenId)){
lambdaQueryWrapper.eq(StClientMemberLevelDemotionTime::getCanteenId, canteenId);
}
StClientMemberLevelDemotionTime ruleSource = this.getOne(lambdaQueryWrapper);
if (ruleSource == null) {
result.put("amount", reChargeAmount);
result.put("integral", reChargePIntegral);
return result;
}
//储值赠送方式
List<StMemberLevelStoredVO> storedVOS = JSON.parseArray(ruleSource.getStoredRule(), StMemberLevelStoredVO.class);
if (!CollectionUtils.isEmpty(storedVOS)) {
AtomicInteger flag = new AtomicInteger(ruleSource.getStoredRuleFlag());
if (flag.get() == 1) { //固定规则
for (StMemberLevelStoredVO s : storedVOS) {
//获得对应的赠送金额
Float rewardAmount = s.getRewardAmount() == null ? 0f : s.getRewardAmount();
//获得对应的赠送积分
Integer rewardIntegral = s.getRewardIntegral() == null ? 0 : s.getRewardIntegral();
if (topUpPrice < s.getRechargePresenter()) {
//获取上一区间对应的赠送金额及积分
// result.put("amount", reChargeAmount);
// result.put("integral", reChargePIntegral);
continue;
} else {
//获得对应的赠送金额
// reChargeAmount = (topUpPrice / s.getRechargePresenter()) * rewardAmount;
reChargeAmount = rewardAmount;
//获得对应的赠送积分
reChargePIntegral = rewardIntegral;
}
}
} else { //比例规则
//至多一条记录
StMemberLevelStoredVO storedVO = storedVOS.get(0);
//赠送积分
if (topUpPrice < storedVO.getRechargePresenter()) {
reChargePIntegral = 0;
} else {
//赠送比例
Float rewardAmount = storedVO.getRewardAmount();
reChargeAmount = topUpPrice * (rewardAmount / 100);
reChargePIntegral = storedVO.getRewardIntegral();
}
}
}
result.put("amount", reChargeAmount);
result.put("integral", reChargePIntegral);
return result;
} catch (Exception ex) {
ex.printStackTrace();
result.put("amount", 0);
result.put("integral", 0);
return result;
}
}
@Override
public IPage<StClientMemberLevelDemotionTimeVO> selectStClientMemberLevelDemotionTimePage(StClientMemberLevelDemotionTimeVO query){
Page<StClientMemberLevelDemotionTimeVO> page = new Page<>(query.getPageNo(), query.getPageSize());
List<StClientMemberLevelDemotionTimeVO> pageList = baseMapper.selectSwClientMemberLevelDemotionTimePage(page,query);
return page.setRecords(pageList);
}
@Override
public Boolean saveOrUpdateService(StClientMemberLevelDemotionTimeVO vo) {
//获得机构对应的配置
StClientMemberLevelDemotionTime demotionTime = null;
if(StringUtils.isNotBlank(vo.getId())){
demotionTime = getById(vo.getId());
}
if (demotionTime == null) {
demotionTime = new StClientMemberLevelDemotionTime();
demotionTime.setCanteenId(vo.getCanteenId());
}
demotionTime.setRuleName(vo.getRuleName());
//储值规则
demotionTime.setStoredRuleFlag(vo.getStoredRuleFlag());
//储值扣款顺序
demotionTime.setPaymentOrder(vo.getPaymentOrder());
demotionTime.setRewardAmountReset(vo.getRewardAmountReset());
//降级时间
if (!org.springframework.util.StringUtils.isEmpty(vo.getHourMinuteStr())) {
demotionTime.setDHour(Integer.parseInt(vo.getHourMinuteStr().split(":")[0]));
demotionTime.setDMinute(Integer.parseInt(vo.getHourMinuteStr().split(":")[1]));
}
//储值规则
List<StMemberLevelStoredVO> storedVOS = vo.getStoredVOS();
if (!CollectionUtils.isEmpty(storedVOS)) {
String storedStr = JSON.toJSONString(storedVOS);
demotionTime.setStoredRule(storedStr);
}
//积分抵现规则
if (!org.springframework.util.StringUtils.isEmpty(vo.getIntegralVO())) {
StMemberLevelIntegralVO integralVO = vo.getIntegralVO();
String intStr = JSON.toJSONString(integralVO);
demotionTime.setIntegralRule(intStr);
//新增单笔订单积分抵扣规则
// if (StringUtils.isBlank(vo.getId()) && integralVO.getStatus() == 1 && integralVO.getDeductionAmount() != null && integralVO.getIntegralCount() != null) {
StMemberLevelSingleVO singleVO = vo.getSingleVO();
String singleStr = JSON.toJSONString(singleVO);
demotionTime.setSingleMaxIntegralRule(singleStr);
// }
}
//积分清零规则
if (!org.springframework.util.StringUtils.isEmpty(vo.getResetVO())) {
StMemberLevelResetVO resetVO = vo.getResetVO();
String reStr = JSON.toJSONString(resetVO);
demotionTime.setIntegralResetRule(reStr);
}
//积分清零提示短信
if (!org.springframework.util.StringUtils.isEmpty(vo.getResetMessageVO())) {
StMemberLevelResetMessageVO messageVO = vo.getResetMessageVO();
String messStr = JSON.toJSONString(messageVO);
demotionTime.setIntegralResetRemindMessage(messStr);
}
demotionTime.setIsSync(0);
return saveOrUpdate(demotionTime);
}
@Override
public StClientMemberLevelDemotionTimeVO getOneService(StClientMemberLevelDemotionTime swClientMemberLevelDemotionTime) {
StClientMemberLevelDemotionTimeVO vo = new StClientMemberLevelDemotionTimeVO();
StClientMemberLevelDemotionTime memberLevel = getById(swClientMemberLevelDemotionTime.getId());
if (memberLevel == null) {
return null;
}
BeanUtils.copyProperties(memberLevel, vo);
if (vo.getStoredRuleFlag() == null) {
vo.setStoredRuleFlag(1);
}
if (vo.getPaymentOrder() == null) {
vo.setPaymentOrder(1);
}
/**
* 解析会员卡等级储值规则
*/
String storedRule = memberLevel.getStoredRule();
if (!org.springframework.util.StringUtils.isEmpty(storedRule)) {
List<StMemberLevelStoredVO> storedVOS = JSON.parseArray(storedRule, StMemberLevelStoredVO.class);
vo.setStoredVOS(storedVOS);
} else {
vo.setStoredVOS(new ArrayList<StMemberLevelStoredVO>());
}
/**
* 积分抵现规则
*/
String integralRule = memberLevel.getIntegralRule();
StMemberLevelIntegralVO integralVO;
if (!org.springframework.util.StringUtils.isEmpty(integralRule)) {
integralVO = JSON.parseObject(integralRule, StMemberLevelIntegralVO.class);
} else {
integralVO = new StMemberLevelIntegralVO();
integralVO.setStatus(0);
}
vo.setIntegralVO(integralVO);
/**
* 单笔积分抵扣上限规则
*/
String singleRule = memberLevel.getSingleMaxIntegralRule();
StMemberLevelSingleVO singleVO;
if (!org.springframework.util.StringUtils.isEmpty(singleRule)) {
singleVO = JSON.parseObject(singleRule, StMemberLevelSingleVO.class);
} else {
singleVO = new StMemberLevelSingleVO();
singleVO.setStatus(0);
}
vo.setSingleVO(singleVO);
/**
* 积分清零规则
*/
String resetRule = memberLevel.getIntegralResetRule();
StMemberLevelResetVO resetVO;
if (!org.springframework.util.StringUtils.isEmpty(resetRule)) {
resetVO = JSON.parseObject(resetRule, StMemberLevelResetVO.class);
} else {
resetVO = new StMemberLevelResetVO();
resetVO.setStatus(0);
}
vo.setResetVO(resetVO);
/**
* 提示短信
*/
String messageRule = memberLevel.getIntegralResetRemindMessage();
StMemberLevelResetMessageVO messageVO;
if (!org.springframework.util.StringUtils.isEmpty(messageRule)) {
messageVO = JSON.parseObject(messageRule, StMemberLevelResetMessageVO.class);
} else {
messageVO = new StMemberLevelResetMessageVO();
messageVO.setStatus(0);
}
vo.setResetMessageVO(messageVO);
return vo;
}
@Override
public List<StMemberLevelStoredVO> appMemberLevelStoredService() {
String canteenId = JwtUtil.getCanteenId();
StClientMemberLevelDemotionTime memberLevelDemotionTime =
getOne(new LambdaQueryWrapper<StClientMemberLevelDemotionTime>()
.eq(StClientMemberLevelDemotionTime::getCanteenId, canteenId));
if (memberLevelDemotionTime != null) {
String storedRule = memberLevelDemotionTime.getStoredRule();
if (!org.springframework.util.StringUtils.isEmpty(storedRule)) {
List<StMemberLevelStoredVO> storedRuleList = JSON.parseArray(storedRule, StMemberLevelStoredVO.class);
Integer storedRuleFlag = memberLevelDemotionTime.getStoredRuleFlag();
switch (storedRuleFlag) {
case 1:
return storedRuleList;
case 2:
/**
* 处理按比例
*/
StMemberLevelStoredVO levelStored = storedRuleList.get(0);
//每满金额*赠送比例
BigDecimal rechargePresenter =
new BigDecimal(levelStored.getRechargePresenter() == null ? 0 : levelStored.getRechargePresenter());
BigDecimal rewardAmount =
new BigDecimal(levelStored.getRewardAmount() == null ? 0 : levelStored.getRewardAmount());
float newRewardAmount = rechargePresenter.multiply(rewardAmount).floatValue();
levelStored.setRewardAmount(newRewardAmount);
return storedRuleList;
}
} else {
return null;
}
}
return null;
}
@Override
public Result<?> memberLevelDemotionTimeByCanteenId(String canteenId){
if(StringUtils.isBlank(canteenId)){
return Result.error("食堂ID不能为空");
}
try {
LambdaQueryWrapper<StClientMemberLevelDemotionTime> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
lambdaQueryWrapper1.eq(StClientMemberLevelDemotionTime::getCanteenId,canteenId);
lambdaQueryWrapper1.eq(StClientMemberLevelDemotionTime::getIsEnable,1);
StClientMemberLevelDemotionTime memberLevel = this.getOne(lambdaQueryWrapper1);
if(null != memberLevel){
return Result.OK(memberLevel);
}
} catch (Exception e) {
return Result.error("食堂扣费规则获取异常请检查后台配置是否正常");
}
return Result.error("食堂扣费顺序未设置");
}
}
@@ -0,0 +1,101 @@
package org.jeecg.payment.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.system.base.service.impl.JeecgServiceImpl;
import org.jeecg.payment.dto.StClientMemberTransactionRecordDTO;
import org.jeecg.payment.entity.StClientMemberTransactionRecord;
import org.jeecg.payment.enums.MemberEnum;
import org.jeecg.payment.enums.MemberTransactionTypeEnum;
import org.jeecg.payment.mapper.StClientMemberTransactionRecordMapper;
import org.jeecg.payment.service.IStClientMemberTransactionRecordService;
import org.jeecg.payment.vo.InOutRecordInfoVo;
import org.jeecg.payment.vo.StClientMemberTransactionRecordVO;
import org.jeecg.system.service.ISysPayDepartService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* 交易记录
*/
@Service
public class StClientMemberTransactionRecordServiceImpl extends JeecgServiceImpl<StClientMemberTransactionRecordMapper, StClientMemberTransactionRecord> implements IStClientMemberTransactionRecordService {
@Resource
private ISysPayDepartService iSysPayDepartService;
@Override
public IPage<StClientMemberTransactionRecordVO> pageQuery(StClientMemberTransactionRecordDTO query) {
Page<StClientMemberTransactionRecordVO> page = new Page<>(query.getPageNo(), query.getPageSize());
if(StringUtils.isNotBlank(query.getDepartId())){
List<String> allCascadeDeptIds = iSysPayDepartService.getAllCascadeDeptIds(query.getDepartId());
if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(allCascadeDeptIds)){
query.setList(allCascadeDeptIds);
}
}
List<StClientMemberTransactionRecordVO> pageList = baseMapper.pageList(page,query);
if (CollectionUtils.isNotEmpty(pageList)) {
for (StClientMemberTransactionRecordVO model : pageList) {
model.setStatusName(MemberTransactionTypeEnum.getName(model.getStatus()));
model.setPaymentMethodName(MemberEnum.getXcxName(model.getPaymentMethod()));
model.setUpdateStatusName(null != model.getUpdateStatus() && 1 == model.getUpdateStatus() ? "前端":"后台");
if(null != model.getBusinessModel()&& 1 == model.getBusinessModel() ){
model.setBusinessModelName("定值模式");//扣费类型(1:固定扣费,2:固定+补贴扣费,3:按量扣费,4:自定义金额)
}
if(null != model.getBusinessModel()&& 4 == model.getBusinessModel() ){
model.setBusinessModelName("金额模式");//扣费类型(1:固定扣费,2:固定+补贴扣费,3:按量扣费,4:自定义金额)
}
}
}
return page.setRecords(pageList);
}
@Override
public List<StClientMemberTransactionRecordVO> queryList(StClientMemberTransactionRecordDTO query) {
List<StClientMemberTransactionRecordVO> pageList = baseMapper.pageList(query);
if (CollectionUtils.isNotEmpty(pageList)) {
for (StClientMemberTransactionRecordVO model : pageList) {
model.setStatusName(MemberTransactionTypeEnum.getName(model.getStatus()));
model.setPaymentMethodName(MemberEnum.getXcxName(model.getPaymentMethod()));
model.setUpdateStatusName(null != model.getUpdateStatus() && 1 == model.getUpdateStatus() ? "前端":"后台");
if(null != model.getBusinessModel()&& 1 == model.getBusinessModel() ){
model.setBusinessModelName("定值模式");//扣费类型(1:固定扣费,2:固定+补贴扣费,3:按量扣费,4:自定义金额)
}
if(null != model.getBusinessModel()&& 4 == model.getBusinessModel() ){
model.setBusinessModelName("金额模式");//扣费类型(1:固定扣费,2:固定+补贴扣费,3:按量扣费,4:自定义金额)
}
}
}
return pageList;
}
@Override
public IPage<StClientMemberTransactionRecordVO> pageBalanceRefundList(Page<StClientMemberTransactionRecordVO> page,StClientMemberTransactionRecordDTO query) {
List<StClientMemberTransactionRecordVO> pageList = baseMapper.pageBalanceRefundList(page,query);
if (CollectionUtils.isNotEmpty(pageList)) {
for (StClientMemberTransactionRecordVO model : pageList) {
model.setStatusName(MemberTransactionTypeEnum.getName(model.getStatus()));
}
}
return page.setRecords(pageList);
}
@Override
public InOutRecordInfoVo getOneInOutInfo(String recordId) {
InOutRecordInfoVo oneInOutInfo = baseMapper.getOneInOutInfo(recordId);
if(oneInOutInfo != null){
String xcxPayMethodName = MemberEnum.getXcxName(Integer.parseInt(oneInOutInfo.getPaymentMethod()));
oneInOutInfo.setPaymentMethod(xcxPayMethodName);
return oneInOutInfo;
}
return null;
}
}
@@ -0,0 +1,378 @@
package org.jeecg.payment.utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jeecg.payment.dto.StClientMemberTopUpDTO;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Slf4j
public class ExcelResultGenerator {
/**
* 生成带标记和报告的Excel
* @param file 原始Excel文件
* @param canteenId 食堂ID
* @param idCardSet 需要标记为红色的身份证号集合
* @param resultMap 导入结果映射 key:身份证号 value:结果描述
* @return 处理后的Excel输入流
*/
public InputStream generateResultExcel(MultipartFile file, String canteenId,
Set<String> idCardSet, Map<String, String> resultMap) {
try {
// 1. 读取原始Excel
InputStream inputStream = file.getInputStream();
String fileName = file.getOriginalFilename();
Workbook workbook;
// 根据文件格式创建对应的Workbook
if (fileName != null && fileName.endsWith(".xls")) {
workbook = new HSSFWorkbook(inputStream);
} else {
workbook = new XSSFWorkbook(inputStream);
}
// 2. 获取第一个工作表
Sheet sheet = workbook.getSheetAt(0);
if (sheet == null) {
return null;
}
// 3. 创建红色背景样式
CellStyle redBgStyle = workbook.createCellStyle();
redBgStyle.cloneStyleFrom(sheet.getRow(0).getCell(0).getCellStyle()); // 复制原始样式
redBgStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
redBgStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
// 4. 获取最后一列索引,准备添加结果列
int lastColNum = 0;
Row firstRow = sheet.getRow(0);
if (firstRow != null) {
lastColNum = firstRow.getLastCellNum();
}
// 在第一行添加结果列标题
Cell resultTitleCell = firstRow.createCell(lastColNum);
resultTitleCell.setCellValue("导入结果");
CellStyle titleStyle = workbook.createCellStyle();
titleStyle.cloneStyleFrom(firstRow.getCell(0).getCellStyle());
titleStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
titleStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
resultTitleCell.setCellStyle(titleStyle);
// 5. 遍历处理每一行数据
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
if (row == null) {
continue;
}
// 获取身份证号单元格(第3列,索引为2)
Cell idCardCell = row.getCell(2);
String idCard = "";
if (idCardCell != null) {
idCardCell.setCellType(CellType.STRING);
idCard = idCardCell.getStringCellValue();
}
// 6. 处理行背景色:如果身份证号在指定集合中,设置红色背景
if (idCardSet.contains(idCard)) {
for (int j = 0; j <= row.getLastCellNum(); j++) {
Cell cell = row.getCell(j);
if (cell == null) {
cell = row.createCell(j);
}
cell.setCellStyle(redBgStyle);
}
}
// 7. 添加导入结果描述
Cell resultCell = row.createCell(lastColNum);
String resultDesc = resultMap.getOrDefault(idCard, "未处理");
resultCell.setCellValue(resultDesc);
// 保持与该行其他单元格相同的样式
if (row.getLastCellNum() > 0) {
CellStyle cellStyle = row.getCell(0).getCellStyle();
resultCell.setCellStyle(cellStyle);
}
}
// 8. 调整最后一列宽度自适应内容
sheet.autoSizeColumn(lastColNum);
// 9. 将处理后的Workbook转换为InputStream
ByteArrayOutputStream out = new ByteArrayOutputStream();
workbook.write(out);
workbook.close();
inputStream.close();
return new ByteArrayInputStream(out.toByteArray());
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* 核心工具方法:生成带标记的结果Excel
* 功能:1. 保留原始Excel格式;2. 异常行(重复/缺失用户等)标红;3. 最后一列追加导入结果描述
* @param originalFile 原始上传文件
* @param successList 充值成功的DTO列表
* @param failList 充值失败的DTO列表
* @param duplicateSerialList 流水号重复的DTO列表
* @param multiUserList 用户重复的DTO列表
* @param missingUserList 用户缺失的DTO列表
* @return 处理后的Excel输入流
*/
public static InputStream generateResultExcel(
MultipartFile originalFile,
List<StClientMemberTopUpDTO> successList,
List<StClientMemberTopUpDTO> failList,
List<StClientMemberTopUpDTO> duplicateSerialList,
List<StClientMemberTopUpDTO> multiUserList,
List<StClientMemberTopUpDTO> missingUserList) throws IOException {
// 1. 读取原始Excel,创建Workbook(兼容.xls和.xlsx
InputStream originalInputStream = originalFile.getInputStream();
String fileName = originalFile.getOriginalFilename();
Workbook workbook;
int maxColumnIndex;
if (fileName != null && fileName.endsWith(".xls")) {
workbook = new HSSFWorkbook(originalInputStream);
maxColumnIndex = 255; // Excel 2003最大列索引(A~IV
} else {
workbook = new XSSFWorkbook(originalInputStream);
maxColumnIndex = 16383; // Excel 2007+最大列索引(A~XFD
}
Sheet sheet = workbook.getSheetAt(0);
if (sheet == null) {
throw new RuntimeException("原始Excel无工作表,请检查文件格式");
}
// 2. 初始化样式(保留原始格式,避免错乱)
Row headerRow = sheet.getRow(0);
CellStyle redBgStyle = workbook.createCellStyle();
CellStyle resultHeaderStyle = workbook.createCellStyle();
if (headerRow != null && headerRow.getCell(0) != null) {
// 复制表头样式(字体、边框、对齐方式与原始一致)
redBgStyle.cloneStyleFrom(headerRow.getCell(0).getCellStyle());
resultHeaderStyle.cloneStyleFrom(headerRow.getCell(0).getCellStyle());
}
redBgStyle.setFillForegroundColor(IndexedColors.RED.getIndex());
redBgStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
resultHeaderStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
resultHeaderStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
// 3. 构建「身份证号→导入结果」映射(核心修复:格式统一+优先级处理)
Map<String, String> idCardToResultMap = new HashMap<>();
// 3.2 按业务优先级添加结果(成功 > 重复 > 多用户 > 缺失 > 失败)
// 优先级1:充值成功(不被后续低优先级结果覆盖)
for (StClientMemberTopUpDTO dto : successList) {
if (dto == null) continue;
String normalizedCardNo = dto.getCardNo();
if (StringUtils.isNotBlank(normalizedCardNo) && !idCardToResultMap.containsKey(normalizedCardNo)) {
idCardToResultMap.put(normalizedCardNo, "校验正常");
log.debug("映射添加[成功]{} → 校验正常", normalizedCardNo);
}
}
// 优先级2:流水号重复(不覆盖成功结果)
for (StClientMemberTopUpDTO dto : duplicateSerialList) {
if (dto == null) continue;
String normalizedCardNo = dto.getCardNo();
if (StringUtils.isNotBlank(normalizedCardNo) && !idCardToResultMap.containsKey(normalizedCardNo)) {
idCardToResultMap.put(normalizedCardNo, "流水号已导入(历史重复)");
log.debug("映射添加[重复]:{} → 流水号已导入(历史重复)", normalizedCardNo);
}
}
// 优先级3:身份证对应多个用户(不覆盖成功/重复结果)
for (StClientMemberTopUpDTO dto : multiUserList) {
if (dto == null) continue;
String normalizedCardNo = dto.getCardNo();
if (StringUtils.isNotBlank(normalizedCardNo) && !idCardToResultMap.containsKey(normalizedCardNo)) {
idCardToResultMap.put(normalizedCardNo, "身份证对应多个用户(请核查)");
log.debug("映射添加[多用户]:{} → 身份证对应多个用户(请核查)", normalizedCardNo);
}
}
// 优先级4:身份证无对应用户(不覆盖前3类结果)
for (StClientMemberTopUpDTO dto : missingUserList) {
if (dto == null) continue;
String normalizedCardNo = dto.getCardNo();
if (StringUtils.isNotBlank(normalizedCardNo) && !idCardToResultMap.containsKey(normalizedCardNo)) {
idCardToResultMap.put(normalizedCardNo, "身份证无对应用户/钱包(请先创建)");
log.debug("映射添加[缺失用户]:{} → 身份证无对应用户/钱包(请先创建)", normalizedCardNo);
}
}
// 优先级5:通用充值失败(仅覆盖未匹配到前4类的结果)
for (StClientMemberTopUpDTO dto : failList) {
if (dto == null) continue;
String normalizedCardNo = dto.getCardNo();
if (StringUtils.isNotBlank(normalizedCardNo) && !idCardToResultMap.containsKey(normalizedCardNo)) {
idCardToResultMap.put(normalizedCardNo, "充值失败(系统异常,请重试)");
log.debug("映射添加[失败]:{} → 充值失败(系统异常,请重试)", normalizedCardNo);
}
}
// 4. 处理Excel内容:添加结果列+标红异常行(核心修复:身份证号匹配逻辑)
int resultColumnIndex;
// 4.1 计算结果列索引(避免列数超限)
if (headerRow == null) {
resultColumnIndex = 0;
headerRow = sheet.createRow(0); // 无表头时新建表头行
} else {
int originalLastColNum = headerRow.getLastCellNum();
resultColumnIndex = originalLastColNum;
if (resultColumnIndex > maxColumnIndex) {
throw new RuntimeException(
"原始Excel列数已达上限(" + (maxColumnIndex + 1) + "列),无法添加「导入结果」列,请简化原始表格后重试"
);
}
}
// 4.2 表头添加“导入结果”列
Cell resultHeaderCell = headerRow.createCell(resultColumnIndex);
resultHeaderCell.setCellValue("导入结果");
resultHeaderCell.setCellStyle(resultHeaderStyle);
// 4.3 遍历数据行(逐行匹配结果,区分不同错误类型)
for (int rowNum = 1; rowNum <= sheet.getLastRowNum(); rowNum++) {
Row dataRow = sheet.getRow(rowNum);
if (dataRow == null) {
log.debug("Excel第{}行为空,跳过处理", rowNum + 1);
continue;
}
// 判断行是否为空行(有行对象但无有效单元格数据)
boolean isEmptyRow = isEmptyRowMethod(dataRow);
if (isEmptyRow) {
log.debug("Excel第{}行为空行(无有效单元格),跳过处理", rowNum + 1);
continue;
}
// 4.3.1 读取并标准化当前行的身份证号(与映射表格式保持一致)
Cell idCardCell = dataRow.getCell(3); // 假设身份证号在第3列(索引2
String currentIdCard = null;
if (idCardCell != null) {
idCardCell.setCellType(CellType.STRING); // 强制转为字符串,避免数字格式问题
currentIdCard = idCardCell.getStringCellValue(); // 标准化格式
log.debug("Excel第{}行:读取的身份证号(标准化后)→ {}", rowNum + 1, currentIdCard);
}
// 4.3.2 匹配结果(区分4种场景,避免统一错误)
String resultDesc;
if (currentIdCard == null || currentIdCard.isEmpty()) {
// 场景1Excel中无身份证号
resultDesc = "未处理(无身份证信息)";
} else if (!idCardToResultMap.containsKey(currentIdCard)) {
// 场景2:身份证号存在,但未参与充值流程(未在任何DTO列表中)
resultDesc = "未处理(身份证号未参与充值流程)";
} else {
// 场景3:匹配到映射表中的结果(成功/重复/多用户/缺失/失败)
resultDesc = idCardToResultMap.get(currentIdCard);
}
log.debug("Excel第{}行:最终结果→ {}", rowNum + 1, resultDesc);
// 4.3.3 添加结果单元格并复制原始样式
Cell resultCell = dataRow.createCell(resultColumnIndex);
resultCell.setCellValue(resultDesc);
if (dataRow.getLastCellNum() > 0) {
Cell firstCell = dataRow.getCell(0);
if (firstCell != null) {
CellStyle dataCellStyle = workbook.createCellStyle();
dataCellStyle.cloneStyleFrom(firstCell.getCellStyle());
resultCell.setCellStyle(dataCellStyle);
}
}
// 4.3.4 标红异常行(仅“校验正常”不标红)
if (!"校验正常".equals(resultDesc)) {
int maxCol = Math.min(dataRow.getLastCellNum(), maxColumnIndex);
for (int colNum = 0; colNum <= maxCol; colNum++) {
Cell cell = dataRow.getCell(colNum);
if (cell == null) cell = dataRow.createCell(colNum); // 空单元格也标红
cell.setCellStyle(redBgStyle);
}
resultCell.setCellStyle(redBgStyle);
}
}
// 4.4 自适应结果列宽度(避免内容被截断)
sheet.autoSizeColumn(resultColumnIndex);
// 5. 流转换与资源关闭(避免内存泄漏)
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
workbook.write(outputStream);
outputStream.flush();
// 按顺序关闭资源(先关Workbook,再关输入流)
workbook.close();
originalInputStream.close();
outputStream.close();
return new ByteArrayInputStream(outputStream.toByteArray());
}
// 工具方法:判断行是否为空行(无有效单元格数据)
private static boolean isEmptyRowMethod(Row row) {
// 情况1:行的单元格集合为空(_cells数量为0)
if (row.getPhysicalNumberOfCells() == 0) {
return true;
}
// 情况2:遍历所有单元格,检查是否均为空白(处理单元格存在但值为空的情况)
for (int cellNum = row.getFirstCellNum(); cellNum <= row.getLastCellNum(); cellNum++) {
Cell cell = row.getCell(cellNum, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
String cellValue = getCellValue(cell).trim(); // 自定义方法:获取单元格文本值
if (StringUtils.isNotBlank(cellValue)) {
// 存在非空白单元格,不是空行
return false;
}
}
// 所有单元格均为空白,视为空行
return true;
}
// 辅助方法:获取单元格的文本值(兼容各种单元格类型)
private static String getCellValue(Cell cell) {
if (cell == null) {
return "";
}
switch (cell.getCellType()) {
case STRING:
return cell.getStringCellValue();
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
return cell.getDateCellValue().toString();
} else {
// 处理数字避免科学计数法
return new BigDecimal(cell.getNumericCellValue()).toPlainString();
}
case BOOLEAN:
return String.valueOf(cell.getBooleanCellValue());
case FORMULA:
return cell.getCellFormula(); // 或解析公式结果:evaluateFormulaCell
default:
return "";
}
}
}
@@ -0,0 +1,472 @@
package org.jeecg.payment.utils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
/**
* 支持复合表头导出的Excel工具类
* @author fans
* @version 1.0
* @date 2024/11/25
*/
public class ExcelUtils {
private ExcelUtils() {
throw new UnsupportedOperationException("initialization is prohibited...");
}
private static Logger logger = LoggerFactory.getLogger(ExcelUtils.class);
/**
* 图片
*/
public static class Image {
private byte[] imageData;
public Image(byte[] imageData) {
this.imageData = imageData;
}
public byte[] getImageData() {
return imageData;
}
}
/**
* 导出(目前仅支持小于两行表头的合并操作)
* @param realName 导出文件名
* @param data 导出数据
* @param fields 导出字段,比如 date|时间,firstHeader|表头1,secondHeader|表头2,sub001|编号-0001|子标题1,sub002|编号-0001|子标题2,sub003|编号-0001|子标题3,sub004|编号-0001|子标题4,remark|备注
*/
public static void export(HttpServletResponse response, String realName, List<LinkedHashMap<String, Object>> data, String fields) {
String fileName = realName + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss")) + ".xlsx";
writeFileToResponse(construct(fields, data, fileName), response);
}
/**
* 导出并转换时间格式(目前仅支持小于两行表头的合并操作)
* @param realName 导出文件名
* @param list 导出数据
* @param fields 导出字段,比如 date|时间,firstHeader|表头1,secondHeader|表头2,sub001|编号-0001|子标题1,sub002|编号-0001|子标题2,sub003|编号-0001|子标题3,sub004|编号-0001|子标题4,remark|备注
* @param formatter 日期格式化字符串
* @param tableHeader 是否将文件名称同时设置为表格内的标题行(true:设置,false:不设置)
*/
public static void export(HttpServletResponse response, String realName, List list, String fields, String formatter,Boolean tableHeader) {
if(tableHeader){
if(StringUtils.isNotBlank(fields) && fields.contains("|")){
fields = fields.replaceAll("\\|", "|"+realName+"|");
}
}
List<LinkedHashMap<String, Object>> data = ExcelUtils.listObjToListMap(list);
convertDateToStr(data, formatter);
export(response, realName, data, fields);
}
/**
* 将文件写入响应流
* @param file 文件
* @param response 响应
* @throws UnsupportedEncodingException
*/
public static void writeFileToResponse(MultipartFile file, HttpServletResponse response) {
// 设置文件ContentType类型,这样设置,会自动判断下载文件类型
response.setContentType("multipart/form-data");
InputStream inputStream = null;
try {
String fileName = URLEncoder.encode(file.getOriginalFilename(), "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
response.setHeader("Pragma", "public");
response.setDateHeader("Expires", (System.currentTimeMillis() + 1000));
inputStream = file.getInputStream();
OutputStream out = response.getOutputStream();
byte[] buffer = new byte[1024];
int count = 0;
while ((count = inputStream.read(buffer)) != -1) {
out.write(buffer, 0, count);
}
out.close();
out.flush();
} catch (IOException e) {
logger.error("文件下载异常:文件名【%s】", file.getName(), e);
} finally {
IOUtils.closeQuietly(inputStream);
}
}
/**
* 创建生成 excel 文档
* @param fields 导出字段
* @param data 导出数据
* @param fileName 导出文档名称
* @return 生成的 excel 文档
*/
// private static MultipartFile construct(String fields, List<LinkedHashMap<String, Object>> data, String fileName) {
// Workbook workbook = new XSSFWorkbook();
// Sheet sheet = workbook.createSheet();
// CellStyle cellStyle = createCellStyle(workbook);
// Map<String, Integer> fieldOrder = getFieldOrder(fields);
// // 头部占的行数
// int headerRows = calculateHeaderRows(fields);
//
// // 创建一个新的单元格样式
// CellStyle cellStyle1 = createCellStyle(workbook);
// // 创建一个字体
// Font font = workbook.createFont();
//// font.setFontName("Arial"); // 设置字体名称
//// font.setFontHeightInPoints((short) 14); // 设置字号
// font.setBold(true); // 设置加粗
// // 将字体应用到样式
// cellStyle1.setFont(font);
//
// initHeader(sheet, cellStyle1, fields, headerRows);
// fillData(workbook, sheet, cellStyle, data, fieldOrder, headerRows);
// try {
// fileName = URLEncoder.encode(fileName, "UTF-8");
// } catch (UnsupportedEncodingException e) {
// e.printStackTrace();
// }
// DiskFileItem fileItem = (DiskFileItem)(new DiskFileItemFactory()).createItem("file", "text/plain", true, fileName);
// try {
// OutputStream os = fileItem.getOutputStream();
// Throwable var8 = null;
//
// try {
// workbook.write(os);
// } catch (Throwable var18) {
// var8 = var18;
// throw var18;
// } finally {
// if (os != null) {
// if (var8 != null) {
// try {
// os.close();
// } catch (Throwable var17) {
// var8.addSuppressed(var17);
// }
// } else {
// os.close();
// }
// }
//
// }
//
// } catch (Exception var20) {
// throw new IllegalArgumentException("Invalid file: " + var20, var20);
// }
//
// return new CommonsMultipartFile(fileItem);
// }
private static MultipartFile construct(String fields, List<LinkedHashMap<String, Object>> data, String fileName) {
try (Workbook workbook = new XSSFWorkbook();
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
Sheet sheet = workbook.createSheet();
CellStyle cellStyle = createCellStyle(workbook);
Map<String, Integer> fieldOrder = getFieldOrder(fields);
// 头部占的行数
int headerRows = calculateHeaderRows(fields);
// 创建一个新的单元格样式
CellStyle cellStyle1 = createCellStyle(workbook);
// 创建一个字体
Font font = workbook.createFont();
font.setBold(true); // 设置加粗
cellStyle1.setFont(font);
initHeader(sheet, cellStyle1, fields, headerRows);
fillData(workbook, sheet, cellStyle, data, fieldOrder, headerRows);
// 写入输出流
workbook.write(baos);
// URL编码文件名(如果需要)
String encodedFileName;
try {
encodedFileName = URLEncoder.encode(fileName, "UTF-8");
} catch (Exception e) {
encodedFileName = fileName;
}
return new MockMultipartFile(
"file",
encodedFileName,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
baos.toByteArray()
);
} catch (IOException e) {
throw new RuntimeException("Excel文件生成失败", e);
}
}
/**
* 初始化表头
* @param sheet sheet页
* @param cellStyle 单元格样式
* @param fields 导出字段
* @param headerRows 头部所占的行数
*/
private static void initHeader(Sheet sheet, CellStyle cellStyle, String fields, int headerRows) {
// 构造表头
Row row1 = sheet.createRow(0);
Row row2 = null;
if (headerRows > 1) {
row2 = sheet.createRow(1);
}
String[] field = fields.split(",");
// 上一个合并的表头名称
String preMergeName = null;
// 合并的起止索引
int startIdx = 0,endIdx = -1;
for (int i = 0; i < field.length; i++) {
String[] f = field[i].split("\\|");
Cell c1 = row1.createCell(i);
c1.setCellStyle(cellStyle);
c1.setCellValue(f[1]);
// 设置列宽(单位是字符宽度的1/256)
sheet.setColumnWidth(i, 5000); // 第一列宽度
if (f.length > 2) {
Cell c2 = row2.createCell(i);
c2.setCellStyle(cellStyle);
c2.setCellValue(f[f.length - 1]);
if (preMergeName == null) {
preMergeName = f[1];
startIdx = i;
endIdx = startIdx;
} else if (preMergeName.equals(f[1])){
endIdx++;
} else {
mergeRegion(sheet, 0, 0, startIdx, endIdx);
preMergeName = f[1];
startIdx = i;
endIdx = startIdx;
}
} else {
if (headerRows > 1) {
mergeRegion(sheet, 0, 1, i, i);
}
if (preMergeName != null) {
mergeRegion(sheet, 0, 0, startIdx, endIdx);
preMergeName = null;
}
}
// 处理最后一次循环
if (i == field.length -1) {
if (preMergeName != null) {
mergeRegion(sheet, 0, 0, startIdx, endIdx);
}
}
}
}
/**
* 计算表头需要占用的行数
* @param fields 导出字段
* @return 表头需要占用的行数
*/
private static int calculateHeaderRows(String fields) {
int rowMax = 0;
int rowCount = 0;
char[] chars = fields.toCharArray();
for (char c : chars) {
if (c == '|') {
rowCount ++;
} else if (c == ',') {
if (rowCount > rowMax) {
rowMax = rowCount;
}
rowCount = 0;
}
}
return rowMax;
}
/**
* 填充数据
* @param workbook workbook文档
* @param sheet sheet页
* @param cellStyle 单元格样式
* @param data 待填充的数据
* @param fieldOrder 字段填充顺序
* @param headerRows 头部占的行数
*/
private static void fillData(Workbook workbook, Sheet sheet, CellStyle cellStyle, List<LinkedHashMap<String, Object>> data, Map<String, Integer> fieldOrder, int headerRows) {
for (int i = 0; i < data.size(); i++) {
Row row = sheet.createRow(headerRows + i);
LinkedHashMap<String, Object> linkedHashMap = data.get(i);
data.get(i).forEach((key, value) -> {
// 为了保证只导出 fields 中的字段,这里必须加这个判断
if (fieldOrder.get(key) != null) {
Cell cell = row.createCell(fieldOrder.get(key));
cell.setCellStyle(cellStyle);
if (value != null) {
if (value instanceof Image) {
setCellPicture(workbook, sheet, cell, (Image) value);
} else if(value instanceof BigDecimal){
BigDecimal decimal = (BigDecimal) value;
BigDecimal strippedValue = decimal.stripTrailingZeros();
//去掉小数点后零后的值
cell.setCellValue(strippedValue.toPlainString());
} else {
cell.setCellValue(String.valueOf(value));
}
} else {
cell.setCellValue("");
}
}
});
}
}
/**
* 设置单元格图片(图片是悬浮的)
* @param workbook workbook文档
* @param sheet sheet页
* @param cell 单元格
* @param image 图片
*/
private static void setCellPicture(Workbook workbook, Sheet sheet, Cell cell, Image image) {
int rowIndex = cell.getRowIndex();
int columnIndex = cell.getColumnIndex();
// 绘图对象
Drawing<?> patriarch = sheet.createDrawingPatriarch();
// 创建锚点
XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, columnIndex, rowIndex, columnIndex + 1, rowIndex + 1);
patriarch.createPicture(anchor, workbook.addPicture(image.getImageData(), XSSFWorkbook.PICTURE_TYPE_JPEG));
}
/**
* 得到字段的行索引
* @param fields 字段
* @return 字段索引map
*/
private static Map<String, Integer> getFieldOrder(String fields) {
Map<String, Integer> fieldOrder = new HashMap<>(16);
String[] field = fields.split(",");
for (int i = 0; i < field.length; ++i) {
String[] f = field[i].split("\\|");
fieldOrder.put(f[0], i);
}
return fieldOrder;
}
/**
* 创建自定义单元格样式
* @param workbook 工作簿
*/
private static CellStyle createCellStyle(Workbook workbook) {
// 为单元格设置边框线
CellStyle cellStyle = workbook.createCellStyle();
cellStyle.setBorderTop(BorderStyle.THIN);
cellStyle.setBorderBottom(BorderStyle.THIN);
cellStyle.setBorderLeft(BorderStyle.THIN);
cellStyle.setBorderRight(BorderStyle.THIN);
// 居中显示
cellStyle.setAlignment(HorizontalAlignment.CENTER);
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
// 设置单元格样式为文本格式
DataFormat format = workbook.createDataFormat();
cellStyle.setDataFormat(format.getFormat("@"));
return cellStyle;
}
/**
* 合并区域
* @param sheet sheet页
* @param firstRow 起始行
* @param lastRow 结束行
* @param firstCol 起始列
* @param lastCol 结束列
*/
private static void mergeRegion(Sheet sheet,int firstRow, int lastRow, int firstCol, int lastCol) {
if (firstRow == lastRow && firstCol == lastCol) {
return;
}
CellRangeAddress cra = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol);
sheet.addMergedRegion(cra);
// 为合并后的单元格添加边框线
RegionUtil.setBorderTop(BorderStyle.THIN, cra, sheet);
RegionUtil.setBorderBottom(BorderStyle.THIN, cra, sheet);
RegionUtil.setBorderLeft(BorderStyle.THIN, cra, sheet);
RegionUtil.setBorderRight(BorderStyle.THIN, cra, sheet);
}
/**
* 转换时间格式
* @param data 导出数据
* @param formatter 转换格式 formatter
*/
private static void convertDateToStr(List<LinkedHashMap<String, Object>> data, String formatter) {
for (LinkedHashMap<String, Object> datum : data) {
for (Map.Entry<String, Object> stringObjectEntry : datum.entrySet()) {
String key = stringObjectEntry.getKey();
Object value = stringObjectEntry.getValue();
if (value != null) {
if (value instanceof Date) {
datum.put(key, DateFormatUtils.format((Date) value, formatter));
} else if (value instanceof LocalDateTime) {
datum.put(key, ((LocalDateTime) value).format(DateTimeFormatter.ofPattern(formatter)));
}
}
}
}
}
/**
* 集合对象转集合map
* @param tList
* @return
*/
public static List<LinkedHashMap<String, Object>> listObjToListMap(List tList){
List<LinkedHashMap<String, Object>> mapList = new ArrayList<>();
tList.forEach(obj -> {
ObjectMapper mapper = new ObjectMapper();
LinkedHashMap personMap = mapper.convertValue(obj, LinkedHashMap.class);
mapList.add(personMap);
});
return mapList;
}
public void exportTest(HttpServletResponse response) {
List< Object> mapList = new ArrayList<>();
String exportFields = "date|时间,firstHeader|表头1,secondHeader|表头2," +
"sub001|编号-0001|子标题1,sub002|编号-0001|子标题2,sub003|编号-0001|子标题3,sub004|编号-0001|子标题4,remark|备注";
ExcelUtils.export(response, "导出的文件名", mapList, exportFields, "yyyy-MM-dd HH:mm", false);
}
}
@@ -0,0 +1,81 @@
package org.jeecg.payment.utils;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.List;
/**
* 通用数值字段求和工具类
* 支持对任意对象列表中的BigDecimal类型字段进行累加求和
* 返回与列表元素类型相同的汇总对象
*/
public class GenericSumUtil {
/**
* 对列表中所有对象的BigDecimal类型字段进行求和
* @param list 待求和的对象列表
* @param clazz 列表元素的类类型
* @param <T> 泛型类型
* @return 汇总后的对象(与列表元素同类型,非数值字段保留默认值)
*/
public static <T> T sumList(List<T> list, Class<T> clazz) {
// 处理空列表
if (CollectionUtils.isEmpty(list)) {
return createEmptySumObject(clazz);
}
try {
// 创建汇总结果对象
T result = clazz.getDeclaredConstructor().newInstance();
// 获取所有BigDecimal类型的字段
Field[] fields = clazz.getDeclaredFields();
// 遍历每个字段,对列表中所有对象的该字段进行累加
for (Field field : fields) {
// 只处理BigDecimal类型的字段
if (field.getType() == BigDecimal.class) {
field.setAccessible(true); // 允许访问私有字段
// 累加所有对象的该字段值
BigDecimal sum = BigDecimal.ZERO;
for (T item : list) {
BigDecimal value = (BigDecimal) field.get(item);
sum = sum.add(value != null ? value : BigDecimal.ZERO);
}
// 将累加结果设置到汇总对象
field.set(result, sum);
}
}
return result;
} catch (Exception e) {
throw new RuntimeException("对象求和失败: " + e.getMessage(), e);
}
}
/**
* 创建空列表的默认汇总对象(所有BigDecimal字段设为0
*/
private static <T> T createEmptySumObject(Class<T> clazz) {
try {
T result = clazz.getDeclaredConstructor().newInstance();
// 获取所有BigDecimal类型的字段并设置为0
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.getType() == BigDecimal.class) {
field.setAccessible(true);
field.set(result, BigDecimal.ZERO);
}
}
return result;
} catch (Exception e) {
throw new RuntimeException("创建空汇总对象失败: " + e.getMessage(), e);
}
}
}
@@ -0,0 +1,79 @@
package org.jeecg.payment.utils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
public class MealGroupingUtil {
// 定义默认餐次时间范围的常量(开始时间,结束时间,餐次名称)
private static final List<TimeRange> DEFAULT_MEAL_TIMES;
private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss");
static {
// 初始化默认餐次时间范围
DEFAULT_MEAL_TIMES = new ArrayList<>();
try {
DEFAULT_MEAL_TIMES.add(new TimeRange(TIME_FORMAT.parse("06:00:00"), TIME_FORMAT.parse("09:30:00"), "早餐"));
DEFAULT_MEAL_TIMES.add(new TimeRange(TIME_FORMAT.parse("09:31:00"), TIME_FORMAT.parse("14:30:00"), "午餐"));
DEFAULT_MEAL_TIMES.add(new TimeRange(TIME_FORMAT.parse("14:31:00"), TIME_FORMAT.parse("20:00:00"), "晚餐"));
DEFAULT_MEAL_TIMES.add(new TimeRange(TIME_FORMAT.parse("20:01:00"), TIME_FORMAT.parse("05:59:00"), "加餐"));
} catch (ParseException e) {
throw new RuntimeException("初始化默认餐次时间失败", e);
}
}
// 时间范围内部类
private static class TimeRange {
Date startTime;
Date endTime;
String mealType;
TimeRange(Date startTime, Date endTime, String mealType) {
this.startTime = startTime;
this.endTime = endTime;
this.mealType = mealType;
}
}
/**
* 精确到秒的餐次判断,确保时间区间比较准确
*/
public static String getDefaultMealType(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int totalSeconds = calendar.get(Calendar.HOUR_OF_DAY) * 3600
+ calendar.get(Calendar.MINUTE) * 60
+ calendar.get(Calendar.SECOND);
for (TimeRange range : DEFAULT_MEAL_TIMES) {
int startSeconds = timeToSeconds(range.startTime);
int endSeconds = timeToSeconds(range.endTime);
if ("加餐".equals(range.mealType)) {
if (totalSeconds >= startSeconds || totalSeconds <= endSeconds) {
return range.mealType;
}
} else {
// 正常时间范围:开始秒数 <= 当前秒数 <= 结束秒数
if (totalSeconds >= startSeconds && totalSeconds <= endSeconds) {
return range.mealType;
}
}
}
return "未知餐次";
}
/**
* 将时间转换为当天的总秒数(0-86399),消除日期影响
*/
private static int timeToSeconds(Date time) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(time);
return calendar.get(Calendar.HOUR_OF_DAY) * 3600
+ calendar.get(Calendar.MINUTE) * 60
+ calendar.get(Calendar.SECOND);
}
}
@@ -0,0 +1,88 @@
package org.jeecg.restaurant.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.aspect.SendNotification;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.restaurant.entity.SlBaseRestaurant;
import org.jeecg.restaurant.mapper.SlBaseRestaurantMapper;
import org.jeecg.restaurant.service.ISlBaseDinnerTimeService;
import org.jeecg.restaurant.service.ISlBaseRestaurantService;
import org.jeecg.restaurant.vo.SlBaseRestaurantVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* @Description: 食堂基本信息
* @Author: jeecg-boot
* @Date: 2022-03-16
* @Version: V1.0
*/
@Tag(name = "食堂基本信息")
@RestController
@RequestMapping("/restaurant/slBaseRestaurant")
@Slf4j
public class SlBaseRestaurantController extends JeecgController<SlBaseRestaurant, ISlBaseRestaurantService> {
@Autowired
private ISlBaseRestaurantService slBaseRestaurantService;
/**
* 编辑
*
* @param slBaseRestaurant
* @return
*/
@AutoLog(value = "编辑")
@Operation(summary = "编辑", description= "编辑")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
@SendNotification()
public Result<String> edit(@RequestBody SlBaseRestaurant slBaseRestaurant) {
slBaseRestaurant.setIsSync(0);
slBaseRestaurantService.updateById(slBaseRestaurant);
return Result.OK("编辑成功!");
}
/**
* 通过id查询
*
* @param id
* @return
*/
//@AutoLog(value = "通过id查询")
@Operation(summary = "通过id查询", description= "通过id查询")
@GetMapping(value = "/queryById")
public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
return slBaseRestaurantService.queryById(id);
}
/**
* 添加
*
* @param slBaseRestaurant
* @return
*/
@AutoLog(value = "添加或修改")
@Operation(summary = "添加或修改", description= "添加或修改")
@PostMapping(value = "/addOrEdit")
@SendNotification()
public Result<String> addOrEdit(@RequestBody SlBaseRestaurantVo slBaseRestaurant) {
return slBaseRestaurantService.addOrEdit(slBaseRestaurant);
}
}
@@ -0,0 +1,59 @@
package org.jeecg.restaurant.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.ScreenVo;
import org.jeecg.restaurant.entity.SlBaseRestaurant;
import org.jeecg.restaurant.service.ISlBaseRestaurantService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
* @Description: s
* @Author: yucl
* @Date: 2022-04-20
* @Version: V1.0
*/
@Slf4j
@Tag(name = "食堂部门")
@RestController
@RequestMapping("/restaurant/stBaseRestaurantDept")
public class StBaseRestaurantDeptController {
@Autowired
private ISlBaseRestaurantService slBaseRestaurantService;
//@AutoLog(value = "食堂id")
@Operation(summary = "获得食堂数据", description= "获得食堂数据")
@GetMapping(value = "/getRestaurantList")
public Result<?> getRestaurantList() {
LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
List<ScreenVo> list = user.getCanteenIdList();
if(CollectionUtils.isNotEmpty(list)){
return Result.OK(list);
} else {//解决管理员(医生)角色,查看 营养监控 没有食堂列表问题
List<ScreenVo> screenVoArrayList = new ArrayList<>();
List<SlBaseRestaurant> slBaseRestaurantList = slBaseRestaurantService.list();
if(CollectionUtils.isNotEmpty(slBaseRestaurantList)){
slBaseRestaurantList.forEach(slBaseRestaurant -> {
if(!"0".equals(slBaseRestaurant.getId())){
ScreenVo screenVo = new ScreenVo();
screenVo.setId(slBaseRestaurant.getId());
screenVo.setRestName(slBaseRestaurant.getRestName());
screenVoArrayList.add(screenVo);
}
});
}
return Result.OK(screenVoArrayList);
}
}
}
@@ -0,0 +1,14 @@
package org.jeecg.restaurant.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.restaurant.entity.SlBaseDinnerTime;
/**
* @Description: 食堂餐次定义
* @Author: jeecg-boot
* @Date: 2022-03-17
* @Version: V1.0
*/
public interface SlBaseDinnerTimeMapper extends BaseMapper<SlBaseDinnerTime> {
}
@@ -0,0 +1,25 @@
package org.jeecg.restaurant.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.jeecg.common.system.vo.ScreenVo;
import org.jeecg.restaurant.entity.SlBaseRestaurant;
import org.jeecg.restaurant.vo.SlBaseRestaurantVo;
import java.util.List;
import java.util.Map;
/**
* @Description: 食堂基本信息
* @Author: jeecg-boot
* @Date: 2022-03-16
* @Version: V1.0
*/
public interface SlBaseRestaurantMapper extends BaseMapper<SlBaseRestaurant> {
List<SlBaseRestaurantVo> queryById(@Param("canteenId") String canteenId);
}
@@ -0,0 +1,7 @@
<?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="org.jeecg.restaurant.mapper.SlBaseDinnerTimeMapper">
</mapper>
@@ -0,0 +1,25 @@
<?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="org.jeecg.restaurant.mapper.SlBaseRestaurantMapper">
<select id="queryById" resultType="org.jeecg.restaurant.vo.SlBaseRestaurantVo">
SELECT
DISTINCT
br.*,
d.depart_name restDepartName,
u.username
FROM
st_base_restaurant br
left join sys_user_screen us on br.id = us.screen_id
left join sys_user u on us.user_id = u.id
left join sys_depart d on br.rest_depart = d.id
WHERE
1 = 1
and br.id = #{canteenId}
and u.user_identity = '4'
group by br.id,
u.username
</select>
</mapper>
@@ -0,0 +1,19 @@
package org.jeecg.restaurant.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.restaurant.entity.SlBaseDinnerTime;
import java.util.Date;
/**
* @Description: 食堂餐次定义
* @Author: jeecg-boot
* @Date: 2022-03-17
* @Version: V1.0
*/
public interface ISlBaseDinnerTimeService extends IService<SlBaseDinnerTime> {
SlBaseDinnerTime getCanteenDinnerType(String canteenId, Date dataTime);
SlBaseDinnerTime getCanteenDinnerType(String canteenId);
}
@@ -0,0 +1,27 @@
package org.jeecg.restaurant.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.ScreenVo;
import org.jeecg.restaurant.entity.SlBaseRestaurant;
import org.jeecg.restaurant.vo.*;
import java.util.List;
import java.util.Map;
/**
* @Description: 食堂基本信息
* @Author: jeecg-boot
* @Date: 2022-03-16
* @Version: V1.0
*/
public interface ISlBaseRestaurantService extends IService<SlBaseRestaurant> {
Result<?> queryById(String canteenId);
Result<String> addOrEdit(SlBaseRestaurantVo slBaseRestaurant);
}
@@ -0,0 +1,64 @@
package org.jeecg.restaurant.service.impl;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.collections.CollectionUtils;
import org.jeecg.common.util.DateUtils;
import org.jeecg.restaurant.entity.SlBaseDinnerTime;
import org.jeecg.restaurant.mapper.SlBaseDinnerTimeMapper;
import org.jeecg.restaurant.service.ISlBaseDinnerTimeService;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
/**
* @Description: 食堂餐次定义
* @Author: jeecg-boot
* @Date: 2022-03-17
* @Version: V1.0
*/
@Service
public class SlBaseDinnerTimeServiceImpl extends ServiceImpl<SlBaseDinnerTimeMapper, SlBaseDinnerTime> implements ISlBaseDinnerTimeService {
@Override
public SlBaseDinnerTime getCanteenDinnerType(String canteenId,Date dataTime) {
List<SlBaseDinnerTime> list = this.list(new LambdaQueryWrapper<SlBaseDinnerTime>()
.eq(SlBaseDinnerTime::getRestId, canteenId)
.orderByAsc(SlBaseDinnerTime::getEndTime));
if (CollectionUtils.isNotEmpty(list)) {
for (SlBaseDinnerTime slBaseDinnerTime : list) {
DateTime endTime = DateUtil.parse(DateUtil.today() + " " + slBaseDinnerTime.getEndTime());
Date date = new Date();
if(null != dataTime){
endTime = DateUtil.parse(DateUtils.formatDate(dataTime,"yyyy-MM-dd") + " " + slBaseDinnerTime.getEndTime());
date = dataTime;
}
if (DateUtil.compare(date, endTime) <= 0) {
return slBaseDinnerTime;
}
}
return list.get(list.size() - 1);
}
return null;
}
@Override
public SlBaseDinnerTime getCanteenDinnerType(String canteenId) {
List<SlBaseDinnerTime> list = this.list(new LambdaQueryWrapper<SlBaseDinnerTime>()
.eq(SlBaseDinnerTime::getRestId, canteenId)
.orderByAsc(SlBaseDinnerTime::getEndTime));
if (CollectionUtils.isNotEmpty(list)) {
for (SlBaseDinnerTime slBaseDinnerTime : list) {
DateTime endTime = DateUtil.parse(DateUtil.today() + " " + slBaseDinnerTime.getEndTime());
if (DateUtil.compare(new Date(), endTime) <= 0) {
return slBaseDinnerTime;
}
}
return list.get(list.size() - 1);
}
return null;
}
}
@@ -0,0 +1,104 @@
package org.jeecg.restaurant.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.ScreenVo;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.PasswordUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.restaurant.entity.SlBaseDinnerTime;
import org.jeecg.restaurant.entity.SlBaseRestaurant;
import org.jeecg.restaurant.mapper.SlBaseRestaurantMapper;
import org.jeecg.restaurant.service.ISlBaseDinnerTimeService;
import org.jeecg.restaurant.service.ISlBaseRestaurantService;
import org.jeecg.restaurant.vo.SlBaseRestaurantVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
/**
* @Description: 食堂基本信息
* @Author: jeecg-boot
* @Date: 2022-03-16
* @Version: V1.0
*/
@Service
@Slf4j
public class SlBaseRestaurantServiceImpl extends ServiceImpl<SlBaseRestaurantMapper, SlBaseRestaurant> implements ISlBaseRestaurantService {
@Autowired
private ISlBaseDinnerTimeService stBaseDinnerTimeService;
@Resource
private SlBaseRestaurantMapper stBaseRestaurantMapper;
@Autowired
private RedisUtil redisUtil;
@Override
public Result<?> queryById(String canteenId) {
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
if (sysUser.getUserIdentity().equals(CommonConstant.USER_IDENTITY_4) || sysUser.getUserIdentity().equals(CommonConstant.USER_IDENTITY_5)) {
canteenId = sysUser.getCanteenId();
}
List<SlBaseRestaurantVo> slBaseRestaurantVoList = stBaseRestaurantMapper.queryById(canteenId);
SlBaseRestaurantVo slBaseRestaurantVo = new SlBaseRestaurantVo();
if (CollectionUtil.isNotEmpty(slBaseRestaurantVoList)) {
slBaseRestaurantVo = slBaseRestaurantVoList.get(0);
}
List<SlBaseDinnerTime> dinnerTimeList = stBaseDinnerTimeService.list(new LambdaQueryWrapper<SlBaseDinnerTime>().eq(SlBaseDinnerTime::getRestId, canteenId));
if (CollectionUtils.isEmpty(dinnerTimeList)) {
List<String> dinnerTypeList = Arrays.asList("早餐", "午餐", "晚餐", "加餐");
for (String dinnerType : dinnerTypeList) {
SlBaseDinnerTime dinnerTime = new SlBaseDinnerTime();
dinnerTime.setStartTime("");
dinnerTime.setDinnerType(dinnerType);
dinnerTime.setEndTime("");
dinnerTime.setRestId(canteenId);
dinnerTimeList.add(dinnerTime);
}
}
slBaseRestaurantVo.setSlBaseDinnerTimeList(dinnerTimeList);
return Result.OK(slBaseRestaurantVo);
}
@Override
public Result<String> addOrEdit(SlBaseRestaurantVo restaurantVo) {
if (restaurantVo.getId() != null) {
restaurantVo.setIsSync(0);
this.updateById(restaurantVo);
// List<SlBaseDinnerTime> slBaseDinnerTimeList = stBaseDinnerTimeService.list(new LambdaQueryWrapper<SlBaseDinnerTime>().eq(SlBaseDinnerTime::getRestId, restaurantVo.getId()));
//删除对应的餐次定义
stBaseDinnerTimeService.remove(new LambdaQueryWrapper<SlBaseDinnerTime>().eq(SlBaseDinnerTime::getRestId, restaurantVo.getId()));
}
//餐次定义
if (CollectionUtils.isNotEmpty(restaurantVo.getSlBaseDinnerTimeList())) {
for (SlBaseDinnerTime slBaseDinnerTime : restaurantVo.getSlBaseDinnerTimeList()) {
slBaseDinnerTime.setId(null);
slBaseDinnerTime.setRestId(restaurantVo.getId());
slBaseDinnerTime.setIsSync(0);
stBaseDinnerTimeService.save(slBaseDinnerTime);
}
}
return Result.OK("操作成功!");
}
}
@@ -0,0 +1,517 @@
package org.jeecg.system.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xkcoding.http.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLDecoder;
import java.net.URLEncoder;
/**
* <p>
* 用户表 前端控制器
* </p>
*
* @Author scott
* @since 2018-12-20
*/
@Slf4j
@RestController
@RequestMapping("/sys/common")
public class CommonController {
/**
* 文件上传根目录 设置(这里设置的路径要和file-server.application-dev.yml的file.path保持一致)
* @return
*/
@Value(value = "${jeecg.path.upload}")
private String uploadpath;
/**
* 本地:local miniominio 阿里:alioss
*/
@Value(value="${jeecg.uploadType}")
private String uploadType;
/**
* 服务部署的外网ip端口、域名地址:用于下载
*/
@Value(value="${jeecg.serverPublicIp.ip}")
private String serverPublicIp;
/**
* @Author 政辉
* @return
*/
@GetMapping("/403")
public Result<?> noauth() {
return Result.error("没有权限,请联系管理员授权");
}
/**
* 文件上传统一方法
* @param request
* @param response
* @return
*/
@PostMapping(value = "/upload")
public Result<?> upload(HttpServletRequest request, HttpServletResponse response) {
Result<?> result = new Result<>();
String savePath = "";
String bizPath = request.getParameter("biz");
boolean needThumbnailFlag = true;//默认改成需要上传缩略图
// if (request.getParameter("needThumbnail") != null && request.getParameter("needThumbnail").equals("1")){
// needThumbnailFlag = true;
// }
//LOWCOD-2580 sys/common/upload接口存在任意文件上传漏洞
if (oConvertUtils.isNotEmpty(bizPath) && (bizPath.contains("../") || bizPath.contains("..\\"))) {
throw new JeecgBootException("上传目录bizPath,格式非法!");
}
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
MultipartFile file = multipartRequest.getFile("file");// 获取上传文件对象
if(request.getParameter("faceFile") != null && "1".equals(request.getParameter("faceFile")) && file != null){//加参数 faceFile = 1 表示人脸图片上传场景
long fileSize = file.getSize(); // 获取文件大小
// 设定上传文件的最大大小,例如1MB
long maxSize = 2;
long size = 1024 * 1024;
long maxSizeValue = maxSize * size;
if (fileSize > maxSizeValue) {
String msg = "文件超过了允许的"+maxSize+ "M大小限制。";
System.out.println(msg);
result.setMessage(msg);
result.setSuccess(false);
return result;
}
}
if(oConvertUtils.isEmpty(bizPath)){
if(CommonConstant.UPLOAD_TYPE_OSS.equals(uploadType)){
//未指定目录,则用阿里云默认目录 upload
bizPath = "upload";
//result.setMessage("使用阿里云文件上传时,必须添加目录!");
//result.setSuccess(false);
//return result;
}else{
bizPath = "";
}
}
if(CommonConstant.UPLOAD_TYPE_LOCAL.equals(uploadType)){
//update-begin-author:lvdandan date:20200928 for:修改JEditor编辑器本地上传
try {
String fileName = file.getOriginalFilename();// 获取文件名
savePath = LocalUploadUtil.uploadLocal(file.getInputStream(), bizPath, fileName);
// savePath = this.uploadLocal(file,bizPath);
}catch (Exception e){
e.printStackTrace();
}
}else{
//update-begin-author:taoyan date:20200814 for:文件上传改造
savePath = CommonUtils.upload(file, bizPath, uploadType, needThumbnailFlag);
//update-end-author:taoyan date:20200814 for:文件上传改造
}
if(oConvertUtils.isNotEmpty(savePath)){
return Result.OK(savePath,FileShowUtil.getShowUrl(savePath));
}else {
result.setMessage("上传失败!");
result.setSuccess(false);
}
return result;
}
// public String getShowUrl(String path) {
// if (StringUtil.isEmpty(path)) {
// return serverPublicIp+"/sys/common/static/default.png";
// }
// if(path.contains("https")){
// return path;
// }
// path = path.replaceAll("\\\\","/");
// return serverPublicIp+"/sys/common/static/static/" + path;
// }
/**
* 文件上传统一方法(上传文件 固定目录 带缩略图(同名覆盖))
*
* @return
*/
@PostMapping(value = "/upload/fixedDirectory")
public Result<?> uploadFixedDirectory(HttpServletRequest request, HttpServletResponse response) {
Result<?> result = new Result<>();
String savePath = "";
String bizPath = request.getParameter("biz");
boolean needThumbnailFlag = true;//默认改成需要上传缩略图
//LOWCOD-2580 sys/common/upload接口存在任意文件上传漏洞
if (oConvertUtils.isNotEmpty(bizPath) && (bizPath.contains("../") || bizPath.contains("..\\"))) {
throw new JeecgBootException("上传目录bizPath,格式非法!");
}
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
MultipartFile file = multipartRequest.getFile("file");// 获取上传文件对象
if(request.getParameter("faceFile") != null && "1".equals(request.getParameter("faceFile")) && file != null){//加参数 faceFile = 1 表示人脸图片上传场景
long fileSize = file.getSize(); // 获取文件大小
// 设定上传文件的最大大小,例如1MB
long maxSize = 2;
long size = 1024 * 1024;
long maxSizeValue = maxSize * size;
if (fileSize > maxSizeValue) {
String msg = "文件超过了允许的"+maxSize+ "M大小限制。";
System.out.println(msg);
result.setMessage(msg);
result.setSuccess(false);
return result;
}
}
if(oConvertUtils.isEmpty(bizPath)){
if(CommonConstant.UPLOAD_TYPE_OSS.equals(uploadType)){
//未指定目录,则用阿里云默认目录 upload
bizPath = "upload";
//result.setMessage("使用阿里云文件上传时,必须添加目录!");
//result.setSuccess(false);
//return result;
}else{
bizPath = "";
}
}
if(CommonConstant.UPLOAD_TYPE_LOCAL.equals(uploadType)){
//update-begin-author:lvdandan date:20200928 for:修改JEditor编辑器本地上传
savePath = this.uploadLocal(file,bizPath);
//update-begin-author:lvdandan date:20200928 for:修改JEditor编辑器本地上传
/** 富文本编辑器及markdown本地上传时,采用返回链接方式
//针对jeditor编辑器如何使 lcaol模式,采用 base64格式存储
String jeditor = request.getParameter("jeditor");
if(oConvertUtils.isNotEmpty(jeditor)){
result.setMessage(CommonConstant.UPLOAD_TYPE_LOCAL);
result.setSuccess(true);
return result;
}else{
savePath = this.uploadLocal(file,bizPath);
}
*/
}else{
//update-begin-author:taoyan date:20200814 for:文件上传改造
savePath = CommonUtils.uploadFixedDirectory(file, bizPath, uploadType, needThumbnailFlag);
//update-end-author:taoyan date:20200814 for:文件上传改造
}
if(oConvertUtils.isNotEmpty(savePath)){
return Result.OK(savePath,FileShowUtil.getShowUrl(savePath));
}else {
result.setMessage("上传失败!");
result.setSuccess(false);
}
return result;
}
/**
* 本地文件上传
* @param mf 文件
* @param bizPath 自定义路径
* @return
*/
private String uploadLocal(MultipartFile mf,String bizPath){
try {
String ctxPath = uploadpath;
String fileName = null;
//解决路径遍历漏洞-路径:高危
// File file = new File(ctxPath + File.separator + bizPath + File.separator );
String paths = ctxPath + File.separator + bizPath + File.separator;
String pathNew= FilenameUtils.getFullPath(paths);// 输出: C:\Users\Example\Documents\
System.out.println(pathNew);
File file = new File(XssUtils.checkTraversal(pathNew));
if (!file.exists()) {
file.mkdirs();// 创建文件根目录
}
String orgName = mf.getOriginalFilename();// 获取文件名
orgName = CommonUtils.getFileName(orgName);
if(orgName.indexOf(".")!=-1){
fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.lastIndexOf("."));
}else{
fileName = orgName+ "_" + System.currentTimeMillis();
}
//解决路径遍历漏洞-路径:高危
// String savePath = file.getPath() + File.separator + fileName;
fileName = FilenameUtils.getName(fileName);//// 输出: file.txt
String normalized = pathNew.replace("\\", "/");
String path = XssUtils.checkTraversal(normalized);
String savePath = path + fileName;
File savefile = new File(savePath);
FileCopyUtils.copy(mf.getBytes(), savefile);
String dbpath = null;
if(oConvertUtils.isNotEmpty(bizPath)){
dbpath = bizPath + File.separator + fileName;
}else{
dbpath = fileName;
}
if (dbpath.contains("\\")) {
dbpath = dbpath.replace("\\", "/");
}
return dbpath;
} catch (IOException e) {
log.error(e.getMessage(), e);
}
return "";
}
// @PostMapping(value = "/upload2")
// public Result<?> upload2(HttpServletRequest request, HttpServletResponse response) {
// Result<?> result = new Result<>();
// try {
// String ctxPath = uploadpath;
// String fileName = null;
// String bizPath = "files";
// String tempBizPath = request.getParameter("biz");
// if(oConvertUtils.isNotEmpty(tempBizPath)){
// bizPath = tempBizPath;
// }
// String nowday = new SimpleDateFormat("yyyyMMdd").format(new Date());
// File file = new File(ctxPath + File.separator + bizPath + File.separator + nowday);
// if (!file.exists()) {
// file.mkdirs();// 创建文件根目录
// }
// MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
// MultipartFile mf = multipartRequest.getFile("file");// 获取上传文件对象
// String orgName = mf.getOriginalFilename();// 获取文件名
// fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.indexOf("."));
// String savePath = file.getPath() + File.separator + fileName;
// File savefile = new File(savePath);
// FileCopyUtils.copy(mf.getBytes(), savefile);
// String dbpath = bizPath + File.separator + nowday + File.separator + fileName;
// if (dbpath.contains("\\")) {
// dbpath = dbpath.replace("\\", "/");
// }
// result.setMessage(dbpath);
// result.setSuccess(true);
// } catch (IOException e) {
// result.setSuccess(false);
// result.setMessage(e.getMessage());
// log.error(e.getMessage(), e);
// }
// return result;
// }
/**
* 预览图片&下载文件
* 请求地址:http://localhost:8080/common/static/{user/20190119/e1fe9925bc315c60addea1b98eb1cb1349547719_1547866868179.jpg}
*
* @param request
* @param response
*/
@GetMapping(value = "/static/**")
public void view(HttpServletRequest request, HttpServletResponse response) {
// ISO-8859-1 ==> UTF-8 进行编码转换
String imgPath = extractPathFromPattern(request);
if(oConvertUtils.isEmpty(imgPath) || imgPath=="null"){
return;
}
// 其余处理略
InputStream inputStream = null;
OutputStream outputStream = null;
try {
imgPath = imgPath.replace("..", "").replace("../","");
if (imgPath.endsWith(",")) {
imgPath = imgPath.substring(0, imgPath.length() - 1);
}
String path = uploadpath + File.separator + imgPath;
//解决路径遍历漏洞-路径:高危
String filePath = FilenameUtils.getFullPath(path);
File file = new File(XssUtils.checkTraversal(filePath));
if(!file.exists()){
response.setStatus(404);
throw new RuntimeException("文件["+imgPath+"]不存在..");
}
response.setContentType("application/force-download");// 设置强制下载不打开
//代码注入-HTTP响应截断:中危
String fileName = URLEncoder.encode(file.getName(), "UTF-8");
response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
// response.addHeader("Content-Disposition", "attachment;fileName=" + new String(file.getName().getBytes("UTF-8"),"iso-8859-1"));
inputStream = new BufferedInputStream(new FileInputStream(filePath));
outputStream = response.getOutputStream();
byte[] buf = new byte[1024];
int len;
while ((len = inputStream.read(buf)) > 0) {
outputStream.write(buf, 0, len);
}
response.flushBuffer();
} catch (IOException e) {
log.error("预览文件失败" + e.getMessage());
response.setStatus(404);
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
}
}
// /**
// * 下载文件
// * 请求地址:http://localhost:8080/common/download/{user/20190119/e1fe9925bc315c60addea1b98eb1cb1349547719_1547866868179.jpg}
// *
// * @param request
// * @param response
// * @throws Exception
// */
// @GetMapping(value = "/download/**")
// public void download(HttpServletRequest request, HttpServletResponse response) throws Exception {
// // ISO-8859-1 ==> UTF-8 进行编码转换
// String filePath = extractPathFromPattern(request);
// // 其余处理略
// InputStream inputStream = null;
// OutputStream outputStream = null;
// try {
// filePath = filePath.replace("..", "");
// if (filePath.endsWith(",")) {
// filePath = filePath.substring(0, filePath.length() - 1);
// }
// String localPath = uploadpath;
// String downloadFilePath = localPath + File.separator + filePath;
// File file = new File(downloadFilePath);
// if (file.exists()) {
// response.setContentType("application/force-download");// 设置强制下载不打开            
// response.addHeader("Content-Disposition", "attachment;fileName=" + new String(file.getName().getBytes("UTF-8"),"iso-8859-1"));
// inputStream = new BufferedInputStream(new FileInputStream(file));
// outputStream = response.getOutputStream();
// byte[] buf = new byte[1024];
// int len;
// while ((len = inputStream.read(buf)) > 0) {
// outputStream.write(buf, 0, len);
// }
// response.flushBuffer();
// }
//
// } catch (Exception e) {
// log.info("文件下载失败" + e.getMessage());
// // e.printStackTrace();
// } finally {
// if (inputStream != null) {
// try {
// inputStream.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
// if (outputStream != null) {
// try {
// outputStream.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
// }
//
// }
/**
* @功能:pdf预览Iframe
* @param modelAndView
* @return
*/
@RequestMapping("/pdf/pdfPreviewIframe")
public ModelAndView pdfPreviewIframe(ModelAndView modelAndView) {
modelAndView.setViewName("pdfPreviewIframe");
return modelAndView;
}
/**
* 把指定URL后的字符串全部截断当成参数
* 这么做是为了防止URL中包含中文或者特殊字符(/等)时,匹配不了的问题
* @param request
* @return
*/
private static String extractPathFromPattern(final HttpServletRequest request) {
String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
String bestMatchPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
return new AntPathMatcher().extractPathWithinPattern(bestMatchPattern, path);
}
/**
* 中转HTTP请求,解决跨域问题
*
* @param url 必填:请求地址
* @return
*/
@RequestMapping("/transitRESTful")
public Result transitRESTful(@RequestParam("url") String url, HttpServletRequest request) {
try {
ServletServerHttpRequest httpRequest = new ServletServerHttpRequest(request);
// 中转请求method、body
HttpMethod method = httpRequest.getMethod();
JSONObject params;
try {
params = JSON.parseObject(JSON.toJSONString(httpRequest.getBody()));
} catch (Exception e) {
params = new JSONObject();
}
// 中转请求问号参数
JSONObject variables = JSON.parseObject(JSON.toJSONString(request.getParameterMap()));
variables.remove("url");
// 在 headers 里传递Token
String token = TokenUtils.getTokenByRequest(request);
HttpHeaders headers = new HttpHeaders();
//代码注入-HTTP响应截断:中危
token = URLEncoder.encode(token, "UTF-8");
headers.set("X-Access-Token", token);
// 发送请求
String httpURL = URLDecoder.decode(url, "UTF-8");
ResponseEntity<String> response = RestUtil.request(httpURL, method, headers , variables, params, String.class);
// 封装返回结果
Result<Object> result = new Result<>();
int statusCode = response.getStatusCodeValue();
result.setCode(statusCode);
result.setSuccess(statusCode == 200);
String responseBody = response.getBody();
try {
// 尝试将返回结果转为JSON
Object json = JSON.parse(responseBody);
result.setResult(json);
} catch (Exception e) {
// 转成JSON失败,直接返回原始数据
result.setResult(responseBody);
}
return result;
} catch (Exception e) {
log.debug("中转HTTP请求失败", e);
return Result.error(e.getMessage());
}
}
}
@@ -0,0 +1,262 @@
package org.jeecg.system.controller;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.ScreenVo;
import org.jeecg.common.util.*;
import org.jeecg.modules.base.service.BaseCommonService;
import org.jeecg.system.dto.SysLoginModel;
import org.jeecg.system.service.ISysUserScreenService;
import org.jeecg.system.service.ISysUserService;
import org.jeecg.user.entity.SysUser;
import org.jeecg.user.entity.SysUserScreen;
import org.jeecg.user.vo.SysUserVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
/**
* @Author scott
* @since 2018-12-17
*/
@RestController
@RequestMapping("/sys")
@Tag(name = "用户登录")
@Slf4j
public class LoginController {
@Autowired
private ISysUserService sysUserService;
@Autowired
private RedisUtil redisUtil;
@Resource
private BaseCommonService baseCommonService;
@Resource
private ISysUserScreenService sysUserScreenService;
@Operation(summary="登录接口")
@RequestMapping(value = "/login", method = RequestMethod.POST)
public Result<JSONObject> login(@RequestBody SysLoginModel sysLoginModel) {
Result<JSONObject> result = new Result<JSONObject>();
String username = sysLoginModel.getUsername();
String password = sysLoginModel.getPassword();
//进行密码解密逻辑
if(StringUtils.isNotBlank(sysLoginModel.getTimes())){
String passwordEncode = sysLoginModel.getPassword();
String times = sysLoginModel.getTimes();
String passwordDecode = Base64Util.decode(passwordEncode);
password = passwordDecode.replace(times,"");
}
//update-begin-author:taoyan date:20190828 for:校验验证码
String captcha = sysLoginModel.getCaptcha();
if (captcha == null) {
result.error500("验证码无效");
return result;
}
String lowerCaseCaptcha = captcha.toLowerCase();
String realKey = MD5Util.MD5Encode(lowerCaseCaptcha + sysLoginModel.getCheckKey(), "utf-8");
Object checkCode = redisUtil.get(realKey);
//当进入登录页时,有一定几率出现验证码错误 #1714
if (checkCode == null || !checkCode.toString().equals(lowerCaseCaptcha)) {
log.warn("验证码错误,key= {} , Ui checkCode= {}, Redis checkCode = {}", sysLoginModel.getCheckKey(), lowerCaseCaptcha, checkCode);
result.error500("验证码错误");
return result;
}
//1. 校验用户是否有效
//update-begin-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug,if条件永远为false
LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysUser::getUsername, username);
// 2.username可能重复,所以查出来list挨个匹配
List<SysUser> sysUserList = new ArrayList<>();
SysUser sysUser = null;
if (StringUtils.equals(CommonConstant.SYSTEM_NAME, username)) {
sysUser = sysUserService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, "system"));
sysUserList.add(sysUser);
} else {
sysUserList = sysUserService.list(queryWrapper);
}
// 用户名或密码错误错误标记
boolean errorFlag = false;
boolean adminFlag = false;//员工(就餐人员))不能登录管理后台
if (CollectionUtils.isNotEmpty(sysUserList)) {
for (SysUser user : sysUserList) {
//3. 校验用户名或密码是否正确
String userpassword = PasswordUtil.encrypt(username, password, user.getSalt());
String syspassword = user.getPassword();
if (syspassword.equals(userpassword)) {
if (CommonConstant.USER_IDENTITY_6.equals(user.getUserIdentity())) {
adminFlag = true;
break;
}
errorFlag = true;
sysUser = user;
break;
}
}
}
if (adminFlag) {
result.error500("请使用管理员账号登录!");
return result;
}
if (!errorFlag) {
result.error500("用户名或密码错误");
return result;
}
// 登录增加校验,食堂管理员登录需判断是否还有关联食堂。
if (null != sysUser && null != sysUser.getUserIdentity() && CommonConstant.USER_IDENTITY_4.equals(sysUser.getUserIdentity())) {
//查找食堂id
SysUserScreen sysUserScreen = sysUserScreenService.getOne(new LambdaQueryWrapper<SysUserScreen>().eq(SysUserScreen::getUserId, sysUser.getId()));
if (ObjectUtils.isEmpty(sysUserScreen)) {
result.error500("请检查该账户对应的食堂是否存在");
return result;
}
}
//update-end-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug,if条件永远为false
result = sysUserService.checkUserIsEffective(sysUser);
if (!result.isSuccess()) {
return result;
}
//用户登录信息
userInfo(sysUser, result);
//update-begin--Author:liusq Date:20210126 for:登录成功,删除redis中的验证码
redisUtil.del(realKey);
//update-begin--Author:liusq Date:20210126 for:登录成功,删除redis中的验证码
LoginUser loginUser = new LoginUser();
BeanUtils.copyProperties(sysUser, loginUser);
loginUser.setSysOrgCode(sysUser.getSysOrgCode());
baseCommonService.addLog("用户名: " + username + ",登录成功!", CommonConstant.LOG_TYPE_1, null, loginUser);
//update-end--Author:wangshuai Date:20200714 for:登录日志没有记录人员
return result;
}
/**
* 用户信息
*
* @param sysUser
* @param result
* @return
*/
private Result<JSONObject> userInfo(SysUser sysUser, Result<JSONObject> result) {
String syspassword = sysUser.getPassword();
String userId = sysUser.getId();
// 生成token
String token = JwtUtil.sign(userId, syspassword);
// 设置token缓存有效时间
// redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + username, token);
//修改为hash方式存取
redisUtil.hset(CommonConstant.USER_TOKEN, CommonConstant.PREFIX_USER_TOKEN + userId, token, JwtUtil.EXPIRE_TIME);
JSONObject obj = new JSONObject();
// redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + username, JwtUtil.EXPIRE_TIME);
//登录就拿到用户的食堂数据
SysUserVo vo = new SysUserVo();
BeanUtils.copyProperties(sysUser, vo);
List<ScreenVo> screenVoList = sysUserService.listScreenByUser(sysUser);
if (CollectionUtil.isNotEmpty(screenVoList)) {
vo.setCanteenId(screenVoList.get(0).getId());
}
obj.put("token", token);
obj.put("userInfo", vo);
result.setResult(obj);
result.success("登录成功");
return result;
}
/**
* 后台生成图形验证码 :有效
*
* @param response
* @param key
*/
@Operation(summary="获取验证码")
@GetMapping(value = "/randomImage/{key}")
public Result<String> randomImage(HttpServletResponse response, @PathVariable String key) {
Result<String> res = new Result<String>();
try {
//生成验证码
final String BASE_CHECK_CODES = "qwertyuiplkjhgfdsazxcvbnmQWERTYUPLKJHGFDSAZXCVBNM1234567890";
String code = RandomUtil.randomString(BASE_CHECK_CODES, 4);
//存到redis中
String lowerCaseCode = code.toLowerCase();
String realKey = MD5Util.MD5Encode(lowerCaseCode + key, "utf-8");
log.info("获取验证码,Redis checkCode = {}key = {}", code, key);
redisUtil.set(realKey, lowerCaseCode, 60);
//返回前端
String base64 = RandImageUtil.generate(code);
// res.setSuccess(true);
// res.setResult(base64);
return Result.OK(base64);
} catch (Exception e) {
res.error500("获取验证码出错" + e.getMessage());
e.printStackTrace();
}
return res;
}
/**
* 退出登录
*
* @param request
* @param response
* @return
*/
@RequestMapping(value = "/logout")
public Result<Object> logout(HttpServletRequest request, HttpServletResponse response) {
//用户退出逻辑
String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
if (oConvertUtils.isEmpty(token)) {
return Result.error("退出登录失败!");
}
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
if (sysUser != null) {
//update-begin--Author:wangshuai Date:20200714 for:登出日志没有记录人员
baseCommonService.addLog("用户名: " + sysUser.getRealname() + ",退出成功!", CommonConstant.LOG_TYPE_1, null, sysUser);
//update-end--Author:wangshuai Date:20200714 for:登出日志没有记录人员
log.info(" 用户名: " + sysUser.getRealname() + ",退出成功! ");
//清空用户登录Token缓存
redisUtil.hdel(CommonConstant.USER_TOKEN, CommonConstant.PREFIX_USER_TOKEN + sysUser.getId());
//清空用户登录Shiro权限缓存
redisUtil.del(CommonConstant.PREFIX_USER_SHIRO_CACHE + sysUser.getId());
//清空用户的缓存信息(包括部门信息),例如sys:cache:user::<username>
redisUtil.del(String.format("%s::%s", CacheConstant.SYS_USERS_CACHE, sysUser.getId()));
//调用shiro的logout
SecurityUtils.getSubject().logout();
return Result.ok("退出登录成功!");
} else {
return Result.error("Token无效!");
}
}
}
@@ -0,0 +1,679 @@
package org.jeecg.system.controller;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.http.HttpDownloader;
import com.arcsoft.face.FaceInfo;
import com.arcsoft.face.toolkit.ImageFactory;
import com.arcsoft.face.toolkit.ImageInfo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.aspect.SendNotification;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.util.Base64Util;
import org.jeecg.common.util.FileShowUtil;
import org.jeecg.emp.entity.CqBaseEmployee;
import org.jeecg.emp.service.ICqBaseEmployeeService;
import org.jeecg.face.service.FaceEngineService;
import org.jeecg.system.mapper.SwUserFaceimgMapper;
import org.jeecg.system.service.ISwUserFaceimgService;
import org.jeecg.system.service.ISwUserFaceimgSubService;
import org.jeecg.system.service.UserFaceCacheService;
import org.jeecg.user.entity.SwUserFaceimg;
import org.jeecg.user.entity.SwUserFaceimgSub;
import org.jeecg.user.vo.SwUserFaceimgWeightScaleV2Vo;
import org.jeecg.user.vo.UserFaceInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @Description: 用户人脸数据
* @Author: jeecg-boot
* @Date: 2022-04-12
* @Version: V1.0
*/
@Tag(name= "用户人脸数据")
@RestController
@RequestMapping("/userface/swUserFaceimg")
@Slf4j
public class SwUserFaceimgController extends JeecgController<SwUserFaceimg, ISwUserFaceimgService> {
@Autowired
private ISwUserFaceimgService swUserFaceimgService;
@Autowired
private FaceEngineService faceEngineService;
@Autowired
private UserFaceCacheService userFaceCacheService;
@Resource
private SwUserFaceimgMapper swUserFaceimgMapper;
@Autowired
private ICqBaseEmployeeService iCqBaseEmployeeService;
@Resource
private ISwUserFaceimgSubService swUserFaceimgSubService;
/**
* 通过id查询
*
* @param id
* @return
*/
//@AutoLog(value = "用户人脸数据-通过id查询")
@Operation(summary = "用户人脸数据-通过id查询", description = "用户人脸数据-通过id查询")
@GetMapping(value = "/queryById")
public Result<SwUserFaceimg> queryById(@RequestParam(name = "id", required = true) String id) {
SwUserFaceimg swUserFaceimg = swUserFaceimgService.getById(id);
if (swUserFaceimg == null) {
return Result.error("未找到对应数据", null);
}
return Result.OK(swUserFaceimg);
}
/**
* 导出excel
*
* @param request
* @param swUserFaceimg
*/
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, SwUserFaceimg swUserFaceimg) {
return super.exportXls(request, swUserFaceimg, SwUserFaceimg.class, "用户人脸数据");
}
/**
* 通过excel导入数据
*
* @param request
* @param response
* @return
*/
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, SwUserFaceimg.class);
}
@AutoLog(value = "新增人脸信息")
@Operation(summary = "新增人脸信息", description = "新增人脸信息")
@PostMapping(value = "/saveFaceImg")
@SendNotification()
public Result<?> saveFaceImg(@RequestBody Map map) {
if(!map.containsKey("userType")){
map.put("userType",0);
}
//用户类型(0: 正式员工 1:非正式员工,2:家庭用户)
Integer userType = (Integer)map.get("userType");
if(userType != 0){
//非正式员工
return saveSubFaceImg(map);
}
//正式员工
String userId = map.get("userId").toString();
String imgSrc = map.get("imgSrc").toString();
if (StringUtils.isEmpty(userId) || StringUtils.isEmpty(imgSrc)) {
return Result.error("参数有误");
}
if(map.containsKey("face")){
LambdaQueryWrapper<SwUserFaceimg> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(SwUserFaceimg::getUserId, userId);
lambdaQueryWrapper.isNotNull(SwUserFaceimg::getFaceFeatureData);
List<SwUserFaceimg> list = swUserFaceimgService.list(lambdaQueryWrapper);
if(CollectionUtils.isNotEmpty(list)){
log.error("同步员工提取人脸特征,已存在人脸特征,跳过");
return Result.OK();
}
}
SwUserFaceimg slUserFaceimg = new SwUserFaceimg();
// slUserFaceimg.setFaceImgDataString(imgSrc);
String imgUrlByBase64 = swUserFaceimgService.getImgUrlByBase64(imgSrc);
slUserFaceimg.setFaceImg(imgUrlByBase64);
ImageInfo rgbData = ImageFactory.getRGBData(Base64Util.base64ToBytes(imgSrc));
List<FaceInfo> faceInfoList = faceEngineService.detectFaces(rgbData);
if (CollectionUtils.isNotEmpty(faceInfoList)) {
for (FaceInfo faceInfo : faceInfoList) {
byte[] feature = faceEngineService.extractFaceFeature(rgbData, faceInfo);
slUserFaceimg.setFaceFeatureData(feature);
}
}
slUserFaceimg.setFaceStatus("1");
slUserFaceimg.setUserId(userId);
CqBaseEmployee cqBaseEmployee = iCqBaseEmployeeService.getById(userId);
if(null != cqBaseEmployee && StringUtils.isNotBlank(cqBaseEmployee.getEmpIdcard())){
slUserFaceimg.setCardNumber(cqBaseEmployee.getEmpIdcard());
}
swUserFaceimgService.save(slUserFaceimg);
//默认最多保存三张照片
List<SwUserFaceimg> slUserFaceimgList = swUserFaceimgService.lambdaQuery().eq(SwUserFaceimg::getUserId, userId)
.eq(SwUserFaceimg::getFaceSource, 0).eq(SwUserFaceimg::getDataType, 0).eq(SwUserFaceimg::getFaceStatus, "1").orderByDesc(SwUserFaceimg::getCreateTime).list();
if (slUserFaceimgList.size() > 3) {
List<SwUserFaceimg> upList = slUserFaceimgList.subList(3, slUserFaceimgList.size());
if (CollectionUtils.isNotEmpty(upList)) {
upList.forEach(i -> {
i.setIsSync(0);
i.setFaceStatus("0");
});
swUserFaceimgService.saveOrUpdateBatch(upList);
}
}
//添加/更新人脸缓存
UserFaceInfo userInfo = new UserFaceInfo();
userInfo.setUserId(userId);
userInfo.setUserFaceId(slUserFaceimg.getId());
userInfo.setFaceFeature(slUserFaceimg.getFaceFeatureData());
userFaceCacheService.putUser(userInfo);
//发送消息到扣费闸机(查询下人员是否是sub扣费表的用户)
//保存新增扣费闸机人脸特征数据到增量表
UserFaceInfo userFaceInfo = new UserFaceInfo();
userFaceInfo.setUserId(slUserFaceimg.getUserId());
userFaceInfo.setUserFaceId(slUserFaceimg.getId());
userFaceInfo.setFaceFeatureString(slUserFaceimg.getFaceFeatureDataString());
swUserFaceimgService.sendPaymentGateUserInfo(userFaceInfo,1,true,userFaceInfo.getUserId());
return Result.OK().success("添加成功!");
}
public Result<?> saveSubFaceImg(Map map){
String userId = map.get("userId").toString();
String imgSrc = map.get("imgSrc").toString();
if (StringUtils.isEmpty(userId) || StringUtils.isEmpty(imgSrc)) {
return Result.error("参数有误");
}
if(map.containsKey("face")){
LambdaQueryWrapper<SwUserFaceimgSub> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(SwUserFaceimgSub::getUserId, userId);
lambdaQueryWrapper.isNotNull(SwUserFaceimgSub::getFaceFeatureData);
List<SwUserFaceimgSub> list = swUserFaceimgSubService.list(lambdaQueryWrapper);
if(CollectionUtils.isNotEmpty(list)){
log.error("同步员工提取人脸特征,已存在人脸特征,跳过");
return Result.OK();
}
}
SwUserFaceimgSub slUserFaceimg = new SwUserFaceimgSub();
String imgUrlByBase64 = swUserFaceimgService.getImgUrlByBase64(imgSrc);
slUserFaceimg.setFaceImg(imgUrlByBase64);
ImageInfo rgbData = ImageFactory.getRGBData(Base64Util.base64ToBytes(imgSrc));
List<FaceInfo> faceInfoList = faceEngineService.detectFaces(rgbData);
if (CollectionUtils.isNotEmpty(faceInfoList)) {
for (FaceInfo faceInfo : faceInfoList) {
byte[] feature = faceEngineService.extractFaceFeature(rgbData, faceInfo);
slUserFaceimg.setFaceFeatureData(feature);
}
}
slUserFaceimg.setFaceStatus("1");
slUserFaceimg.setUserId(userId);
swUserFaceimgSubService.save(slUserFaceimg);
//默认最多保存三张照片
List<SwUserFaceimgSub> slUserFaceimgList = swUserFaceimgSubService.lambdaQuery().eq(SwUserFaceimgSub::getUserId, userId)
.eq(SwUserFaceimgSub::getFaceSource, 0).eq(SwUserFaceimgSub::getFaceStatus, "1").orderByDesc(SwUserFaceimgSub::getCreateTime).list();
if (slUserFaceimgList.size() > 3) {
List<SwUserFaceimgSub> upList = slUserFaceimgList.subList(3, slUserFaceimgList.size());
if (CollectionUtils.isNotEmpty(upList)) {
upList.forEach(i -> {
i.setIsSync(0);
i.setFaceStatus("0");
});
swUserFaceimgSubService.saveOrUpdateBatch(upList);
}
}
//保存新增扣费闸机人脸特征数据到增量表
UserFaceInfo userInfo = new UserFaceInfo();
userInfo.setUserId(slUserFaceimg.getUserId());
userInfo.setUserFaceId(slUserFaceimg.getId());
userInfo.setFaceFeatureString(slUserFaceimg.getFaceFeatureDataString());
swUserFaceimgService.sendPaymentGateUserInfo(userInfo,1,false,null);
return Result.OK().success("添加成功!");
}
@AutoLog(value = "新增人脸信息本地上传图片")
@Operation(summary = "新增人脸信息本地上传图片", description = "新增人脸信息本地上传图片")
@PostMapping(value = "/saveFaceImgLocalUpload")
@SendNotification()
public Result<?> saveFaceImgLocalUpload(@RequestBody Map map) {
if(!map.containsKey("userType")){
map.put("userType",0);
}
//用户类型(0: 正式员工 1:非正式员工,2:家庭用户)
Integer userType = (Integer)map.get("userType");
if(userType != 0){
//非正式员工
return saveFaceImgSubLocalUpload(map);
}
String userId = map.get("userId").toString();
String img = map.get("imgSrc").toString();
if (StringUtils.isEmpty(userId) || StringUtils.isEmpty(img)) {
System.out.println("+++++++++++++++++++++1+++++++++++++++参数有误++++++++++++++");
return Result.error("参数有误");
}
System.out.println("+++++++++++++++++++++2+++++++++++++++img++++++++++++++"+img);
// String img = "http://192.168.10.6:8888/temp/20231011/1c8a1042-9760-4bf4-a89f-ca1f8c0d460d_1697006660528.png";
//服务器上替换img地址
if(img.contains("yyjk")){
img= img.replaceAll("https://yyjk.cqygjk.com/gateway","http://10.78.1.52:9090");
}
if(img.contains("yyjk")){
img= img.replaceAll("http://yyjk.cqygjk.com/gateway","http://10.78.1.52:9090");
}
System.out.println("+++++++++++++++++++++3+++++++++++++++img++++++++++++++"+img);
String imgSrc = "data:image/png;base64," + Base64Util.netImageToBase64(img);
System.out.println("+++++++++++++++++++++4+++++++++++++++imgSrc++++++++++++++"+imgSrc);
imgSrc = imgSrc.replaceAll("\r|\n", "");
SwUserFaceimg slUserFaceimg = new SwUserFaceimg();
System.out.println("+++++++++++++++++++++5+++++++++++++++imgSrc++++++++++++++"+imgSrc);
// slUserFaceimg.setFaceImgDataString(imgSrc);
ImageInfo rgbData = ImageFactory.getRGBData(Base64Util.base64ToBytes(imgSrc));
List<FaceInfo> faceInfoList = faceEngineService.detectFaces(rgbData);
if (CollectionUtils.isNotEmpty(faceInfoList)) {
for (FaceInfo faceInfo : faceInfoList) {
byte[] feature = faceEngineService.extractFaceFeature(rgbData, faceInfo);
slUserFaceimg.setFaceFeatureData(feature);
}
}
slUserFaceimg.setFaceStatus("1");
slUserFaceimg.setUserId(userId);
CqBaseEmployee cqBaseEmployee = iCqBaseEmployeeService.getById(userId);
if(null != cqBaseEmployee && StringUtils.isNotBlank(cqBaseEmployee.getEmpIdcard())){
slUserFaceimg.setCardNumber(cqBaseEmployee.getEmpIdcard());
}
slUserFaceimg.setFaceImg(img);
swUserFaceimgService.save(slUserFaceimg);
//默认最多保存三张照片
List<SwUserFaceimg> slUserFaceimgList = swUserFaceimgService.lambdaQuery().eq(SwUserFaceimg::getUserId, userId)
.eq(SwUserFaceimg::getFaceSource, 0).eq(SwUserFaceimg::getDataType, 0).eq(SwUserFaceimg::getFaceStatus, "1").orderByDesc(SwUserFaceimg::getCreateTime).list();
if (slUserFaceimgList.size() > 3) {
List<SwUserFaceimg> upList = slUserFaceimgList.subList(3, slUserFaceimgList.size());
if (CollectionUtils.isNotEmpty(upList)) {
upList.forEach(i -> {
i.setFaceStatus("0");
});
swUserFaceimgService.saveOrUpdateBatch(upList);
}
}
//添加/更新人脸缓存
UserFaceInfo userInfo = new UserFaceInfo();
userInfo.setUserId(userId);
userInfo.setUserFaceId(slUserFaceimg.getId());
userInfo.setFaceFeature(slUserFaceimg.getFaceFeatureData());
userFaceCacheService.putUser(userInfo);
//保存新增扣费闸机人脸特征数据到增量表
UserFaceInfo userFaceInfo = new UserFaceInfo();
userFaceInfo.setUserId(slUserFaceimg.getUserId());
userFaceInfo.setUserFaceId(slUserFaceimg.getId());
userFaceInfo.setFaceFeatureString(slUserFaceimg.getFaceFeatureDataString());
swUserFaceimgService.sendPaymentGateUserInfo(userFaceInfo,1,true,userFaceInfo.getUserId());
return Result.OK().success("添加成功!");
}
public Result<?> saveFaceImgSubLocalUpload(@RequestBody Map map) {
String userId = map.get("userId").toString();
String img = map.get("imgSrc").toString();
if (StringUtils.isEmpty(userId) || StringUtils.isEmpty(img)) {
System.out.println("+++++++++++++++++++++1+++++++++++++++参数有误++++++++++++++");
return Result.error("参数有误");
}
System.out.println("+++++++++++++++++++++2+++++++++++++++img++++++++++++++"+img);
// String img = "http://192.168.10.6:8888/temp/20231011/1c8a1042-9760-4bf4-a89f-ca1f8c0d460d_1697006660528.png";
//服务器上替换img地址
if(img.contains("yyjk")){
img= img.replaceAll("https://yyjk.cqygjk.com/gateway","http://10.78.1.52:9090");
}
if(img.contains("yyjk")){
img= img.replaceAll("http://yyjk.cqygjk.com/gateway","http://10.78.1.52:9090");
}
System.out.println("+++++++++++++++++++++3+++++++++++++++img++++++++++++++"+img);
String imgSrc = "data:image/png;base64," + Base64Util.netImageToBase64(img);
System.out.println("+++++++++++++++++++++4+++++++++++++++imgSrc++++++++++++++"+imgSrc);
imgSrc = imgSrc.replaceAll("\r|\n", "");
SwUserFaceimgSub slUserFaceimg = new SwUserFaceimgSub();
System.out.println("+++++++++++++++++++++5+++++++++++++++imgSrc++++++++++++++"+imgSrc);
ImageInfo rgbData = ImageFactory.getRGBData(Base64Util.base64ToBytes(imgSrc));
List<FaceInfo> faceInfoList = faceEngineService.detectFaces(rgbData);
if (CollectionUtils.isNotEmpty(faceInfoList)) {
for (FaceInfo faceInfo : faceInfoList) {
byte[] feature = faceEngineService.extractFaceFeature(rgbData, faceInfo);
slUserFaceimg.setFaceFeatureData(feature);
}
}
slUserFaceimg.setFaceStatus("1");
slUserFaceimg.setUserId(userId);
slUserFaceimg.setFaceImg(img);
swUserFaceimgSubService.save(slUserFaceimg);
//默认最多保存三张照片
List<SwUserFaceimgSub> slUserFaceimgList = swUserFaceimgSubService.lambdaQuery().eq(SwUserFaceimgSub::getUserId, userId)
.eq(SwUserFaceimgSub::getFaceSource, 0).eq(SwUserFaceimgSub::getFaceStatus, "1").orderByDesc(SwUserFaceimgSub::getCreateTime).list();
if (slUserFaceimgList.size() > 3) {
List<SwUserFaceimgSub> upList = slUserFaceimgList.subList(3, slUserFaceimgList.size());
if (CollectionUtils.isNotEmpty(upList)) {
upList.forEach(i -> {
i.setFaceStatus("0");
});
swUserFaceimgSubService.saveOrUpdateBatch(upList);
}
}
//保存新增扣费闸机人脸特征数据到增量表
UserFaceInfo userFaceInfo = new UserFaceInfo();
userFaceInfo.setUserId(slUserFaceimg.getUserId());
userFaceInfo.setUserFaceId(slUserFaceimg.getId());
userFaceInfo.setFaceFeatureString(slUserFaceimg.getFaceFeatureDataString());
swUserFaceimgService.sendPaymentGateUserInfo(userFaceInfo,1,false,null);
return Result.OK().success("添加成功!");
}
@AutoLog(value = "查询人脸信息列表")
@Operation(summary = "查询人脸信息列表", description = "查询人脸信息列表")
@GetMapping(value = "/queryFaceImgList")
public Result<?> queryFaceImgList(@RequestParam("userId") String userId,
@RequestParam(value = "userType",defaultValue = "0") Integer userType) {
if(userType != 0){
return queryFaceImgSubList(userId,userType);
}
List<SwUserFaceimg> slUserFaceimgList = swUserFaceimgService.lambdaQuery().eq(SwUserFaceimg::getUserId, userId)
.eq(SwUserFaceimg::getFaceStatus, "1")
.eq(SwUserFaceimg::getFaceSource, 0).list();//只展示非绑盘机渠道获取的人脸图片和特征
slUserFaceimgList.forEach(i -> {
if(StringUtils.isNotEmpty(i.getFaceImg())){
i.setFaceImg(FileShowUtil.getShowUrl(i.getFaceImg()));
}
});
return Result.OK(slUserFaceimgList);
}
public Result<?> queryFaceImgSubList(String userId,Integer userType) {
List<SwUserFaceimgSub> slUserFaceimgList = swUserFaceimgSubService.lambdaQuery().eq(SwUserFaceimgSub::getUserId, userId)
.eq(SwUserFaceimgSub::getFaceStatus, "1")
.eq(SwUserFaceimgSub::getDelFlag, 0)
.eq(SwUserFaceimgSub::getFaceSource, 0).list();//只展示非绑盘机渠道获取的人脸图片和特征
slUserFaceimgList.forEach(i -> {
if(StringUtils.isNotEmpty(i.getFaceImg())){
i.setFaceImg(FileShowUtil.getShowUrl(i.getFaceImg()));
}
});
return Result.OK(slUserFaceimgList);
}
@AutoLog(value = "删除指定人脸照片")
@Operation(summary = "删除指定人脸照片", description = "删除指定人脸照片")
@DeleteMapping(value = "/deleteFaceImgById")
@SendNotification()
public Result<?> deleteFaceImgById(@RequestParam("id") String id,
@RequestParam(value = "userType",defaultValue = "0") Integer userType) {
//用户类型(0: 正式员工 1:非正式员工,2:家庭用户)
if(userType != 0){
//非正式员工
SwUserFaceimgSub swUserFaceimgSub = swUserFaceimgSubService.getById(id);
swUserFaceimgSub.setDelFlag(1);
//2025-05-07 余:逻辑删除用户特征
swUserFaceimgSubService.updateById(swUserFaceimgSub);
//发送删除扣费闸机人脸特征数据
UserFaceInfo userInfo = new UserFaceInfo();
userInfo.setUserFaceId(swUserFaceimgSub.getId());
swUserFaceimgService.sendPaymentGateUserInfo(userInfo,0,false,null);
return Result.OK().success("删除成功");
}
SwUserFaceimg swUserFaceimgV1 = swUserFaceimgService.getById(id);
swUserFaceimgService.removeById(id);
//删除人脸数据缓存
if(null != swUserFaceimgV1){
userFaceCacheService.removeUserFaceImgByFaceId(swUserFaceimgV1.getUserId(),id);
//发送删除扣费闸机人脸特征数据
UserFaceInfo userInfo = new UserFaceInfo();
userInfo.setUserFaceId(swUserFaceimgV1.getId());
swUserFaceimgService.sendPaymentGateUserInfo(userInfo,0,true,swUserFaceimgV1.getUserId());
}
return Result.OK().success("删除成功");
}
// @AutoLog(value = "重新获取所有人脸数据到redis中")
// @Operation(summary = "重新获取所有人脸数据到redis中", description = "重新获取所有人脸数据到redis中")
// @DeleteMapping(value = "/reputUserFaceDataToRedis")
// public Result<?> reputUserFaceDataToRedis() {
// swUserFaceimgService.reputUserFaceDataToRedis();
// return Result.OK().success("操作成功");
// }
@AutoLog(value = "指定部门人脸到人脸库中")
@Operation(summary = "指定部门人脸到人脸库中", description = "指定部门人脸到人脸库中")
@PostMapping(value = "/saveOrgCodeDepartUserFaceImgDate")
@SendNotification()
public Result<?> saveFaceImg(@RequestParam(name = "orgCode", required = true) String orgCode) {
// 获取指定二级单位的所有部门
List<String> departList = swUserFaceimgMapper.getDepart(orgCode);
List<Map<String, String>> imgMapList = swUserFaceimgMapper.getUserImgUrl(departList);
List<SwUserFaceimg> swUserFaceimgs = swUserFaceimgMapper.selectList(new LambdaQueryWrapper<>());
if (CollectionUtils.isNotEmpty(imgMapList)){
for (Map<String, String> map : imgMapList) {
try {
// 如果已经有人脸了,就跳过
String userId = map.get("id");
int count = (int)swUserFaceimgs.stream().filter(a -> userId.equals(a.getUserId())).count();
if (count > 0){
continue;
}
// 头像为空跳过
String imgStr = map.get("portrait");
if (StringUtils.isEmpty(imgStr)){
continue;
}
// 下载图片转换成byte数组
String imageType = imgStr.substring(imgStr.lastIndexOf(".") + 1);
//硬编码IP-中等风险
// String preStr = "http://113.200.64.63:9003/cqyt/systemController/showOrDownByurlFTP.do?dbPath=";
// String imgUrl = preStr + imgStr;
byte[] bytes = HttpDownloader.downloadBytes("");
// 获取图片的base64格式不对,出来string太短就跳过
BufferedImage bufferedImage = ImgUtil.toImage(bytes);
String imgSrc = ImgUtil.toBase64DateUri(bufferedImage, imageType);
if (imgSrc.length() < 100){
continue;
}
// 保存逻辑
SwUserFaceimg slUserFaceimg = new SwUserFaceimg();
slUserFaceimg.setFaceImgDataString(imgSrc);
ImageInfo rgbData = ImageFactory.getRGBData(Base64Util.base64ToBytes(imgSrc));
List<FaceInfo> faceInfoList = faceEngineService.detectFaces(rgbData);
if (CollectionUtils.isNotEmpty(faceInfoList)) {
for (FaceInfo faceInfo : faceInfoList) {
byte[] feature = faceEngineService.extractFaceFeature(rgbData, faceInfo);
slUserFaceimg.setFaceFeatureData(feature);
}
}
slUserFaceimg.setFaceStatus("1");
slUserFaceimg.setUserId(userId);
swUserFaceimgService.save(slUserFaceimg);
// 每次重置大对象
bytes = null;
imgSrc = null;
rgbData = null;
} catch (Exception e) {
e.printStackTrace();
}
}
}
return Result.OK();
}
/**
* 上传人脸压缩包
* (支付用户场景暂不处理发送消息通知)
* @param request
* @return
*/
@PostMapping("/uploadFaceImagePackage")
public Result<?> uploadFaceImagePackage(HttpServletRequest request){
return swUserFaceimgService.uploadFaceImagePackage(request,0,null);
}
/**
* 上传人脸压缩包 体重秤
*/
@PostMapping("/uploadFaceImagePackageWeight")
public Result<?> uploadFaceImagePackageWeight(HttpServletRequest request){
return swUserFaceimgService.uploadFaceImagePackage(request,1,null);
}
/**
* 上传人脸压缩包 公共
*/
@PostMapping("/uploadFaceImagePackageCommon")
public Result<?> uploadFaceImagePackageCommon(HttpServletRequest request){
return swUserFaceimgService.uploadFaceImagePackage(request,2,null);
}
/**
* 根据二级部门id 获取没有人脸图片的用户列表
* @return 人员信息
*/
@GetMapping("/getUserInfoNotHaveFaceUrlBySecondDepartId")
public Result<?> getUserInfoNotHaveFaceUrlBySecondDepartId(@RequestParam(name = "secondDepartId") String secondDepartId){
return Result.OK(swUserFaceimgService.getUserInfoNotHaveFaceUrlBySecondDepartId(secondDepartId));
}
@AutoLog(value = "保存新增扣费闸机人脸特征数据到增量表")
@Operation(summary = "保存新增扣费闸机人脸特征数据到增量表", description = "保存新增扣费闸机人脸特征数据到增量表")
@PostMapping(value = "/sendPaymentGateUserInfo")
public Result<?> sendPaymentGateUserInfo(@RequestBody List<String> userIdList) {
//查询该特征人员是否是 SysUserSub 扣费表的用户,是就发送消息给扣费闸机,不是不发送
//发送消息到扣费闸机(查询下人员是否是sub扣费表的用户)
//保存新增扣费闸机人脸特征数据到增量表
if(CollectionUtils.isNotEmpty(userIdList)){
userIdList.forEach(userId->{
List<SwUserFaceimg> slUserFaceimgList = swUserFaceimgService.lambdaQuery()
.select(SwUserFaceimg::getFaceFeatureData,SwUserFaceimg::getId)
.eq(SwUserFaceimg::getUserId, userId)
.eq(SwUserFaceimg::getDataType, 0)
.eq(SwUserFaceimg::getFaceSource, 0)
.eq(SwUserFaceimg::getFaceStatus, "1")
.orderByDesc(SwUserFaceimg::getCreateTime).list();
if(CollectionUtils.isNotEmpty(slUserFaceimgList)){
slUserFaceimgList.forEach(swUserFaceimg -> {
UserFaceInfo userFaceInfo = new UserFaceInfo();
userFaceInfo.setFaceFeatureString(swUserFaceimg.getFaceFeatureDataString());
userFaceInfo.setUserFaceId(swUserFaceimg.getId());
userFaceInfo.setUserId(userId);
swUserFaceimgService.sendPaymentGateUserInfo(userFaceInfo,1,false,userFaceInfo.getUserId());
});
}
});
}
return Result.OK();
}
/**
* 用户人脸图片下载本地(3265=135s)
* @return
*/
@Operation(summary = "用户人脸图片下载本地", description = "用户人脸图片下载本地")
@GetMapping(value = "/exportFaceData")
public Result<?> exportFaceData() {
List<SwUserFaceimgWeightScaleV2Vo> swUserFaceimg = swUserFaceimgMapper.swUserFaceimgListV2();
if (swUserFaceimg == null) {
return Result.error("未找到对应数据", null);
}
List<String> listF = new ArrayList<>();
List<String> listS = new ArrayList<>();
LinkedHashMap<String, Object> stringObjectMap = new LinkedHashMap<>();
for (int i = 0; i < swUserFaceimg.size(); i++) {
// 保存图片到本地
SwUserFaceimgWeightScaleV2Vo swUserFaceimgWeightScaleV2Vo = swUserFaceimg.get(i);
String faceImgDataString = swUserFaceimgWeightScaleV2Vo.getFaceImgDataString();
try {
// // 生成图片文件名
String fileName1 = swUserFaceimgWeightScaleV2Vo.getName() + "_" + swUserFaceimgWeightScaleV2Vo.getCardNumber();
String fileName = generateTimestampFileName(fileName1,extractMimeType(faceImgDataString));
faceImgDataString = faceImgDataString.replaceAll(" ", "+");
faceImgDataString = faceImgDataString.replaceAll("\r|\n", "");
byte[] imageBytes = null;
if(StringUtils.isNotBlank(faceImgDataString)){
if(faceImgDataString.contains(",")){
String img = faceImgDataString.split(",")[1];
imageBytes = Base64.getDecoder().decode(img);
} else {
imageBytes = Base64.getDecoder().decode(faceImgDataString);
}
if(!fileName.contains("unknown")){
saveImageToFile(imageBytes, fileName);
listS.add(swUserFaceimgWeightScaleV2Vo.getName()+"_"+swUserFaceimgWeightScaleV2Vo.getCardNumber());
} else {
listF.add(swUserFaceimgWeightScaleV2Vo.getName()+"_"+swUserFaceimgWeightScaleV2Vo.getCardNumber()+"_图片base64文件格式异常->"+fileName);
log.error("图片base64文件格式异常{},用户信息:{}{}faceImgDataString:{}", fileName,swUserFaceimgWeightScaleV2Vo.getCardNumber(), swUserFaceimgWeightScaleV2Vo.getName(),faceImgDataString);
}
} else {
listF.add(swUserFaceimgWeightScaleV2Vo.getName()+"_"+swUserFaceimgWeightScaleV2Vo.getCardNumber()+"_图片base64为空");
log.error("图片base64为空,用户信息:{}{}faceImgDataString:{}", swUserFaceimgWeightScaleV2Vo.getCardNumber(), swUserFaceimgWeightScaleV2Vo.getName(),faceImgDataString);
}
} catch (IllegalArgumentException | IOException e ) {
listF.add(swUserFaceimgWeightScaleV2Vo.getName()+"_"+swUserFaceimgWeightScaleV2Vo.getCardNumber()+"_图片保存异常");
log.error("图片保存异常,用户信息:{},{},错误:{}", swUserFaceimgWeightScaleV2Vo.getCardNumber(), swUserFaceimgWeightScaleV2Vo.getName(), e.getMessage());
}
}
stringObjectMap.put("人脸总人数",swUserFaceimg.size());
stringObjectMap.put("人脸失败人数",listF.size());
stringObjectMap.put("人脸失败详情",listF);
stringObjectMap.put("人脸成功人数",listS.size());
return Result.OK(stringObjectMap);
}
private static String extractMimeType(String base64Image) {
String mimeType = "image/unknown"; // 默认未知类型
Pattern pattern = Pattern.compile("data:image/(\\w+);base64,");
Matcher matcher = pattern.matcher(base64Image);
if (matcher.find()) {
mimeType = "image/" + matcher.group(1);
}
return mimeType;
}
private static String generateTimestampFileName(String fileName1,String mimeType) {
String extension = mimeType.substring(mimeType.lastIndexOf("/") + 1);
return fileName1 + "." + extension;
}
private static void saveImageToFile(byte[] imageBytes, String fileName) throws IOException {
File folder = new File("C:\\faceImg\\");
if (!folder.exists()) {
folder.mkdirs();
}
String filePath = folder + File.separator + fileName;
try (FileOutputStream fos = new FileOutputStream(filePath)) {
fos.write(imageBytes);
}
}
}
@@ -0,0 +1,89 @@
package org.jeecg.system.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.util.DateUtils;
import org.jeecg.system.service.IStUserFaceimgSubIncremInfoService;
import org.jeecg.system.service.ISwUserFaceimgSubService;
import org.jeecg.user.entity.StUserFaceimgSubIncremInfo;
import org.jeecg.user.entity.SwUserFaceimgSub;
import org.springframework.beans.factory.annotation.Autowired;
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;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.Date;
import java.util.List;
/**
* @Description: 用户人脸数据
* @Author: jeecg-boot
* @Date: 2022-04-12
* @Version: V1.0
*/
@Tag(name= "用户人脸数据")
@RestController
@RequestMapping("/userface/swUserFaceimgSub")
@Slf4j
public class SwUserFaceimgSubController extends JeecgController<SwUserFaceimgSub, ISwUserFaceimgSubService> {
@Autowired
private ISwUserFaceimgSubService iSwUserFaceimgSubService;
@Resource
private IStUserFaceimgSubIncremInfoService iStUserFaceimgSubIncremInfoService;
/**
* 人脸初始化-分页列表查询
*
* @param pageNo
* @param pageSize
* @return
*/
@AutoLog(value = "人脸初始化-分页列表查询")
@Operation(summary = "人脸初始化-分页列表查询", description = "人脸初始化-分页列表查询")
@GetMapping(value = "/list")
public Result<?> queryPageListV2(
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
Page<SwUserFaceimgSub> page = new Page<SwUserFaceimgSub>(pageNo, pageSize);
IPage<SwUserFaceimgSub> pageList = iSwUserFaceimgSubService.queryPageList(page);
return Result.OK(pageList);
}
/**
* 扣费闸机心跳
*/
@Operation(summary = "扣费闸机心跳", description = "扣费闸机心跳")
@GetMapping("/heartbeat/interface")
@AutoLog(value = "扣费闸机心跳")
public Result heartbeatInterface(@RequestParam(name = "restId", required = false) String restId,
@RequestParam(name = "qrcodeId", required = false) String qrcodeId,
@RequestParam(name = "timeDate", required = false) String timeDate) {
if(StringUtils.isNotBlank(timeDate)){
LambdaQueryWrapper<StUserFaceimgSubIncremInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
Date date = new Date(Long.parseLong(timeDate));
// 设置查询条件:createTime >= 当前时间
lambdaQueryWrapper.ge(StUserFaceimgSubIncremInfo::getCreateTime, DateUtils.formatDate(date,"yyyy-MM-dd HH:mm:ss"));
lambdaQueryWrapper.eq(StUserFaceimgSubIncremInfo::getDelFlag, 0);
// 按 createTime 降序排列,获取最新数据
lambdaQueryWrapper.orderByDesc(StUserFaceimgSubIncremInfo::getCreateTime);
List<StUserFaceimgSubIncremInfo> list = iStUserFaceimgSubIncremInfoService.list(lambdaQueryWrapper);
return Result.OK(list);
}
return Result.OK(Collections.emptyList());
}
}
@@ -0,0 +1,211 @@
package org.jeecg.system.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.system.service.ISysPayDepartService;
import org.jeecg.user.entity.SysPayDepart;
import org.jeecg.user.vo.PayDepartIdModel;
import org.jeecg.user.vo.SysPayDepartTreeModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
/**
* <p>
* 部门表 前端控制器
* <p>
*
* @Author: Steve @Since 2019-01-22
*/
@RestController
@Tag(name = "部门表")
@RequestMapping("/emp/cqBaseEmployee/sys/sysPayDepart")
@Slf4j
public class SysPayDepartController {
@Autowired
private ISysPayDepartService sysDepartService;
/**
* 查询数据 查出所有部门,并以树结构数据格式响应给前端
*
* @return
*/
@Operation(summary = "s-1-部门列表 ", description = "s-1-部门列表")
@RequestMapping(value = "/queryTreeList", method = RequestMethod.GET)
public Result<List<SysPayDepartTreeModel>> queryTreeList(@RequestParam(name = "ids", required = false) String ids) {
try {
if(oConvertUtils.isNotEmpty(ids)){
List<SysPayDepartTreeModel> departList = sysDepartService.queryTreeList(ids);
return Result.OK(departList);
}else{
List<SysPayDepartTreeModel> list = sysDepartService.queryTreeListCach();
return Result.OK(list);
}
} catch (Exception e) {
log.error(e.getMessage(),e);
return Result.error(e.getMessage());
}
}
@RequestMapping(value = "/queryTreeListBy", method = RequestMethod.GET)
public Result<List<SysPayDepart>> queryTreeListBy() {
Result<List<SysPayDepart>> result = new Result<>();
try {
List<SysPayDepart> list = sysDepartService.querySysDepartListBy();
result.setResult(list);
result.setSuccess(true);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return result;
}
/**
* 添加新数据 添加用户新建的部门对象数据,并保存到数据库
*
* @param sysDepart
* @return
*/
@RequestMapping(value = "/add", method = RequestMethod.POST)
public Result<SysPayDepart> add(@RequestBody SysPayDepart sysDepart, HttpServletRequest request) {
Result<SysPayDepart> result = new Result<SysPayDepart>();
String userId = JwtUtil.getUserIdByToken(request);
try {
sysDepart.setCreateBy(userId);
sysDepartService.saveDepartData(sysDepart, userId);
result.success("添加成功!");
} catch (Exception e) {
log.error(e.getMessage(), e);
result.error500("操作失败");
}
return result;
}
/**
* 编辑数据 编辑部门的部分数据,并保存到数据库
*
* @param sysDepart
* @return
*/
@RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
public Result<SysPayDepart> edit(@RequestBody SysPayDepart sysDepart, HttpServletRequest request) {
if(StringUtils.isBlank(sysDepart.getId())){
return Result.error("请选择要修改的部门");
}
String userId = JwtUtil.getUserIdByToken(request);
sysDepart.setUpdateBy(userId);
Result<SysPayDepart> result = new Result<SysPayDepart>();
SysPayDepart sysDepartEntity = sysDepartService.getById(sysDepart.getId());
if (sysDepartEntity == null) {
result.error500("未找到对应实体");
} else {
boolean ok = sysDepartService.updateDepartDataById(sysDepart, userId);
}
return result;
}
/**
* 通过id删除
*
* @param id
* @return
*/
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
public Result<SysPayDepart> delete(@RequestParam(name = "id", required = true) String id) {
Result<SysPayDepart> result = new Result<SysPayDepart>();
SysPayDepart sysDepart = sysDepartService.getById(id);
if (sysDepart == null) {
result.error500("未找到对应实体");
} else {
boolean ok = sysDepartService.delete(id);
if (ok) {
result.success("删除成功!");
}
}
return result;
}
/**
* 批量删除 根据前端请求的多个ID,对数据库执行删除相关部门数据的操作
*
* @param ids
* @return
*/
@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
public Result<SysPayDepart> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
Result<SysPayDepart> result = new Result<SysPayDepart>();
if (ids == null || "".equals(ids.trim())) {
result.error500("参数不识别!");
} else {
this.sysDepartService.deleteBatchWithChildren(Arrays.asList(ids.split(",")));
result.success("删除成功!");
}
return result;
}
/**
* 查询数据 添加或编辑页面对该方法发起请求,以树结构形式加载所有部门的名称,方便用户的操作
*
* @return
*/
@RequestMapping(value = "/queryIdTree", method = RequestMethod.GET)
public Result<List<PayDepartIdModel>> queryIdTree() {
Result<List<PayDepartIdModel>> result = new Result<>();
try {
List<PayDepartIdModel> list = sysDepartService.queryDepartIdTreeList();
result.setResult(list);
result.setSuccess(true);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return result;
}
/**
* <p>
* 部门搜索功能方法,根据关键字模糊搜索相关部门
* </p>
*
* @param keyWord
* @return
*/
@RequestMapping(value = "/searchBy", method = RequestMethod.GET)
public Result<List<SysPayDepartTreeModel>> searchBy(@RequestParam(name = "keyWord", required = true) String keyWord, @RequestParam(name = "myDeptSearch", required = false) String myDeptSearch) {
Result<List<SysPayDepartTreeModel>> result = new Result<List<SysPayDepartTreeModel>>();
//部门查询,myDeptSearch为1时为我的部门查询,登录用户为上级时查只查负责部门下数据
LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
String departIds = null;
if (oConvertUtils.isNotEmpty(user.getUserIdentity()) && user.getUserIdentity().equals(CommonConstant.USER_IDENTITY_2)) {
departIds = user.getDepartIds();
}
List<SysPayDepartTreeModel> treeList = this.sysDepartService.searchByKeyWord(keyWord, myDeptSearch, departIds);
if (treeList == null || treeList.size() == 0) {
result.setSuccess(false);
result.setMessage("未查询匹配数据!");
return result;
}
result.setResult(treeList);
return result;
}
}
@@ -0,0 +1,18 @@
package org.jeecg.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.jeecg.user.entity.StUserFaceimgSubIncremInfo;
import java.util.List;
/**
* @Description: 支付用户人脸信息增量记录表
* @Author: jeecg-boot
* @Date: 2022-04-12
* @Version: V1.0
*/
public interface StUserFaceimgSubIncremInfoMapper extends BaseMapper<StUserFaceimgSubIncremInfo> {
List<StUserFaceimgSubIncremInfo> selectFaceImagesAndSubs(@Param("timestamp") Long timestamp);
}
@@ -0,0 +1,49 @@
package org.jeecg.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.jeecg.emp.vo.UserInfoVo;
import org.jeecg.user.entity.SwUserFaceimg;
import org.jeecg.user.entity.SysUserSub;
import org.jeecg.user.vo.SwUserFaceimgWeightScaleV2Vo;
import org.jeecg.user.vo.SwUserFaceimgWeightScaleVo;
import java.util.List;
import java.util.Map;
/**
* @Description: 用户人脸数据
* @Author: jeecg-boot
* @Date: 2022-04-12
* @Version: V1.0
*/
public interface SwUserFaceimgMapper extends BaseMapper<SwUserFaceimg> {
List<Map<String, String>> getUserImgUrl(@Param("departIdList") List<String> departIdList);
List<String> getDepart(String orgCode);
@Select("select id, user_id, face_feature_data from st_user_faceimg")
List<SwUserFaceimg> getList();
List<Map<String,Object>> getSecondDepartNotHaveFaceUrl(String secondDepartId);
List<SwUserFaceimgWeightScaleVo> swUserFaceimgList(Page<SwUserFaceimgWeightScaleVo> page);
List<SwUserFaceimgWeightScaleV2Vo> swUserFaceimgListV2();
IPage<SwUserFaceimg> selectFaceImagesAndSubs(@Param("page") Page<SwUserFaceimg> page,@Param("orgCode") String orgCode);
List<UserInfoVo> selectUserIdByOrgCode(@Param("orgCode") String orgCode);
/**
* 查询扣费闸机人员数据
* @param userId
* @param status 状态(1-正常,2-冻结)
* @return
*/
SysUserSub getUserSubInfo(@Param("userId") String userId, @Param("status") Integer status);
}
@@ -0,0 +1,19 @@
package org.jeecg.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Select;
import org.jeecg.user.entity.SwUserFaceimgSelf;
import java.util.List;
/**
* @Description: 用户人脸数据-自研引擎
* @Author: jeecg-boot
* @Date: 2022-04-12
* @Version: V1.0
*/
public interface SwUserFaceimgSelfMapper extends BaseMapper<SwUserFaceimgSelf> {
@Select("select id, user_id, face_feature_data from st_user_faceimg_self")
List<SwUserFaceimgSelf> getList();
}
@@ -0,0 +1,40 @@
package org.jeecg.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.jeecg.user.entity.SwUserFaceimgSub;
import org.jeecg.user.vo.SwUserFaceimgWeightScaleV2Vo;
import org.jeecg.user.vo.SwUserFaceimgWeightScaleVo;
import java.util.List;
import java.util.Map;
/**
* @Description: 用户人脸数据
* @Author: jeecg-boot
* @Date: 2022-04-12
* @Version: V1.0
*/
public interface SwUserFaceimgSubMapper extends BaseMapper<SwUserFaceimgSub> {
List<Map<String, String>> getUserImgUrl(@Param("departIdList") List<String> departIdList);
List<String> getDepart(String orgCode);
@Select("select id, user_id, face_feature_data from st_user_faceimg_sub")
List<SwUserFaceimgSub> getList();
List<Map<String,Object>> getSecondDepartNotHaveFaceUrl(String secondDepartId);
List<SwUserFaceimgWeightScaleVo> swUserFaceimgList(Page<SwUserFaceimgWeightScaleVo> page);
List<SwUserFaceimgWeightScaleV2Vo> swUserFaceimgListV2();
IPage<SwUserFaceimgSub> selectFaceImagesAndSubs(@Param("page") Page<SwUserFaceimgSub> page,@Param("timestamp") Long timestamp);
List<SwUserFaceimgSub> selectFaceImagesAndSubs(@Param("timestamp") Long timestamp);
}
@@ -0,0 +1,14 @@
package org.jeecg.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.system.entity.SysGatewayRoute;
/**
* @Description: gateway路由管理
* @Author: jeecg-boot
* @Date: 2020-05-26
* @Version: V1.0
*/
public interface SysGatewayRouteMapper extends BaseMapper<SysGatewayRoute> {
}
@@ -0,0 +1,61 @@
package org.jeecg.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Select;
import org.jeecg.user.entity.SysPayDepart;
import org.springframework.data.repository.query.Param;
import java.util.List;
/**
* <p>
* 部门 Mapper 接口
* <p>
*
* @Author: Steve
* @Since 2019-01-22
*/
public interface SysPayDepartMapper extends BaseMapper<SysPayDepart> {
/**
* 根据用户ID查询部门集合
*/
public List<SysPayDepart> queryUserDeparts(@Param("userId") String userId);
/**
* 根据用户名查询部门
*
* @param username
* @return
*/
public List<SysPayDepart> queryDepartsByUsername(@Param("username") String username);
@Select("select id,parent_id from sys_depart where id=#{departId}")
public SysPayDepart getParentDepartId(@Param("departId") String departId);
/**
* 根据部门Id查询,当前和下级所有部门IDS
* @param departId
* @return
*/
List<String> getSubDepIdsByDepId(@Param("departId") String departId);
/**
* 根据部门编码获取部门下所有IDS
* @param orgCodes
* @return
*/
List<String> getSubDepIdsByOrgCodes(@org.apache.ibatis.annotations.Param("orgCodes") String[] orgCodes);
List<SysPayDepart> queryTreeListByPid(@Param("parentId") String parentId);
/**
* 根据OrgCod查询所属公司信息
* @param orgCode
* @return
*/
SysPayDepart queryCompByOrgCode(@Param("orgCode")String orgCode);
String findIdByName(String name);
}
@@ -0,0 +1,30 @@
package org.jeecg.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.jeecg.common.system.vo.ScreenVo;
import org.jeecg.user.entity.SysUser;
import java.util.List;
/**
* <p>
* 用户表 Mapper 接口
* </p>
*
* @Author scott
* @since 2018-12-20
*/
public interface SysUserMapper extends BaseMapper<SysUser> {
/**
* 按照用户所属机构编码前置匹配食堂编号进行数据权限处理
*/
@Select("select * from st_base_restaurant where id!=0 and rest_no LIKE CONCAT(#{orgCode},'%')")
List<ScreenVo> queryScreenVOByorgCode(@Param("orgCode") String orgCode);
@Select("select * from st_base_restaurant r, sys_user_screen s where s.screen_id=r.id and s.user_id=#{userId}")
List<ScreenVo> queryScreenVOByUserId(@Param("userId") String userId);
}
@@ -0,0 +1,14 @@
package org.jeecg.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.user.entity.SysUserScreen;
/**
* @Description: s
* @Author: yucl
* @Date: 2022-04-20
* @Version: V1.0
*/
public interface SysUserScreenMapper extends BaseMapper<SysUserScreen> {
}
@@ -0,0 +1,23 @@
package org.jeecg.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.jeecg.user.entity.SysUserSub;
import org.jeecg.user.vo.StClientMemberBalanceVo;
/**
* <p>
* 子用户表 Mapper 接口
* </p>
*
* @Author scott
* @since 2018-12-20
*/
public interface SysUserSubMapper extends BaseMapper<SysUserSub> {
void insertStClientMemberBalance(StClientMemberBalanceVo stClientMemberBalanceVo);
StClientMemberBalanceVo selectByMemberId(@Param("memberId") String memberId);
}
@@ -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="org.jeecg.system.mapper.StUserFaceimgSubIncremInfoMapper">
<!-- 查询 sys_user_sub.user_type=0 关联 st_user_faceimg 的数据和 sys_user_sub.user_type=1 关联st_user_faceimg_sub 的数据 -->
<select id="selectFaceImagesAndSubs" resultType="org.jeecg.user.entity.StUserFaceimgSubIncremInfo">
SELECT
f.id AS id,
f.user_id AS userId,
f.face_feature_data AS faceFeatureData,
0 userType,
s.realname,
s.status
FROM st_user_faceimg_sub_increm_info f
WHERE f.del_flag = 0
<if test="timestamp != null and timestamp !='' ">
AND f.create_time > FROM_UNIXTIME(#{timestamp} / 1000)
</if>
</select>
</mapper>
@@ -0,0 +1,135 @@
<?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="org.jeecg.system.mapper.SwUserFaceimgMapper">
<select id="getDepart" resultType="java.lang.String">
SELECT
ID
FROM
initdb.t_s_depart
WHERE
org_code = #{orgCode}
UNION
SELECT
ID
FROM
initdb.t_s_depart
WHERE
parentdepartid = ( SELECT id FROM initdb.t_s_depart WHERE org_code = #{orgCode} )
</select>
<select id="getUserImgUrl" resultType="java.util.Map">
SELECT
u.id ,
u.portrait
FROM
initdb.t_s_user_org uo
LEFT JOIN initdb.t_s_base_user bu ON bu.id = uo.user_id
LEFT JOIN initdb.t_s_user u ON bu.id = u.id
LEFT JOIN initdb.tbl_base_employee emp ON bu.id = emp.id
where uo.org_id in
<foreach collection="departIdList" item="departId" separator="," open="(" close=")">
#{departId}
</foreach>
and emp.emp_idcard is not null
and u.portrait is not null
</select>
<select id="getSecondDepartNotHaveFaceUrl" resultType="java.util.Map">
SELECT
dd.depart_name,su.id,su.realname,su.card_no,e.emp_idcard,uf.face_feature_data,uf.face_img_data
FROM
sys_user su
JOIN cq_base_employee e ON su.id = e.id
LEFT JOIN sys_user_depart sud ON sud.user_id = su.id AND sud.del_flag = 0
LEFT JOIN sys_depart sd ON sud.dep_id = sd.id AND sd.del_flag = 0
LEFT JOIN sys_depart dd ON LEFT ( sd.org_code, 6 ) = dd.org_code AND dd.del_flag = 0
LEFT JOIN st_user_faceimg uf ON su.id = uf.user_id AND uf.face_status = 1
WHERE su.user_identity = 6 and dd.id = #{secondDepartId}
AND (uf.face_feature_data is NULL or uf.face_img_data is NULL)
GROUP BY su.id
</select>
<select id="swUserFaceimgList" resultType="org.jeecg.user.vo.SwUserFaceimgWeightScaleVo">
SELECT
suf.*,
su.realname as name
FROM
st_user_faceimg suf
LEFT JOIN sys_user su on su.id = suf.user_id
LEFT JOIN cq_base_employee ce on ce.id = suf.user_id
WHERE ce.id is not null and su.id is not null and suf.card_number is not null
and suf.user_id is not null
and suf.face_feature_data is not null
and suf.face_status = 1
ORDER BY suf.id desc
</select>
<select id="swUserFaceimgListV2" resultType="org.jeecg.user.vo.SwUserFaceimgWeightScaleV2Vo">
SELECT
suf.face_img_data as faceImgData,
su.realname as name,
ce.emp_idcard as cardNumber
FROM
st_user_faceimg suf
LEFT JOIN sys_user su on su.id = suf.user_id
LEFT JOIN cq_base_employee ce on ce.id = suf.user_id
WHERE ce.id is not null and su.id is not null
and suf.user_id is not null
and suf.face_img_data is not null
AND LENGTH(suf.face_img_data) > 0
and suf.face_feature_data is not null
and suf.face_status = 1
and suf.face_source =0
GROUP BY suf.user_id
</select>
<select id="selectFaceImagesAndSubs" resultType="org.jeecg.user.entity.SwUserFaceimg">
SELECT
uf.id,
uf.user_id,
uf.face_feature_data
FROM
sys_user su
JOIN cq_base_employee e ON su.id = e.id
LEFT JOIN sys_user_depart sud ON sud.user_id = su.id
AND sud.del_flag = 0
LEFT JOIN sys_depart sd ON sud.dep_id = sd.id
LEFT JOIN sys_depart dd ON LEFT ( sd.org_code, 6 ) = dd.org_code AND dd.del_flag = 0
LEFT JOIN st_user_faceimg uf ON su.id = uf.user_id
AND uf.face_status = 1
WHERE
su.user_identity = 6
and dd.org_code = #{orgCode}
AND ( uf.face_feature_data IS not NULL);
</select>
<select id="selectUserIdByOrgCode" resultType="org.jeecg.emp.vo.UserInfoVo">
SELECT
su.id
FROM
sys_user su
JOIN cq_base_employee e ON su.id = e.id
LEFT JOIN sys_user_depart sud ON sud.user_id = su.id AND sud.del_flag = 0
LEFT JOIN sys_depart sd ON sud.dep_id = sd.id
LEFT JOIN sys_depart dd ON LEFT ( sd.org_code, 6 ) = dd.org_code AND dd.del_flag = 0
WHERE
su.user_identity = 6
and dd.org_code = #{orgCode};
</select>
<select id="getUserSubInfo" resultType="org.jeecg.user.entity.SysUserSub">
SELECT
uo.*
FROM
sys_user_sub uo
where
uo.del_flag = 0
<if test="status != null and status != ''">
and uo.status = #{status}
</if>
and uo.id = #{userId}
</select>
</mapper>
@@ -0,0 +1,5 @@
<?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="org.jeecg.system.mapper.SwUserFaceimgSelfMapper">
</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="org.jeecg.system.mapper.SwUserFaceimgSubMapper">
<select id="getDepart" resultType="java.lang.String">
SELECT
ID
FROM
initdb.t_s_depart
WHERE
org_code = #{orgCode}
UNION
SELECT
ID
FROM
initdb.t_s_depart
WHERE
parentdepartid = ( SELECT id FROM initdb.t_s_depart WHERE org_code = #{orgCode} )
</select>
<select id="getUserImgUrl" resultType="java.util.Map">
SELECT
u.id ,
u.portrait
FROM
initdb.t_s_user_org uo
LEFT JOIN initdb.t_s_base_user bu ON bu.id = uo.user_id
LEFT JOIN initdb.t_s_user u ON bu.id = u.id
LEFT JOIN initdb.tbl_base_employee emp ON bu.id = emp.id
where uo.org_id in
<foreach collection="departIdList" item="departId" separator="," open="(" close=")">
#{departId}
</foreach>
and emp.emp_idcard is not null
and u.portrait is not null
</select>
<select id="getSecondDepartNotHaveFaceUrl" resultType="java.util.Map">
SELECT
dd.depart_name,su.id,su.realname,su.card_no,e.emp_idcard,uf.face_feature_data,uf.face_img_data
FROM
sys_user su
JOIN cq_base_employee e ON su.id = e.id
LEFT JOIN sys_user_depart sud ON sud.user_id = su.id AND sud.del_flag = 0
LEFT JOIN sys_depart sd ON sud.dep_id = sd.id AND sd.del_flag = 0
LEFT JOIN sys_depart dd ON LEFT ( sd.org_code, 6 ) = dd.org_code AND dd.del_flag = 0
LEFT JOIN st_user_faceimg uf ON su.id = uf.user_id AND uf.face_status = 1
WHERE su.user_identity = 6 and dd.id = #{secondDepartId}
AND (uf.face_feature_data is NULL or uf.face_img_data is NULL)
GROUP BY su.id
</select>
<select id="swUserFaceimgList" resultType="org.jeecg.user.vo.SwUserFaceimgWeightScaleVo">
SELECT
suf.*,
su.realname as name
FROM
st_user_faceimg suf
LEFT JOIN sys_user su on su.id = suf.user_id
LEFT JOIN cq_base_employee ce on ce.id = suf.user_id
WHERE ce.id is not null and su.id is not null and suf.card_number is not null
and suf.user_id is not null
and suf.face_feature_data is not null
and suf.face_status = 1
ORDER BY suf.id desc
</select>
<select id="swUserFaceimgListV2" resultType="org.jeecg.user.vo.SwUserFaceimgWeightScaleV2Vo">
SELECT
suf.face_img_data as faceImgData,
su.realname as name,
ce.emp_idcard as cardNumber
FROM
st_user_faceimg suf
LEFT JOIN sys_user su on su.id = suf.user_id
LEFT JOIN cq_base_employee ce on ce.id = suf.user_id
WHERE ce.id is not null and su.id is not null
and suf.user_id is not null
and suf.face_img_data is not null
AND LENGTH(suf.face_img_data) > 0
and suf.face_feature_data is not null
and suf.face_status = 1
and suf.face_source =0
GROUP BY suf.user_id
</select>
<!-- 查询 sys_user_sub.user_type=0 关联 st_user_faceimg 的数据和 sys_user_sub.user_type=1 关联st_user_faceimg_sub 的数据 -->
<select id="selectFaceImagesAndSubs" resultType="org.jeecg.user.entity.SwUserFaceimgSub">
SELECT
f.id AS id,
f.user_id AS userId,
f.face_feature_data AS faceFeatureData,
0 userType,
s.realname,
s.status
FROM st_user_faceimg f
JOIN sys_user_sub s ON f.user_id = s.id
WHERE s.user_type = 0
and f.del_flag = 0
and f.face_status = 1
and s.del_flag = 0
and f.face_feature_data is not null
<if test="timestamp != null and timestamp !='' ">
AND f.create_time > FROM_UNIXTIME(#{timestamp} / 1000)
</if>
UNION ALL
SELECT
f.id AS id,
f.user_id AS userId,
f.face_feature_data AS faceFeatureData,
1 userType,
s.realname,
s.status
FROM st_user_faceimg_sub f
JOIN sys_user_sub s ON f.user_id = s.id
WHERE s.user_type != 0 and f.face_status = 1
and f.del_flag = 0
and s.del_flag = 0
and f.face_feature_data is not null
<if test="timestamp != null and timestamp !='' ">
AND f.create_time > FROM_UNIXTIME(#{timestamp} / 1000)
</if>
</select>
</mapper>
@@ -0,0 +1,5 @@
<?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="org.jeecg.modules.system.mapper.SysGatewayRouteMapper">
</mapper>
@@ -0,0 +1,62 @@
<?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="org.jeecg.system.mapper.SysPayDepartMapper">
<select id="queryUserDeparts" parameterType="String" resultType="org.jeecg.user.entity.SysPayDepart">
select * from sys_pay_depart where id IN ( select dep_id from sys_user_depart where user_id = #{userId} )
</select>
<!-- 根据username查询所拥有的部门 -->
<select id="queryDepartsByUsername" parameterType="String" resultType="org.jeecg.user.entity.SysPayDepart">
SELECT *
FROM sys_pay_depart
WHERE id IN (
SELECT dep_id
FROM sys_user_depart
WHERE user_id = (
SELECT id
FROM sys_user
WHERE username = #{username}
)
)
</select>
<!-- 根据部门Id查询,当前和下级所有部门IDS -->
<select id="getSubDepIdsByDepId" resultType="java.lang.String">
select id from sys_pay_depart where del_flag = '0' and org_code like concat((select org_code from sys_pay_depart where id=#{departId}),'%')
</select>
<!--根据部门编码获取我的部门下所有部门ids -->
<select id="getSubDepIdsByOrgCodes" resultType="java.lang.String">
select id from sys_pay_depart where del_flag = '0' and
<foreach collection="orgCodes" item="item" index="index" open="(" separator="or" close=")">
org_code LIKE CONCAT(#{item},'%')
</foreach>
</select>
<!--根据parent_id查询下级部门-->
<select id="queryTreeListByPid" parameterType="Object" resultType="org.jeecg.user.entity.SysPayDepart">
SELECT * FROM sys_pay_depart where del_flag = '0'
<choose>
<when test="parentId != null and parentId != ''">
AND parent_id = #{parentId,jdbcType=VARCHAR}
</when>
<otherwise>
AND parent_id is null or parent_id=''
</otherwise>
</choose>
order by depart_order
</select>
<!-- 根据OrgCod查询公司信息 -->
<select id="queryCompByOrgCode" resultType="org.jeecg.user.entity.SysPayDepart">
select * from sys_pay_depart where del_flag = '0' and org_category='1' and org_code= #{orgCode,jdbcType=VARCHAR}
</select>
<select id="findIdByName" resultType="java.lang.String">
SELECT
id
FROM
sys_pay_depart
WHERE
depart_name = #{name}
</select>
</mapper>
@@ -0,0 +1,5 @@
<?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="org.jeecg.system.mapper.SysUserMapper">
</mapper>
@@ -0,0 +1,5 @@
<?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="org.jeecg.system.mapper.SysUserScreenMapper">
</mapper>
@@ -0,0 +1,73 @@
<?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="org.jeecg.system.mapper.SysUserSubMapper">
<insert id="insertStClientMemberBalance" parameterType="org.jeecg.user.vo.StClientMemberBalanceVo">
INSERT INTO st_client_member_balance (
id,
member_id,
top_up_total,
top_up_balance,
reward_balance,
integral_balance,
consumption_count,
consumption_total,
last_consumption_time,
first_top_up_time,
invoice_total,
user_inner_type,
is_del,
is_status,
canteen_id,
create_by,
create_time,
is_sync
) VALUES (
#{id},
#{memberId},
#{topUpTotal, jdbcType=DECIMAL},
#{topUpBalance, jdbcType=DECIMAL},
#{rewardBalance, jdbcType=DECIMAL},
#{integralBalance, jdbcType=INTEGER},
#{consumptionCount, jdbcType=INTEGER},
#{consumptionTotal, jdbcType=DECIMAL},
#{lastConsumptionTime, jdbcType=TIMESTAMP},
#{firstTopUpTime, jdbcType=TIMESTAMP},
#{invoiceTotal, jdbcType=DECIMAL},
#{userInnerType, jdbcType=INTEGER},
#{isDel, jdbcType=INTEGER},
#{isStatus, jdbcType=INTEGER},
#{canteenId, jdbcType=VARCHAR},
#{createBy, jdbcType=VARCHAR},
#{createTime, jdbcType=TIMESTAMP},
#{isSync, jdbcType=INTEGER}
)
</insert>
<select id="selectByMemberId" parameterType="String" resultType="org.jeecg.user.vo.StClientMemberBalanceVo">
SELECT
id,
member_id AS memberId,
top_up_total AS topUpTotal,
top_up_balance AS topUpBalance,
reward_balance AS rewardBalance,
integral_balance AS integralBalance,
consumption_count AS consumptionCount,
consumption_total AS consumptionTotal,
last_consumption_time AS lastConsumptionTime,
first_top_up_time AS firstTopUpTime,
invoice_total AS invoiceTotal,
user_inner_type AS userInnerType,
is_del AS isDel,
is_status AS isStatus,
canteen_id AS canteenId,
create_by AS createBy,
create_time AS createTime,
update_by AS updateBy,
update_time AS updateTime,
is_sync AS isSync
FROM st_client_member_balance
WHERE member_id = #{memberId} AND is_del = 0
</select>
</mapper>
@@ -0,0 +1,14 @@
package org.jeecg.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.user.entity.StUserFaceimgSubIncremInfo;
/**
* @Description: 支付用户人脸信息增量记录表
* @Author: jeecg-boot
* @Date: 2022-04-12
* @Version: V1.0
*/
public interface IStUserFaceimgSubIncremInfoService extends IService<StUserFaceimgSubIncremInfo> {
}
@@ -0,0 +1,14 @@
package org.jeecg.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.user.entity.SwUserFaceimgSelf;
/**
* @Description: 用户人脸数据-自研引擎
* @Author: jeecg-boot
* @Date: 2022-04-12
* @Version: V1.0
*/
public interface ISwUserFaceimgSelfService extends IService<SwUserFaceimgSelf> {
}
@@ -0,0 +1,48 @@
package org.jeecg.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.common.api.vo.Result;
import org.jeecg.user.entity.SwUserFaceimg;
import org.jeecg.user.vo.UserFaceInfo;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
/**
* @Description: 用户人脸数据
* @Author: jeecg-boot
* @Date: 2022-04-12
* @Version: V1.0
*/
public interface ISwUserFaceimgService extends IService<SwUserFaceimg> {
/**
* 重新获取所有人脸数据到redis中
*/
void reputUserFaceDataToRedis();
String getImgUrlByBase64(String imgSrc);
/**
* 上传人脸压缩包
* @param request 文件
* @param dataType 数据标记 0:食堂,1:体重秤 2:公共
* @param dataStatus 用户借调数据状态(1:借调数据 ,否则默认非借调数据 )
* @return 上传人脸压缩包
*/
Result<?> uploadFaceImagePackage(HttpServletRequest request,Integer dataType,String dataStatus);
List<Map<String,Object>> getUserInfoNotHaveFaceUrlBySecondDepartId(String secondDepartId);
/**
* 发送扣费闸机人脸特征数据,删除/更新他本地数据
* @param userFaceInfo
* @param type type =0 人员特征删除数据
* type =1 人员特征新增数据
* type =3 人员特征初始化
* @param isConfirm 是否需要入库前确认扣费系统人员:true需要确认,false不需要确认
* @param userId isConfirm= true需要确认 ,根据userId确认
*/
void sendPaymentGateUserInfo(UserFaceInfo userFaceInfo, Integer type, Boolean isConfirm, String userId) ;
}
@@ -0,0 +1,28 @@
package org.jeecg.system.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.user.entity.SwUserFaceimgSub;
import java.util.List;
/**
* @Description: 用户人脸数据
* @Author: jeecg-boot
* @Date: 2022-04-12
* @Version: V1.0
*/
public interface ISwUserFaceimgSubService extends IService<SwUserFaceimgSub> {
/**
* 重新获取所有人脸数据到redis中
*/
void reputUserFaceDataToRedis();
IPage<SwUserFaceimgSub> queryPageList(Page<SwUserFaceimgSub> page);
List<SwUserFaceimgSub> queryPageList(Long timestamp);
}
@@ -0,0 +1,38 @@
package org.jeecg.system.service;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.system.entity.SysGatewayRoute;
/**
* @Description: gateway路由管理
* @Author: jeecg-boot
* @Date: 2020-05-26
* @Version: V1.0
*/
public interface ISysGatewayRouteService extends IService<SysGatewayRoute> {
/**
* 添加所有的路由信息到redis
* @param key
*/
void addRoute2Redis(String key);
/**
* 删除路由
* @param id
*/
void deleteById(String id);
/**
* 保存路由配置
* @param array
*/
void updateAll(JSONObject array);
/**
* 清空redis中的route信息
*/
void clearRedis();
}
@@ -0,0 +1,99 @@
package org.jeecg.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.user.entity.SysPayDepart;
import org.jeecg.user.vo.PayDepartIdModel;
import org.jeecg.user.vo.SysPayDepartTreeModel;
import java.util.List;
/**
* <p>
* 部门表 服务实现类
* <p>
*
*/
public interface ISysPayDepartService extends IService<SysPayDepart>{
/**
* 根据任意一级部门ID,查询其级联的所有部门ID(包括自身及所有子部门)
*
* @param deptId 部门ID
* @return 级联部门ID集合
*/
List<String> getAllCascadeDeptIds(String deptId);
/**
* 根据部门ID查询其完整层级路径(从顶级部门到当前部门)
* 例如:采气厂->定边保障点->定边外雇人员
*
* @param deptId 部门ID
* @return 层级路径字符串,若部门不存在则返回空
*/
String getDeptHierarchyName(String deptId);
/**
* 查询所有部门信息,并分节点进行显示
* @return
*/
List<SysPayDepartTreeModel> queryTreeListCach();
/**
* 根据type查询部门 目前type =1 查询二级部门以上的
* @return
*/
List<SysPayDepart> querySysDepartListBy();
/**
* 查询所有部门信息,并分节点进行显示
* @return
*/
List<SysPayDepartTreeModel> queryTreeList(String ids);
/**
* 查询所有部门DepartId信息,并分节点进行显示
* @return
*/
List<PayDepartIdModel> queryDepartIdTreeList();
/**
* 保存部门数据
* @param sysDepart
*/
void saveDepartData(SysPayDepart sysDepart,String username);
/**
* 更新depart数据
* @param sysDepart
* @return
*/
Boolean updateDepartDataById(SysPayDepart sysDepart,String username);
/**
* 根据关键字搜索相关的部门数据
* @param keyWord
* @return
*/
List<SysPayDepartTreeModel> searchByKeyWord(String keyWord,String myDeptSearch,String departIds);
/**
* 根据部门id删除并删除其可能存在的子级部门
* @param id
* @return
*/
boolean delete(String id);
/**
* 根据部门id批量删除并删除其可能存在的子级部门
* @return
*/
void deleteBatchWithChildren(List<String> ids);
}
@@ -0,0 +1,14 @@
package org.jeecg.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.user.entity.SysUserScreen;
/**
* @Description: s
* @Author: yucl
* @Date: 2022-04-20
* @Version: V1.0
*/
public interface ISysUserScreenService extends IService<SysUserScreen> {
}

Some files were not shown because too many files have changed in this diff Show More