ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/poji/shop/ShopAppointableTime.java
@@ -34,7 +34,7 @@ * 预约时间 */ @TableField("appointable_time") private String appointableTime; private LocalDateTime appointableTime; /** * 状态(0=已取消,1=待确认,2=等待中,3=已结束) */ ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/poji/shop/ShopNonAppointableTime.java
@@ -8,6 +8,8 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.time.LocalDateTime; /** * @author zhibing.pu * @Date 2025/5/26 14:25 @@ -31,11 +33,11 @@ */ @TableField("non_appointable_start_time") @ApiModelProperty("不可预约开始时间") private String nonAppointableStartTime; private LocalDateTime nonAppointableStartTime; /** * 不可预约结束时间 */ @TableField("non_appointable_end_time") @ApiModelProperty("不可预约结束时间") private String nonAppointableEndTime; private LocalDateTime nonAppointableEndTime; } ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/vo/MerHomeShopTotalVo.java
@@ -45,4 +45,7 @@ @ApiModelProperty(value = "生日卡1开2关") private Integer platformBirthdayFlag; @ApiModelProperty(value = "待处理预约单数量") private Integer unHandleReserve; } ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/vo/ShopRelUserVo.java
@@ -9,6 +9,12 @@ @ApiModelProperty(value="商户id") private Long shopId; @ApiModelProperty(value = "商户数量") private Integer shopNum; @ApiModelProperty(value = "商户名称") private String shopName; @ApiModelProperty(value="用户姓名") private String userName; } ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/model/OauthUserVo.java
@@ -9,6 +9,12 @@ @ApiModelProperty(value="商户id") private Long shopId; @ApiModelProperty(value = "商户数量") private Integer shopNum; @ApiModelProperty(value = "商户名称") private String shopName; @ApiModelProperty(value="成员UserID") private String userid; ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/model/QwH5LoginVo.java
@@ -13,6 +13,12 @@ @ApiModelProperty(value="商户id") private Long shopId; @ApiModelProperty(value = "商户数量") private Integer shopNum; @ApiModelProperty(value = "商户名称") private String shopName; @ApiModelProperty(value="手机") private String mobile; ruoyi-auth/src/main/java/com/ruoyi/auth/controller/QwH5Controller.java
@@ -89,7 +89,7 @@ } @GetMapping("/h5/oauthUser") @ApiOperation("通过code获取商户端用户登录") @ApiOperation("通过code获取商户端用户登录【2.0】") public R<OauthUserVo> oauthUser(@ApiParam(value = "成员授权获取到的code", required = true) @RequestParam("code") String code) throws IOException { // 通过code获取访问用户敏感信息 JSONObject result = qywxInnerService.getOauthUser(code); ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java
@@ -257,6 +257,8 @@ } userInfo.setShopId(shopInfo.getShopId()); userInfo.setShopName(shopInfo.getShopName()); userInfo.setShopNum(shopInfo.getShopNum()); recordLogService.recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功",Constants.FROM_SHOP); return userInfo; } ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java
@@ -135,6 +135,8 @@ // 接口返回信息 OauthUserVo oauthUserVo = new OauthUserVo(); oauthUserVo.setShopId(qwH5LoginVo.getShopId()); oauthUserVo.setShopNum(qwH5LoginVo.getShopNum()); oauthUserVo.setShopName(qwH5LoginVo.getShopName()); oauthUserVo.setToken(JwtUtils.createToken(claimsMap)); oauthUserVo.setExpiresIn(EXPIRE_TIME); oauthUserVo.setUserid(qwH5LoginVo.getUserid()); ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/dto/AnswerQuestionDto.java
New file @@ -0,0 +1,18 @@ package com.ruoyi.goods.domain.dto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * @author zhibing.pu * @Date 2025/5/27 10:45 */ @Data @ApiModel public class AnswerQuestionDto { @ApiModelProperty(value = "抽奖id") private String id; @ApiModelProperty(value = "当前题号") private Integer current; @ApiModelProperty(value = "答案") private String answer; } ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/dto/LotteryEventQuestionsDto.java
New file @@ -0,0 +1,18 @@ package com.ruoyi.goods.domain.dto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * @author zhibing.pu * @Date 2025/5/27 10:22 */ @Data @ApiModel public class LotteryEventQuestionsDto { @ApiModelProperty(value = "抽奖id") private String id; @ApiModelProperty(value = "当前题号") private Integer current; @ApiModelProperty(value = "-1=上一题,1=下一题") private Integer stepOrDown; } ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/LotteryEventQuestionsVo.java
New file @@ -0,0 +1,29 @@ package com.ruoyi.goods.domain.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.List; import java.util.Map; /** * @author zhibing.pu * @Date 2025/5/27 10:05 */ @Data @ApiModel public class LotteryEventQuestionsVo { @ApiModelProperty(value = "抽奖id") private String id; @ApiModelProperty("题干名称") private String name; @ApiModelProperty("总提数") private Integer total; @ApiModelProperty("当前题数") private Integer current; @ApiModelProperty("已答答案") private String answer; @ApiModelProperty("答题选项") private List<Map<String, String>> options; } ruoyi-modules/ruoyi-member/src/main/java/com/ruoyi/member/domain/vo/CouponInfoVo.java
New file @@ -0,0 +1,48 @@ package com.ruoyi.member.domain.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.math.BigDecimal; /** * @author zhibing.pu * @Date 2025/5/27 12:01 */ @ApiModel @Data public class CouponInfoVo { @ApiModelProperty(value = "优惠券id") private String id; @ApiModelProperty(value = "优惠券名称") private String name; @ApiModelProperty(value = "优惠券类型1.满减2.折扣3.代金4.商品") private Integer type; @ApiModelProperty(value = "门槛金额") private BigDecimal moneyThreshold; @ApiModelProperty(value = "折扣") private BigDecimal discountPercent; @ApiModelProperty(value = "优惠金额") private BigDecimal discountMoney; @ApiModelProperty(value = "有效期类型1.时间段2.领取之日起") private Integer validType; @ApiModelProperty(value = "有效期") private Integer validDays; @ApiModelProperty(value = "有效期开始时间") private String validStartTime; @ApiModelProperty(value = "有效期结束时间") private String validEndTime; @ApiModelProperty(value = "使用范围商品") private String useGoods; @ApiModelProperty(value = "发放限制0否1是") private Integer limitFlag; @ApiModelProperty(value = "可领数量") private Integer receiveNum; @ApiModelProperty(value = "剩余数量") private Integer laveNum; @ApiModelProperty(value = "宣传海报") private String propagandaPoster; @ApiModelProperty(value = "优惠券状态-1删除0已过期1已领取2已使用") private Integer status; } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/controller/business/MerShopController.java
@@ -1,27 +1,37 @@ package com.ruoyi.shop.controller.business; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.shop.domain.dto.*; import com.ruoyi.shop.domain.pojo.shop.ShopRelUser; import com.ruoyi.shop.domain.vo.MerAgencyPageVo; import com.ruoyi.shop.domain.vo.MerShopCertificateListVo; import com.ruoyi.shop.domain.vo.MerShopSuggestVo; import com.ruoyi.shop.domain.vo.MerchantBasicdataSettlementVo; import com.ruoyi.shop.domain.vo.*; import com.ruoyi.shop.service.shop.*; import com.ruoyi.system.api.domain.dto.*; import com.ruoyi.system.api.domain.dto.MerBaseDto; import com.ruoyi.system.api.domain.dto.MerBaseGetDto; import com.ruoyi.system.api.domain.dto.MerEditUserDto; import com.ruoyi.system.api.domain.dto.MerPageDto; import com.ruoyi.system.api.domain.poji.shop.Shop; import com.ruoyi.system.api.domain.poji.shop.ShopAppointableTime; import com.ruoyi.system.api.domain.poji.shop.ShopNonAppointableTime; import com.ruoyi.system.api.domain.vo.MerHomeShopTotalVo; import com.ruoyi.system.api.domain.vo.MerStaffInfoVo; import com.ruoyi.system.api.domain.vo.MgtSimpleShopVo; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.time.format.DateTimeFormatter; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * @author jqs34 @@ -51,13 +61,21 @@ @Resource private ShopSuggestService shopSuggestService; @Resource private ShopNonAppointableTimeService shopNonAppointableTimeService; @Resource private ShopAppointableTimeService shopAppointableTimeService; /** * 未完成实际统计 * * @param merBaseDto * @return */ @RequestMapping(value = "/getMerHomeTotal", method = RequestMethod.POST) @ApiOperation(value = "获取商户端商业统计") @ApiOperation(value = "获取商户端商业统计【2.0】") public R<MerHomeShopTotalVo> getMerHomeTotal(@RequestBody MerBaseDto merBaseDto) { Long userId = SecurityUtils.getUserId(); merBaseDto.setUserId(userId); @@ -102,11 +120,13 @@ } @RequestMapping(value = "/getShopStaffInfo", method = RequestMethod.POST) @ApiOperation(value = "获取员工信息") public R<MerStaffInfoVo> getShopStaffInfo() { @ApiOperation(value = "获取员工信息【2.0】") @ApiImplicitParams({ @ApiImplicitParam(value = "当前商户id", name = "shopId", required = true, dataType = "Long", paramType = "query") }) public R<MerStaffInfoVo> getShopStaffInfo(@RequestParam("shopId") Long shopId) { Long userId = SecurityUtils.getUserId(); ShopRelUser shopRelUser = shopRelUserService.getByUserId(userId); Shop shop = shopService.getByShopId(shopRelUser.getShopId()); Shop shop = shopService.getByShopId(shopId); MerStaffInfoVo merStaffInfoVo = shopStaffService.getShopStaffInfo(userId,shop); return R.ok(merStaffInfoVo); } @@ -153,15 +173,12 @@ } @RequestMapping(value = "/listShopByShop", method = RequestMethod.POST) @ApiOperation(value = "获取商户下属代理商") public R<List<MgtSimpleShopVo>> listShopByShop(@RequestBody MerBaseDto merBaseDto) { public R<List<MgtSimpleShopVo>> listShopByShop(@RequestBody MerBaseDto merBaseDto) { List<MgtSimpleShopVo> mgtShopListSimpleVos = shopService.listShopByShop(merBaseDto.getShopId()); return R.ok(mgtShopListSimpleVos); } @RequestMapping(value = "/getShopMerchantBasicDataSettlement", method = RequestMethod.POST) @@ -169,4 +186,104 @@ public R<List<MerchantBasicdataSettlementVo>> getMerchantBasicDataSettlement(@Validated @RequestBody MerchantBasicdataSettlementDto mgtShopShareRatioSetDto){ return shopService.getMerchantBasicDataSettlement(mgtShopShareRatioSetDto); } @RequestMapping(value = "/getUserShopList", method = RequestMethod.POST) @ApiOperation(value = "获取切换门店列表【2.0】") public R<List<Shop>> getUserShopList() { List<ShopRelUser> shopRelUsers = shopRelUserService.getByUserId(SecurityUtils.getUserId()); shopRelUsers.sort(Comparator.comparing(ShopRelUser::getIsDefault)); List<Shop> collect = shopRelUsers.stream().map(shopRelUser -> { Shop shop = shopService.getById(shopRelUser.getShopId()); return shop; }).collect(Collectors.toList()); return R.ok(collect); } @RequestMapping(value = "/getShopReservationConfig/{shopId}", method = RequestMethod.POST) @ApiOperation(value = "获取门店预约管理配置【2.0】") public R<ShopReservationConfigVo> getShopReservationConfig(@PathVariable("shopId") Long shopId) { Shop shop = shopService.getById(shopId); Integer subscribe = shop.getSubscribe(); ShopReservationConfigVo vo = new ShopReservationConfigVo(); vo.setSubscribe(subscribe); List<ShopNonAppointableTime> list = shopNonAppointableTimeService.list(new LambdaQueryWrapper<ShopNonAppointableTime>().eq(ShopNonAppointableTime::getShopId, shopId) .orderByAsc(ShopNonAppointableTime::getNonAppointableStartTime)); vo.setUnsubscribeTime(list.stream().map(shopNonAppointableTime -> { Map<String, String> map = new HashMap<>(); String time = shopNonAppointableTime.getNonAppointableStartTime().format(DateTimeFormatter.ofPattern("MM月dd日 HH:mm")) + "-" + shopNonAppointableTime.getNonAppointableEndTime().format(DateTimeFormatter.ofPattern("HH:mm")); map.put("time", time); map.put("id", shopNonAppointableTime.getId()); return map; }).collect(Collectors.toList())); return R.ok(vo); } @RequestMapping(value = "/addShopNonAppointableTime", method = RequestMethod.POST) @ApiOperation(value = "门店添加不可预约时间段【2.0】") public R addShopNonAppointableTime(@RequestBody ShopNonAppointableTimeDto dto) { ShopNonAppointableTime shopNonAppointableTime = new ShopNonAppointableTime(); shopNonAppointableTime.setShopId(dto.getShopId()); shopNonAppointableTime.setNonAppointableStartTime(dto.getNonAppointableStartTime()); shopNonAppointableTime.setNonAppointableEndTime(dto.getNonAppointableEndTime()); shopNonAppointableTimeService.save(shopNonAppointableTime); return R.ok(); } @RequestMapping(value = "/switchAppointment/{shopId}/{subscribe}", method = RequestMethod.POST) @ApiOperation(value = "开关门店预约配置【2.0】") @ApiImplicitParams({ @ApiImplicitParam(value = "门店id", name = "shopId", required = true, dataType = "Long", paramType = "path"), @ApiImplicitParam(value = "预约开关(0=关,1=开)", name = "subscribe", required = true, dataType = "Integer", paramType = "path") }) public R switchAppointment(@PathVariable("shopId") Long shopId, @PathVariable("subscribe") Integer subscribe) { Shop shop = shopService.getById(shopId); shop.setSubscribe(subscribe); shopService.updateById(shop); return R.ok(); } @RequestMapping(value = "/getShopAppointableTimeList", method = RequestMethod.POST) @ApiOperation(value = "商户获取预约列表【2.0】") public R<Page<ShopAppointableTimeListVo>> getShopAppointableTimeList(@RequestBody ShopAppointableTimeListDto dto) { Page<ShopAppointableTimeListVo> page = new Page<>(); page.setSize(dto.getPageSize()); page.setCurrent(dto.getPageNum()); List<ShopAppointableTimeListVo> shopAppointableTimeList = shopAppointableTimeService.getShopAppointableTimeList(page, dto); return R.ok(page.setRecords(shopAppointableTimeList)); } @RequestMapping(value = "/confirmReservation/{id}", method = RequestMethod.POST) @ApiOperation(value = "商户确认预约【2.0】") public R confirmReservation(@PathVariable("id") String id) { ShopAppointableTime shopAppointableTime = shopAppointableTimeService.getById(id); if (null == shopAppointableTime) { return R.fail("预约不存在"); } if (1 != shopAppointableTime.getStatus()) { return R.fail("确认预约失败"); } shopAppointableTime.setStatus(2); shopAppointableTimeService.updateById(shopAppointableTime); return R.ok(); } @RequestMapping(value = "/cancelReservation", method = RequestMethod.POST) @ApiOperation(value = "商户取消预约【2.0】") public R cancelReservation(@RequestBody CancelReservationDto dto) { ShopAppointableTime shopAppointableTime = shopAppointableTimeService.getById(dto.getId()); if (null == shopAppointableTime) { return R.fail("预约不存在"); } if (0 == shopAppointableTime.getStatus()) { return R.fail("不能重复操作"); } shopAppointableTime.setStatus(0); shopAppointableTime.setReason(dto.getReason()); shopAppointableTimeService.updateById(shopAppointableTime); return R.ok(); } } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/controller/console/ShopController.java
@@ -1,7 +1,6 @@ package com.ruoyi.shop.controller.console; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.ruoyi.common.core.constant.CacheConstants; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.exception.ServiceException; @@ -16,7 +15,6 @@ import com.ruoyi.system.api.constant.AppErrorConstant; import com.ruoyi.system.api.domain.dto.*; import com.ruoyi.system.api.domain.poji.shop.Shop; import com.ruoyi.system.api.domain.vo.ShopProportionVo; import com.ruoyi.system.api.domain.poji.sys.SysUser; import com.ruoyi.system.api.domain.vo.*; import com.ruoyi.system.api.model.QwH5LoginVo; @@ -32,7 +30,6 @@ import java.util.List; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; /** * @author jqs34 @@ -174,17 +171,20 @@ @PostMapping("/getShopByUserId") public R<ShopRelUserVo> getShopByUserId(@RequestBody Long userId) { ShopRelUser shopRelUser = shopRelUserService.getByUserId(userId); List<ShopRelUser> shopRelUser = shopRelUserService.getByUserId(userId); Optional.ofNullable(shopRelUser).orElseThrow(() -> new ServiceException("未查询到用户关联商户")); ShopRelUserVo shopRelUserVo = new ShopRelUserVo(); shopRelUserVo.setShopId(shopRelUser.getShopId()); shopRelUserVo.setUserName(shopRelUser.getUserName()); ShopRelUser shopRelUser1 = shopRelUser.stream().filter(s -> s.getIsDefault() == 1).collect(Collectors.toList()).get(0); shopRelUserVo.setShopId(shopRelUser1.getShopId()); shopRelUserVo.setUserName(shopRelUser1.getUserName()); Shop shop = shopService.getById(shopRelUser1.getShopId()); shopRelUserVo.setShopName(shop.getShopName()); shopRelUserVo.setShopNum(shopRelUser.size()); return R.ok(shopRelUserVo); } @PostMapping("/getShopByBelongUserId") public R<ShopRelUserVo> getShopByBelongUserId(@RequestBody Long userId) { public R<ShopRelUserVo> getShopByBelongUserId(@RequestBody Long userId) { List<Shop> shopList = shopService.getShopByBelongUserId(userId); Optional.ofNullable(shopList.get(0)).orElseThrow(() -> new ServiceException("未查询到商户信息")); ShopRelUserVo shopRelUserVo = new ShopRelUserVo(); ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/controller/miniapp/AppHomeController.java
@@ -3,7 +3,7 @@ import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.plugins.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.shop.domain.dto.AppNearbyShopDto; @@ -28,6 +28,7 @@ import javax.annotation.Resource; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.List; /** @@ -82,7 +83,7 @@ @ApiOperation(value = "获取商户不可预约时间段【2.0】") public R<List<ShopNonAppointableTime>> getShopAppointmentTime(@RequestBody ShopAppointmentTimeDto dto) { List<ShopNonAppointableTime> list = shopNonAppointableTimeService.list(new QueryWrapper<ShopNonAppointableTime>().eq("shop_id", dto.getId()) .last(" and '" + dto.getDate() + "' like CONCAT('%', non_appointable_start_time, '%') order by non_appointable_start_time")); .last(" and '" + dto.getDate() + "' = DATE(non_appointable_start_time) order by non_appointable_start_time")); return R.ok(list); } @@ -90,14 +91,14 @@ @ApiOperation(value = "门店详情预约操作【2.0】") public R appointmentTime(@RequestBody AppointmentTimeDto dto) { ShopAppointableTime one = shopAppointableTimeService.getOne(new LambdaQueryWrapper<ShopAppointableTime>().eq(ShopAppointableTime::getShopId, dto.getShopId()) .eq(ShopAppointableTime::getAppointableTime, dto.getTime())); .last(" and DATE_FORMAT(appointable_time, '%Y-%m-%d %H:%i') = '" + dto.getTime() + "'")); if (null != one) { return R.fail("不能重复预约"); } Long userId = SecurityUtils.getUserId(); one = new ShopAppointableTime(); one.setShopId(dto.getShopId()); one.setAppointableTime(dto.getTime()); one.setAppointableTime(LocalDateTime.parse(dto.getTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))); one.setUserId(userId); one.setStatus(1); one.setCreateTime(LocalDateTime.now()); ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/domain/dto/CancelReservationDto.java
New file @@ -0,0 +1,16 @@ package com.ruoyi.shop.domain.dto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * @author zhibing.pu * @Date 2025/6/3 16:08 */ @Data @ApiModel public class CancelReservationDto { @ApiModelProperty(value = "预约id") private String id; @ApiModelProperty(value = "取消原因") private String reason; } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/domain/dto/MyAppointmentListDto.java
New file @@ -0,0 +1,20 @@ package com.ruoyi.shop.domain.dto; import com.ruoyi.system.api.domain.dto.MgtBaseDto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * @author zhibing.pu * @Date 2025/5/27 14:29 */ @ApiModel @Data public class MyAppointmentListDto extends MgtBaseDto { @ApiModelProperty("页码,首页1") private Integer pageNum; @ApiModelProperty("页查询条数") private Integer pageSize; @ApiModelProperty("状态(0=已取消,1=待确认,2=等待中,3=已结束)") private Integer status; } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/domain/dto/ShopAppointableTimeListDto.java
New file @@ -0,0 +1,17 @@ package com.ruoyi.shop.domain.dto; import com.ruoyi.system.api.domain.dto.MgtPageDto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * @author zhibing.pu * @Date 2025/6/3 15:17 */ @Data @ApiModel public class ShopAppointableTimeListDto extends MgtPageDto { @ApiModelProperty(value = "商户id") private Integer shopId; @ApiModelProperty(value = "状态(0=已取消,1=待确认,2=等待中,3=已结束)") private Integer status; } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/domain/dto/ShopNonAppointableTimeDto.java
New file @@ -0,0 +1,23 @@ package com.ruoyi.shop.domain.dto; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.time.LocalDateTime; /** * @author zhibing.pu * @Date 2025/6/3 14:59 */ @Data @ApiModel public class ShopNonAppointableTimeDto { @ApiModelProperty("门店id") private Integer shopId; @ApiModelProperty("不可预约开始时间(yyyy-MM-dd HH:mm:ss)") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime nonAppointableStartTime; @ApiModelProperty("不可预约结束时间(yyyy-MM-dd HH:mm:ss)") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime nonAppointableEndTime; } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/domain/pojo/shop/ShopRelUser.java
@@ -1,15 +1,15 @@ package com.ruoyi.shop.domain.pojo.shop; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.activerecord.Model; 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 java.io.Serializable; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; import java.io.Serializable; /** * <p> @@ -40,6 +40,11 @@ @TableField("shop_id") private Long shopId; /** * 默认门店(0=否,1=是) */ @TableField("is_default") private Integer isDefault; /** * 用户id */ @TableField("user_id") ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/domain/vo/MyAppointmentListVo.java
New file @@ -0,0 +1,22 @@ package com.ruoyi.shop.domain.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * @author zhibing.pu * @Date 2025/5/27 14:32 */ @Data @ApiModel public class MyAppointmentListVo { @ApiModelProperty(value = "预约id") private String id; @ApiModelProperty(value = "预约时间") private String appointmentTime; @ApiModelProperty(value = "预约状态(0=已取消,1=待确认,2=等待中,3=已结束)") private Integer status; @ApiModelProperty(value = "预约门店") private String shopName; @ApiModelProperty(value = "商家取消原因") private String cancelReason; } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/domain/vo/ShopAppointableTimeListVo.java
New file @@ -0,0 +1,28 @@ package com.ruoyi.shop.domain.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.time.LocalDateTime; /** * @author zhibing.pu * @Date 2025/6/3 15:19 */ @Data @ApiModel public class ShopAppointableTimeListVo { @ApiModelProperty("预约数据id") private String id; @ApiModelProperty("预约时间") private LocalDateTime appointableTime; @ApiModelProperty("预约状态(0=已取消,1=待确认,2=等待中,3=已结束)") private Integer status; @ApiModelProperty("预约人") private String userName; @ApiModelProperty("预约人手机号") private String mobile; @ApiModelProperty("预约人性别") private String sex; } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/domain/vo/ShopReservationConfigVo.java
New file @@ -0,0 +1,22 @@ package com.ruoyi.shop.domain.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.List; import java.util.Map; /** * @author zhibing.pu * @Date 2025/6/3 14:26 */ @Data @ApiModel public class ShopReservationConfigVo { @ApiModelProperty("预约开关(0=关,1=开)") private Integer subscribe; @ApiModelProperty("不可预约时段") private List<Map<String, String>> unsubscribeTime; } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/mapper/shop/ShopAppointableTimeMapper.java
@@ -1,8 +1,10 @@ package com.ruoyi.shop.mapper.shop; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.plugins.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.shop.domain.dto.ShopAppointableTimeListDto; import com.ruoyi.shop.domain.vo.MyAppointmentListVo; import com.ruoyi.shop.domain.vo.ShopAppointableTimeListVo; import com.ruoyi.system.api.domain.poji.shop.ShopAppointableTime; import org.apache.ibatis.annotations.Param; @@ -24,4 +26,20 @@ * @return */ List<MyAppointmentListVo> pageMyAppointmentList(Page<MyAppointmentListVo> page, @Param("userId") Long userId, @Param("status") Integer status); /** * 商户端获取预约列表数据 * * @param page * @param dto * @return */ List<ShopAppointableTime> getShopAppointableTimeList(Page<ShopAppointableTimeListVo> page, @Param("item") ShopAppointableTimeListDto dto); /** * 定时任务修改预约状态 */ void taskUpdateStatus(); } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/mapper/shop/ShopNonAppointableTimeMapper.java
@@ -8,4 +8,10 @@ * @Date 2025/5/26 14:31 */ public interface ShopNonAppointableTimeMapper extends BaseMapper<ShopNonAppointableTime> { /** * 每天凌晨3点删除3天前的数据 */ void taskDelData(); } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/service/impl/shop/ShopAppointableTimeServiceImpl.java
@@ -1,15 +1,21 @@ package com.ruoyi.shop.service.impl.shop; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.plugins.Page; import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.shop.domain.dto.MyAppointmentListDto; import com.ruoyi.shop.domain.dto.ShopAppointableTimeListDto; import com.ruoyi.shop.domain.vo.MyAppointmentListVo; import com.ruoyi.shop.domain.vo.ShopAppointableTimeListVo; import com.ruoyi.shop.mapper.shop.ShopAppointableTimeMapper; import com.ruoyi.shop.service.shop.ShopAppointableTimeService; import com.ruoyi.system.api.domain.poji.member.Member; import com.ruoyi.system.api.domain.poji.shop.ShopAppointableTime; import com.ruoyi.system.api.service.RemoteMemberService; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.ArrayList; import java.util.List; /** @@ -18,6 +24,9 @@ */ @Service public class ShopAppointableTimeServiceImpl extends ServiceImpl<ShopAppointableTimeMapper, ShopAppointableTime> implements ShopAppointableTimeService { @Resource private RemoteMemberService remoteMemberService; /** @@ -32,4 +41,39 @@ Long userId = SecurityUtils.getUserId(); return this.baseMapper.pageMyAppointmentList(page, userId, dto.getStatus()); } /** * 商户端获取预约列表 * * @param page * @param dto * @return */ @Override public List<ShopAppointableTimeListVo> getShopAppointableTimeList(Page<ShopAppointableTimeListVo> page, ShopAppointableTimeListDto dto) { List<ShopAppointableTime> shopAppointableTimeList = this.baseMapper.getShopAppointableTimeList(page, dto); List<ShopAppointableTimeListVo> list = new ArrayList<>(); shopAppointableTimeList.forEach(shopAppointableTime -> { ShopAppointableTimeListVo shopAppointableTimeListVo = new ShopAppointableTimeListVo(); shopAppointableTimeListVo.setId(shopAppointableTime.getId()); shopAppointableTimeListVo.setAppointableTime(shopAppointableTime.getAppointableTime()); shopAppointableTimeListVo.setStatus(shopAppointableTime.getStatus()); Member member = remoteMemberService.getMember(shopAppointableTime.getUserId()).getData(); shopAppointableTimeListVo.setUserName(member.getRealName()); shopAppointableTimeListVo.setMobile(member.getMobile()); shopAppointableTimeListVo.setSex(member.getGender() == 1 ? "女" : member.getGender() == 0 ? "男" : "未知"); list.add(shopAppointableTimeListVo); }); return list; } /** * 定时任务修改预约状态 */ @Override public void taskUpdateStatus() { this.baseMapper.taskUpdateStatus(); } } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/service/impl/shop/ShopNonAppointableTimeServiceImpl.java
@@ -12,4 +12,13 @@ */ @Service public class ShopNonAppointableTimeServiceImpl extends ServiceImpl<ShopNonAppointableTimeMapper, ShopNonAppointableTime> implements ShopNonAppointableTimeService { /** * 每天凌晨3点删除3天前的数据 */ @Override public void taskDelData() { this.baseMapper.taskDelData(); } } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/service/impl/shop/ShopRelUserServiceImpl.java
@@ -3,10 +3,10 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.shop.domain.pojo.shop.ShopRelUser; import com.ruoyi.shop.mapper.shop.ShopRelUserMapper; import com.ruoyi.shop.service.shop.ShopRelUserService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -59,15 +59,14 @@ /** * * @param userId * @return */ @Override public ShopRelUser getByUserId(Long userId){ public List<ShopRelUser> getByUserId(Long userId) { LambdaQueryWrapper<ShopRelUser> queryWrapper = Wrappers.lambdaQuery(); queryWrapper.eq(ShopRelUser::getDelFlag, 0).eq(ShopRelUser::getUserId, userId); return this.getOne(queryWrapper,false); return this.list(queryWrapper); } /** ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/service/impl/shop/ShopServiceImpl.java
@@ -1,6 +1,5 @@ package com.ruoyi.shop.service.impl.shop; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson2.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; @@ -8,7 +7,6 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.github.binarywang.wxpay.bean.ecommerce.ApplymentsResult; import com.github.binarywang.wxpay.bean.ecommerce.ApplymentsStatusResult; import com.github.binarywang.wxpay.bean.ecommerce.ProfitSharingReceiverRequest; @@ -18,7 +16,6 @@ import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.exception.ServiceException; import com.ruoyi.common.core.utils.DateUtils; import com.ruoyi.common.core.utils.ExceptionUtil; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.bean.BeanUtils; import com.ruoyi.common.core.utils.uuid.IdUtils; @@ -46,20 +43,18 @@ import com.ruoyi.system.api.domain.poji.config.SysTag; import com.ruoyi.system.api.domain.poji.member.Member; import com.ruoyi.system.api.domain.poji.shop.Shop; import com.ruoyi.system.api.domain.poji.shop.ShopAppointableTime; import com.ruoyi.system.api.domain.poji.sys.SysUser; import com.ruoyi.system.api.domain.vo.*; import com.ruoyi.system.api.service.*; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.math.BigDecimal; import java.nio.charset.StandardCharsets; import java.rmi.ServerException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -151,9 +146,11 @@ @Resource private RemoteUserService remoteUserService; @Resource private ShopAppointableTimeService shopAppointableTimeService; @Value("${callback_path}") private String callback_path; /** @@ -194,6 +191,7 @@ /** * 创建商户 * * @param mgtEditShopDto */ @Override @@ -203,32 +201,32 @@ BigDecimal zeroBig = BigDecimal.ZERO; //验证关联账号唯一 String relUserIds = mgtEditShopDto.getRelUserIds(); if(StringUtils.isNotBlank(relUserIds)) { if(relUserIds.startsWith(",")){ relUserIds = relUserIds.substring(1); } String[] relUserIdArray = relUserIds.split(","); ShopRelUser shopRelUser; Long userId; if(mgtEditShopDto.getShopId()!=null){ for (String str : relUserIdArray) { userId = Long.valueOf(str); shopRelUser = shopRelUserService.getByUserId(userId); if(shopRelUser!=null&&!shopRelUser.getShopId().equals(mgtEditShopDto.getShopId())){ throw new ServiceException(AppErrorConstant.SHOP_USER_DOUBLE); } } }else { for (String str : relUserIdArray) { userId = Long.valueOf(str); shopRelUser = shopRelUserService.getByUserId(userId); if(shopRelUser!=null){ throw new ServiceException(AppErrorConstant.SHOP_USER_DOUBLE); } } } } // if(StringUtils.isNotBlank(relUserIds)) { // if(relUserIds.startsWith(",")){ // relUserIds = relUserIds.substring(1); // } // String[] relUserIdArray = relUserIds.split(","); // ShopRelUser shopRelUser; // Long userId; // if(mgtEditShopDto.getShopId()!=null){ // for (String str : relUserIdArray) { // userId = Long.valueOf(str); // shopRelUser = shopRelUserService.getByUserId(userId); // if(shopRelUser!=null&&!shopRelUser.getShopId().equals(mgtEditShopDto.getShopId())){ // throw new ServiceException(AppErrorConstant.SHOP_USER_DOUBLE); // } // } // }else { // for (String str : relUserIdArray) { // userId = Long.valueOf(str); // shopRelUser = shopRelUserService.getByUserId(userId); // if(shopRelUser!=null){ // throw new ServiceException(AppErrorConstant.SHOP_USER_DOUBLE); // } // } // } // // } //验证商户名唯一 //Shop shopSame = this.getOne(new LambdaQueryWrapper<Shop>().eq(Shop::getDelFlag,0).eq(Shop::getShopName,mgtEditShopDto.getShopName())); if(mgtEditShopDto.getShopId()!=null){ @@ -918,8 +916,10 @@ staffHomeShopTotalVo.setShopTask(shopTaskCount); return staffHomeShopTotalVo; } /** * 获取商户端 * * @param merBaseDto * @return */ @@ -927,14 +927,13 @@ public MerHomeShopTotalVo getMerHomeTotal(MerBaseDto merBaseDto){ Long userId = merBaseDto.getUserId(); MerHomeShopTotalVo merHomeShopTotalVo = new MerHomeShopTotalVo(); ShopRelUser shopRelUser = shopRelUserService.getByUserId(userId); Long shopId = shopRelUser.getShopId(); Long shopId = merBaseDto.getShopId(); //如果商户变动刷新token if(!shopId.equals(merBaseDto.getShopId())){ String userKey = SecurityUtils.getUserKey(); redisService.deleteObject(CacheConstants.LOGIN_TOKEN_KEY+userKey); throw new ServiceException("登录状态已过期",401); } // if(!shopId.equals(merBaseDto.getShopId())){ // String userKey = SecurityUtils.getUserKey(); // redisService.deleteObject(CacheConstants.LOGIN_TOKEN_KEY+userKey); // throw new ServiceException("登录状态已过期",401); // } merHomeShopTotalVo.setShopId(shopId); Shop shop = this.getById(shopId); if(shop.getFrozenFlag()==1){ @@ -955,6 +954,8 @@ merHomeShopTotalVo.setExplorationSurp(orderVo.getExplorationSurp()); merHomeShopTotalVo.setPlatformBirthdayFlag(shop.getPlatformBirthdayFlag()); merHomeShopTotalVo.setPlatformCouponFlag(shop.getPlatformCouponFlag()); int unHandleReserve = shopAppointableTimeService.count(new LambdaQueryWrapper<ShopAppointableTime>().eq(ShopAppointableTime::getShopId, shopId).eq(ShopAppointableTime::getStatus, 1)); merHomeShopTotalVo.setUnHandleReserve(unHandleReserve); return merHomeShopTotalVo; } @@ -1456,11 +1457,11 @@ } /** * @param userId * @return Shop * @description 获取用户管理商户 * @author jqs * @date 2023/7/14 10:00 * @param userId * @return Shop */ @Override public List<Shop> getShopByBelongUserId(Long userId){ ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/service/shop/ShopAppointableTimeService.java
@@ -1,9 +1,11 @@ package com.ruoyi.shop.service.shop; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.plugins.Page; import com.ruoyi.shop.domain.dto.MyAppointmentListDto; import com.ruoyi.shop.domain.dto.ShopAppointableTimeListDto; import com.ruoyi.shop.domain.vo.MyAppointmentListVo; import com.ruoyi.shop.domain.vo.ShopAppointableTimeListVo; import com.ruoyi.system.api.domain.poji.shop.ShopAppointableTime; import java.util.List; @@ -23,4 +25,20 @@ * @return */ List<MyAppointmentListVo> pageMyAppointmentList(Page<MyAppointmentListVo> page, MyAppointmentListDto dto); /** * 商户端获取预约列表 * * @param page * @param dto * @return */ List<ShopAppointableTimeListVo> getShopAppointableTimeList(Page<ShopAppointableTimeListVo> page, ShopAppointableTimeListDto dto); /** * 定时任务修改预约状态 */ void taskUpdateStatus(); } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/service/shop/ShopNonAppointableTimeService.java
@@ -8,4 +8,10 @@ * @Date 2025/5/26 14:30 */ public interface ShopNonAppointableTimeService extends IService<ShopNonAppointableTime> { /** * 每天凌晨3点删除3天前的数据 */ void taskDelData(); } ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/service/shop/ShopRelUserService.java
@@ -1,7 +1,7 @@ package com.ruoyi.shop.service.shop; import com.ruoyi.shop.domain.pojo.shop.ShopRelUser; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.shop.domain.pojo.shop.ShopRelUser; import java.util.List; @@ -33,7 +33,7 @@ * @param userId * @return */ ShopRelUser getByUserId(Long userId); List<ShopRelUser> getByUserId(Long userId); /** * 通过用户id删除关联 ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/TaskUtil.java
New file @@ -0,0 +1,40 @@ package com.ruoyi.shop.util; import com.ruoyi.shop.service.shop.ShopAppointableTimeService; import com.ruoyi.shop.service.shop.ShopNonAppointableTimeService; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import javax.annotation.Resource; /** * @author zhibing.pu * @Date 2025/6/3 16:11 */ @Component public class TaskUtil { @Resource private ShopAppointableTimeService shopAppointableTimeService; @Resource private ShopNonAppointableTimeService shopNonAppointableTimeService; /** * 每天3点执行的定时任务 */ @Scheduled(cron="0 0 3 * * ?") public void timingTask(){ shopNonAppointableTimeService.taskDelData(); } /** * 每分钟执行的定时任务 */ @Scheduled(cron="0 0/1 * * * ?") public void timingTask1(){ shopAppointableTimeService.taskUpdateStatus(); } } ruoyi-modules/ruoyi-shop/src/main/resources/mapper/shop/ShopAppointableTimeMapper.xml
New file @@ -0,0 +1,44 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.shop.mapper.shop.ShopAppointableTimeMapper"> <select id="pageMyAppointmentList" resultType="com.ruoyi.shop.domain.vo.MyAppointmentListVo"> select * from ( select a.id, DATE_FORMAT(a.appointable_time, '%Y-%m-%d %H:%i') as appointmentTime, a.status, b.shop_name as shopName, a.reason as cancelReason, CASE WHEN a.`status` in (1, 2) THEN 1 WHEN a.`status` = 3 THEN 2 ELSE 3 END as sort from t_shop_appointable_time a left join t_shop b on (a.shop_id = b.shop_id) where a.user_id = #{userId} <if test="status != null"> and a.status = #{status} </if> ) as aa order by aa.sort, aa.appointmentTime </select> <select id="getShopAppointableTimeList" resultType="com.ruoyi.system.api.domain.poji.shop.ShopAppointableTime"> select * from ( select a.*, CASE WHEN a.`status` = 3 THEN 3 WHEN a.`status` = 0 THEN 2 ELSE 1 END as sort from t_shop_appointable_time a where shop_id = #{item.shopId} <if test="null != item.status"> and a.status = #{item.status} </if> ) as aa order by aa.sort,aa.appointable_time </select> <update id="taskUpdateStatus"> update t_shop_appointable_time set status = 3 where status in (1, 2) and appointment_time < now() </update> </mapper> ruoyi-modules/ruoyi-shop/src/main/resources/mapper/shop/ShopNonAppointableTimeMapper.xml
New file @@ -0,0 +1,10 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.shop.mapper.shop.ShopNonAppointableTimeMapper"> <delete id="taskDelData"> delete from t_shop_non_appointable_time where DATE(non_appointable_start_time) < DATE(DATE_SUB(NOW(), INTERVAL 3 DAY)) </delete> </mapper>