diff --git a/api/src/main/java/com/sv/api/controller/VenueController.java b/api/src/main/java/com/sv/api/controller/VenueController.java index 3a5aff2..098ae94 100644 --- a/api/src/main/java/com/sv/api/controller/VenueController.java +++ b/api/src/main/java/com/sv/api/controller/VenueController.java @@ -116,7 +116,6 @@ public class VenueController extends BaseApiController { * @return */ @RequestMapping(value = "/venue/join", method = RequestMethod.GET) - @Transactional public ResponseDTO join(@RequestParam("venueId") Integer venueId) { Integer memberId = getMemberIdByAccessToken(); BarCodeResult join = venueService.join(memberId, venueId); @@ -146,7 +145,6 @@ public class VenueController extends BaseApiController { * @return */ @RequestMapping(value = "/venue/out", method = RequestMethod.GET) - @Transactional public ResponseDTO out(@RequestParam("venueId") Integer venueId) { Integer memberId = getMemberIdByAccessToken(); diff --git a/api/src/main/java/com/sv/api/task/MemberCardUpdate.java b/api/src/main/java/com/sv/api/task/MemberCardUpdate.java index 82488b1..5ceb858 100644 --- a/api/src/main/java/com/sv/api/task/MemberCardUpdate.java +++ b/api/src/main/java/com/sv/api/task/MemberCardUpdate.java @@ -1,7 +1,6 @@ package com.sv.api.task; -import com.enums.VipTypeEnum; import com.sv.entity.MemberCard; import com.sv.service.api.MemberCardService; import org.slf4j.Logger; @@ -22,12 +21,11 @@ import java.util.List; @Component public class MemberCardUpdate { - private final Logger logger = LoggerFactory.getLogger(MemberCardUpdate.class); - @Resource private MemberCardService memberCardService; + // 每天执行一次 @Scheduled(cron = "0 0 0 * * ?") @Transactional public void execute(){ diff --git a/api/src/test/java/com/sv/wx/VenueJoinTest.java b/api/src/test/java/com/sv/wx/VenueJoinTest.java new file mode 100644 index 0000000..7114917 --- /dev/null +++ b/api/src/test/java/com/sv/wx/VenueJoinTest.java @@ -0,0 +1,68 @@ +package com.sv.wx; + +import com.WeiXinApplication; +import com.enums.EnterEnum; +import com.enums.VenueTypeEnum; +import com.sv.dto.BarCodeResult; +import com.sv.entity.*; +import com.sv.mapper.WxConfigMapper; +import com.sv.netty.config.MessageType; +import com.sv.netty.config.VenueMessage; +import com.sv.netty.utils.JsonUtils; +import com.sv.netty.utils.ServerMessageUtils; +import com.sv.service.api.MemberEnterVenueLogService; +import com.sv.service.api.MemberService; +import com.sv.service.api.VenueLessonService; +import com.sv.service.api.VenueService; +import com.sv.service.api.util.DateUtilCard; +import com.sv.service.message.SendMsg; +import com.sv.service.message.WeiXinSendUtils; +import com.ydd.oms.entity.sys.WxConfig; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.Rollback; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; + +import javax.annotation.Resource; +import java.util.List; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes={WeiXinApplication.class}) +public class VenueJoinTest { + + @Resource + VenueService venueService; + @Resource + MemberService memberService; + @Resource + MemberEnterVenueLogService memberEnterVenueLogService; + + @Test + public void testJoin(){ + BarCodeResult join = venueService.join(535, 32); + System.out.println(JsonUtils.encode(join)); + Member member = memberService.findById(535); + if (member != null) { + MemberEnterVenueLog memberEnterVenueLog = new MemberEnterVenueLog(); + memberEnterVenueLog.setOrderSn("barcode"); + memberEnterVenueLog.setType(EnterEnum.ENTER.getValue()); + memberEnterVenueLog.setMemberId(member.getId()); + memberEnterVenueLog.setPlatformId(member.getPlatformId() == null ? 1 : member.getPlatformId()); + memberEnterVenueLog.setVenueId(32); + memberEnterVenueLogService.save(memberEnterVenueLog); + } + } + + + + + @Test + public void testOut(){ + BarCodeResult out = venueService.out(535, 32); + System.out.println(JsonUtils.encode(out)); + } + +} diff --git a/entity/src/main/java/com/sv/entity/BarcodeOrderTime.java b/entity/src/main/java/com/sv/entity/BarcodeOrderTime.java index 1cde2b7..bd6f25c 100644 --- a/entity/src/main/java/com/sv/entity/BarcodeOrderTime.java +++ b/entity/src/main/java/com/sv/entity/BarcodeOrderTime.java @@ -17,7 +17,9 @@ public class BarcodeOrderTime { private Date orderEnd; - public BarcodeOrderTime(Integer id, Integer memberId, Integer venueId, Date createdTime, Date modifiedTime, Date orderStart, Date orderEnd) { + private Integer status; + + public BarcodeOrderTime(Integer id, Integer memberId, Integer venueId, Date createdTime, Date modifiedTime, Date orderStart, Date orderEnd, Integer status) { this.id = id; this.memberId = memberId; this.venueId = venueId; @@ -25,6 +27,7 @@ public class BarcodeOrderTime { this.modifiedTime = modifiedTime; this.orderStart = orderStart; this.orderEnd = orderEnd; + this.status = status; } public BarcodeOrderTime() { @@ -86,4 +89,12 @@ public class BarcodeOrderTime { public void setOrderEnd(Date orderEnd) { this.orderEnd = orderEnd; } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } } \ No newline at end of file diff --git a/oms/src/main/java/com/ydd/oms/task/BarcodeTimeOrderTask.java b/oms/src/main/java/com/ydd/oms/task/BarcodeTimeOrderTask.java new file mode 100644 index 0000000..9b45f3f --- /dev/null +++ b/oms/src/main/java/com/ydd/oms/task/BarcodeTimeOrderTask.java @@ -0,0 +1,49 @@ +package com.ydd.oms.task; + +import com.enums.BarCodeStatusEnum; +import com.sv.entity.BarcodeOrderTime; +import com.sv.mapper.BarcodeOrderTimeMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.Date; +import java.util.List; + +/** + * Controller - 修改用户会员卡 + * + * @author limqsh + * @since 2023-12-06 + */ +@Component +public class BarcodeTimeOrderTask { + + private final Logger logger = LoggerFactory.getLogger(BarcodeTimeOrderTask.class); + + @Resource + BarcodeOrderTimeMapper barcodeOrderTimeMapper; + + @Scheduled(cron = "0 0/5 * * * ?") + @Transactional + public void execute(){ + // 查询用户已经过期的按次入场订单 + List barcodeOrderTimes = barcodeOrderTimeMapper.endOrderList(new Date()); + if (barcodeOrderTimes != null && barcodeOrderTimes.size() > 0){ + for (BarcodeOrderTime barcodeOrderTime : barcodeOrderTimes) { + logger.info("用户:" + barcodeOrderTime.getMemberId() + ",在场馆" + barcodeOrderTime.getVenueId() + "已到期"); + barcodeOrderTime.setStatus(BarCodeStatusEnum.USED.getValue()); + barcodeOrderTimeMapper.updateByPrimaryKey(barcodeOrderTime); + } + } + } + + @Transactional + public void clearMember(){ + // TODO 清场,将所有没有出场记录的用户、都删除最近一次入场记录、希望这个内容能够做成一个新表,记录场馆以及用户的出入场状态 + } + +} diff --git a/oms/src/test/java/com/ydd/oms/task/BarcodeTimeTaskTest.java b/oms/src/test/java/com/ydd/oms/task/BarcodeTimeTaskTest.java new file mode 100644 index 0000000..b4acde1 --- /dev/null +++ b/oms/src/test/java/com/ydd/oms/task/BarcodeTimeTaskTest.java @@ -0,0 +1,23 @@ +package com.ydd.oms.task; + +import com.OmsApplication; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.annotation.Resource; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes={OmsApplication.class}) +public class BarcodeTimeTaskTest { + + @Resource + BarcodeTimeOrderTask barcodeTimeOrderTask; + + @Test + public void testTask(){ + barcodeTimeOrderTask.execute(); + } + +} diff --git a/other/sql/202312.sql b/other/sql/202312.sql index 05ab4b5..46636e6 100644 --- a/other/sql/202312.sql +++ b/other/sql/202312.sql @@ -2,4 +2,7 @@ ALTER TABLE `smart_venue`.`sv_venue` ADD COLUMN `pay_style` int(11) NULL DEFAULT 0 COMMENT '计费方式 0-按次收费、1-按时收费' AFTER `copy_control`; ALTER TABLE `smart_venue`.`sv_venue` -ADD COLUMN `time_pay_hours` int(11) NULL COMMENT '按次收费几小时内免费' AFTER `pay_style`; +ADD COLUMN `time_pay_hour` int(11) NULL COMMENT '按次收费几小时内免费' AFTER `pay_style`; + +ALTER TABLE `smart_venue`.`sv_barcode_order_time` +ADD COLUMN `status` int(11) NULL COMMENT '0- 有效 1-失效' AFTER `order_end`; \ No newline at end of file diff --git a/service/src/main/java/com/sv/mapper/BarcodeOrderTimeMapper.java b/service/src/main/java/com/sv/mapper/BarcodeOrderTimeMapper.java index 3f0eee9..03182fc 100644 --- a/service/src/main/java/com/sv/mapper/BarcodeOrderTimeMapper.java +++ b/service/src/main/java/com/sv/mapper/BarcodeOrderTimeMapper.java @@ -1,6 +1,10 @@ package com.sv.mapper; import com.sv.entity.BarcodeOrderTime; +import org.apache.ibatis.annotations.Param; + +import java.util.Date; +import java.util.List; public interface BarcodeOrderTimeMapper { int deleteByPrimaryKey(Integer id); @@ -14,4 +18,9 @@ public interface BarcodeOrderTimeMapper { int updateByPrimaryKeySelective(BarcodeOrderTime record); int updateByPrimaryKey(BarcodeOrderTime record); + + int findEffOrder(@Param("currentDate") Date currentDate,@Param("memberId") Integer memberId, @Param("venueId") Integer venueId); + + List endOrderList(@Param("currentDate") Date currentDate); + } \ No newline at end of file diff --git a/service/src/main/java/com/sv/service/api/VenueService.java b/service/src/main/java/com/sv/service/api/VenueService.java index b4c310e..c223567 100644 --- a/service/src/main/java/com/sv/service/api/VenueService.java +++ b/service/src/main/java/com/sv/service/api/VenueService.java @@ -8,7 +8,7 @@ import com.sv.dto.api.MemberCardVenuesDTO; import com.sv.dto.api.VenueDTO; import com.sv.entity.*; import com.sv.exception.api.ExceptionCodeTemplate; -import com.sv.mapper.BarcodeMapper; +import com.sv.mapper.BarcodeOrderTimeMapper; import com.sv.mapper.VenueMapper; import com.sv.service.api.util.DateUtilCard; import com.sv.service.api.util.GeoHashUtils; @@ -59,7 +59,7 @@ public class VenueService extends BaseServiceImpl { @Resource private VenuePriceService venuePriceService; @Resource - BarcodeMapper barcodeMapper; + BarcodeOrderTimeMapper barcodeOrderTimeMapper; /** * 更新场馆 @@ -214,6 +214,7 @@ public class VenueService extends BaseServiceImpl { * api 接口 * 我要进场 */ + @Transactional(rollbackFor = Exception.class) public BarCodeResult join(Integer memberId, Integer venueId) { BarCodeResult barCodeResult = new BarCodeResult(); Integer flag = 0; @@ -223,46 +224,59 @@ public class VenueService extends BaseServiceImpl { } //参数校验 ValidationUtils.assertNotNull(venueId); - synchronized (("scancode-in" + memberId).intern()) { - // 1.判断用户有没有该馆的会员卡(有效期内,如果有免费卡和别的卡,优先使用别的卡),有不判断余额 - List memberCards = memberCardService.findByMemberId(venueId, memberId); - // 2. 查询该场馆需要的费用,并比较用户余额是否足够 - // 查询当前时间内,场馆对应的价格 - String time = DateUtilCard.nowTime().toString(); - Venue venue = venueMapper.findById(venueId); - VenuePrice venuePrice = venuePriceService.findPrice(venueId, time); - BigDecimal price = venuePrice.getPrice(); - if(PayStyleEnum.TIME.getValue() == venue.getPayStyle()){ - // 按次入场先收钱,且多久之后不收钱,出场不收钱 - Integer timePayHour = venue.getTimePayHour(); - // 进过场,判断订单是否超时 - Barcode res = barcodeMapper.findBarcode(venueId, memberId); - if (res != null) { - // 已经生成了二维码,而且二维码有效 - res.getCreatedTime(); -// DateUtilCard.getTimeFromDate(memberLastLog.getCreatedTime()); + // 1.判断用户有没有该馆的会员卡(有效期内,如果有免费卡和别的卡,优先使用别的卡),有不判断余额 + List memberCards = memberCardService.findByMemberId(venueId, memberId); + // 2. 查询该场馆需要的费用,并比较用户余额是否足够 + // 查询当前时间内,场馆对应的价格 + String time = DateUtilCard.nowTime().toString(); + Venue venue = venueMapper.findById(venueId); + VenuePrice venuePrice = venuePriceService.findPrice(venueId, time); + BigDecimal price = venuePrice.getPrice(); + if (PayStyleEnum.HOUR.getValue() == venue.getPayStyle()){ + // 按时入场余额需要包含两个小时的场地费 + price = price.multiply(new BigDecimal(2)); + } + if (venuePrice == null) { + throw new ServiceException(ExceptionCodeTemplate.VENUE_ERROR); + } + if (memberCards.size() == 0) { + Member member = memberService.findById(memberId); + if (member.getMoney().compareTo(price) == -1) { + flag = 2; + } + } + if(PayStyleEnum.TIME.getValue() == venue.getPayStyle()){ + // 按次入场先收钱,且多久不收钱,出场不收钱 + // 该用户上次订单的是否逾期 + Integer timePayHour = venue.getTimePayHour(); + if (timePayHour == null) { + timePayHour = 4; + } + int effOrder = barcodeOrderTimeMapper.findEffOrder(new Date(), memberId, venueId); + if (effOrder <= 0) { + // 单次订单已超时 需要重新付费 + synchronized (("scancode-in" + memberId).intern()) { + createBarcodeTimeOrder(memberId,venueId,timePayHour); + if (memberService.isMoneyEnough(memberId, price)) { + logger.info("用户" + memberId + "使用余额核销订单"); + createMemberMoneyLog(MoneyLogEnum.JOIN.value, price, memberId, 1, PayTypeEnum.BALANCE.value, null, + venue.getId(), venue.getType()); + } else { + //余额不足 + logger.error("用户" + memberId + "余额不足核销失败"); + barCodeResult.setFlg(2); + barCodeResult.setMsg("此次订单金额为:" + price + "元,余额不足,请先充值"); } - }else { - // 按时入场余额需要包含两个小时的场地费 - price = price.multiply(new BigDecimal(2)); - } - if (venuePrice == null) { - throw new ServiceException(ExceptionCodeTemplate.VENUE_ERROR); - } - if (memberCards.size() == 0) { - Member member = memberService.findById(memberId); - if (member.getMoney().compareTo(price) == -1) { - flag = 2; } } - barCodeResult.setFlg(flag); - // 3.判断用户有没有人脸识别的图像,根据用户ID查找,一个用户只能有一条 - // MemberFaceInfo memberFaceInfo = memberFaceInfoService.findByMemberId(memberId); - // if (memberFaceInfo == null) { - // flag = 1; - // return flag; - // } } + barCodeResult.setFlg(flag); + // 3.判断用户有没有人脸识别的图像,根据用户ID查找,一个用户只能有一条 +// MemberFaceInfo memberFaceInfo = memberFaceInfoService.findByMemberId(memberId); +// if (memberFaceInfo == null) { +// flag = 1; +// return flag; +// } return barCodeResult; } @@ -272,6 +286,7 @@ public class VenueService extends BaseServiceImpl { * @param venueId * @return */ + @Transactional(rollbackFor = Exception.class) public BarCodeResult out(Integer memberId, Integer venueId) { BarCodeResult result = new BarCodeResult(); result.setFlg(0); @@ -340,28 +355,27 @@ public class VenueService extends BaseServiceImpl { String enterTime = DateUtilCard.getTimeFromDate(memberLastLog.getCreatedTime()); String outTime = DateUtilCard.nowTime().toString(); BigDecimal price = BigDecimal.ZERO; - if(PayStyleEnum.TIME.getValue() == venue.getPayStyle()){ + if(PayStyleEnum.HOUR.getValue() == venue.getPayStyle()){ // 按次出场不扣钱 // 取入场的价格 VenuePrice venuePriceEnter = venuePriceService.findPrice(venueId, enterTime); -// VenuePrice venuePriceOut = venuePriceService.findPrice(venueId, outTime); - price = venuePriceEnter.getPrice(); - }else { // 按时出场选择按照分钟四舍五入到角扣款 - VenuePrice venuePriceEnter = venuePriceService.findPrice(venueId, enterTime); price = venuePriceEnter.getPrice(); - int hours = DateUtilCard.diffHours(enterTime, outTime); - price = price.multiply(new BigDecimal(hours)); - } - if (memberService.isMoneyEnough(member.getId(), price)) { - logger.info("用户" + member.getNickname() + "使用余额核销订单"); - createMemberMoneyLog(MoneyLogEnum.JOIN.value, price, member.getId(), member.getPlatformId(), PayTypeEnum.BALANCE.value, null, - venue.getId(), venue.getType()); - } else { - //余额不足 - logger.error("用户" + member.getNickname() + "余额不足核销失败"); - result.setFlg(1); - result.setMsg("此次订单金额为:" + price + "元,余额不足,请先充值"); + int minutes = DateUtilCard.diffMinute(enterTime, outTime); + price = price.divide(new BigDecimal(60),4,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(minutes)).setScale(1,BigDecimal.ROUND_HALF_UP); + if (price.compareTo(BigDecimal.ZERO) < 0) { + price = BigDecimal.ZERO; + } + if (memberService.isMoneyEnough(member.getId(), price)) { + logger.info("用户" + member.getNickname() + "使用余额核销订单"); + createMemberMoneyLog(MoneyLogEnum.JOIN.value, price, member.getId(), member.getPlatformId(), PayTypeEnum.BALANCE.value, null, + venue.getId(), venue.getType()); + } else { + //余额不足 + logger.error("用户" + member.getNickname() + "余额不足核销失败"); + result.setFlg(2); + result.setMsg("此次订单金额为:" + price + "元,余额不足,请先充值"); + } } } } @@ -422,6 +436,25 @@ public class VenueService extends BaseServiceImpl { memberMoneyLogService.create(memberId,platformId == null ? 1 : platformId,type,price.negate(),payType,cardType,venueId,venueType,null); } + + /** + * 按次入场订单入库 + * @param memberId + * @param venueId + * @param timePayHour + */ + private void createBarcodeTimeOrder(Integer memberId, Integer venueId, Integer timePayHour) { + Date startDate = new Date(); + Date endDate = DateUtilCard.addHours(startDate, timePayHour); + BarcodeOrderTime barcodeOrderTime = new BarcodeOrderTime(); + barcodeOrderTime.setMemberId(memberId); + barcodeOrderTime.setVenueId(venueId); + barcodeOrderTime.setOrderStart(startDate); + barcodeOrderTime.setOrderEnd(endDate); + barcodeOrderTime.setStatus(BarCodeStatusEnum.INIT.getValue()); + barcodeOrderTimeMapper.insert(barcodeOrderTime); + } + @Transactional(rollbackFor = Exception.class) public void addNumber(Integer venueId, Integer number, Integer memberId) { if (number > 0 && venueMapper.countByMember(memberId, venueId) <= 0) { diff --git a/service/src/main/java/com/sv/service/api/util/DateUtilCard.java b/service/src/main/java/com/sv/service/api/util/DateUtilCard.java index b248bbe..8335d9d 100644 --- a/service/src/main/java/com/sv/service/api/util/DateUtilCard.java +++ b/service/src/main/java/com/sv/service/api/util/DateUtilCard.java @@ -169,21 +169,28 @@ public class DateUtilCard { return calendar.getTime(); //这个时间就是日期往后推一天的结果 } - public static int diffHours(String startTime,String endTime){ + public static Date addHours(Date date,int hours){ + Calendar calendar = new GregorianCalendar(); + calendar.setTime(date); + calendar.add(calendar.HOUR,hours); //把日期往后增加一小时,整数 往后推,负数往前移动 + return calendar.getTime(); //这个时间就是日期往后推一天的结果 + } + + public static int diffMinute(String startTime,String endTime){ if (StringUtils.isEmpty(startTime) || StringUtils.isEmpty(endTime)){ return 1; } try { String[] split1 = startTime.split(":"); - String[] split2 = startTime.split(":"); + String[] split2 = endTime.split(":"); int t1 = 0; int t2 = 0; t1 = (Integer.parseInt(split1[0]) * 3600) + (Integer.parseInt(split1[1]) * 60) + Integer.parseInt(split1[2]); t2 = (Integer.parseInt(split2[0]) * 3600) + (Integer.parseInt(split2[1]) * 60) + Integer.parseInt(split2[2]); - int diff = t2 - t1 - 600; - return (diff / 3600) + 1; + int diff = t2 - t1; + return (diff / 60) + 1; }catch (Exception e){ return 1; } diff --git a/service/src/main/resources/mybatis/mapper/sv/BarcodeOrderTimeMapper.xml b/service/src/main/resources/mybatis/mapper/sv/BarcodeOrderTimeMapper.xml index 9d3f0fc..e54ec4a 100644 --- a/service/src/main/resources/mybatis/mapper/sv/BarcodeOrderTimeMapper.xml +++ b/service/src/main/resources/mybatis/mapper/sv/BarcodeOrderTimeMapper.xml @@ -10,10 +10,11 @@ + - id, member_id, venue_id, created_time, modified_time, order_start, order_end + id, member_id, venue_id, created_time, modified_time, order_start, order_end, status + select count(1) + from sv_barcode_order_time + where status = 0 and order_end >= #{currentDate} and member_id = #{memberId,jdbcType=INTEGER} and venue_id = #{venueId,jdbcType=INTEGER} + + + + \ No newline at end of file