新功能及bug修改

This commit is contained in:
hejiayang
2025-11-29 20:54:54 +08:00
parent b10310a8fa
commit 46476badc7
42 changed files with 1259 additions and 81 deletions
@@ -445,4 +445,12 @@ public interface CommonConstant {
// 食堂支付人脸数据键名 // 食堂支付人脸数据键名
String FACE_CACHE_PAY = "FACE_CACHE_PAY"; String FACE_CACHE_PAY = "FACE_CACHE_PAY";
/**
* 设备状态缓存 key: 设备编号 value 时间戳
*/
String DEVICE_STATUS = "device_status";
/**
* 下发信息缓存 key: 设备编号
*/
String ISSUE_INFORMATION = "issue_information";
} }
@@ -10,5 +10,13 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-system-local-api</artifactId> <artifactId>jeecg-system-local-api</artifactId>
<dependencies>
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>5.7.1</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project> </project>
@@ -46,6 +46,10 @@ public class StUserBalanceVo {
* 用户类型 0正式 1非正式 2家庭成员 * 用户类型 0正式 1非正式 2家庭成员
*/ */
private String userType; private String userType;
/**
* 家庭成员 对应主用户id
*/
private String mainUserId;
/** /**
* 食堂id * 食堂id
*/ */
@@ -0,0 +1,16 @@
package org.jeecg.equipment.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class StEquipmentDto {
@Schema(title = "设备名称编码")
private String appPackageLocalUrl;
@Schema(title = "所在位置")
private String placement;
@Schema(title = "备注")
private String remark;
}
@@ -0,0 +1,63 @@
package org.jeecg.equipment.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.jeecgframework.poi.excel.annotation.Excel;
import java.io.Serializable;
import java.util.Date;
/**
* @Description: 设备管理表
* @Author: jeecg-boot
* @Date: 2022-08-30
* @Version: V1.0
*/
@Data
@TableName("st_canteen_equipment")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@Tag(name="st_canteen_equipment对象", description="食堂设备表")
public class StCanteenEquipment implements Serializable {
private static final long serialVersionUID = 1L;
/**主键*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(title = "设备编码")
private String equipmentCode;
/**食堂id*/
@Schema(title = "食堂id")
private String canteenId;
@Schema(title = "设备ip")
private String equipmentIp;
/**
* 本地人脸数
*/
@Schema(title = "本地人脸数")
private Integer faceNum;
/**
* 设备剩余存储量
*/
@Schema(title = "设备剩余存储量")
private String availableMemory;
/**创建日期*/
@Schema(title = "创建日期")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**更新日期*/
@Schema(title = "更新日期")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
}
@@ -117,4 +117,10 @@ public class StEquipment implements Serializable {
/**所属餐道餐道中的顺序*/ /**所属餐道餐道中的顺序*/
@Schema(title = "所属餐道餐道中的顺序") @Schema(title = "所属餐道餐道中的顺序")
private Integer owningTrackOrder; private Integer owningTrackOrder;
@Schema(title = "所在位置")
private String placement;
@Schema(title = "备注")
private String remark;
} }
@@ -19,6 +19,8 @@ public class StClientMemberTransactionRecordDTO {
@DateTimeFormat(pattern="yyyy-MM-dd") @DateTimeFormat(pattern="yyyy-MM-dd")
@Schema(title ="就餐时间") @Schema(title ="就餐时间")
private String mainTimeDay; private String mainTimeDay;
private String startDate;
private String endDate;
private String startTime; private String startTime;
@@ -82,4 +84,7 @@ public class StClientMemberTransactionRecordDTO {
//直接部门ID //直接部门ID
private String departId; private String departId;
@Schema(title ="餐次")
private String dinnerType;
} }
@@ -0,0 +1,46 @@
package org.jeecg.payment.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import java.util.List;
/**
*/
@Data
@Tag(name= "StExceptionRecordDTO对象", description = "消费异常记录")
public class StExceptionRecordDTO {
/**
* 时间区间
*/
private List<String> dates;
private String startTime;
private String endTime;
@Schema(title ="手机号")
private String phone;
@Schema(title ="会员姓名")
private String userName;
@Schema(title ="工号")
private String workNo;
@Schema(title ="卡号")
private String cardCode;
//直接部门ID
private String departId;
@Schema(title="部门集合")
private List<String> list;
@Schema(title ="当前页")
private Integer pageNo;
@Schema(title ="数量/页")
private Integer pageSize;
}
@@ -43,6 +43,10 @@ public class StBbzxOrderInfo extends JeecgEntity implements Serializable {
@Schema(title ="餐次名称") @Schema(title ="餐次名称")
private String dinnerType; private String dinnerType;
@Schema(title ="设备编码")
private String deviceCode;
/** /**
* 经营模式、扣费类型(1:固定扣费,2:固定+补贴扣费,3:按量扣费) * 经营模式、扣费类型(1:固定扣费,2:固定+补贴扣费,3:按量扣费)
*/ */
@@ -38,6 +38,9 @@ public class StClientMemberTransactionRecord extends JeecgEntity implements Seri
@Schema(title ="交易流水号") @Schema(title ="交易流水号")
private String serialNo; private String serialNo;
@Schema(title ="设备编码")
private String deviceCode;
/** /**
* 订单号 * 订单号
*/ */
@@ -0,0 +1,66 @@
/**
* use shuwei code generator created
*/
package org.jeecg.payment.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
@Data
@TableName("st_consumption_exception_record")
@EqualsAndHashCode(callSuper = false)
@Tag(name= "StConsumptionExceptionRecord对象", description = "异常消费流水")
public class StConsumptionExceptionRecord implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(type = IdType.ASSIGN_ID)
@Schema(title ="ID")
private String id;
@Schema(title ="用户id")
private String userId;
@Schema(title ="设备编码")
private String deviceCode;
@Schema(title ="食堂ID")
private String canteenId;
@Schema(title ="卡号")
private String cardCode;
@Schema(title ="支付唯一id")
private String payId;
@Schema(title ="消费时间(时间戳)")
private String dateTime;
@Schema(title ="消费时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date payTime;
@Schema(title ="消费金额")
private BigDecimal spendMoney;
@Schema(title ="二次扣费标记 1 是; 0 否")
private Integer secondChargeFlag;
@Schema(title ="自定义扣费标记 1 是 ; 0 否")
private Integer isCustom;
@Schema(title ="恢复标记 1 是; 0 否")
private Integer isRestore;
/**创建日期*/
@Schema(title = "创建日期")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**更新日期*/
@Schema(title = "更新日期")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
}
@@ -0,0 +1,34 @@
package org.jeecg.payment.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class StCanteenEquipmentVo {
@Schema(description = "食堂id")
private String canteenId;
@Schema(description = "食堂名称")
private String restName;
@Schema(description = "设备名称")
private String equipmentName;
@Schema(description = "设备编码")
private String equipmentCode;
@Schema(description = "设备编码(前端展示)")
private String appPackageLocalUrl;
@Schema(description = "所在位置")
private String placement;
@Schema(description = "设备描述")
private String remark;
@Schema(description = "设备ip")
private String equipmentIp;
@Schema(description = "本地人脸数")
private Integer faceNum;
@Schema(description = "设备剩余存储量")
private String availableMemory;
@Schema(description = "设备状态: 0离线 1在线")
private String status;
@Schema(description = "上传数量")
private Integer totalNum;
}
@@ -0,0 +1,51 @@
package org.jeecg.payment.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.jeecg.common.util.BigDecimalSerialize;
import java.math.BigDecimal;
import java.util.Date;
@Data
public class StExceptionRecordVo {
@Schema(title ="id")
private String id;
@Schema(title ="卡号")
private String cardCode;
@Schema(title ="会员姓名")
private String userName;
@Schema(title ="会员电话")
private String phone;
@Schema(title ="工号")
private String workNo;
@Schema(title ="本次扣费金额")
private BigDecimal spendMoney;
@Schema(title ="自定义扣费标记 1 是 ; 0 否")
private Integer isCustom;
@Schema(title ="恢复标记 1 已恢复; 0 否")
private Integer isRestore;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@Schema(title ="消费时间")
private Date payTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@Schema(title ="数据上传时间")
private Date createTime;
@Schema(title ="食堂名称")
private String restName;
@Schema(title ="餐次名称")
private String dinnerType;
@Schema(title ="部门名称")
private String deptName;
}
@@ -0,0 +1,14 @@
package org.jeecg.payment.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class StRecordNumVo {
@Schema(description = "数量")
private Integer num;
@Schema(description = "设备编码")
private String deviceCode;
}
@@ -1,5 +1,6 @@
package org.jeecg.payment.vo; package org.jeecg.payment.vo;
import com.opencsv.bean.CsvBindByName;
import lombok.Data; import lombok.Data;
import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotEmpty;
@@ -14,6 +15,7 @@ import java.math.BigDecimal;
@Data @Data
public class StRfidVo { public class StRfidVo {
// @NotEmpty(message = "用户ID不能为空") // @NotEmpty(message = "用户ID不能为空")
@CsvBindByName(column = "user_id")
private String userId; private String userId;
@NotEmpty(message = "设备编码不能为空") @NotEmpty(message = "设备编码不能为空")
private String deviceCode; private String deviceCode;
@@ -22,25 +24,35 @@ public class StRfidVo {
/** /**
* 卡号 * 卡号
*/ */
@CsvBindByName(column = "card_code")
private String cardCode; private String cardCode;
/** /**
* 闸机记录的支付唯一id(用于判断防止重复支付的标记) * 闸机记录的支付唯一id(用于判断防止重复支付的标记)
*/ */
@CsvBindByName(column = "pay_id")
private String payId; private String payId;
//===离线扣费场景参数 //===离线扣费场景参数
//消费时间(时间戳) //消费时间(时间戳)
@CsvBindByName(column = "date_time")
private String dateTime; private String dateTime;
//本次扣费金额(后端根据规则计算) //本次扣费金额(后端根据规则计算)
@CsvBindByName(column = "spend_money")
private BigDecimal spendMoney; private BigDecimal spendMoney;
/** /**
* 二次扣费标记 1 是; 0 否 * 二次扣费标记 1 是; 0 否
*/ */
@CsvBindByName(column = "second_charge_flag")
private Integer secondChargeFlag; private Integer secondChargeFlag;
/** /**
* 自定义扣费标记 1 是 ; 0 否 * 自定义扣费标记 1 是 ; 0 否
*/ */
@CsvBindByName(column = "is_custom")
private Integer isCustom; private Integer isCustom;
/**
* 恢复标记 1 是; 0 否
*/
private Integer isRestore;
} }
@@ -0,0 +1,20 @@
package org.jeecg.system.vo;
import lombok.Data;
import org.jeecg.user.entity.StUserFaceimgSubIncremInfo;
import java.util.List;
@Data
public class SwHeartbeatFaceVo {
/**
* 是否下发
*/
private boolean isIssue;
/**
* 人脸数据
*/
private List<StUserFaceimgSubIncremInfo> faceList;
}
@@ -521,6 +521,34 @@
limit 1 limit 1
</select> </select>
<select id="getUserBalanceList" resultType="org.jeecg.emp.vo.StUserBalanceVo"> <select id="getUserBalanceList" resultType="org.jeecg.emp.vo.StUserBalanceVo">
<!-- SELECT-->
<!-- us.id,-->
<!-- us.realname,-->
<!-- us.card_code,-->
<!-- us.card_code_status,-->
<!-- IF(us.card_code_status = 1,'正常',IF(us.card_code_status = 2, '挂失','未绑定/已解绑')) card_code_status_name,-->
<!-- us.phone,-->
<!-- us.work_no,-->
<!-- us.card_no,-->
<!-- us.depart_ids,-->
<!-- us.user_type,-->
<!-- us.canteen_id,-->
<!-- us.main_user_id,-->
<!-- IFNULL(( mb.top_up_balance + mb.reward_balance ),0) balance-->
<!-- FROM-->
<!-- sys_user_sub us-->
<!-- <if test="timestamp == null">-->
<!-- left join st_client_member_balance mb ON us.id = mb.member_id-->
<!-- </if>-->
<!-- <if test="timestamp != null and timestamp !='' ">-->
<!-- join st_client_member_balance mb ON us.id = mb.member_id-->
<!-- AND (mb.create_time > FROM_UNIXTIME(#{timestamp} / 1000)-->
<!-- or us.update_time > FROM_UNIXTIME(#{timestamp} / 1000)-->
<!-- or us.create_time > FROM_UNIXTIME(#{timestamp} / 1000)-->
<!-- or mb.update_time > FROM_UNIXTIME(#{timestamp} / 1000)-->
<!-- or mb.last_consumption_time > FROM_UNIXTIME(#{timestamp} / 1000))-->
<!-- </if>-->
SELECT SELECT
us.id, us.id,
us.realname, us.realname,
@@ -533,14 +561,35 @@
us.depart_ids, us.depart_ids,
us.user_type, us.user_type,
us.canteen_id, us.canteen_id,
us.main_user_id,
IFNULL(( mb.top_up_balance + mb.reward_balance ),0) balance IFNULL(( mb.top_up_balance + mb.reward_balance ),0) balance
FROM FROM
sys_user_sub us sys_user_sub us
JOIN st_client_member_balance mb ON us.id = mb.member_id <if test="timestamp == 0">
<if test="timestamp != null and timestamp !='' "> LEFT JOIN st_client_member_balance mb ON us.id = mb.member_id
AND (mb.create_time > FROM_UNIXTIME(#{timestamp} / 1000) </if>
or mb.update_time > FROM_UNIXTIME(#{timestamp} / 1000) <if test="timestamp > 0">
or mb.last_consumption_time > FROM_UNIXTIME(#{timestamp} / 1000)) LEFT JOIN (
</if> SELECT
member_id,
top_up_balance,
reward_balance,
(top_up_balance + reward_balance) AS balance
FROM
st_client_member_balance
WHERE
create_time > FROM_UNIXTIME(#{timestamp} / 1000)
OR update_time > FROM_UNIXTIME(#{timestamp} / 1000)
OR last_consumption_time > FROM_UNIXTIME(#{timestamp} / 1000)
) mb ON us.id = mb.member_id
</if>
WHERE 1=1
<if test="timestamp > 0">
AND (
us.update_time > FROM_UNIXTIME(#{timestamp} / 1000)
OR us.create_time > FROM_UNIXTIME(#{timestamp} / 1000)
OR mb.member_id IS NOT NULL
)
</if>
</select> </select>
</mapper> </mapper>
@@ -1,24 +0,0 @@
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> {
}
@@ -1,18 +1,26 @@
package org.jeecg.equipment.controller; package org.jeecg.equipment.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result; import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog; import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController; import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.util.JwtUtil; import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.equipment.dto.StEquipmentDto;
import org.jeecg.equipment.entity.StEquipment; import org.jeecg.equipment.entity.StEquipment;
import org.jeecg.equipment.service.IStCanteenEquipmentService;
import org.jeecg.equipment.service.IStEquipmentService; import org.jeecg.equipment.service.IStEquipmentService;
import org.jeecg.payment.vo.StCanteenEquipmentVo;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List; import java.util.List;
/** /**
@@ -25,9 +33,13 @@ import java.util.List;
@RestController @RestController
@RequestMapping("/restaurant/equipment/stEquipment") @RequestMapping("/restaurant/equipment/stEquipment")
@Slf4j @Slf4j
public class StRestaurantEquipmentController extends JeecgController<StEquipment, IStEquipmentService> { public class StRestaurantEquipmentController {
@Autowired @Autowired
private IStEquipmentService stEquipmentService; private IStEquipmentService stEquipmentService;
@Resource
private IStCanteenEquipmentService stCanteenEquipmentService;
@Resource
private RedisUtil redisUtil;
/** /**
@@ -52,4 +64,65 @@ public class StRestaurantEquipmentController extends JeecgController<StEquipment
return Result.OK(token); return Result.OK(token);
} }
/**
* 获取设备列表根据食堂id
*/
@Operation(summary = "获取设备列表根据食堂id", description = "获取设备列表根据食堂id")
@GetMapping("/getEquipmentListByCanteenId")
@AutoLog(value = "获取设备列表根据食堂id")
public Result<List<StEquipment>> getEquipmentListByCanteenId(@RequestParam(name = "canteenId", required = true) String canteenId) {
if(StringUtils.isBlank(canteenId)){
return Result.error("参数异常");
}
List<StEquipment> stEquipmentList = stEquipmentService.getEquipmentList(canteenId);
return Result.OK(stEquipmentList);
}
/**
* 保存设备
* @param dto 设备信息
* @return 保存结果
*/
@Operation(summary = "保存设备", description = "保存设备")
@PostMapping("/saveEquipment")
@AutoLog(value = "保存设备")
public Result<String> saveEquipment(@RequestBody StEquipmentDto dto) {
if(StringUtils.isBlank(dto.getAppPackageLocalUrl())){
return Result.error("设备编码不能为空");
}
LambdaUpdateWrapper<StEquipment> stEquipmentLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
stEquipmentLambdaUpdateWrapper
.eq(StEquipment::getAppPackageLocalUrl, dto.getAppPackageLocalUrl())
.set(StEquipment::getPlacement, dto.getPlacement())
.set(StEquipment::getRemark, dto.getRemark());
stEquipmentService.update(stEquipmentLambdaUpdateWrapper);
return Result.OK("操作成功");
}
/**
* 设备管理列表
* @param canteenId 食堂id
* @param appPackageLocalUrl 设备编码
* @param pageNo 页码
* @param pageSize 每页条数
* @return 设备管理列表
*/
@Operation(summary = "设备管理列表", description = "设备管理列表")
@GetMapping("/pageList")
@AutoLog(value = "设备管理列表")
public Result<IPage<StCanteenEquipmentVo>> pageList(@RequestParam(name = "canteenId",required = false) String canteenId,
@RequestParam(name = "appPackageLocalUrl",required = false) String appPackageLocalUrl,
@RequestParam(name = "pageNo",required = false,defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize",required = false,defaultValue = "10") Integer pageSize){
return Result.OK(stCanteenEquipmentService.pageList(canteenId,appPackageLocalUrl,pageNo,pageSize));
}
@Operation(summary = "下发用户信息", description = "下发用户信息")
@GetMapping("/issueInformation")
@AutoLog(value = "下发用户信息")
public Result<String> issueInformation(@RequestParam(name = "equipmentCode") String equipmentCode){
redisUtil.hset(CommonConstant.ISSUE_INFORMATION,equipmentCode,"1");
return Result.OK("命令发送成功");
}
} }
@@ -0,0 +1,23 @@
package org.jeecg.equipment.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.jeecg.equipment.entity.StCanteenEquipment;
import org.jeecg.payment.vo.StCanteenEquipmentVo;
import org.jeecg.payment.vo.StRecordNumVo;
import java.util.List;
public interface StCanteenEquipmentMapper extends BaseMapper<StCanteenEquipment> {
IPage<StCanteenEquipmentVo> pageList(@Param("page") Page<StCanteenEquipmentVo> page, @Param("canteenId") String canteenId,@Param("appPackageLocalUrl") String appPackageLocalUrl);
List<StRecordNumVo> getNormalNum(@Param("list") List<String> deviceCodes);
List<StRecordNumVo> getAbnormalNum(@Param("list") List<String> deviceCodes);
}
@@ -1,8 +1,11 @@
package org.jeecg.equipment.mapper; package org.jeecg.equipment.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.jeecg.equipment.entity.StEquipment; import org.jeecg.equipment.entity.StEquipment;
import java.util.List;
/** /**
* @Description: 设备管理表 * @Description: 设备管理表
* @Author: jeecg-boot * @Author: jeecg-boot
@@ -11,4 +14,5 @@ import org.jeecg.equipment.entity.StEquipment;
*/ */
public interface StEquipmentMapper extends BaseMapper<StEquipment> { public interface StEquipmentMapper extends BaseMapper<StEquipment> {
List<StEquipment> getEquipmentList(@Param("canteenId") String canteenId);
} }
@@ -0,0 +1,58 @@
<?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.StCanteenEquipmentMapper">
<select id="pageList" resultType="org.jeecg.payment.vo.StCanteenEquipmentVo">
SELECT
r.id canteen_id,
r.rest_name,
e.equipment_name,
e.equipment_code,
e.app_package_local_url,
e.placement,
e.remark,
ce.equipment_ip,
ce.face_num,
ce.available_memory
FROM
st_base_restaurant r
LEFT JOIN st_equipment e ON r.rest_no = e.canteen_id
LEFT JOIN st_canteen_equipment ce ON ce.equipment_code = e.equipment_code
WHERE e.equipment_name = 'com.sw.billing'
<if test="canteenId != null and canteenId != ''">
AND r.id = #{canteenId}
</if>
<if test="appPackageLocalUrl != null and appPackageLocalUrl != ''">
AND e.app_package_local_url LIKE CONCAT(CONCAT('%', #{appPackageLocalUrl}), '%')
</if>
</select>
<select id="getNormalNum" resultType="org.jeecg.payment.vo.StRecordNumVo">
SELECT
r.device_code,
COUNT(r.id) num
FROM
st_client_member_transaction_record r
WHERE
r.`status` = 101
AND r.device_code IN
<foreach item="item" collection="list" separator="," open="(" close=")">
#{item}
</foreach>
GROUP BY r.device_code
</select>
<select id="getAbnormalNum" resultType="org.jeecg.payment.vo.StRecordNumVo">
SELECT
r.device_code,
COUNT(r.id) num
FROM
st_consumption_exception_record r
WHERE
r.device_code IN
<foreach item="item" collection="list" separator="," open="(" close=")">
#{item}
</foreach>
GROUP BY r.device_code
</select>
</mapper>
@@ -2,4 +2,13 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!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 namespace="org.jeecg.equipment.mapper.StEquipmentMapper">
<select id="getEquipmentList" resultType="org.jeecg.equipment.entity.StEquipment">
SELECT
e.*
FROM
st_equipment e
LEFT JOIN st_base_restaurant r ON e.canteen_id = r.rest_no
WHERE
r.id = #{canteenId}
</select>
</mapper> </mapper>
@@ -0,0 +1,16 @@
package org.jeecg.equipment.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.equipment.entity.StCanteenEquipment;
import org.jeecg.equipment.entity.StEquipment;
import org.jeecg.payment.vo.StCanteenEquipmentVo;
import java.util.List;
public interface IStCanteenEquipmentService extends IService<StCanteenEquipment> {
IPage<StCanteenEquipmentVo> pageList(String canteenId, String appPackageLocalUrl, Integer pageNo, Integer pageSize);
}
@@ -3,6 +3,8 @@ package org.jeecg.equipment.service;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.equipment.entity.StEquipment; import org.jeecg.equipment.entity.StEquipment;
import java.util.List;
/** /**
* @Description: 设备管理表 * @Description: 设备管理表
* @Author: jeecg-boot * @Author: jeecg-boot
@@ -11,4 +13,5 @@ import org.jeecg.equipment.entity.StEquipment;
*/ */
public interface IStEquipmentService extends IService<StEquipment> { public interface IStEquipmentService extends IService<StEquipment> {
List<StEquipment> getEquipmentList(String canteenId);
} }
@@ -0,0 +1,64 @@
package org.jeecg.equipment.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.collections4.CollectionUtils;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.equipment.entity.StCanteenEquipment;
import org.jeecg.equipment.mapper.StCanteenEquipmentMapper;
import org.jeecg.equipment.service.IStCanteenEquipmentService;
import org.jeecg.payment.vo.StCanteenEquipmentVo;
import org.jeecg.payment.vo.StRecordNumVo;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
public class StCanteenEquipmentServiceImpl extends ServiceImpl<StCanteenEquipmentMapper, StCanteenEquipment> implements IStCanteenEquipmentService {
@Resource
private RedisUtil redisUtil;
@Override
public IPage<StCanteenEquipmentVo> pageList(String canteenId,String appPackageLocalUrl,Integer pageNo,Integer pageSize){
Page<StCanteenEquipmentVo> page = new Page<>(pageNo, pageSize);
IPage<StCanteenEquipmentVo> stCanteenEquipmentVoIPage = baseMapper.pageList(page, canteenId, appPackageLocalUrl);
if(CollectionUtils.isNotEmpty(stCanteenEquipmentVoIPage.getRecords())){
List<String> collect = stCanteenEquipmentVoIPage.getRecords().stream().map(StCanteenEquipmentVo::getEquipmentCode).collect(Collectors.toList());
List<StRecordNumVo> normalNum = baseMapper.getNormalNum(collect);
List<StRecordNumVo> abnormalNum = baseMapper.getAbnormalNum(collect);
Map<String, Integer> normalNumMap = normalNum.stream().collect(Collectors.toMap(StRecordNumVo::getDeviceCode, StRecordNumVo::getNum));
Map<String, Integer> abnormalNumMap = abnormalNum.stream().collect(Collectors.toMap(StRecordNumVo::getDeviceCode,StRecordNumVo::getNum));
Map<Object, Object> hmget = redisUtil.hmget(CommonConstant.DEVICE_STATUS);
long oneMinuteMs = 2 * 60 * 1000;
stCanteenEquipmentVoIPage.getRecords().forEach(equipment ->{
//设备上传数据量
Integer a = normalNumMap.get(equipment.getEquipmentCode()) == null ? 0 : normalNumMap.get(equipment.getEquipmentCode());
Integer b = abnormalNumMap.get(equipment.getEquipmentCode()) == null ? 0 : abnormalNumMap.get(equipment.getEquipmentCode());
equipment.setTotalNum(a+b);
equipment.setStatus("离线");
//设备状态
Object o = hmget.get(equipment.getEquipmentCode());
if(o != null){
//对比设备心跳时间与当前时间, 如果时间差小于2分钟 , 视为在线
long deviceTime = Long.parseLong((String) o);
long now = new Date().getTime();
if(now - deviceTime > oneMinuteMs){
equipment.setStatus("在线");
}
}
});
}
return stCanteenEquipmentVoIPage;
}
}
@@ -1,5 +1,6 @@
package org.jeecg.equipment.service.impl; package org.jeecg.equipment.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.jeecg.equipment.entity.StEquipment; import org.jeecg.equipment.entity.StEquipment;
import org.jeecg.equipment.mapper.StEquipmentMapper; import org.jeecg.equipment.mapper.StEquipmentMapper;
import org.jeecg.equipment.service.IStEquipmentService; import org.jeecg.equipment.service.IStEquipmentService;
@@ -7,6 +8,8 @@ import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import java.util.List;
/** /**
* @Description: 设备管理表 * @Description: 设备管理表
* @Author: jeecg-boot * @Author: jeecg-boot
@@ -16,4 +19,8 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@Service @Service
public class StEquipmentServiceImpl extends ServiceImpl<StEquipmentMapper, StEquipment> implements IStEquipmentService { public class StEquipmentServiceImpl extends ServiceImpl<StEquipmentMapper, StEquipment> implements IStEquipmentService {
@Override
public List<StEquipment> getEquipmentList(String canteenId) {
return baseMapper.getEquipmentList(canteenId);
}
} }
@@ -112,13 +112,89 @@ public class StPayController {
@AutoLog(value = "获取用户类型,余额信息") @AutoLog(value = "获取用户类型,余额信息")
public Result<?> getUserBalanceList(@RequestParam(name = "pageNo", required = false) Integer pageNo, public Result<?> getUserBalanceList(@RequestParam(name = "pageNo", required = false) Integer pageNo,
@RequestParam(name = "pageSize", required = false) Integer pageSize, @RequestParam(name = "pageSize", required = false) Integer pageSize,
@RequestParam(name = "timestamp", required = false) Long timestamp){ @RequestParam(name = "timestamp", required = false, defaultValue = "0") Long timestamp){
if(null == pageNo || pageSize == 0){ if(null == pageNo || pageSize == 0){
log.error("getUserBalanceList 用户信息,分页调用全量数据");
return Result.OK(cqBaseEmployeeService.getUserBalanceList(timestamp)); return Result.OK(cqBaseEmployeeService.getUserBalanceList(timestamp));
}else { }else {
log.error("getUserBalanceList 用户信息心跳 时间戳,timestamp={},date = {}", JSONObject.toJSONString(timestamp), DateUtil.format(new Date(timestamp), "yyyy-MM-dd HH:mm:ss"));
return Result.OK(cqBaseEmployeeService.getUserBalanceList(pageNo, pageSize, timestamp)); return Result.OK(cqBaseEmployeeService.getUserBalanceList(pageNo, pageSize, timestamp));
} }
} }
/**
* 离线人脸扣费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,false);
}
/**
* 在线扣费
* @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,true);
}
@@ -243,35 +319,6 @@ public class StPayController {
return Result.OK("扣费成功"); 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);
}
/** /**
@@ -344,6 +344,7 @@ public class StBbzxOrderInfoController {
StClientMemberTransactionRecordVO stClientMemberTransactionRecordVO = new StClientMemberTransactionRecordVO();//只汇总交易金额 StClientMemberTransactionRecordVO stClientMemberTransactionRecordVO = new StClientMemberTransactionRecordVO();//只汇总交易金额
stClientMemberTransactionRecordVO.setSerialNo("总计"); stClientMemberTransactionRecordVO.setSerialNo("总计");
stClientMemberTransactionRecordVO.setTransactionAmount(sumResult.getTransactionAmount()); stClientMemberTransactionRecordVO.setTransactionAmount(sumResult.getTransactionAmount());
stClientMemberTransactionRecordVO.setAvailableBalance(sumResult.getAvailableBalance());
return Result.OK(stClientMemberTransactionRecordVO); return Result.OK(stClientMemberTransactionRecordVO);
} }
@@ -512,6 +512,12 @@ public class StClientMemberBalanceController {
query.setStartTime(split[0]); query.setStartTime(split[0]);
query.setEndTime(split[1]); query.setEndTime(split[1]);
} }
if(StringUtils.isNotBlank(query.getStartDate())){
query.setStartTime(query.getStartDate());
}
if(StringUtils.isNotBlank(query.getEndDate())){
query.setStartTime(query.getEndDate());
}
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
//餐品总库只查询内置食堂 //餐品总库只查询内置食堂
if(sysUser.getUserIdentity().equals(CommonConstant.USER_IDENTITY_0) || sysUser.getUserIdentity().equals(CommonConstant.USER_IDENTITY_1)){ if(sysUser.getUserIdentity().equals(CommonConstant.USER_IDENTITY_0) || sysUser.getUserIdentity().equals(CommonConstant.USER_IDENTITY_1)){
@@ -0,0 +1,122 @@
package org.jeecg.payment.controller;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.v3.oas.annotations.tags.Tag;
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.payment.dto.StExceptionRecordDTO;
import org.jeecg.payment.entity.StConsumptionExceptionRecord;
import org.jeecg.payment.service.IStClientMemberLevelDeductRuleService;
import org.jeecg.payment.service.IStConsumptionExceptionRecordService;
import org.jeecg.payment.utils.ExcelUtils;
import org.jeecg.payment.vo.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.List;
@RestController
@RequestMapping("/payment/exceptionRecord")
@Tag(name = "消费异常流水")
public class StConsumptionExceptionRecordController {
@Resource
private IStConsumptionExceptionRecordService stConsumptionExceptionRecordService;
@Resource
private IStClientMemberLevelDeductRuleService iStClientMemberLevelDeductRuleService;
@RequestMapping("/restore")
@Tag(name = "恢复")
@AutoLog(value = "恢复")
public Result<StClientMemberSpendVO> restore(String id) {
StConsumptionExceptionRecord record = stConsumptionExceptionRecordService.getById(id);
StRfidVo stRfidVo = new StRfidVo();
stRfidVo.setUserId(record.getUserId());
stRfidVo.setDeviceCode(record.getDeviceCode());
stRfidVo.setRestId(record.getCanteenId());
stRfidVo.setCardCode(record.getCardCode());
stRfidVo.setPayId(record.getPayId());
stRfidVo.setDateTime(record.getDateTime());
stRfidVo.setSpendMoney(record.getSpendMoney());
stRfidVo.setSecondChargeFlag(record.getSecondChargeFlag());
stRfidVo.setIsCustom(record.getIsCustom());
stRfidVo.setIsRestore(1);
StRfidoffLineVo stRfidoffLineVo = new StRfidoffLineVo();
stRfidoffLineVo.setDeviceCode(stRfidVo.getDeviceCode());
stRfidoffLineVo.setVoList(Collections.singletonList(stRfidVo));
stRfidoffLineVo.setRestId(stRfidVo.getRestId());
//防止循环调用, 写在Controller层
//走扣费逻辑
Result<StClientMemberSpendVO> result = iStClientMemberLevelDeductRuleService.bindUserOfflineCardCode(stRfidoffLineVo,true);
if (result.isSuccess()) {
//更新恢复状态
stConsumptionExceptionRecordService.update(new LambdaUpdateWrapper<StConsumptionExceptionRecord>()
.set(StConsumptionExceptionRecord::getIsRestore, 1)
.eq(StConsumptionExceptionRecord::getId, id));
}
return result;
}
@PostMapping("/pageList")
@Tag(name = "异常流水列表")
@AutoLog(value = "异常流水列表")
public Result<IPage<StExceptionRecordVo>> pageList(@RequestBody StExceptionRecordDTO query){
return Result.OK(stConsumptionExceptionRecordService.exceptionRecordPage(query));
}
@GetMapping("/export")
@AutoLog(value = "异常流水列表导出")
public void getSpendingOrRechargeInfoListExport(HttpServletResponse response,
@RequestParam(name = "startDate", required = false) String startDate,
@RequestParam(name = "endDate", required = false) String endDate) {
StExceptionRecordDTO query = new StExceptionRecordDTO();
if(StringUtils.isNotBlank(startDate)){
query.setStartTime(startDate);
}
if(StringUtils.isNotBlank(startDate)){
query.setEndTime(endDate);
}
List<StExceptionRecordVo> stExceptionRecordVos = stConsumptionExceptionRecordService.exceptionRecordPageExport(query);
if(CollectionUtils.isNotEmpty(stExceptionRecordVos)){
String exportFields = "userName|姓名,phone|手机号,workNo|工号,cardCode|卡号,spendMoney|本次扣费金额,payTime|消费时间,createTime|创建时间";
ExcelUtils.export(response, "异常消费流水", stExceptionRecordVos, exportFields, "yyyy-MM-dd HH:mm",true);
}
}
/**
* 导入消费记录: 针对刷脸机设备出现问题时,从刷脸机导出数据,然后通过导入消费记录,重新计算用户余额
* @param file 文件
* @param canteenId 所属食堂
* @param deviceCode 设备编码
*/
@AutoLog(value = "导入消费记录 刷脸机设备出现问题时 ")
@PostMapping("/importRechargeData")
public Result<?> importRechargeData(@RequestParam(name ="file", required = true) MultipartFile file,
@RequestParam(name = "deviceCode") String deviceCode,
@RequestParam(name = "canteenId") String canteenId) {
try {
List<StRfidVo> stRfidVos = stConsumptionExceptionRecordService.parse(file, deviceCode, canteenId);
StRfidoffLineVo stRfidoffLineVo = new StRfidoffLineVo();
stRfidoffLineVo.setDeviceCode(deviceCode);
stRfidoffLineVo.setVoList(stRfidVos);
stRfidoffLineVo.setRestId(canteenId);
//离线扣费
Result<StClientMemberSpendVO> result = iStClientMemberLevelDeductRuleService.bindUserOfflineCardCode(stRfidoffLineVo,false);
return result;
} catch (Exception e) {
// 异常处理
return Result.error("导入异常");
}
}
}
@@ -0,0 +1,18 @@
package org.jeecg.payment.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.jeecg.payment.dto.StExceptionRecordDTO;
import org.jeecg.payment.entity.StConsumptionExceptionRecord;
import org.jeecg.payment.vo.StExceptionRecordVo;
import java.util.List;
public interface StConsumptionExceptionRecordMapper extends BaseMapper<StConsumptionExceptionRecord> {
IPage<StExceptionRecordVo> exceptionRecordPage(@Param("page") Page<StExceptionRecordVo> page, @Param("query") StExceptionRecordDTO query);
List<StExceptionRecordVo> exceptionRecordPage(@Param("query") StExceptionRecordDTO query);
}
@@ -120,6 +120,9 @@
<if test="vo.canteenId != null and vo.canteenId != ''"> <if test="vo.canteenId != null and vo.canteenId != ''">
and a.canteen_id = #{vo.canteenId} and a.canteen_id = #{vo.canteenId}
</if> </if>
<if test="vo.dinnerType != null and vo.dinnerType != ''">
and sboi.dinner_type = #{vo.dinnerType}
</if>
<if test="vo.list != null"> <if test="vo.list != null">
and pay.depart_ids in and pay.depart_ids in
<foreach item="departId" collection="vo.list" open="(" separator="," close=")"> <foreach item="departId" collection="vo.list" open="(" separator="," close=")">
@@ -0,0 +1,53 @@
<?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.StConsumptionExceptionRecordMapper">
<select id="exceptionRecordPage" resultType="org.jeecg.payment.vo.StExceptionRecordVo">
SELECT
a.id,
a.card_code,
a.spend_money,
a.is_custom,
a.is_restore,
a.date_time,
a.create_time,
a.update_time,
a.pay_time,
u.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,
u.phone,
u.work_no as workNo
FROM
st_consumption_exception_record a
LEFT JOIN sys_user_sub AS u ON a.user_id = u.id
LEFT JOIN sys_pay_depart direct_depart ON u.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 1 = 1
<if test="query.phone != null and query.phone != ''">
and u.phone like CONCAT('%',#{query.phone},'%')
</if>
<if test="query.workNo != null and query.workNo != ''">
and u.work_no like CONCAT('%',#{query.workNo},'%')
</if>
<if test="query.userName != null and query.userName != ''">
and u.realname like CONCAT('%',#{query.userName},'%')
</if>
<if test="query.startTime != null and query.endTime !=''">
and a.pay_time between #{query.startTime} and #{query.endTime}
</if>
<if test="query.list != null">
and u.depart_ids in
<foreach item="departId" collection="query.list" open="(" separator="," close=")">
#{departId}
</foreach>
</if>
order by a.create_time desc
</select>
</mapper>
@@ -44,8 +44,13 @@ public interface IStClientMemberLevelDeductRuleService extends JeecgService<StCl
*/ */
StClientMemberLevelDeductRuleVo bulidStClientMemberLevelDeductRule(StClientMemberLevelDeductRuleVo vo, StClientMemberLevelDeductRule memberLevel); StClientMemberLevelDeductRuleVo bulidStClientMemberLevelDeductRule(StClientMemberLevelDeductRuleVo vo, StClientMemberLevelDeductRule memberLevel);
/**
Result<StClientMemberSpendVO> bindUserOfflineCardCode(@RequestBody StRfidoffLineVo stRfidoffLineVo); *
* @param stRfidoffLineVo
* @param onlineStatus true 在线扣费 false 离线扣费
* @return
*/
Result<StClientMemberSpendVO> bindUserOfflineCardCode(@RequestBody StRfidoffLineVo stRfidoffLineVo,boolean onlineStatus);
/** /**
@@ -0,0 +1,24 @@
package org.jeecg.payment.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.payment.dto.StExceptionRecordDTO;
import org.jeecg.payment.entity.StConsumptionExceptionRecord;
import org.jeecg.payment.vo.StExceptionRecordVo;
import org.jeecg.payment.vo.StRfidVo;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
public interface IStConsumptionExceptionRecordService extends IService<StConsumptionExceptionRecord> {
IPage<StExceptionRecordVo> exceptionRecordPage(StExceptionRecordDTO query);
List<StExceptionRecordVo> exceptionRecordPageExport(StExceptionRecordDTO query);
List<StRfidVo> parse(MultipartFile file, String defaultDeviceCode, String defaultRestId) throws IOException;
}
@@ -775,6 +775,7 @@ public class StBbzxOrderInfoServiceImpl extends JeecgServiceImpl<StBbzxOrderInfo
stBbzxOrderInfo.setOrderPrice(stRfidVo.getSpendMoney()); stBbzxOrderInfo.setOrderPrice(stRfidVo.getSpendMoney());
stBbzxOrderInfo.setCustomerPrice(stRfidVo.getSpendMoney()); stBbzxOrderInfo.setCustomerPrice(stRfidVo.getSpendMoney());
} }
stBbzxOrderInfo.setDeviceCode(stRfidVo.getDeviceCode());
stBbzxOrderInfo.setStatus(OrderStatus.ORDER_STATUS_WAIT_CHECK_OUT.getCode());//待结账 stBbzxOrderInfo.setStatus(OrderStatus.ORDER_STATUS_WAIT_CHECK_OUT.getCode());//待结账
stBbzxOrderInfo.setCanteenId(restId); stBbzxOrderInfo.setCanteenId(restId);
stBbzxOrderInfo.setBusinessModel(deductionType); stBbzxOrderInfo.setBusinessModel(deductionType);
@@ -812,6 +813,7 @@ public class StBbzxOrderInfoServiceImpl extends JeecgServiceImpl<StBbzxOrderInfo
String memberPhone,Integer deductionType,StClientMemberLevelDeductRuleVo levelDeductRuleVo , String memberPhone,Integer deductionType,StClientMemberLevelDeductRuleVo levelDeductRuleVo ,
String remark,StRfidVo stRfidVo,StMiniMineBalanceVo miniMineBalanceVo){ String remark,StRfidVo stRfidVo,StMiniMineBalanceVo miniMineBalanceVo){
StBbzxOrderInfo stBbzxOrderInfo = new StBbzxOrderInfo(); StBbzxOrderInfo stBbzxOrderInfo = new StBbzxOrderInfo();
stBbzxOrderInfo.setDeviceCode(stRfidVo.getDeviceCode());
stBbzxOrderInfo.setOrderType(3); stBbzxOrderInfo.setOrderType(3);
String orderNo = OrderUtils.getOrderCode(10); String orderNo = OrderUtils.getOrderCode(10);
stBbzxOrderInfo.setOrderNo(orderNo); stBbzxOrderInfo.setOrderNo(orderNo);
@@ -1638,6 +1638,7 @@ public class StClientMemberBalanceServiceImpl extends JeecgServiceImpl<StClientM
iStBbzxOrderInfoPayService.save(stBbzxOrderInfoPay); iStBbzxOrderInfoPayService.save(stBbzxOrderInfoPay);
//消费记录数据添加 //消费记录数据添加
StClientMemberTransactionRecord mtr = new StClientMemberTransactionRecord(); StClientMemberTransactionRecord mtr = new StClientMemberTransactionRecord();
mtr.setDeviceCode(StringUtils.isNotBlank(stBbzxOrderInfo.getDeviceCode()) ? stBbzxOrderInfo.getDeviceCode() : null );
mtr.setMemberId(stBbzxOrderInfo.getMemberId()); mtr.setMemberId(stBbzxOrderInfo.getMemberId());
mtr.setPayMemberId(query.getId()); mtr.setPayMemberId(query.getId());
mtr.setSerialNo(RandomUtil.randomNumbers(19)); mtr.setSerialNo(RandomUtil.randomNumbers(19));
@@ -17,14 +17,15 @@ import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.base.service.impl.JeecgServiceImpl; import org.jeecg.common.system.base.service.impl.JeecgServiceImpl;
import org.jeecg.common.util.DateUtils; import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.RedisLockUtil; import org.jeecg.common.util.RedisLockUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.payment.entity.StBbzxOrderInfo; import org.jeecg.payment.entity.StBbzxOrderInfo;
import org.jeecg.payment.entity.StClientMemberLevelDeductRule; import org.jeecg.payment.entity.StClientMemberLevelDeductRule;
import org.jeecg.payment.entity.StConsumptionExceptionRecord;
import org.jeecg.payment.enums.DeductionTypeEnum; import org.jeecg.payment.enums.DeductionTypeEnum;
import org.jeecg.payment.mapper.StClientMemberLevelDeductRuleMapper; import org.jeecg.payment.mapper.StClientMemberLevelDeductRuleMapper;
import org.jeecg.payment.service.IStBbzxOrderInfoService; import org.jeecg.payment.service.IStBbzxOrderInfoService;
import org.jeecg.payment.service.IStClientMemberBalanceService; import org.jeecg.payment.service.IStClientMemberBalanceService;
import org.jeecg.payment.service.IStClientMemberLevelDeductRuleService; import org.jeecg.payment.service.IStClientMemberLevelDeductRuleService;
import org.jeecg.payment.service.IStConsumptionExceptionRecordService;
import org.jeecg.payment.utils.MealGroupingUtil; import org.jeecg.payment.utils.MealGroupingUtil;
import org.jeecg.payment.vo.*; import org.jeecg.payment.vo.*;
import org.jeecg.restaurant.entity.SlBaseDinnerTime; import org.jeecg.restaurant.entity.SlBaseDinnerTime;
@@ -34,7 +35,6 @@ import org.jeecg.restaurant.service.ISlBaseDinnerTimeService;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.math.BigDecimal; import java.math.BigDecimal;
@@ -63,6 +63,8 @@ public class StClientMemberLevelDeductRuleServiceImpl extends JeecgServiceImpl<S
private ISlBaseDinnerTimeService stBaseDinnerTimeService; private ISlBaseDinnerTimeService stBaseDinnerTimeService;
@Resource @Resource
private RedisLockUtil redisLockUtil; private RedisLockUtil redisLockUtil;
@Resource
private IStConsumptionExceptionRecordService stConsumptionExceptionRecordService;
@Override @Override
@@ -299,19 +301,21 @@ public class StClientMemberLevelDeductRuleServiceImpl extends JeecgServiceImpl<S
} }
//用户一天 一餐 不是二次扣费的数据 , 只留一条 //用户一天 一餐 不是二次扣费的数据 , 只留一条
public List<StRfidVo> processUserMealDataSimplified(List<StRfidVo> dataList) { //非二次扣费, 只保留一条正常扣费, 剩下的数据添加到消费异常记录表中
public List<StRfidVo> processUserMealDataSimplified(List<StRfidVo> dataList,String restId) {
if (dataList == null || dataList.isEmpty()) { if (dataList == null || dataList.isEmpty()) {
return new ArrayList<>(); return new ArrayList<>();
} }
String restId = dataList.get(0).getRestId();
List<SlBaseDinnerTime> dinnerTimeList = stBaseDinnerTimeService.list(new LambdaQueryWrapper<SlBaseDinnerTime>() List<SlBaseDinnerTime> dinnerTimeList = stBaseDinnerTimeService.list(new LambdaQueryWrapper<SlBaseDinnerTime>()
.eq(SlBaseDinnerTime::getRestId, restId) .eq(SlBaseDinnerTime::getRestId, restId)
.orderByAsc(SlBaseDinnerTime::getEndTime)); .orderByAsc(SlBaseDinnerTime::getEndTime));
//异常数据
List<StRfidVo> unselectedData = new ArrayList<>();
// 按用户ID、日期、餐次分组,然后处理每组数据 // 按用户ID、日期、餐次分组,然后处理每组数据
return dataList.stream() List<StRfidVo> collect = dataList.stream()
.collect(Collectors.groupingBy(vo -> .collect(Collectors.groupingBy(vo ->
vo.getUserId() + "_" + DateUtils.formatDate(new Date(Long.parseLong(vo.getDateTime())), "yyyy-MM-dd") + "_" + getDinnerType(dinnerTimeList,vo.getDateTime()))) vo.getUserId() + "_" + DateUtils.formatDate(new Date(Long.parseLong(vo.getDateTime())), "yyyy-MM-dd") + "_" + getDinnerType(dinnerTimeList, vo.getDateTime())))
.values() .values()
.stream() .stream()
.flatMap(group -> { .flatMap(group -> {
@@ -331,12 +335,46 @@ public class StClientMemberLevelDeductRuleServiceImpl extends JeecgServiceImpl<S
.min((vo1, vo2) -> compareByDateTime(vo1.getDateTime(), vo2.getDateTime())) .min((vo1, vo2) -> compareByDateTime(vo1.getDateTime(), vo2.getDateTime()))
.orElse(nonSecondCharge.get(0)); .orElse(nonSecondCharge.get(0));
resultGroup.add(stRfidVo); resultGroup.add(stRfidVo);
List<StRfidVo> remaining = nonSecondCharge.stream()
.filter(vo -> !vo.equals(stRfidVo))
.collect(Collectors.toList());
unselectedData.addAll(remaining);
} }
resultGroup.addAll(secondCharge); resultGroup.addAll(secondCharge);
return resultGroup.stream(); return resultGroup.stream();
}) })
.collect(Collectors.toList()); .collect(Collectors.toList());
//保存异常消费数据
if(CollectionUtils.isNotEmpty(unselectedData)){
saveExceptionRecord(unselectedData);
}
return collect;
}
//保存异常消费数据
private void saveExceptionRecord(List<StRfidVo> unselectedData){
List<StConsumptionExceptionRecord> unselectedEntities = unselectedData.stream()
.map(vo -> {
StConsumptionExceptionRecord entity = new StConsumptionExceptionRecord();
entity.setUserId(vo.getUserId());
entity.setDeviceCode(vo.getDeviceCode());
entity.setCanteenId(vo.getRestId());
entity.setCardCode(vo.getCardCode());
entity.setPayId(vo.getPayId());
entity.setDateTime(vo.getDateTime());
entity.setSpendMoney(vo.getSpendMoney());
entity.setSecondChargeFlag(vo.getSecondChargeFlag());
entity.setIsCustom(vo.getIsCustom());
entity.setPayTime(new Date(Long.parseLong(vo.getDateTime())));
entity.setCreateTime(new Date());
entity.setUpdateTime(new Date());
return entity;
})
.collect(Collectors.toList());
stConsumptionExceptionRecordService.saveBatch(unselectedEntities);
} }
/** /**
@@ -369,7 +407,7 @@ public class StClientMemberLevelDeductRuleServiceImpl extends JeecgServiceImpl<S
* 食堂扣费主接口 * 食堂扣费主接口
*/ */
@Override @Override
public Result<StClientMemberSpendVO> bindUserOfflineCardCode(StRfidoffLineVo stRfidoffLineVo) { public Result<StClientMemberSpendVO> bindUserOfflineCardCode(StRfidoffLineVo stRfidoffLineVo,boolean onlineStatus) {
String deviceCode = stRfidoffLineVo.getDeviceCode(); String deviceCode = stRfidoffLineVo.getDeviceCode();
String restId = stRfidoffLineVo.getRestId(); String restId = stRfidoffLineVo.getRestId();
List<StRfidVo> voListAll = stRfidoffLineVo.getVoList(); List<StRfidVo> voListAll = stRfidoffLineVo.getVoList();
@@ -379,7 +417,7 @@ public class StClientMemberLevelDeductRuleServiceImpl extends JeecgServiceImpl<S
// //去重 // //去重
// voListAll = filterDuplicateTimestamp(voListAll); // voListAll = filterDuplicateTimestamp(voListAll);
//数据预处理: 一人 一餐 除二次扣费外 只有一条扣费数据 //数据预处理: 一人 一餐 除二次扣费外 只有一条扣费数据
voListAll = processUserMealDataSimplified(voListAll); voListAll = processUserMealDataSimplified(voListAll,restId);
Map<String, List<StRfidVo>> userListMaps = voListAll.stream().collect(Collectors.groupingBy(StRfidVo::getUserId)); Map<String, List<StRfidVo>> userListMaps = voListAll.stream().collect(Collectors.groupingBy(StRfidVo::getUserId));
for (Map.Entry<String, List<StRfidVo>> userListMap : userListMaps.entrySet()) { for (Map.Entry<String, List<StRfidVo>> userListMap : userListMaps.entrySet()) {
@@ -400,7 +438,7 @@ public class StClientMemberLevelDeductRuleServiceImpl extends JeecgServiceImpl<S
StClientMemberLevelDeductRuleVo levelDeductRuleVo = this.getDeductRuleByCanteenId(restId); StClientMemberLevelDeductRuleVo levelDeductRuleVo = this.getDeductRuleByCanteenId(restId);
// //过滤时间小于1分钟的记录 // //过滤时间小于1分钟的记录
// value = filterRecentThanOneMinute(value,maxTime.getTime()); // value = filterRecentThanOneMinute(value,maxTime.getTime());
if(value.size() > 1){//离线扣费 if(!onlineStatus){//离线扣费
//加异步处理 //加异步处理
List<StRfidVo> finalVoListAll = value; List<StRfidVo> finalVoListAll = value;
CompletableFuture.runAsync(() -> { CompletableFuture.runAsync(() -> {
@@ -443,11 +481,20 @@ public class StClientMemberLevelDeductRuleServiceImpl extends JeecgServiceImpl<S
Map<String, List<StRfidVo>> stringListMap = groupByMeal(voListAll, restId); Map<String, List<StRfidVo>> stringListMap = groupByMeal(voListAll, restId);
StMiniMineBalanceVo stMiniMineBalanceVoOnline = new StMiniMineBalanceVo(); StMiniMineBalanceVo stMiniMineBalanceVoOnline = new StMiniMineBalanceVo();
List<StRfidVo> unselectedData = new ArrayList<>();
for (Map.Entry<String, List<StRfidVo>> entry : stringListMap.entrySet()) { for (Map.Entry<String, List<StRfidVo>> entry : stringListMap.entrySet()) {
List<StRfidVo> voList = entry.getValue(); List<StRfidVo> voList = entry.getValue();
//数据排序: 防止 离线数据 一次正常扣费, 多次二次扣费, 导致数据添加有问题
voList.sort((o1, o2) ->
Long.compare(
Long.parseLong(o1.getDateTime()),
Long.parseLong(o2.getDateTime())
)
);
for (StRfidVo stRfidVo : voList) { // 改用普通for循环,方便控制流程 for (StRfidVo stRfidVo : voList) { // 改用普通for循环,方便控制流程
//判断用户本餐是否已经有数据 //判断用户本餐是否已经有数据
System.out.println("二次扣费标记" + stRfidVo.getSecondChargeFlag());
if(stRfidVo.getSecondChargeFlag() == null || stRfidVo.getSecondChargeFlag() == 0){ if(stRfidVo.getSecondChargeFlag() == null || stRfidVo.getSecondChargeFlag() == 0){
long count = iStBbzxOrderInfoService.count(new LambdaQueryWrapper<StBbzxOrderInfo>() long count = iStBbzxOrderInfoService.count(new LambdaQueryWrapper<StBbzxOrderInfo>()
.eq(StBbzxOrderInfo::getMemberId, stRfidVo.getUserId()) .eq(StBbzxOrderInfo::getMemberId, stRfidVo.getUserId())
@@ -457,8 +504,12 @@ public class StClientMemberLevelDeductRuleServiceImpl extends JeecgServiceImpl<S
.eq(StBbzxOrderInfo::getEatDay, DateUtils.formatDate(new Date(Long.parseLong(stRfidVo.getDateTime())), "yyyy-MM-dd")) .eq(StBbzxOrderInfo::getEatDay, DateUtils.formatDate(new Date(Long.parseLong(stRfidVo.getDateTime())), "yyyy-MM-dd"))
); );
if(count > 0){ if(count > 0){
errorMessages = "用户本餐已扣费"; if(stRfidVo.getIsRestore() == null){
continue; unselectedData.add(stRfidVo);
errorMessages = "用户本餐已扣费";
System.out.println("用户本餐已扣费");
continue;
}
} }
} }
stRfidVo.setDeviceCode(deviceCode); stRfidVo.setDeviceCode(deviceCode);
@@ -486,6 +537,7 @@ public class StClientMemberLevelDeductRuleServiceImpl extends JeecgServiceImpl<S
// 当前餐次 // 当前餐次
String timesName = entry.getKey(); String timesName = entry.getKey();
System.out.println("当前餐次" + timesName);
BigDecimal rewardDeduction = BigDecimal.ZERO; BigDecimal rewardDeduction = BigDecimal.ZERO;
BigDecimal totalDeduction = BigDecimal.ZERO; BigDecimal totalDeduction = BigDecimal.ZERO;
Date dateTime = new Date(Long.parseLong(stRfidVo.getDateTime())); Date dateTime = new Date(Long.parseLong(stRfidVo.getDateTime()));
@@ -659,6 +711,11 @@ public class StClientMemberLevelDeductRuleServiceImpl extends JeecgServiceImpl<S
} }
} }
} }
//保存异常消费数据
if(CollectionUtils.isNotEmpty(unselectedData)){
saveExceptionRecord(unselectedData);
}
if(online){//在线 if(online){//在线
// 根据错误信息返回不同结果 // 根据错误信息返回不同结果
if (StringUtils.isBlank(errorMessages)) { if (StringUtils.isBlank(errorMessages)) {
@@ -0,0 +1,135 @@
package org.jeecg.payment.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.opencsv.bean.CsvToBean;
import com.opencsv.bean.CsvToBeanBuilder;
import com.opencsv.bean.HeaderColumnNameMappingStrategy;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.payment.dto.StExceptionRecordDTO;
import org.jeecg.payment.entity.StConsumptionExceptionRecord;
import org.jeecg.payment.mapper.StConsumptionExceptionRecordMapper;
import org.jeecg.payment.service.IStConsumptionExceptionRecordService;
import org.jeecg.payment.vo.StExceptionRecordVo;
import org.jeecg.payment.vo.StRfidVo;
import org.jeecg.system.service.ISysPayDepartService;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Service
public class StConsumptionExceptionRecordServiceImpl extends ServiceImpl<StConsumptionExceptionRecordMapper, StConsumptionExceptionRecord> implements IStConsumptionExceptionRecordService {
@Resource
private ISysPayDepartService iSysPayDepartService;
private static final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
@Override
public IPage<StExceptionRecordVo> exceptionRecordPage(StExceptionRecordDTO query){
//处理时间
if(CollectionUtils.isNotEmpty(query.getDates())){
query.setStartTime(query.getDates().get(0));
query.setEndTime(query.getDates().get(1));
}
if(StringUtils.isNotBlank(query.getDepartId())){
List<String> allCascadeDeptIds = iSysPayDepartService.getAllCascadeDeptIds(query.getDepartId());
if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(allCascadeDeptIds)){
query.setList(allCascadeDeptIds);
}
}
Page<StExceptionRecordVo> page = new Page<>(query.getPageNo(), query.getPageSize());
return baseMapper.exceptionRecordPage(page, query);
}
@Override
public List<StExceptionRecordVo> exceptionRecordPageExport(StExceptionRecordDTO query){
//处理时间
if(CollectionUtils.isNotEmpty(query.getDates())){
query.setStartTime(query.getDates().get(0));
query.setEndTime(query.getDates().get(1));
}
if(StringUtils.isNotBlank(query.getDepartId())){
List<String> allCascadeDeptIds = iSysPayDepartService.getAllCascadeDeptIds(query.getDepartId());
if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(allCascadeDeptIds)){
query.setList(allCascadeDeptIds);
}
}
return baseMapper.exceptionRecordPage(query);
}
/**
* 解析CSV文件到StRfidVo列表
* @param file 上传的CSV文件
* @param defaultDeviceCode 默认设备编码(必填字段)
* @param defaultRestId 默认食堂ID(必填字段)
* @return 解析后的对象列表
* @throws IOException 文件读取异常
*/
@Override
public List<StRfidVo> parse(MultipartFile file, String defaultDeviceCode, String defaultRestId) throws IOException {
// 检查文件类型
if (!file.getOriginalFilename().endsWith(".csv")) {
throw new IllegalArgumentException("仅支持CSV文件");
}
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8))) {
// 使用自定义映射策略
HeaderColumnNameMappingStrategy<StRfidVo> strategy = new HeaderColumnNameMappingStrategy<>();
strategy.setType(StRfidVo.class);
// 解析CSV
CsvToBean<StRfidVo> csvToBean = new CsvToBeanBuilder<StRfidVo>(reader)
.withMappingStrategy(strategy)
.withIgnoreLeadingWhiteSpace(true)
.withIgnoreEmptyLine(true)
.build();
List<StRfidVo> result = new ArrayList<>();
// 逐行处理并验证
csvToBean.forEach(vo -> {
// 设置必填字段
vo.setDeviceCode(defaultDeviceCode);
if (vo.getRestId() == null) {
vo.setRestId(defaultRestId);
}
// 验证对象
validateStRfidVo(vo);
result.add(vo);
});
return result;
}
}
private static void validateStRfidVo(StRfidVo vo) {
Set<ConstraintViolation<StRfidVo>> violations = validator.validate(vo);
if (!violations.isEmpty()) {
String errorMsg = violations.stream()
.map(v -> v.getPropertyPath() + " " + v.getMessage())
.collect(Collectors.joining(", "));
throw new IllegalArgumentException("数据验证失败: " + errorMsg);
}
}
}
@@ -55,5 +55,23 @@ public class StBaseRestaurantDeptController {
} }
} }
@Operation(summary = "获得食堂数据", description= "获得食堂数据")
@GetMapping(value = "/getAllRestaurantList")
public Result<?> getAllRestaurantList() {
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);
}
} }
@@ -9,10 +9,15 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result; import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog; import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.base.controller.JeecgController; import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.util.DateUtils; import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.equipment.entity.StCanteenEquipment;
import org.jeecg.equipment.service.IStCanteenEquipmentService;
import org.jeecg.system.service.IStUserFaceimgSubIncremInfoService; import org.jeecg.system.service.IStUserFaceimgSubIncremInfoService;
import org.jeecg.system.service.ISwUserFaceimgSubService; import org.jeecg.system.service.ISwUserFaceimgSubService;
import org.jeecg.system.vo.SwHeartbeatFaceVo;
import org.jeecg.user.entity.StUserFaceimgSubIncremInfo; import org.jeecg.user.entity.StUserFaceimgSubIncremInfo;
import org.jeecg.user.entity.SwUserFaceimgSub; import org.jeecg.user.entity.SwUserFaceimgSub;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -42,6 +47,10 @@ public class SwUserFaceimgSubController extends JeecgController<SwUserFaceimgSub
private ISwUserFaceimgSubService iSwUserFaceimgSubService; private ISwUserFaceimgSubService iSwUserFaceimgSubService;
@Resource @Resource
private IStUserFaceimgSubIncremInfoService iStUserFaceimgSubIncremInfoService; private IStUserFaceimgSubIncremInfoService iStUserFaceimgSubIncremInfoService;
@Resource
private IStCanteenEquipmentService stCanteenEquipmentService;
@Resource
private RedisUtil redisUtil;
/** /**
@@ -64,14 +73,37 @@ public class SwUserFaceimgSubController extends JeecgController<SwUserFaceimgSub
/** /**
* 扣费闸机心跳 * 扣费闸机心跳 设备大概30s调用一次(如需知道准确时间, 找设备确认)
* 1.人脸相关: 处理逻辑: 用户人脸新增后,会添加数据至st_user_faceimg_sub_increm_info表 , 通过设备上传时间戳 , 获取对应时间戳之后所有的增量人脸数据
* 2.在此心跳接口被调用时, 设备会发送设备本地数据: 设备ip, 设备人脸数, 设备剩余存储大小, 设备ip. 存到食堂设备关联表中
* 3.创建/更新redis中 设备的请求时间(根据心跳机制判断设备是否在线)
* 4.
*
* @param restId 食堂id
* @param qrcodeId 设备code(equipment_code)
* @param timeDate 毫秒级别时间戳
* @param faceNum 人脸数量(设备上)
* @param availableMemory 设备剩余存储大小
* @param ip 设备ip
* @return 增量人脸数据 List<StUserFaceimgSubIncremInfo>
*/ */
@Operation(summary = "扣费闸机心跳", description = "扣费闸机心跳") @Operation(summary = "扣费闸机心跳", description = "扣费闸机心跳")
@GetMapping("/heartbeat/interface") @GetMapping("/heartbeat/interface")
@AutoLog(value = "扣费闸机心跳") @AutoLog(value = "扣费闸机心跳")
public Result heartbeatInterface(@RequestParam(name = "restId", required = false) String restId, public Result heartbeatInterface(@RequestParam(name = "restId", required = false) String restId,
@RequestParam(name = "qrcodeId", required = false) String qrcodeId, @RequestParam(name = "qrcodeId", required = false) String qrcodeId,
@RequestParam(name = "timeDate", required = false) String timeDate) { @RequestParam(name = "timeDate", required = false) String timeDate,
@RequestParam(name = "faceNum", required = false) Integer faceNum,
@RequestParam(name = "availableMemory", required = false) String availableMemory,
@RequestParam(name = "ip", required = false) String ip) {
SwHeartbeatFaceVo vo = new SwHeartbeatFaceVo();
vo.setIssue(false);
Object hget = redisUtil.hget(CommonConstant.ISSUE_INFORMATION, qrcodeId);
if(hget != null){
vo.setIssue(true);
//删除下发指令标记
redisUtil.hdel(CommonConstant.ISSUE_INFORMATION, qrcodeId);
}
if(StringUtils.isNotBlank(timeDate)){ if(StringUtils.isNotBlank(timeDate)){
LambdaQueryWrapper<StUserFaceimgSubIncremInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<StUserFaceimgSubIncremInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
Date date = new Date(Long.parseLong(timeDate)); Date date = new Date(Long.parseLong(timeDate));
@@ -81,9 +113,21 @@ public class SwUserFaceimgSubController extends JeecgController<SwUserFaceimgSub
// 按 createTime 降序排列,获取最新数据 // 按 createTime 降序排列,获取最新数据
lambdaQueryWrapper.orderByDesc(StUserFaceimgSubIncremInfo::getCreateTime); lambdaQueryWrapper.orderByDesc(StUserFaceimgSubIncremInfo::getCreateTime);
List<StUserFaceimgSubIncremInfo> list = iStUserFaceimgSubIncremInfoService.list(lambdaQueryWrapper); List<StUserFaceimgSubIncremInfo> list = iStUserFaceimgSubIncremInfoService.list(lambdaQueryWrapper);
return Result.OK(list);
// 保存食堂设备关联表
StCanteenEquipment stCanteenEquipment = new StCanteenEquipment();
stCanteenEquipment.setEquipmentCode(qrcodeId);
stCanteenEquipment.setCanteenId(restId);
stCanteenEquipment.setEquipmentIp(ip);
stCanteenEquipment.setFaceNum(faceNum);
stCanteenEquipment.setAvailableMemory(availableMemory);
stCanteenEquipmentService.saveOrUpdate(stCanteenEquipment);
redisUtil.hset(CommonConstant.DEVICE_STATUS, qrcodeId, timeDate);
vo.setFaceList(list);
return Result.OK(vo);
} }
return Result.OK(Collections.emptyList()); return Result.OK(vo);
} }
} }