ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/factory/AppUserClientFallbackFactory.java
@@ -2,9 +2,12 @@ import com.ruoyi.account.api.feignClient.AppUserClient; import com.ruoyi.account.api.model.AppUser; import com.ruoyi.account.api.model.AppUserShop; import com.ruoyi.common.core.domain.R; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.openfeign.FallbackFactory; import java.util.List; /** * @author zhibing.pu @@ -37,6 +40,11 @@ throw new RuntimeException("获取优惠券数量失败"); } @Override public R<List<AppUserShop>> getAppUserShop(Long userId) { log.error("获取用户门店信息失败:{}", cause.getMessage()); throw new RuntimeException("获取用户门店信息失败"); } }; } } ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/feignClient/AppUserClient.java
@@ -2,11 +2,16 @@ import com.ruoyi.account.api.factory.AppUserClientFallbackFactory; import com.ruoyi.account.api.model.AppUser; import com.ruoyi.account.api.model.AppUserShop; import com.ruoyi.common.core.constant.ServiceNameConstants; import com.ruoyi.common.core.domain.R; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import java.util.List; /** * @author zhibing.pu @@ -31,4 +36,11 @@ @PostMapping("/appUser/getCouponCount") R<Long> getCouponCount(@RequestParam("userId")Long userId, @RequestParam("couponId") Integer couponId ); /** * 根据用户id查询用户门店信息 */ @GetMapping("/appUserShop/shop/{userId}") R<List<AppUserShop>> getAppUserShop(@PathVariable("userId") Long userId); } ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/model/AppUser.java
@@ -33,6 +33,9 @@ @TableId("id") private Long id; @ApiModelProperty(value = "用户类型(1-普通用户,2-门店员工)") private Integer userType; @ApiModelProperty(value = "用户") @TableField("name") private String name; @@ -122,6 +125,10 @@ @TableField("last_shop_time") private LocalDateTime lastShopTime; @ApiModelProperty(value = "账户余额") @TableField("balance") private BigDecimal balance; @ApiModelProperty(value = "可提现金额") @TableField("withdrawable_amount") private BigDecimal withdrawableAmount; ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/factory/TechnicianClientFallbackFactory.java
New file @@ -0,0 +1,23 @@ package com.ruoyi.other.api.factory; import com.ruoyi.common.core.domain.R; import com.ruoyi.other.api.domain.Technician; import com.ruoyi.other.api.feignClient.TechnicianClient; import org.springframework.cloud.openfeign.FallbackFactory; public class TechnicianClientFallbackFactory implements FallbackFactory<TechnicianClient> { @Override public TechnicianClient create(Throwable cause) { return new TechnicianClient() { @Override public R<Technician> shopdetail(Integer techId) { return R.fail("根据省市区获取地区价格配置失败:" + cause.getMessage()); } @Override public R<Void> updateStatus(Integer status, Integer subscribeId) { return R.fail("跟新技师预约状态失败:" + cause.getMessage()); } }; } } ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/feignClient/TechnicianClient.java
New file @@ -0,0 +1,20 @@ package com.ruoyi.other.api.feignClient; import com.ruoyi.common.core.constant.ServiceNameConstants; import com.ruoyi.common.core.domain.R; import com.ruoyi.other.api.domain.Technician; import com.ruoyi.other.api.factory.TechnicianClientFallbackFactory; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestParam; @FeignClient(contextId = "TechnicianClient", value = ServiceNameConstants.ORDER_SERVICE, fallbackFactory = TechnicianClientFallbackFactory.class) public interface TechnicianClient { @PostMapping("/technician/shop/detail") R<Technician> shopdetail(@RequestParam Integer techId); @PutMapping("/technician-subscribe/updateStatus") R<Void> updateStatus(@RequestParam Integer status, @RequestParam Integer subscribeId); } ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/AppUserShopController.java
@@ -1,6 +1,13 @@ package com.ruoyi.account.controller; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.ruoyi.account.api.model.AppUserShop; import com.ruoyi.account.service.AppUserShopService; import com.ruoyi.common.core.domain.R; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.List; /** @@ -10,6 +17,14 @@ @RestController @RequestMapping("/appUserShop") public class AppUserShopController { @Resource private AppUserShopService appUserShopService; @GetMapping("/shop/{userId}") public R<List<AppUserShop>> getAppUserShop(@PathVariable("userId") Long userId) { return R.ok(appUserShopService.list(new LambdaQueryWrapper<AppUserShop>() .eq(AppUserShop::getAppUserId,userId))); } ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/vo/WalletVO.java
@@ -10,6 +10,9 @@ @ApiModel(value="钱包对象", description="") public class WalletVO { @ApiModelProperty(value = "账户余额") private BigDecimal balance; @ApiModelProperty(value = "可提现金额") private BigDecimal withdrawalAmount; ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/OrderController.java
@@ -1,6 +1,7 @@ package com.ruoyi.order.controller; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.security.service.TokenService; import com.ruoyi.order.service.OrderService; @@ -11,6 +12,7 @@ import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import model.Order; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @@ -70,8 +72,11 @@ @ApiImplicitParam(value = "分享id", name = "shareId", required = true, dataType = "int", paramType="query"), }) @GetMapping("/check/{orderNumber}/{shopId}") public R<Boolean> check(@PathVariable("orderNumber") String orderNumber, @PathVariable("shopId") Long shopId){ return R.ok(orderService.check(orderNumber, shopId)); public R<Boolean> check(@PathVariable("orderNumber") String orderNumber, @PathVariable("shopId") Integer shopId){ LoginUser loginUserApplet = tokenService.getLoginUserApplet(); Order order = orderService.getOne(new LambdaQueryWrapper<Order>() .eq(Order::getOrderNumber, orderNumber)); return R.ok(orderService.check(order, shopId, loginUserApplet.getUserid())); } /** ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/enums/OrderStatus.java
New file @@ -0,0 +1,32 @@ package com.ruoyi.order.enums; import lombok.Getter; @Getter public enum OrderStatus { PENDING_SHIPMENT(1, "待发货"), PENDING_RECEIPT(2, "待收货"), PENDING_USE(3, "待使用"), COMPLETED(4, "已完成"), CANCELLED(5, "已取消"), REFUNDED(6, "已退款"), AFTER_SALE(7, "售后中"); private final int code; private final String description; OrderStatus(int code, String description) { this.code = code; this.description = description; } // 根据代码获取对应的OrderStatus public static OrderStatus fromCode(int code) { for (OrderStatus status : values()) { if (status.getCode() == code) { return status; } } throw new IllegalArgumentException("Unknown order status code: " + code); } } ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/enums/OrderType.java
New file @@ -0,0 +1,26 @@ package com.ruoyi.order.enums; import lombok.Getter; @Getter public enum OrderType { SERVICE(1, "服务单"), GOOD(2, "商品单"); private final int code; private final String description; OrderType(int code, String description) { this.code = code; this.description = description; } public static OrderType fromCode(int code) { for (OrderType type : OrderType.values()) { if (type.getCode() == code) { return type; } } return null; } } ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/OrderService.java
@@ -20,7 +20,7 @@ OrderDetailVO getOrderDetail(Long orderId); boolean check(String orderNumber, Long shopId); boolean check(Order order, Integer shopId, Long userId); void writeOff(String code); void writeOff(String code,Integer shopId); } ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/OrderServiceImpl.java
@@ -3,9 +3,15 @@ import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.account.api.feignClient.AppUserClient; import com.ruoyi.account.api.model.AppUserShop; import com.ruoyi.account.api.model.UserAddress; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.exception.ServiceException; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.security.service.TokenService; import com.ruoyi.order.enums.OrderStatus; import com.ruoyi.order.enums.OrderType; import com.ruoyi.order.mapper.OrderGoodMapper; import com.ruoyi.order.mapper.OrderMapper; import com.ruoyi.order.service.OrderService; @@ -15,13 +21,18 @@ import com.ruoyi.other.api.domain.CouponInfo; import com.ruoyi.other.api.domain.Goods; import com.ruoyi.other.api.domain.OrderActivityInfo; import com.ruoyi.other.api.domain.Technician; import com.ruoyi.other.api.feignClient.TechnicianClient; import com.ruoyi.system.api.model.LoginUser; import model.Order; import model.OrderGood; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; /** * <p> @@ -35,7 +46,14 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService { @Resource private OrderMapper orderMapper; @Resource private OrderGoodMapper orderGoodMapper; @Resource private AppUserClient appUserClient; @Resource private TokenService tokenService; @Resource private TechnicianClient technicianClient; @Override public List<OrderVO> selectOrderListByUserId(Integer status, Long userId) { @@ -115,15 +133,55 @@ } @Override public boolean check(String orderNumber, Long shopId) { Order order = getOne(new LambdaQueryWrapper<Order>() .eq(Order::getOrderNumber, orderNumber) .eq(Order::getShopId, shopId)); return order != null; public boolean check(Order order, Integer shopId, Long userId) { R<List<AppUserShop>> r = appUserClient.getAppUserShop(userId); if (r.getCode() != R.SUCCESS){ throw new ServiceException("获取用户门店信息失败"); } List<AppUserShop> appUserShopList = r.getData(); if (appUserShopList == null || appUserShopList.isEmpty()){ return false; } // 判断用户是否拥有该门店 List<AppUserShop> userShopList = appUserShopList.stream() .filter(appUserShop -> appUserShop.getShopId().equals(shopId)) .collect(Collectors.toList()); if (userShopList.isEmpty()){ return false; } // 判断订单是否属于该门店 if (order == null){ throw new ServiceException("订单不存在"); } return order.getShopId().equals(shopId); } @Override public void writeOff(String code) { @Transactional(rollbackFor = Exception.class) public void writeOff(String code,Integer shopId) { LoginUser loginUserApplet = tokenService.getLoginUserApplet(); Order order = orderMapper.selectOne(new LambdaQueryWrapper<Order>() .eq(Order::getOrderNumber, code)); boolean check = check(order, shopId, loginUserApplet.getUserid()); if (!check){ throw new ServiceException("订单不存在"); } order.setOrderStatus(OrderStatus.COMPLETED.getCode()); orderMapper.updateById(order); Integer orderType = order.getOrderType(); if (orderType.equals(OrderType.SERVICE.getCode())){ R<Technician> shopdetail = technicianClient.shopdetail(order.getTechnicianId()); if (shopdetail.getCode() != R.SUCCESS){ throw new ServiceException("获取技师信息失败"); } Technician technician = shopdetail.getData(); R<Void> r = technicianClient.updateStatus(2, technician.getId()); if (r.getCode() != R.SUCCESS){ throw new ServiceException("修改技师状态失败"); } } } } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TechnicianController.java
@@ -101,6 +101,7 @@ technician.setServeCount(orderIdsByTechId.getData().size()); return R.ok(technician); } @PostMapping("/shop/tech") @ApiOperation(value = "预约操作", tags = {"小程序-门店详情-技师预约"}) public R<Technician> shoptech(@RequestBody TechnicianSubscribe subscribe){ ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TechnicianSubscribeController.java
@@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.page.TableDataInfo; @@ -51,7 +52,7 @@ @PostMapping("/subscribe") @ApiOperation(value = "预约技师", notes = "预约技师", tags = {"小程序-个人中心-门店管理-预约列表-预约技师"}) public R<Void> subscribe(@RequestBody TechnicianSubscribe technicianSubscribe){ technicianSubscribeService.subscribe(technicianSubscribe); technicianSubscribeService.subscribe(technicianSubscribe, technicianSubscribe.getTechnicianId()); return R.ok(); } @@ -73,6 +74,23 @@ return R.ok(); } /** * 跟新技师预约状态 * * @param status */ @PutMapping("/updateStatus") @ApiOperation(value = "跟新技师预约状态", notes = "跟新技师预约状态", tags = {"后台-技师预约管理-跟新技师预约状态"}) public R<Void> updateStatus(@ApiParam @RequestParam Integer status, @ApiParam @RequestParam Long subscribeId) { boolean update = technicianSubscribeService.update(new LambdaUpdateWrapper<TechnicianSubscribe>() .eq(TechnicianSubscribe::getId, subscribeId) .set(TechnicianSubscribe::getStatus, status)); if (!update) { return R.fail("更新失败"); } return R.ok(); } @GetMapping("/home/list") @ApiOperation(value = "列表", notes = "列表", tags = {"小程序-个人中心-我的预约"}) ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/enums/TechnicianStatus.java
New file @@ -0,0 +1,26 @@ package com.ruoyi.other.enums; import lombok.Getter; @Getter public enum TechnicianStatus { UNSUBSCRIBE(0, "待服务"), SERVE(1, "已服务"), CANCEL(2, "已取消"); private final Integer code; private final String message; TechnicianStatus(Integer code, String message) { this.code = code; this.message = message; } public static String getMessage(Integer code) { for (TechnicianStatus value : TechnicianStatus.values()) { if (value.getCode().equals(code)) { return value.getMessage(); } } return null; } } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/TechnicianSubscribeService.java
@@ -20,7 +20,8 @@ * 查询用于指定门店的相关预约记录 */ List<TechnicianSubscribeVO> getTechnicianSubscribeByUserAndShop(Long userId, Long shopId); List<TechnicianSubscribeVO> getTechnicianSubscribeByUser(Long userId, Integer status); void subscribe(TechnicianSubscribe technicianSubscribe); void subscribe(TechnicianSubscribe technicianSubscribe, Long technicianId); } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TechnicianSubscribeServiceImpl.java
@@ -1,18 +1,18 @@ package com.ruoyi.other.service.impl; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.core.exception.ServiceException; import com.ruoyi.common.redis.annotation.DistributedLock; import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.other.api.domain.Technician; import com.ruoyi.other.api.domain.TechnicianSubscribe; import com.ruoyi.other.enums.TechnicianErrorCode; import com.ruoyi.other.enums.TechnicianStatus; import com.ruoyi.other.mapper.TechnicianMapper; import com.ruoyi.other.mapper.TechnicianSubscribeMapper; import com.ruoyi.other.service.TechnicianSubscribeService; import com.ruoyi.other.vo.TechnicianSubscribeVO; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.time.LocalDateTime; @@ -43,26 +43,22 @@ } @Override @Transactional(rollbackFor = Exception.class) public void subscribe(TechnicianSubscribe technicianSubscribe) { @DistributedLock(lockNamePre = "#technician_subscribe_lock", lockNamePost = "#technicianId") public void subscribe(TechnicianSubscribe subscribe, Long technicianId) { Long count = technicianSubscribeMapper.selectCount(new LambdaQueryWrapper<TechnicianSubscribe>() .eq(TechnicianSubscribe::getTechnicianId, technicianId) .eq(TechnicianSubscribe::getSubscribeTime, subscribe.getSubscribeTime()) .eq(TechnicianSubscribe::getStatus, TechnicianStatus.UNSUBSCRIBE.getCode())); if (count > 0) { throw new ServiceException("当前时间段已被预约", TechnicianErrorCode.TECHNICIAN_ALREADY_SUBSCRIBED.getCode()); } // 创建技师预约单 Long technicianId = technicianSubscribe.getTechnicianId(); Long userId = SecurityUtils.getUserId(); TechnicianSubscribe subscribe = new TechnicianSubscribe(); subscribe.setAppUserId(userId); subscribe.setStatus(TechnicianStatus.UNSUBSCRIBE.getCode()); subscribe.setDelFlag(0); subscribe.setCreateTime(LocalDateTime.now()); technicianSubscribeMapper.insert(subscribe); // 更新技师状态 UpdateWrapper<Technician> updateWrapper = new UpdateWrapper<>(); updateWrapper.eq("id", technicianId); updateWrapper.eq("subscribe_status", 1); updateWrapper.eq("status", 2); updateWrapper.set("subscribe_status", 2); updateWrapper.set("create_time", LocalDateTime.now()); int update = technicianMapper.update(null, updateWrapper); if (update == 0){ throw new ServiceException("该技师已被预约", TechnicianErrorCode.TECHNICIAN_ALREADY_SUBSCRIBED.getCode()); } } }