更新版本

This commit is contained in:
tsukiyalo 2025-05-14 13:09:50 +08:00
parent 530f0fb620
commit c5f84d2f05
87 changed files with 4367 additions and 0 deletions

Binary file not shown.

View File

@ -0,0 +1,65 @@
package com.bsz.school_send_back_end.config;
import com.bsz.school_send_back_end.model.domain.Dishes;
import com.bsz.school_send_back_end.model.domain.Orders;
import com.bsz.school_send_back_end.model.vo.BusinessVO;
import com.bsz.school_send_back_end.service.BusinessService;
import com.bsz.school_send_back_end.service.DishesService;
import com.bsz.school_send_back_end.service.LoggingService;
import com.bsz.school_send_back_end.service.OrdersService;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.PromptChatMemoryAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Description;
import java.util.List;
import java.util.function.Function;
@Configuration
public class AIConfig {
@Resource
private BusinessService businessService;
@Resource
private DishesService dishesService;
@Resource
private OrdersService ordersService;
@Bean
ChatClient chatClient(ChatClient.Builder builder, ChatMemory chatMemory) {
return builder.defaultSystem(
"""
你是食刻必达校快送小程序的助手情谊轻松切愉快的语气与用户交流
今天的日期是{current_date}
请讲中文
"""
)
.defaultAdvisors(
new PromptChatMemoryAdvisor(chatMemory),
new LoggingService()
)
.defaultFunctions("getBusinessByAI")
.build();
}
@Bean
@Description("推荐商家")
public Function<Void, List<BusinessVO>> getBusinessByAI() {
List<BusinessVO> allBusiness = businessService.findAllBusiness();
return unused -> allBusiness.stream()
.filter(businessVO -> businessVO.getLevel() == 5)
.toList();
}
// @Bean
// @Description("推荐菜品")
// public Function<Void, List<Dishes>> getDishesByOrders() {
// List<Orders> ordersList = ordersService.list();
// }
}

View File

@ -0,0 +1,98 @@
package com.bsz.school_send_back_end.config;
import com.bsz.school_send_back_end.contant.RabbitMQConstant;
import org.springframework.amqp.core.*;
import org.springframework.amqp.support.converter.DefaultClassMapper;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class RabbitMQConfig {
@Bean
public Queue topicQueue1() {
return QueueBuilder.durable(RabbitMQConstant.TOPIC_QUEUE1).build();
}
@Bean
public Queue topicQueue2() {
return QueueBuilder.durable(RabbitMQConstant.TOPIC_QUEUE2).build();
}
@Bean
public Queue orderReplyQueue() {
return QueueBuilder.durable(RabbitMQConstant.ORDER_REPLY_QUEUE).build();
}
@Bean
public Exchange topicExchange() {
return ExchangeBuilder.topicExchange(RabbitMQConstant.TOPIC_EXCHANGE).build();
}
@Bean
public Exchange responseExchange() {
return ExchangeBuilder.topicExchange(RabbitMQConstant.RESPONSE_EXCHANGE).build();
}
@Bean
public Binding topicBinding1() {
return BindingBuilder.bind(topicQueue1()).to(topicExchange()).with("topic.key1").noargs();
}
@Bean
public Binding topicBinding2() {
return BindingBuilder.bind(topicQueue2()).to(topicExchange()).with("topic.#").noargs();
}
@Bean
public Binding responseBinding() {
return BindingBuilder.bind(orderReplyQueue()).to(responseExchange()).with("response.#").noargs();
}
// /**
// * 声明一个 **延迟交换机**类型必须为 `x-delayed-message`
// */
// @Bean
// public CustomExchange delayedExchange() {
// Map<String, Object> args = new HashMap<>();
// args.put("x-delayed-type", "direct"); // 交换机类型
// return new CustomExchange(RabbitMQConstant.DELAYED_EXCHANGE, "x-delayed-message", true, false, args);
// }
//
// /**
// * 声明队列
// */
// @Bean
// public Queue delayedQueue() {
// return new Queue(RabbitMQConstant.DELAYED_QUEUE, true);
// }
//
// /**
// * 绑定队列到延迟交换机
// */
// @Bean
// public Binding binding(Queue delayedQueue, CustomExchange delayedExchange) {
// return BindingBuilder.bind(delayedQueue).to(delayedExchange).with(RabbitMQConstant.DELAYED_ROUTING_KEY).noargs();
// }
@Bean
public MessageConverter jsonToMapMessageConverter() {
DefaultClassMapper defaultClassMapper = new DefaultClassMapper();
defaultClassMapper.setTrustedPackages("com.bsz.school_send_back_end.utils.MultiDelayMessage"); // trusted packages
Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();
jackson2JsonMessageConverter.setClassMapper(defaultClassMapper);
return jackson2JsonMessageConverter;
}
@Bean
public MessageConverter messageConverter(){
return new Jackson2JsonMessageConverter();
}
}

View File

@ -0,0 +1,16 @@
package com.bsz.school_send_back_end.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "spring.rabbitmq")
@Data
public class RabbitMQConfigProperties {
private String host;
private int port;
private String username;
private String password;
private String virtualHost;
}

View File

@ -0,0 +1,84 @@
package com.bsz.school_send_back_end.contant;
import java.util.List;
public interface RabbitMQConstant {
/**
* 聊天
*/
String TOPIC_QUEUE1 = "topic.chat";
/**
* 商家
*/
String TOPIC_QUEUE2 = "topic.order";
/**
* 跑腿
*/
String TOPIC_QUEUE3 = "topic.errand";
/**
* 交换机
*/
String TOPIC_EXCHANGE = "topicExchage";
/**
* 请求响应交换机用于处理用户和商家之间的异步响应
*/
String RESPONSE_EXCHANGE = "responseExchange";
/**
* 订单响应队列商家处理完成订单后可以发送响应消息到这个队列
*/
String ORDER_REPLY_QUEUE = "orderReplyQueue";
// // 交换机名称
// String DELAYED_EXCHANGE = "delayed.exchange";
// // 队列名称
// String DELAYED_QUEUE = "delayed.queue";
// // 路由键
// String DELAYED_ROUTING_KEY = "delayed.routingKey";
// List<Long> DELAY_MILLIS = List.of(10000L, 10000L, 10000L, 15000L, 15000L, 30000L, 30000L, 60000L, 60000L, 120000L, 300000L, 600000L, 600000L));
// 堂食订单取消3分钟
List<Long> DINE_IN_DELAY_MILLIS = List.of(30000L, 30000L, 30000L, 30000L, 30000L, 30000L);
// 外卖订单退款30分钟多次检查
List<Long> DELIVERY_DELAY_MILLIS = List.of(600000L, 1200000L, 1800000L);
// 取消订单相关常量
String CANCEL_ORDER_EXCHANGE = "cancel_order_exchange"; // 取消订单交换机
String CANCEL_ORDER_QUEUE = "cancel_order_queue"; // 取消订单队列
String CANCEL_ORDER_ROUTING_KEY = "cancel_order_key"; // 取消订单路由键
// 外卖单相关常量
String DELIVERY_DELAY_EXCHANGE = "delivery_exchange"; // 外卖单交换机
String DELIVERY_ORDER_QUEUE = "delivery_queue"; // 外卖单队列
String DELIVERY_ORDER_ROUTING_KEY = "delivery_key"; // 外卖单路由键
// String DELAY_COUPON_QUEUE = "coupon.delay.queue";
//
// String DELAY_COUPON_ROUTING_KEY = "coupon.key";
//
// String DELAY_USER_COUPON_QUEUE = "userCoupon.delay.queue";
//
// String DELAY_USER_COUPON_ROUTING_KEY = "userCoupon.key";
//
// String DELAY_ADVANCE_ORDER_QUEUE = "advanceOrder.delay.queue";
//
// String DELAY_ADVANCE_ROUTING_KEY = "advanceOrder.key";
//
// String DELAY_CLOTHES_RENT_ORDER_QUEUE = "clothesRentOrder.delay.queue";
//
// String DELAY_CLOTHES_RENT_ORDER_ROUTING_KEY = "clothesRentOrder.key";
//
// String DELAY_CLOTHES_RENT_PERIOD_QUEUE = "clothesRentPeriod.delay.queue";
//
// String DELAY_CLOTHES_RENT_PERIOD_ROUTING_KEY = "clothesRentPeriod.key";
//
}

View File

@ -0,0 +1,32 @@
package com.bsz.school_send_back_end.controller;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import java.time.LocalDate;
@RestController
@RequestMapping("/ai")
public class AIController {
@Resource
private ChatClient chatClient;
@GetMapping(value = "/chat/generateStreamAsString", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> generateStreamAsString(@RequestParam(value = "message", defaultValue = "介绍自己") String message) {
Flux<String> content = this.chatClient.prompt()
.system(promptSystemSpec -> promptSystemSpec.param("current_date", LocalDate.now().toString()))
.advisors(advisorSpec -> advisorSpec.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY,100))
.user(message)
.stream()
.content();
return content.concatWith(Flux.just("[complete]"));
}
}

View File

@ -0,0 +1,66 @@
package com.bsz.school_send_back_end.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bsz.school_send_back_end.annotation.AuthCheck;
import com.bsz.school_send_back_end.common.BaseResponse;
import com.bsz.school_send_back_end.common.ResultUtils;
import com.bsz.school_send_back_end.contant.UserConstant;
import com.bsz.school_send_back_end.model.domain.Errand;
import com.bsz.school_send_back_end.model.domain.ErrandBill;
import com.bsz.school_send_back_end.model.domain.OrderRefunds;
import com.bsz.school_send_back_end.model.domain.Orders;
import com.bsz.school_send_back_end.service.ErrandBillService;
import com.bsz.school_send_back_end.service.ErrandService;
import com.bsz.school_send_back_end.service.OrdersService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/bill")
@Slf4j
public class BillController {
@Resource
private ErrandService errandService;
@Resource
private ErrandBillService billService;
@Resource
private OrdersService ordersService;
/**
* 跑腿查询自己的账单
* @param request 网路请求
* @return 账单列表
*/
@PostMapping("/list")
@AuthCheck(mustRole = UserConstant.ERRAND_ROLE)
public BaseResponse<List<ErrandBill>> listBillByErrand(HttpServletRequest request) {
Errand loginErrand = errandService.getLoginErrand(request);
LambdaQueryWrapper<Orders> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Orders::getErrandId, loginErrand.getId());
List<Orders> ordersList = ordersService.list(wrapper);
List<Long> orderIds = ordersList.stream()
.map(Orders::getId)
.collect(Collectors.toList());
LambdaQueryWrapper<ErrandBill> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(ErrandBill::getOrderId, orderIds);
queryWrapper.orderByDesc(ErrandBill::getOrderStartTime);// orderStartTime 降序排序
List<ErrandBill> bills = billService.list(queryWrapper);
return ResultUtils.success(bills);
}
}

View File

@ -0,0 +1,148 @@
package com.bsz.school_send_back_end.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bsz.school_send_back_end.annotation.AuthCheck;
import com.bsz.school_send_back_end.common.BaseResponse;
import com.bsz.school_send_back_end.common.ErrorCode;
import com.bsz.school_send_back_end.common.ResultUtils;
import com.bsz.school_send_back_end.contant.UserConstant;
import com.bsz.school_send_back_end.exception.BusinessException;
import com.bsz.school_send_back_end.exception.ThrowUtils;
import com.bsz.school_send_back_end.model.domain.Business;
import com.bsz.school_send_back_end.model.domain.Businessinfo;
import com.bsz.school_send_back_end.model.dto.CommonRequest;
import com.bsz.school_send_back_end.model.dto.businessinfo.InfoAddRequest;
import com.bsz.school_send_back_end.model.dto.businessinfo.InfoQueryRequest;
import com.bsz.school_send_back_end.service.BusinessService;
import com.bsz.school_send_back_end.service.BusinessinfoService;
import com.github.houbb.sensitive.word.core.SensitiveWordHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import java.util.List;
@RestController
@Slf4j
@RequestMapping("/businessInfo")
public class BusinessInfoController {
@Resource
private BusinessinfoService businessinfoService;
@Resource
private BusinessService businessService;
/**
* 添加公告
* @param addRequest 添加请求体
* @param request 网络请求
* @return 是否添加成功
*/
@PostMapping("/add")
@AuthCheck(mustRole = UserConstant.BUSINESS_ROLE)
public BaseResponse<Boolean> addInfo (@RequestBody InfoAddRequest addRequest, HttpServletRequest request) {
if ( addRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
Business loginBusiness = businessService.getLoginBusiness(request);
Businessinfo businessinfo = new Businessinfo();
String content = addRequest.getContent();
boolean contains = SensitiveWordHelper.contains(content);
ThrowUtils.throwIf(contains, ErrorCode.PARAMS_ERROR, "公告含有违禁词");
BeanUtils.copyProperties(addRequest, businessinfo);
businessinfo.setBusinessId(loginBusiness.getId());
boolean save = businessinfoService.save(businessinfo);
ThrowUtils.throwIf(!save, ErrorCode.SYSTEM_ERROR, "添加公告失败");
return ResultUtils.success(true);
}
/**
* 删除公告
* @param commonRequest 删除请求体
* @param request 网络请求
* @return 是否成功
*/
@PostMapping("/delete")
@AuthCheck(mustRole = UserConstant.BUSINESS_ROLE)
public BaseResponse<Boolean> deleteInfo (@RequestBody CommonRequest commonRequest, HttpServletRequest request) {
if (commonRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
Business loginBusiness = businessService.getLoginBusiness(request);
Long businessId = loginBusiness.getId();
Long id = commonRequest.getId();
LambdaQueryWrapper<Businessinfo> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Businessinfo::getId, id);
queryWrapper.eq(Businessinfo::getBusinessId, businessId);
long count = businessinfoService.count(queryWrapper);
ThrowUtils.throwIf(count != 1, ErrorCode.SYSTEM_ERROR, "当前公告未找到");
boolean remove = businessinfoService.remove(queryWrapper);
ThrowUtils.throwIf(!remove, ErrorCode.SYSTEM_ERROR, "删除失败");
return ResultUtils.success(true);
}
/**
* 查询公告列表 仅商家
* @param request 网络请求
* @return 查询列表
*/
@PostMapping("/list/my")
@AuthCheck(mustRole = UserConstant.BUSINESS_ROLE)
public BaseResponse<List<Businessinfo>> selectMyInfo (HttpServletRequest request) {
Business loginBusiness = businessService.getLoginBusiness(request);
Long businessId = loginBusiness.getId();
LambdaQueryWrapper<Businessinfo> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Businessinfo::getBusinessId, businessId);
queryWrapper.orderByDesc(Businessinfo::getCreateTime);
List<Businessinfo> list = businessinfoService.list(queryWrapper);
return ResultUtils.success(list, "查询成功");
}
/**
* 查询公列表仅管理员 分页
* @param infoQueryRequest 查询请求体
* @return 查询列表
*/
@PostMapping("/list/page")
@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
public BaseResponse<Page<Businessinfo>> selectInfoByPage (@RequestBody InfoQueryRequest infoQueryRequest) {
if (infoQueryRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
long current = infoQueryRequest.getCurrent();
long pageSize = infoQueryRequest.getPageSize();
QueryWrapper<Businessinfo> queryWrapper = businessinfoService.getQueryWrapper(infoQueryRequest);
Page<Businessinfo> page = businessinfoService.page(new Page<>(current, pageSize), queryWrapper);
return ResultUtils.success(page, "查询成功");
}
/**
* 用户查询商家最新公告
* @return 查询列表
*/
@PostMapping("/list")
public BaseResponse<Businessinfo> selectInfo (@RequestBody CommonRequest commonRequest) {
if (commonRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
Long businessId = commonRequest.getId();
LambdaQueryWrapper<Businessinfo> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Businessinfo::getBusinessId, businessId);
queryWrapper.orderByDesc(Businessinfo::getCreateTime);
queryWrapper.last("LIMIT 1");
Businessinfo businessinfo = businessinfoService.getOne(queryWrapper);
return ResultUtils.success(businessinfo, "查询成功");
}
}

View File

@ -0,0 +1,106 @@
package com.bsz.school_send_back_end.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsz.school_send_back_end.annotation.AuthCheck;
import com.bsz.school_send_back_end.common.BaseResponse;
import com.bsz.school_send_back_end.common.ErrorCode;
import com.bsz.school_send_back_end.common.ResultUtils;
import com.bsz.school_send_back_end.contant.UserConstant;
import com.bsz.school_send_back_end.exception.BusinessException;
import com.bsz.school_send_back_end.exception.ThrowUtils;
import com.bsz.school_send_back_end.model.domain.Errand;
import com.bsz.school_send_back_end.model.domain.ErrandAuth;
import com.bsz.school_send_back_end.model.dto.errandAtuh.ErrandAuthAddRequest;
import com.bsz.school_send_back_end.model.dto.errandAtuh.ErrandAuthQueryRequest;
import com.bsz.school_send_back_end.service.ErrandAuthService;
import com.bsz.school_send_back_end.service.ErrandService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
@Slf4j
@RestController
@RequestMapping("/errandAuth")
public class ErrandAuthController {
@Resource
private ErrandAuthService errandAuthService;
@Resource
private ErrandService errandService;
@PostMapping("/add")
public BaseResponse<Boolean> addErrandAuth(@RequestBody ErrandAuthAddRequest addRequest) {
if (addRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
Long errandId = addRequest.getErrandId();
LambdaQueryWrapper<ErrandAuth> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ErrandAuth::getErrandId, errandId);
long count = errandAuthService.count(queryWrapper);
ThrowUtils.throwIf(count > 0, ErrorCode.PARAMS_ERROR, "当前跑腿已认证");
ErrandAuth errandAuth = new ErrandAuth();
BeanUtils.copyProperties(addRequest, errandAuth);
errandAuthService.validErrandAuth(errandAuth,true);
boolean save = errandAuthService.save(errandAuth);
ThrowUtils.throwIf(!save, ErrorCode.SYSTEM_ERROR, "添加跑腿认证失败");
return ResultUtils.success(true);
}
@PostMapping("/update")
@AuthCheck(mustRole = UserConstant.ERRAND_ROLE)
public BaseResponse<Boolean> updateErrandAuth (@RequestBody ErrandAuthAddRequest updateRequest) {
if (updateRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
ErrandAuth errandAuth = new ErrandAuth();
BeanUtils.copyProperties(updateRequest, errandAuth);
errandAuthService.validErrandAuth(errandAuth, false);
LambdaUpdateWrapper<ErrandAuth> wrapper = errandAuthService.getUpdateWrapper(errandAuth);
boolean update = errandAuthService.update(wrapper);
ThrowUtils.throwIf(!update, ErrorCode.SYSTEM_ERROR, "更新跑腿认证信息失败");
return ResultUtils.success(true);
}
@PostMapping("/list/page")
@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
public BaseResponse<Page<ErrandAuth>> listErrandAuthByPage(@RequestBody ErrandAuthQueryRequest errandAuthQueryRequest) {
if (errandAuthQueryRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
long pageSize = errandAuthQueryRequest.getPageSize();
long current = errandAuthQueryRequest.getCurrent();
QueryWrapper<ErrandAuth> queryWrapper = errandAuthService.getQueryWrapper(errandAuthQueryRequest);
Page<ErrandAuth> page = errandAuthService.page(new Page<>(current, pageSize),queryWrapper);
return ResultUtils.success(page);
}
@GetMapping("/getErrandAuthById")
public BaseResponse<ErrandAuth> getErrandAuthById (String errandId) {
Long errandId1 = Long.valueOf(errandId);
ErrandAuth errandAuth = errandAuthService.getErrandAuth(errandId1);
return ResultUtils.success(errandAuth);
}
@PostMapping("/get/my")
public BaseResponse<ErrandAuth> getMyErrandAuth (HttpServletRequest request) {
Errand loginErrand = errandService.getLoginErrand(request);
Long id = loginErrand.getId();
LambdaQueryWrapper<ErrandAuth> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ErrandAuth::getErrandId, id);
ErrandAuth errandAuth = errandAuthService.getOne(queryWrapper);
ThrowUtils.throwIf(errandAuth == null, ErrorCode.OPERATION_ERROR, "当前跑腿为认证");
return ResultUtils.success(errandAuth);
}
}

View File

@ -0,0 +1,323 @@
package com.bsz.school_send_back_end.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsz.school_send_back_end.annotation.AuthCheck;
import com.bsz.school_send_back_end.common.BaseResponse;
import com.bsz.school_send_back_end.common.ErrorCode;
import com.bsz.school_send_back_end.common.ResultUtils;
import com.bsz.school_send_back_end.contant.UserConstant;
import com.bsz.school_send_back_end.exception.BusinessException;
import com.bsz.school_send_back_end.exception.ThrowUtils;
import com.bsz.school_send_back_end.model.domain.*;
import com.bsz.school_send_back_end.model.dto.CommonRequest;
import com.bsz.school_send_back_end.model.dto.errand.ErrandAddRequest;
import com.bsz.school_send_back_end.model.dto.errand.ErrandQueryRequest;
import com.bsz.school_send_back_end.model.dto.errand.ErrandStateRequest;
import com.bsz.school_send_back_end.model.dto.errand.ErrandUpdateRequest;
import com.bsz.school_send_back_end.model.vo.ErrandVO;
import com.bsz.school_send_back_end.model.vo.OrdersVO;
import com.bsz.school_send_back_end.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import static com.bsz.school_send_back_end.contant.UserConstant.*;
@Slf4j
@RestController
@RequestMapping("/errand")
public class ErrandController {
@Resource
private ErrandService errandService;
@Resource
private UserService userService;
@Resource
private OrdersService ordersService;
@Resource
private ErrandAuthService errandAuthService;
@Resource
private ErrandOrderService errandOrderService;
/**
* 注册跑腿
* @param addRequest 注册请求体
* @return 是否成功
*/
@PostMapping("/add")
public BaseResponse<Boolean> addErrand(@RequestBody ErrandAddRequest addRequest) {
if (addRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
User user = new User();
Errand errand = new Errand();
BeanUtils.copyProperties(addRequest, user);
System.out.println("User account: " + user.getUserAccount());
BeanUtils.copyProperties(addRequest, errand);
userService.validUser(user, true);
errandService.validErrand(errand, true);
//加密
String encryptPassword = DigestUtils.md5DigestAsHex((USER_SALT + user.getUserPassword()).getBytes());
user.setUserPassword(encryptPassword);
//更改用户权限为跑腿
user.setUserRole("errand");
//往user表中补充跑腿信息
user.setUsername(errand.getErrandName());
user.setPhone(errand.getErrandPhone());
errandService.addErrand(user, errand);
return ResultUtils.success(true);
}
/**
* 删除跑腿信息
* @param request 当前登录用户
* @return 是否成功
*/
@PostMapping("/delete")
@AuthCheck(mustRole = UserConstant.ERRAND_ROLE)
@Transactional(rollbackFor = Exception.class)
public BaseResponse<Boolean> deleteErrand (HttpServletRequest request){
errandService.deleteErrand(request);
return ResultUtils.success(true);
}
/**
* 修改跑腿信息(管理员)
* @param updateRequest 修改请求体
* @return 是否修改成功
*/
@PostMapping("/update")
@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
public BaseResponse<Boolean> updateErrand(@RequestBody ErrandUpdateRequest updateRequest) {
if (updateRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
Boolean update = errandService.updateErrand(updateRequest);
ThrowUtils.throwIf(!update, ErrorCode.SYSTEM_ERROR,"更新跑腿失败");
return ResultUtils.success(true);
}
/**
* 修改跑腿信息个人
* @param updateRequest 修改请求体
* @param request 当前登录用户
* @return 是否修改成功
*/
@PostMapping("/update/my")
@AuthCheck(mustRole = UserConstant.ERRAND_ROLE)
public BaseResponse<Boolean> updateErrandByUser (@RequestBody ErrandUpdateRequest updateRequest, HttpServletRequest request ) {
if (updateRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
Errand loginErrand = errandService.getLoginErrand(request);
Integer totalOrders = loginErrand.getTotalOrders();
ThrowUtils.throwIf(totalOrders > 0, ErrorCode.OPERATION_ERROR, "当前跑腿还有订单未送");
Boolean update = errandService.updateErrand(updateRequest);
Long errandId = loginErrand.getId();
Long id = updateRequest.getId();
ThrowUtils.throwIf(!id.equals(errandId), ErrorCode.PARAMS_ERROR, "修改的跑腿信息不是当前跑腿");
ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "更新跑腿失败");
return ResultUtils.success(true);
}
/**
* 获取当前跑腿信息列表
* @return 跑腿信息列表
*/
@PostMapping("/list")
@AuthCheck(mustRole = ADMIN_ROLE)
public BaseResponse<List<Errand>> listErrand() {
List<Errand> list = errandService.list();
return ResultUtils.success(list);
}
/**
* 分页获取跑腿信息列表
* @param queryRequest 查询请求体
* @return 跑腿信息分页
*/
@PostMapping("/page")
@AuthCheck(mustRole = ADMIN_ROLE)
public BaseResponse<Page<Errand>> listErrandByPage (@RequestBody ErrandQueryRequest queryRequest) {
if (queryRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
long pageSize = queryRequest.getPageSize();
long current = queryRequest.getCurrent();
QueryWrapper<Errand> queryWrapper = errandService.getQueryWrapper(queryRequest);
Page<Errand> errandPage = errandService.page(new Page<>(current, pageSize), queryWrapper);
return ResultUtils.success(errandPage);
}
/**
* 抢单
* @param commonRequest 订单id
* @param request 当前登录用户
* @return 是否抢单成功
*/
@PostMapping("/get/order")
@AuthCheck(mustRole = UserConstant.ERRAND_ROLE)
@Transactional(rollbackFor = Exception.class)
public BaseResponse<Boolean> getOrder(@RequestBody CommonRequest commonRequest, HttpServletRequest request) {
if (commonRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
Long ordersId = commonRequest.getId();
Errand loginErrand = errandService.getLoginErrand(request);
Long loginErrandId = loginErrand.getId();
ErrandOrder errandOrder = errandOrderService.getOne(Wrappers.<ErrandOrder>lambdaQuery()
.eq(ErrandOrder::getOrderId, ordersId));
Integer state = loginErrand.getState();
if (state != 1) {
throw new BusinessException(ErrorCode.FORBIDDEN_ERROR, "当前跑腿不可抢单");
}
errandService.updateTotal(loginErrand, true);
// 开始事务
Orders orders = ordersService.getOrderWithPessimisticLock(ordersId);
// 判断订单是否已被抢
if (orders == null || orders.getErrandId() != null) {
return ResultUtils.success(false); // 订单已经被抢或不存在
}
// 更新订单的 errandId 和状态
orders.setErrandId(loginErrandId);
boolean update = ordersService.updateById(orders);
ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "抢单失败");
errandOrder.setErrandId(loginErrandId);
errandOrder.setErrandState(2); // 2待取货
boolean update1 = errandOrderService.updateById(errandOrder);
ThrowUtils.throwIf(!update1, ErrorCode.OPERATION_ERROR, "更新跑腿订单关联失败");
return ResultUtils.success(true);
}
/**
* 修改订单
* @param errandStateRequest 订单id
* @param request 当前登录用户
* @return 是否修改成功
*/
@PostMapping("/update/state")
@AuthCheck(mustRole = ERRAND_ROLE)
public BaseResponse<Boolean> updateOrdersStateByErrand (@RequestBody ErrandStateRequest errandStateRequest, HttpServletRequest request) {
if (errandStateRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
errandService.orderToErrand(errandStateRequest, request);
return ResultUtils.success(true);
}
/**
* 根据当前登录用户获取跑腿信息
*/
@PostMapping("/get/current")
@AuthCheck(mustRole = ERRAND_ROLE)
public BaseResponse<ErrandVO> getByErrand (HttpServletRequest request) {
Errand loginErrand = errandService.getLoginErrand(request);
ErrandVO errandVO = errandService.getErrandVO(loginErrand);
return ResultUtils.success(errandVO);
}
/**
* 当前跑腿获取订单
*/
@PostMapping("/list/order")
@AuthCheck(mustRole = ERRAND_ROLE)
public BaseResponse<List<OrdersVO>> listOrdersByErrand(Integer errandState, HttpServletRequest request) {
Errand loginErrand = errandService.getLoginErrand(request);
String distributionScope = loginErrand.getDistributionScope();
// 创建 errand_order 表的查询条件
LambdaQueryWrapper<ErrandOrder> errandOrderQueryWrapper = new LambdaQueryWrapper<>();
errandOrderQueryWrapper.eq(ErrandOrder::getErrandState, errandState);
// 根据 errandState 的不同情况调整查询
if (errandState != 1) {
errandOrderQueryWrapper.eq(ErrandOrder::getErrandId, loginErrand.getId());
} else {
errandOrderQueryWrapper.isNull(ErrandOrder::getErrandId);
errandOrderQueryWrapper.ge(ErrandOrder::getEndTime, new Date());
}
// 查询符合条件的 errand_order 数据
List<ErrandOrder> errandOrderList = errandOrderService.list(errandOrderQueryWrapper);
// 获取符合条件的 orderId 列表
List<Long> orderIds = errandOrderList.stream().map(ErrandOrder::getOrderId).collect(Collectors.toList());
// 如果没有符合条件的订单则返回空
if (orderIds.isEmpty()) {
return ResultUtils.success(Collections.emptyList());
}
// 查询 orders 获取相关订单信息
LambdaQueryWrapper<Orders> ordersQueryWrapper = new LambdaQueryWrapper<>();
ordersQueryWrapper.in(Orders::getId, orderIds);
ordersQueryWrapper.eq(Orders::getLocation, distributionScope);
// 获取订单数据
List<Orders> ordersList = ordersService.list(ordersQueryWrapper);
List<OrdersVO> ordersVO = ordersService.getOrdersVO(ordersList);
// 如果转换后的订单VO为空也返回空响应
if (CollectionUtils.isEmpty(ordersVO)) {
return ResultUtils.success(Collections.emptyList());
}
return ResultUtils.success(ordersVO);
}
/**
* 根据Id获取跑腿信息
* @return 跑腿信息
*/
@PostMapping("/get/id")
@AuthCheck(mustRole = ADMIN_ROLE)
public BaseResponse<ErrandVO> getErrandById (String errandId1) {
Long errandId = Long.valueOf(errandId1);
Errand errand = errandService.getOne(Wrappers.<Errand>lambdaQuery().eq(Errand::getId, errandId));
ThrowUtils.throwIf(errand == null, ErrorCode.PARAMS_ERROR, "当前跑腿id不正确");
ErrandVO errandVO = errandService.getErrandVO(errand);
ErrandAuth errandAuth = errandAuthService.getErrandAuth(errandId);
errandVO.setBackIdCard(errandAuth.getBackIdCard());
errandVO.setBankCard(errandAuth.getBankCard());
errandVO.setFrontIdCard(errandAuth.getFrontIdCard());
return ResultUtils.success(errandVO);
}
}

View File

@ -0,0 +1,135 @@
package com.bsz.school_send_back_end.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsz.school_send_back_end.annotation.AuthCheck;
import com.bsz.school_send_back_end.common.BaseResponse;
import com.bsz.school_send_back_end.common.ErrorCode;
import com.bsz.school_send_back_end.common.ResultUtils;
import com.bsz.school_send_back_end.contant.UserConstant;
import com.bsz.school_send_back_end.exception.BusinessException;
import com.bsz.school_send_back_end.exception.ThrowUtils;
import com.bsz.school_send_back_end.model.domain.Errand;
import com.bsz.school_send_back_end.model.domain.ErrandIncome;
import com.bsz.school_send_back_end.model.domain.User;
import com.bsz.school_send_back_end.model.dto.CommonRequest;
import com.bsz.school_send_back_end.model.dto.erradnIncome.ErrandIncomeQueryRequest;
import com.bsz.school_send_back_end.service.ErrandIncomeService;
import com.bsz.school_send_back_end.service.ErrandService;
import com.bsz.school_send_back_end.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
@RestController
@Slf4j
@RequestMapping("/errandIncome")
public class ErrandIncomeController {
@Resource
private ErrandService errandService;
@Resource
private ErrandIncomeService errandIncomeService;
@Resource
private UserService userService;
@PostMapping("/count/number")
@AuthCheck(mustRole = UserConstant.ERRAND_ROLE)
public BaseResponse<Long> countIncomeNumber(HttpServletRequest request) {
Errand loginErrand = errandService.getLoginErrand(request);
LambdaQueryWrapper<ErrandIncome> queryWrapper = errandIncomeService.getQueryWrapper(loginErrand.getId());
long count = errandIncomeService.count(queryWrapper);
return ResultUtils.success(count);
}
@PostMapping("/count/money")
@AuthCheck(mustRole = UserConstant.ERRAND_ROLE)
public BaseResponse<BigDecimal> countIncomeMoney(HttpServletRequest request) {
Errand loginErrand = errandService.getLoginErrand(request);
LambdaQueryWrapper<ErrandIncome> queryWrapper = errandIncomeService.getQueryWrapper(loginErrand.getId());
queryWrapper.eq(ErrandIncome::getState, 1);
List<ErrandIncome> list = errandIncomeService.list(queryWrapper);
BigDecimal price = list.stream().map(ErrandIncome::getIncome).reduce(BigDecimal.ZERO, BigDecimal::add);
return ResultUtils.success(price);
}
@PostMapping("/count/total-money")
@AuthCheck(mustRole = UserConstant.ERRAND_ROLE)
public BaseResponse<BigDecimal> countTotalIncome(HttpServletRequest request) {
// 获取登录跑腿信息
Errand loginErrand = errandService.getLoginErrand(request);
// 从跑腿表直接获取总收入字段值
BigDecimal totalIncome = loginErrand.getTotalPrice();
// 返回结果
return ResultUtils.success(totalIncome);
}
@PostMapping("/list")
@AuthCheck(mustRole = UserConstant.ERRAND_ROLE)
public BaseResponse<List<ErrandIncome>> listErrandIncome(@RequestBody CommonRequest commonRequest, HttpServletRequest request) {
if (commonRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
Long errandId = commonRequest.getId();
User loginUser = userService.getLoginUser(request);
String userRole = loginUser.getUserRole();
if (userRole.equals(UserConstant.ERRAND_ROLE)) {
Errand loginErrand = errandService.getLoginErrand(request);
Long id = loginErrand.getId();
ThrowUtils.throwIf(!id.equals(errandId), ErrorCode.PARAMS_ERROR, "传输的跑腿id不正确");
}
LambdaQueryWrapper<ErrandIncome> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ErrandIncome::getErrandId, errandId);
List<ErrandIncome> list = errandIncomeService.list(queryWrapper);
if (list == null) {
list = new ArrayList<>();
}
return ResultUtils.success(list);
}
@PostMapping("/list/page")
@AuthCheck(mustRole = UserConstant.ERRAND_ROLE)
public BaseResponse<Page<ErrandIncome>> listErrandIncomeByPage(@RequestBody ErrandIncomeQueryRequest queryRequest) {
if (queryRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
long pageSize = queryRequest.getPageSize();
long current = queryRequest.getCurrent();
QueryWrapper<ErrandIncome> queryWrapper = errandIncomeService.getWrapper(queryRequest);
Page<ErrandIncome> page = errandIncomeService.page(new Page<>(current, pageSize), queryWrapper);
if (page == null) {
page = new Page<>();
}
return ResultUtils.success(page);
}
@PostMapping("/count/money/no")
@AuthCheck(mustRole = UserConstant.ERRAND_ROLE)
public BaseResponse<BigDecimal> countIncomeMoneyNo(HttpServletRequest request) {
Errand loginErrand = errandService.getLoginErrand(request);
LambdaQueryWrapper<ErrandIncome> queryWrapper = errandIncomeService.getQueryWrapper(loginErrand.getId());
queryWrapper.eq(ErrandIncome::getState, 0);
List<ErrandIncome> list = errandIncomeService.list(queryWrapper);
BigDecimal price = list.stream().map(ErrandIncome::getIncome).reduce(BigDecimal.ZERO, BigDecimal::add);
return ResultUtils.success(price);
}
}

View File

@ -0,0 +1,140 @@
package com.bsz.school_send_back_end.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.bsz.school_send_back_end.annotation.AuthCheck;
import com.bsz.school_send_back_end.common.BaseResponse;
import com.bsz.school_send_back_end.common.ErrorCode;
import com.bsz.school_send_back_end.common.ResultUtils;
import com.bsz.school_send_back_end.contant.UserConstant;
import com.bsz.school_send_back_end.exception.BusinessException;
import com.bsz.school_send_back_end.exception.ThrowUtils;
import com.bsz.school_send_back_end.model.domain.Business;
import com.bsz.school_send_back_end.model.domain.OrderRefunds;
import com.bsz.school_send_back_end.model.domain.Orders;
import com.bsz.school_send_back_end.model.domain.User;
import com.bsz.school_send_back_end.model.dto.refund.RefundAddRequest;
import com.bsz.school_send_back_end.model.dto.refund.RefundUpdateRequest;
import com.bsz.school_send_back_end.service.BusinessService;
import com.bsz.school_send_back_end.service.OrderRefundsService;
import com.bsz.school_send_back_end.service.OrdersService;
import com.bsz.school_send_back_end.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/refund")
public class RefundController {
@Resource
private UserService userService;
@Resource
private OrderRefundsService refundsService;
@Resource
private OrdersService ordersService;
@Resource
private BusinessService businessService;
/**
* 用户申请退款
* @param refundAddRequest 退款请求
* @param request 网络请求
* @return 是否成功
*/
@PostMapping("/add")
public BaseResponse<Boolean> addRefund(@RequestBody RefundAddRequest refundAddRequest, HttpServletRequest request) {
User loginUser = userService.getLoginUser(request);
Long orderId = refundAddRequest.getOrderId();
LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Orders::getId, orderId);
Orders orders = ordersService.getOne(queryWrapper);
ThrowUtils.throwIf(orders == null, ErrorCode.NOT_FOUND_ERROR, "未找到退款申请");
ThrowUtils.throwIf(orders.getState() != 1, ErrorCode.SYSTEM_ERROR, "该订单未支付");
OrderRefunds orderRefunds = new OrderRefunds();
BeanUtils.copyProperties(refundAddRequest, orderRefunds);
orderRefunds.setUserId(loginUser.getId());
boolean save = refundsService.save(orderRefunds);
ThrowUtils.throwIf(!save, ErrorCode.OPERATION_ERROR, "创建退款单失败");
return ResultUtils.success(true, "申请退款成功,等待商家确认");
}
/**
* 商家查询退款单
* @param status 退款单的状态
* @param request 网络请求
* @return 退款列表
*/
@GetMapping("/list/business")
@AuthCheck(mustRole = UserConstant.BUSINESS_ROLE)
public BaseResponse<List<OrderRefunds>> listRefundByBusiness(@RequestParam Integer status, HttpServletRequest request) {
Business loginBusiness = businessService.getLoginBusiness(request);
Long id = loginBusiness.getId();
LambdaQueryWrapper<OrderRefunds> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(OrderRefunds::getStatus, status)
.inSql(OrderRefunds::getOrderId, "SELECT id FROM orders WHERE businessId = " + id); // 根据商家ID过滤订单
List<OrderRefunds> list = refundsService.list(queryWrapper);
return ResultUtils.success(list);
}
@PostMapping("/update")
@AuthCheck(mustRole = UserConstant.BUSINESS_ROLE)
public BaseResponse<Boolean> updateRefundByBusiness (@RequestBody RefundUpdateRequest updateRequest, HttpServletRequest request) {
if (updateRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR);
}
Long orderId = updateRequest.getOrderId();
Integer status = updateRequest.getStatus();
Business loginBusiness = businessService.getLoginBusiness(request);
Long businessId = loginBusiness.getId();
Orders orders = ordersService.getOne(Wrappers.<Orders>lambdaQuery()
.eq(Orders::getId, orderId));
ThrowUtils.throwIf(orders == null, ErrorCode.PARAMS_ERROR, "传入的订单id不正确");
ThrowUtils.throwIf(businessId.equals(orders.getBusinessId()), ErrorCode.PARAMS_ERROR, "当前订单不属于该商家");
LambdaQueryWrapper<OrderRefunds> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(OrderRefunds::getOrderId, orderId);
OrderRefunds refunds = refundsService.getOne(queryWrapper);
refunds.setStatus(status); // 1-已同意 2 - 已拒绝
ThrowUtils.throwIf(status == 2 && updateRequest.getRefuseReason() == null, ErrorCode.PARAMS_ERROR, "请填写退款原因");
boolean updateById = refundsService.updateById(refunds);
ThrowUtils.throwIf(!updateById, ErrorCode.OPERATION_ERROR, "修改退款单状态失败");
return ResultUtils.success(true);
}
@PostMapping("/list/reson")
@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
public BaseResponse<List<String>> getReasonByAdmin() {
// 获取今天的开始和结束时间
LocalDate today = LocalDate.now();
LocalDateTime startOfDay = today.atStartOfDay(); // 今天的00:00:00
LocalDateTime endOfDay = today.atTime(LocalTime.MAX); // 今天的23:59:59.999999999
// LocalDateTime 转换为 Date
Date startOfDayDate = Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
Date endOfDayDate = Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant());
LambdaQueryWrapper<OrderRefunds> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.ge(OrderRefunds::getCreateTime, startOfDayDate);
queryWrapper.le(OrderRefunds::getCreateTime, endOfDayDate);
List<OrderRefunds> refunds = refundsService.list(queryWrapper);
List<String> collect = refunds.stream()
.map(OrderRefunds::getReason)
.collect(Collectors.toList());
return ResultUtils.success(collect);
}
}

View File

@ -0,0 +1,51 @@
package com.bsz.school_send_back_end.controller;
import com.bsz.school_send_back_end.common.BaseResponse;
import com.bsz.school_send_back_end.common.ResultUtils;
import com.bsz.school_send_back_end.utils.AliyunSmsUtils;
import com.bsz.school_send_back_end.utils.RandomNumberGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import jakarta.annotation.Resource;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
@RestController
@Slf4j
@RequestMapping("/sms")
public class SmsController {
@Resource
private RedisTemplate redisTemplate;
@Resource
private RandomNumberGenerator randomNumberGenerator;
@Resource
private AliyunSmsUtils aliyunSmsUtils;
@GetMapping("/send/{phone}")
public BaseResponse<String> sendCode (@PathVariable String phone) {
String code = (String) redisTemplate.opsForValue().get(phone);
log.info("获取验证码:{}", code);
if (code == null) {
String fourBitRandom = randomNumberGenerator.getFourBitRandom();
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("code", fourBitRandom);
log.info("生成的验证码:" + fourBitRandom);
redisTemplate.opsForValue().set(phone, fourBitRandom, 5, TimeUnit.MINUTES);
boolean b = aliyunSmsUtils.sendSms(phone, hashMap);
log.info("短信发送状态,{}", b);
return ResultUtils.success("发送成功");
} else {
return ResultUtils.success("请勿重复发送验证码");
}
}
}

View File

@ -0,0 +1,142 @@
package com.bsz.school_send_back_end.listener;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bsz.school_send_back_end.common.ErrorCode;
import com.bsz.school_send_back_end.contant.RabbitMQConstant;
import com.bsz.school_send_back_end.exception.ThrowUtils;
import com.bsz.school_send_back_end.model.domain.Orders;
import com.bsz.school_send_back_end.model.domain.PrivateMessage;
import com.bsz.school_send_back_end.service.OrdersService;
import com.bsz.school_send_back_end.utils.MultiDelayMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
@Component
@Slf4j
public class RabbitMQReceiver {
@Resource
private OrdersService ordersService;
@Resource
private RabbitTemplate rabbitTemplate;
@RabbitListener(queues = RabbitMQConstant.TOPIC_QUEUE2)
public Orders receiveOrder (Orders message) {
log.info("接收数据:" + message);
return message;
}
@RabbitListener(queues = RabbitMQConstant.TOPIC_QUEUE1)
public PrivateMessage receive (PrivateMessage message) {
log.info("接收数据:" + message);
return message;
}
/**
* 过三分钟未支付自动取消
* @param msg
*/
@RabbitListener(bindings = @QueueBinding(
value = @Queue(RabbitMQConstant.CANCEL_ORDER_QUEUE),
exchange = @Exchange(name = RabbitMQConstant.CANCEL_ORDER_EXCHANGE, delayed = "true"),
key = RabbitMQConstant.CANCEL_ORDER_ROUTING_KEY
))
public void handleExpiredOrder(MultiDelayMessage<Long> msg) {
Long orderId = msg.getData();
log.info("订单超时检查订单ID{}", orderId);
// 查询订单
LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Orders::getId, orderId);
Orders orders = ordersService.getOne(queryWrapper);
if (orders == null) {
log.warn("订单不存在订单ID{}", orderId);
return;
}
if (orders.getState() == 0) { // 订单仍未支付
if (msg.hasNextDelay()) {
// 还有下一个检查点继续发送延迟消息
int nextDelay = msg.removeNextDelay().intValue();
rabbitTemplate.convertAndSend(RabbitMQConstant.CANCEL_ORDER_EXCHANGE,
RabbitMQConstant.CANCEL_ORDER_ROUTING_KEY, msg, message -> {
message.getMessageProperties().setDelay(nextDelay);
return message;
});
log.info("订单未支付,下一次检查延迟 {} 毫秒订单ID{}", nextDelay, orderId);
} else {
// **所有检查点都执行完才执行订单取消**
log.info("订单超时未支付自动取消订单ID{}", orderId);
orders.setState(3); // 订单状态修改为已取消假设 3 代表已取消
boolean update = ordersService.updateById(orders);
ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "订单取消失败");
log.info("订单超时已取消订单ID{}", orderId);
}
} else {
log.info("订单已支付无需取消订单ID{}", orderId);
}
}
/**
* 过三十分钟无人接单自动退款
* @param msg
*/
@RabbitListener(bindings = @QueueBinding(
value = @Queue(RabbitMQConstant.DELIVERY_ORDER_QUEUE),
exchange = @Exchange(name = RabbitMQConstant.DELIVERY_DELAY_EXCHANGE, delayed = "true"),
key = RabbitMQConstant.DELIVERY_ORDER_ROUTING_KEY
))
public void handleExpiredDeliveryOrder(MultiDelayMessage<Long> msg) {
Long orderId = msg.getData();
log.info("外卖单超时检查订单ID{}", orderId);
// 查询订单
LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Orders::getId, orderId);
Orders orders = ordersService.getOne(queryWrapper);
if (orders == null) {
log.warn("外卖订单不存在订单ID{}", orderId);
return;
}
if (orders.getState() == 1) { // 外卖单仍未支付
// 外卖单超时退款逻辑
if (msg.hasNextDelay()) {
int nextDelay = msg.removeNextDelay().intValue();
rabbitTemplate.convertAndSend(RabbitMQConstant.DELIVERY_DELAY_EXCHANGE,
RabbitMQConstant.DELIVERY_ORDER_ROUTING_KEY, msg, message -> {
message.getMessageProperties().setDelay(nextDelay);
return message;
});
log.info("外卖单未接单,下一次检查延迟 {} 毫秒订单ID{}", nextDelay, orderId);
} else {
// 超过30分钟未接单自动退款
log.info("外卖单超时未接单自动退款订单ID{}", orderId);
orders.setState(2); // 订单状态修改为已退款
boolean update = ordersService.updateById(orders);
ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "外卖单退款修改失败");
log.info("外卖单超时退款成功订单ID{}", orderId);
}
} else {
log.info("外卖单已支付无需退款订单ID{}", orderId);
}
}
}

View File

@ -0,0 +1,97 @@
package com.bsz.school_send_back_end.listener;
import com.bsz.school_send_back_end.contant.RabbitMQConstant;
import com.bsz.school_send_back_end.model.domain.Orders;
import com.bsz.school_send_back_end.model.domain.PrivateMessage;
import com.bsz.school_send_back_end.utils.MultiDelayMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
import java.util.*;
@Component
@Slf4j
public class RabbitMQSender {
@Resource
private AmqpTemplate amqpTemplate;
@Resource
private RabbitTemplate rabbitTemplate;
public void sendOrderMessage (Orders message) {
log.info("消息队列 MQSender 业务消息发送 send OrderMessage:" + message);
amqpTemplate.convertAndSend(RabbitMQConstant.TOPIC_QUEUE2,message, msg->{
msg.getMessageProperties().setReplyTo(RabbitMQConstant.ORDER_REPLY_QUEUE);
return msg;
});
}
public void sendPrivateMessage(PrivateMessage message) {
log.info("消息队列 MQSender 业务消息发送 send message:" + message);
amqpTemplate.convertAndSend(RabbitMQConstant.TOPIC_QUEUE1,message, msg->{
msg.getMessageProperties().setReplyTo(RabbitMQConstant.TOPIC_QUEUE1);
return msg;
});
}
// public void sendDelayedOrderMessage(long orderId, long delayMillis) {
// Map<String, Object> headers = new HashMap<>();
// headers.put("x-delay", delayMillis); // 设置延迟时间毫秒
//
// amqpTemplate.convertAndSend(
// RabbitMQConstant.DELAYED_EXCHANGE, // 交换机
// RabbitMQConstant.DELAYED_ROUTING_KEY, // 路由键
// orderId, // 消息内容订单 ID
// message -> {
// message.getMessageProperties().getHeaders().putAll(headers); // 将延迟时间添加到消息头部
// return message;
// });
// log.info("发送延迟订单取消消息订单ID: " + orderId + ",延迟时间: " + delayMillis + "ms");
// }
//
//
// public void sendDelayedMessage() {
// // 设置延迟时间为 5
// MessageProperties messageProperties = new MessageProperties();
// messageProperties.setHeader("x-delay", 5000); // 延迟时间单位毫秒
// Message message = new Message("Hello, delayed world!".getBytes(), messageProperties);
//
// // 发送到延迟交换机
// amqpTemplate.send(RabbitMQConstant.DELAYED_EXCHANGE, RabbitMQConstant.DELAYED_ROUTING_KEY, message);
// log.info("发送延迟成功:" + new Date());
// }
public void sendCreateOrderMessage(Long orderId) {
// 复制 DELAY_MILLIS 到一个新的 ArrayList
List<Long> newDelayMillis = new ArrayList<>(RabbitMQConstant.DINE_IN_DELAY_MILLIS);
// 延迟检查订单状态信息
MultiDelayMessage<Long> msg = new MultiDelayMessage<>(orderId, newDelayMillis);
int delayValue = msg.removeNextDelay().intValue();
rabbitTemplate.convertAndSend(RabbitMQConstant.CANCEL_ORDER_EXCHANGE,
RabbitMQConstant.CANCEL_ORDER_ROUTING_KEY, msg, message -> {
// 添加延迟消息属性
message.getMessageProperties().setDelay(delayValue);
return message;
});
log.info("发送成功orderID{}", orderId);
}
//自动退款30分钟未接单的
public void sendCreateDeliveryOrderMessage (Long orderId) {
List newDelayMillis = new ArrayList<>(RabbitMQConstant.DELIVERY_DELAY_MILLIS); // 假设延迟时间在此列表中
MultiDelayMessage msg = new MultiDelayMessage<>(orderId, newDelayMillis);
int delayValue = msg.removeNextDelay().intValue();
rabbitTemplate.convertAndSend(RabbitMQConstant.DELIVERY_DELAY_EXCHANGE,
RabbitMQConstant.DELIVERY_ORDER_ROUTING_KEY, msg, message -> {
message.getMessageProperties().setDelay(delayValue);
return message;
});
log.info("外卖单延迟消息发送成功订单ID{}", orderId);
}
}

View File

@ -0,0 +1,15 @@
package com.bsz.school_send_back_end.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bsz.school_send_back_end.model.domain.Businessinfo;
/**
* @author xy
*/
public interface BusinessinfoMapper extends BaseMapper<Businessinfo> {
}

View File

@ -0,0 +1,15 @@
package com.bsz.school_send_back_end.mapper;
import com.bsz.school_send_back_end.model.domain.ErrandAuth;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author xy
*/
public interface ErrandAuthMapper extends BaseMapper<ErrandAuth> {
}

View File

@ -0,0 +1,15 @@
package com.bsz.school_send_back_end.mapper;
import com.bsz.school_send_back_end.model.domain.ErrandBill;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author xy
*/
public interface ErrandBillMapper extends BaseMapper<ErrandBill> {
}

View File

@ -0,0 +1,15 @@
package com.bsz.school_send_back_end.mapper;
import com.bsz.school_send_back_end.model.domain.ErrandIncome;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author xy
*/
public interface ErrandIncomeMapper extends BaseMapper<ErrandIncome> {
}

View File

@ -0,0 +1,15 @@
package com.bsz.school_send_back_end.mapper;
import com.bsz.school_send_back_end.model.domain.ErrandLevel;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author xy
*/
public interface ErrandLevelMapper extends BaseMapper<ErrandLevel> {
}

View File

@ -0,0 +1,15 @@
package com.bsz.school_send_back_end.mapper;
import com.bsz.school_send_back_end.model.domain.Errand;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author xy
*/
public interface ErrandMapper extends BaseMapper<Errand> {
}

View File

@ -0,0 +1,15 @@
package com.bsz.school_send_back_end.mapper;
import com.bsz.school_send_back_end.model.domain.ErrandOrder;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author xy
*/
public interface ErrandOrderMapper extends BaseMapper<ErrandOrder> {
}

View File

@ -0,0 +1,15 @@
package com.bsz.school_send_back_end.mapper;
import com.bsz.school_send_back_end.model.domain.OrderImage;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author xy
*/
public interface OrderImageMapper extends BaseMapper<OrderImage> {
}

View File

@ -0,0 +1,15 @@
package com.bsz.school_send_back_end.mapper;
import com.bsz.school_send_back_end.model.domain.OrderRefunds;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author xy
*/
public interface OrderRefundsMapper extends BaseMapper<OrderRefunds> {
}

View File

@ -0,0 +1,41 @@
package com.bsz.school_send_back_end.model.domain;
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 java.util.Date;
import lombok.Data;
/**
* 系统信息
* @TableName businessinfo
*/
@TableName(value ="businessinfo")
@Data
public class Businessinfo implements Serializable {
/**
* id
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 商家id
*/
private Long businessId;
/**
* 功能内容
*/
private String content;
/**
* 创建时间
*/
private Date createTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,93 @@
package com.bsz.school_send_back_end.model.domain;
import com.baomidou.mybatisplus.annotation.*;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import lombok.Data;
/**
* 跑腿
* @TableName errand
*/
@TableName(value ="errand")
@Data
public class Errand implements Serializable {
/**
* id
*/
@TableId(type = IdType.ASSIGN_ID)
private Long id;
/**
* 用户id
*/
private Long userId;
/**
* 跑腿姓名
*/
private String errandName;
/**
* 跑腿姓名
*/
private String errandAvatarUrl;
/**
* 性别
*/
private Integer gender;
/**
* 手机号
*/
private String errandPhone;
/**
* 配送范围
*/
private String distributionScope;
/**
* 审核状态 0-未审核 1-审核通过
*/
private Integer state;
/**
* 接单量
*/
private Integer totalOrders;
/**
* 最大接单量
*/
private Integer maxOrders;
/**
* 总金额
*/
private BigDecimal totalPrice;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
/**
* 是否删除
*/
@TableLogic
private Integer isDelete;
@TableField(exist = false)
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,72 @@
package com.bsz.school_send_back_end.model.domain;
import com.baomidou.mybatisplus.annotation.*;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import lombok.Data;
/**
* 跑腿认证
* @TableName errand_auth
*/
@TableName(value ="errand_auth")
@Data
public class ErrandAuth implements Serializable {
/**
* id
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 跑腿id
*/
private Long errandId;
/**
* 银行卡号
*/
private String bankCard;
/**
* 身份证正面
*/
private String frontIdCard;
/**
* 身份证反面
*/
private String backIdCard;
/**
* 健康证
*/
private String healthCertificate;
/**
* 健康证开始时间
*/
private Date certificateStartTime;
/**
* 健康证结束时间
*/
private Date certificateEndTime;
/**
* 创建时间
*/
private Date createTime;
/**
* 逻辑删除
*/
@TableLogic
private Integer isDelete;
@TableField(exist = false)
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,57 @@
package com.bsz.school_send_back_end.model.domain;
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 java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 跑腿账单表
* @TableName errand_bill
*/
@TableName(value ="errand_bill")
@Data
@Schema(description = "跑腿账单响应体")
public class ErrandBill implements Serializable {
/**
* id
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 订单Id
*/
private Long orderId;
/**
* 用户手机号
*/
private String username;
/**
* 综合评分
*/
private BigDecimal income;
/**
* 收入状态0-待结算 1-已结算
*/
private Integer errandState;
/**
* 订单创建时间
*/
private LocalDateTime orderStartTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,55 @@
package com.bsz.school_send_back_end.model.domain;
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.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import lombok.Data;
/**
* 跑腿收入
* @TableName errand_income
*/
@TableName(value ="errand_income")
@Data
public class ErrandIncome implements Serializable {
/**
* id
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 跑腿id
*/
private Long errandId;
/**
* 订单id
*/
private Long orderId;
/**
* 综合评分
*/
private BigDecimal income;
/**
* 0未结算 1已结算 2已提现
*/
private Integer state;
/**
* 创建时间
*/
private Date createTime;
@TableField(exist = false)
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,52 @@
package com.bsz.school_send_back_end.model.domain;
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 java.math.BigDecimal;
import java.util.Date;
import lombok.Data;
/**
* 跑腿等级
* @TableName errand_level
*/
@TableName(value ="errand_level")
@Data
public class ErrandLevel implements Serializable {
/**
* id
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 跑腿Id
*/
private Long errandId;
/**
* 综合评分
*/
private BigDecimal averageScore;
/**
* 等级
*/
private Integer level;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,72 @@
package com.bsz.school_send_back_end.model.domain;
import com.baomidou.mybatisplus.annotation.*;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import lombok.Data;
/**
* 跑腿任务表
* @TableName errand_order
*/
@TableName(value ="errand_order")
@Data
public class ErrandOrder implements Serializable {
/**
* id
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 订单ID
*/
private Long orderId;
/**
* 跑腿状态: 0无跑腿 1待抢单 2待取货 3待送达 4已送达 5再次抢单
*/
private Integer errandState;
/**
* 送餐开始时间
*/
@TableField(updateStrategy = FieldStrategy.IGNORED)
private LocalDateTime startTime;
/**
* 送餐结束时间
*/
@TableField(updateStrategy = FieldStrategy.IGNORED)
private LocalDateTime endTime;
/**
* 跑腿员ID
*/
@TableField(updateStrategy = FieldStrategy.IGNORED)
private Long errandId;
/**
* 任务创建时间
*/
private Date createTime;
/**
* 任务更新时间
*/
private Date updateTime;
/**
* 是否删除
*/
@TableLogic
private Integer isDelete;
@TableField(exist = false)
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,30 @@
package com.bsz.school_send_back_end.model.domain;
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;
/**
* 外卖图片
* @TableName order_image
*/
@TableName(value ="order_image")
@Data
public class OrderImage implements Serializable {
/**
* id
*/
@TableId(type = IdType.AUTO)
private Long orderId;
/**
* 外卖地址
*/
private String imageAddress;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,62 @@
package com.bsz.school_send_back_end.model.domain;
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 java.math.BigDecimal;
import java.util.Date;
import lombok.Data;
/**
* 退款申请表
* @TableName order_refunds
*/
@TableName(value ="order_refunds")
@Data
public class OrderRefunds implements Serializable {
/**
* 退款申请ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 订单号唯一标识
*/
private Long orderId;
/**
* 用户ID
*/
private Long userId;
/**
* 退款原因
*/
private String reason;
/**
* 退款金额
*/
private BigDecimal amount;
/**
* 退款状态0-待审核, 1-已同意, 2-已拒绝
*/
private Integer status;
/**
* 申请时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,18 @@
package com.bsz.school_send_back_end.model.dto.businessinfo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
@Data
public class InfoAddRequest implements Serializable {
/**
* 功能内容
*/
private String content;
@Serial
private static final long serialVersionUID = 8089646587314575974L;
}

View File

@ -0,0 +1,27 @@
package com.bsz.school_send_back_end.model.dto.businessinfo;
import com.bsz.school_send_back_end.model.dto.PageRequest;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
@Data
@EqualsAndHashCode(callSuper = true)
public class InfoQueryRequest extends PageRequest implements Serializable {
/**
* 商家id
*/
private Long businessId;
/**
* 创建时间
*/
private Date createTime;
@Serial
private static final long serialVersionUID = -1976825924815005032L;
}

View File

@ -0,0 +1,31 @@
package com.bsz.school_send_back_end.model.dto.erradnIncome;
import com.bsz.school_send_back_end.model.dto.PageRequest;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
@Data
public class ErrandIncomeQueryRequest extends PageRequest implements Serializable {
/**
* id
*/
private Long id;
/**
* 跑腿id
*/
private Long errandId;
/**
* 订单id
*/
private Long orderId;
/**
* 0未结算 1已结算 2已提现
*/
private Integer state;
}

View File

@ -0,0 +1,48 @@
package com.bsz.school_send_back_end.model.dto.errand;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
@Data
public class ErrandAddRequest implements Serializable {
/**
* 账号
*/
private String userAccount;
/**
* 密码
*/
private String userPassword;
/**
* 密码
*/
private String checkPassword;
/**
* 跑腿姓名
*/
private String errandName;
/**
* 性别
*/
private Integer gender;
/**
* 手机号
*/
private String errandPhone;
/**
* 配送范围
*/
private String distributionScope;
@Serial
private static final long serialVersionUID = 1429991098597318147L;
}

View File

@ -0,0 +1,44 @@
package com.bsz.school_send_back_end.model.dto.errand;
import com.bsz.school_send_back_end.model.dto.PageRequest;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
@Data
public class ErrandQueryRequest extends PageRequest implements Serializable {
/**
* id
*/
private Long id;
/**
* 跑腿姓名
*/
private String errandName;
/**
* 性别
*/
private Integer gender;
/**
* 手机号
*/
private String errandPhone;
/**
* 配送范围
*/
private String distributionScope;
/**
* 审核状态 0-未审核 1-审核通过
*/
private Integer state;
@Serial
private static final long serialVersionUID = -1612139663948514866L;
}

View File

@ -0,0 +1,23 @@
package com.bsz.school_send_back_end.model.dto.errand;
import lombok.Data;
import java.io.Serializable;
@Data
public class ErrandStateRequest implements Serializable {
/**
* 订单id
*/
private Long orderId;
/**
* 需要修改的订单状态
*/
private Integer errandsState;
/**
* 外卖图片地址
*/
private String imageAddress;
}

View File

@ -0,0 +1,43 @@
package com.bsz.school_send_back_end.model.dto.errand;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
@Data
public class ErrandUpdateRequest implements Serializable {
/**
* id
*/
private Long id;
/**
* 跑腿姓名
*/
private String errandName;
/**
* 性别
*/
private Integer gender;
/**
* 手机号
*/
private String errandPhone;
/**
* 配送范围
*/
private String distributionScope;
/**
* 审核状态 0-未审核 1-审核通过
*/
private Integer state;
@Serial
private static final long serialVersionUID = -1612139663948514866L;
}

View File

@ -0,0 +1,33 @@
package com.bsz.school_send_back_end.model.dto.errandAtuh;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
@Data
public class ErrandAuthAddRequest implements Serializable {
/**
* 跑腿id
*/
private Long errandId;
/**
* 银行卡号
*/
private String bankCard;
/**
* 身份证正面
*/
private String frontIdCard;
/**
* 身份证反面
*/
private String backIdCard;
@Serial
private static final long serialVersionUID = -7134209258589017758L;
}

View File

@ -0,0 +1,35 @@
package com.bsz.school_send_back_end.model.dto.errandAtuh;
import com.bsz.school_send_back_end.model.dto.PageRequest;
import lombok.Data;
import java.io.Serializable;
@Data
public class ErrandAuthQueryRequest extends PageRequest implements Serializable {
/**
* id
*/
private Long id;
/**
* 跑腿id
*/
private Long errandId;
/**
* 银行卡号
*/
private String bankCard;
/**
* 身份证正面
*/
private String frontIdCard;
/**
* 身份证反面
*/
private String backIdCard;
}

View File

@ -0,0 +1,41 @@
package com.bsz.school_send_back_end.model.dto.order;
import lombok.Data;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
@Data
public class OrderUpdateRequest {
/**
* id
*/
private Long orderId;
/**
* 取餐方式(0堂食 1自提 2外卖)
*/
private Integer pickupMethod;
/**
* 配送地址
*/
private String location;
/**
* 取餐开始时间
*/
private LocalDateTime pickupStartTime;
/**
* 取餐开始时间
*/
private LocalDateTime pickupEndTime;
/**
* 备注
*/
private String notes;
}

View File

@ -0,0 +1,16 @@
package com.bsz.school_send_back_end.model.dto.order;
import lombok.Data;
@Data
public class OrdersCountByErrandRequest {
/**
* 跑腿id
*/
private Long errandId;
/**
* 审核状态 0-未审核 1-审核通过
*/
private Integer state;
}

View File

@ -0,0 +1,28 @@
package com.bsz.school_send_back_end.model.dto.refund;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class RefundAddRequest {
/**
* 订单号唯一标识
*/
private Long orderId;
/**
* 退款原因
*/
private String reason;
/**
* 退款金额
*/
private BigDecimal amount;
/**
* 退款状态0-待审核, 1-已同意, 2-已拒绝
*/
private Integer status;
}

View File

@ -0,0 +1,21 @@
package com.bsz.school_send_back_end.model.dto.refund;
import lombok.Data;
@Data
public class RefundUpdateRequest {
/*
订单id
*/
private Long orderId;
/*
需要修改的状态
*/
private Integer status;
/*
拒绝原因
*/
private String RefuseReason;
}

View File

@ -0,0 +1,31 @@
package com.bsz.school_send_back_end.model.vo;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@Data
public class BillVO {
/**
* 电话
*/
private String phone;
/**
* 开始时间
*/
private Date startTime;
/**
* 综合评分
*/
private BigDecimal income;
/**
* 0未结算 1已结算 2已提现
*/
private Integer state;
}

View File

@ -0,0 +1,76 @@
package com.bsz.school_send_back_end.model.vo;
import lombok.Data;
@Data
public class ErrandAuthVO {
/**
* id
*/
private Long id;
/**
* 用户id
*/
private Long userId;
/**
* 跑腿姓名
*/
private String errandName;
/**
* 跑腿头像
*/
private String errandAvatarUrl;
/**
* 性别
*/
private Integer gender;
/**
* 手机号
*/
private String errandPhone;
/**
* 配送范围
*/
private String distributionScope;
/**
* 审核状态 0-未审核 1-审核通过
*/
private Integer state;
/**
* 接单量
*/
private Integer totalOrders;
/**
* 最大接单量
*/
private Integer maxOrders;
/**
* 等级
*/
private Integer level;
/**
* 银行卡号
*/
private String bankCard;
/**
* 身份证正面
*/
private String frontIdCard;
/**
* 身份证反面
*/
private String backIdCard;
}

View File

@ -0,0 +1,78 @@
package com.bsz.school_send_back_end.model.vo;
import lombok.Data;
@Data
public class ErrandVO {
/**
* id
*/
private Long id;
/**
* 用户id
*/
private Long userId;
/**
* 跑腿姓名
*/
private String errandName;
/**
* 跑腿头像
*/
private String errandAvatarUrl;
/**
* 性别
*/
private Integer gender;
/**
* 手机号
*/
private String errandPhone;
/**
* 配送范围
*/
private String distributionScope;
/**
* 审核状态 0-未审核 1-审核通过
*/
private Integer state;
/**
* 接单量
*/
private Integer totalOrders;
/**
* 最大接单量
*/
private Integer maxOrders;
/**
* 等级
*/
private Integer level;
/**
* 银行卡号
*/
private String bankCard;
/**
* 身份证正面
*/
private String frontIdCard;
/**
* 身份证反面
*/
private String backIdCard;
}

View File

@ -0,0 +1,36 @@
package com.bsz.school_send_back_end.model.vo;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.util.Date;
@Data
public class OrderErrandVO {
/**
* 取餐码
*/
private String pickupCode;
/**
* 送达时间
*/
private Date deliveryTime;
/**
* 门店名称
*/
private String businessName;
/**
* 配送地址
*/
private String location;
/**
* 外卖图片
*/
private String imageAddress;
}

View File

@ -0,0 +1,37 @@
package com.bsz.school_send_back_end.model.vo;
import lombok.Data;
@Data
public class OrderStatusVO {
/**
* 订单Id
*/
private Long id;
/**
* 订单状态
*/
private Integer orderState;
/**
* 跑腿状态
*/
private Integer errandState;
/**
* 图片地址
*/
private String imageAddress;
/**
* 取餐方式(0堂食 1自提 2外卖)
*/
private Integer pickupMethod;
/**
* 取餐码
*/
private String pickupCode;
}

View File

@ -0,0 +1,80 @@
package com.bsz.school_send_back_end.model.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.NumberFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Objects;
/**
* Excel订单信息导出
*
* @author xy
*/
@Data
public class OrdersExcelByErrandVO {
/**
* 订单编号
*/
@ColumnWidth(20)
@NumberFormat("#")
@ExcelProperty(value = "订单编号", index = 0)
private Long id;
/**
* 下单时间
*/
@ColumnWidth(20)
@ExcelProperty(value = "下单时间", index = 1)
private String createTime;
/**
* 手机号
*/
@ColumnWidth(20)
@ExcelProperty(value = "手机号", index = 2)
private String phone;
/**
* 订单状态
*/
@ExcelProperty(value = "订单状态", index = 3)
private String state;
/**
* 跑腿订单状态
*/
@ExcelProperty(value = "跑腿订单状态", index = 4)
private String errandState;
/**
* 订单金额
*/
@NumberFormat("0.00")
@ExcelProperty(value = "跑腿收入", index = 5)
private BigDecimal errandIncome;
/**
* 解决 EasyExcel "Duplicate key" 问题
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
OrdersExcelByErrandVO that = (OrdersExcelByErrandVO) o;
return Objects.equals(id, that.id) &&
Objects.equals(createTime, that.createTime) &&
Objects.equals(phone, that.phone) &&
Objects.equals(state, that.state) &&
Objects.equals(errandState, that.errandState) &&
Objects.equals(errandIncome.stripTrailingZeros(), that.errandIncome.stripTrailingZeros());
}
@Override
public int hashCode() {
return Objects.hash(id, createTime, phone, state, errandState, errandIncome.stripTrailingZeros());
}
}

View File

@ -0,0 +1,27 @@
package com.bsz.school_send_back_end.model.vo;
import lombok.Data;
@Data
public class OrdersPickVO {
/**
* 日期
*/
private String date;
/**
* 外卖单
*/
private Long takeOutNum;
/**
* 自提单量
*/
private Long selfLiftNum;
/**
* 堂食单量
*/
private Long eatInNum;
}

View File

@ -0,0 +1,94 @@
package com.bsz.school_send_back_end.scheduler;
import com.alipay.api.AlipayApiException;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.bsz.school_send_back_end.common.ErrorCode;
import com.bsz.school_send_back_end.config.AlipayClients;
import com.bsz.school_send_back_end.exception.BusinessException;
import com.bsz.school_send_back_end.exception.ThrowUtils;
import com.bsz.school_send_back_end.model.domain.Orders;
import com.bsz.school_send_back_end.service.OrdersService;
import com.bsz.school_send_back_end.utils.UniqueNumberGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
@Slf4j
@Component
public class CancelOrder {
@Resource
private OrdersService ordersService;
@Scheduled(cron = "0 0/30 * * * *") // 每30分钟执行一次
public void cancelOrder() throws AlipayApiException {
log.info("定时任务开始执行");
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MINUTE, -30);
Date halfHourAgo = calendar.getTime();
// 查询超时订单
List<Orders> cancelOrders = ordersService.findCancelOrders(halfHourAgo);
log.info("查询到的超时订单数量:{}", cancelOrders.size());
if (CollectionUtils.isEmpty(cancelOrders)) {
log.info("当前没有订单超时");
return;
}
// 遍历每个订单进行处理
for (Orders orders : cancelOrders) {
try {
log.info("正在处理超时订单订单ID{}", orders.getId());
this.closeOrder(orders.getPickupCode()); // 关闭订单或退款
log.info("订单超时取消成功订单ID{}", orders.getId());
} catch (Exception e) {
log.error("处理订单超时取消失败订单ID{}", orders.getId(), e);
}
}
log.info("所有超时订单处理完成!");
}
public void closeOrder(String orderNo) throws AlipayApiException {
AlipayClients clients = new AlipayClients();
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
AlipayTradeRefundModel model = new AlipayTradeRefundModel();
QueryWrapper<Orders> ordersQueryWrapper = new QueryWrapper<>();
ordersQueryWrapper.eq("pickupCode", orderNo);
log.info("orderNo" + orderNo);
Orders orders = ordersService.getOne(ordersQueryWrapper);
model.setOutTradeNo(orderNo);
model.setRefundAmount(String.valueOf(orders.getTotalPrice()));
ThrowUtils.throwIf(!orders.getState().equals(1) || orders.getState().equals(2),ErrorCode.SYSTEM_ERROR,"当前订单未支付");
//退款请求单号 要求唯一 需改
String number = UniqueNumberGenerator.generateNumber();
model.setOutRequestNo(number);
log.info("outRequestNo:" + number);
request.setBizModel(model);
orders.setState(2);
boolean update = ordersService.updateById(orders);
ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "修改订单状态失败");
log.info("orderState:" + orders.getState());
AlipayTradeRefundResponse response = clients.alipayClient().execute(request);
if (!response.isSuccess()) {
throw new BusinessException(ErrorCode.OPERATION_ERROR, "退款失败");
}
log.info("退款成功");
log.info(response.getBody());
}
}

View File

@ -0,0 +1,44 @@
package com.bsz.school_send_back_end.scheduler;
import com.bsz.school_send_back_end.model.domain.Business;
import com.bsz.school_send_back_end.model.domain.Errand;
import com.bsz.school_send_back_end.service.BusinessLevelService;
import com.bsz.school_send_back_end.service.BusinessService;
import com.bsz.school_send_back_end.service.ErrandLevelService;
import com.bsz.school_send_back_end.service.ErrandService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
import java.util.Date;
import java.util.List;
@Component
@Slf4j
public class UpdateBusinessErrand {
@Resource
private BusinessService businessService;
@Resource
private BusinessLevelService businessLevelService;
@Resource
private ErrandService errandService;
@Resource
private ErrandLevelService errandLevelService;
@Scheduled(cron = "0 0 0 * * ?")
public void updateBusinessLevels() {
List<Business> list = businessService.list();
for (Business business : list) {
businessLevelService.updateBusinessLevel(business.getId());
}
List<Errand> errandList = errandService.list();
for (Errand errand : errandList) {
errandLevelService.updateErrandLevel(errand.getId());
}
log.info("更新商家和跑腿时间:" + new Date());
}
}

View File

@ -0,0 +1,102 @@
package com.bsz.school_send_back_end.scheduler;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.bsz.school_send_back_end.common.ErrorCode;
import com.bsz.school_send_back_end.exception.ThrowUtils;
import com.bsz.school_send_back_end.model.domain.*;
import com.bsz.school_send_back_end.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
@Component
@Slf4j
public class UpdateOrder {
@Resource
private OrdersService ordersService;
@Resource
private ErrandIncomeService errandIncomeService;
@Resource
private ErrandService errandService;
@Resource
private ErrandBillService billService;
@Resource
private UserService userService;
@Scheduled(cron = "0 0 * * * ?") // 1小时执行一次
public void completeExpiredOrders() {
// 获取当前时间的 24 小时前
LocalDateTime deadline = LocalDateTime.now().minusHours(24);
// 查询已出餐且超过 24 小时的订单
List<Orders> expiredOrders = ordersService.findExpiredOrders(deadline);
if (CollectionUtils.isEmpty(expiredOrders)) {
return;
}
// 订单 ID 列表
List<Long> expiredOrderIds = expiredOrders.stream()
.filter(order -> order.getLocation() != null && !order.getLocation().isEmpty())
.map(Orders::getId)
.collect(Collectors.toList());
// **如果存在需要结算的订单**
if (!CollectionUtils.isEmpty(expiredOrderIds)) {
// 查询 `ErrandIncome` 中相关的收入记录
LambdaQueryWrapper<ErrandIncome> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(ErrandIncome::getOrderId, expiredOrderIds);
List<ErrandIncome> errandIncomes = errandIncomeService.list(queryWrapper);
// 更新收入状态
errandIncomes.forEach(income -> {
income.setState(1);
Errand errand = errandService.getById(income.getErrandId());
Orders orders = ordersService.getById(income.getOrderId());
User user = userService.getById(orders.getUserId());
if (errand != null) {
BigDecimal totalPrice = errand.getTotalPrice();
totalPrice = totalPrice.add(income.getIncome());
errand.setTotalPrice(totalPrice);
boolean update = errandService.updateById(errand);
ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "收入加入总金额失败");
ErrandBill errandBill = new ErrandBill();
errandBill.setOrderId(orders.getId());
errandBill.setErrandState(income.getState());
errandBill.setIncome(income.getIncome());
errandBill.setUsername(user.getUsername());
errandBill.setOrderStartTime(orders.getCreateTime());
boolean save = billService.save(errandBill);
ThrowUtils.throwIf(!save, ErrorCode.OPERATION_ERROR, "添加跑腿账单失败");
}
}); // 1 = 已结算 将收入加入总金额
boolean updatedIncome = errandIncomeService.updateBatchById(errandIncomes);
ThrowUtils.throwIf(!updatedIncome, ErrorCode.OPERATION_ERROR, "修改订单收入状态失败");
}
// 更新订单状态
for (Orders order : expiredOrders) {
order.setState(5);
}
boolean updated = ordersService.updateBatchById(expiredOrders);
if (updated) {
log.info("成功完成 {} 个超时订单", expiredOrders.size());
} else {
log.warn("自动完成订单时发生错误");
}
}
}

View File

@ -0,0 +1,17 @@
package com.bsz.school_send_back_end.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bsz.school_send_back_end.model.domain.Businessinfo;
import com.bsz.school_send_back_end.model.dto.businessinfo.InfoQueryRequest;
import java.util.List;
/**
* @author xy
*/
public interface BusinessinfoService extends IService<Businessinfo> {
QueryWrapper<Businessinfo> getQueryWrapper (InfoQueryRequest infoQueryRequest);
}

View File

@ -0,0 +1,34 @@
package com.bsz.school_send_back_end.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.bsz.school_send_back_end.model.domain.ErrandAuth;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bsz.school_send_back_end.model.dto.errandAtuh.ErrandAuthQueryRequest;
/**
* @author xy
*/
public interface ErrandAuthService extends IService<ErrandAuth> {
/**
* 校验跑腿认证
*/
void validErrandAuth (ErrandAuth errandAuth, boolean add);
/**
* 获取修改对象
*/
LambdaUpdateWrapper<ErrandAuth> getUpdateWrapper (ErrandAuth errandAuth);
/**
* 获取查询对象
*/
QueryWrapper<ErrandAuth> getQueryWrapper (ErrandAuthQueryRequest errandAuthQueryRequest);
/**
* 根据id获取跑腿认证信息
*/
ErrandAuth getErrandAuth(Long errandId);
}

View File

@ -0,0 +1,11 @@
package com.bsz.school_send_back_end.service;
import com.bsz.school_send_back_end.model.domain.ErrandBill;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @author xy
*/
public interface ErrandBillService extends IService<ErrandBill> {
}

View File

@ -0,0 +1,28 @@
package com.bsz.school_send_back_end.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bsz.school_send_back_end.model.domain.ErrandIncome;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bsz.school_send_back_end.model.domain.Orders;
import com.bsz.school_send_back_end.model.dto.erradnIncome.ErrandIncomeQueryRequest;
/**
* @author xy
*/
public interface ErrandIncomeService extends IService<ErrandIncome> {
/**
* 添加跑腿收入
*/
void addErrandIncome(Orders orders);
/**
* 分页查询
*/
QueryWrapper<ErrandIncome> getWrapper(ErrandIncomeQueryRequest queryRequest);
/**
* 获取当日跑腿定案查询条件
*/
LambdaQueryWrapper<ErrandIncome> getQueryWrapper (Long errandId);
}

View File

@ -0,0 +1,15 @@
package com.bsz.school_send_back_end.service;
import com.bsz.school_send_back_end.model.domain.ErrandLevel;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @author xy
*/
public interface ErrandLevelService extends IService<ErrandLevel> {
/**
* 更新跑腿等级
*/
void updateErrandLevel(Long errandId);
}

View File

@ -0,0 +1,11 @@
package com.bsz.school_send_back_end.service;
import com.bsz.school_send_back_end.model.domain.ErrandOrder;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @author xy
*/
public interface ErrandOrderService extends IService<ErrandOrder> {
}

View File

@ -0,0 +1,68 @@
package com.bsz.school_send_back_end.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bsz.school_send_back_end.model.domain.Errand;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bsz.school_send_back_end.model.domain.ErrandIncome;
import com.bsz.school_send_back_end.model.domain.Orders;
import com.bsz.school_send_back_end.model.domain.User;
import com.bsz.school_send_back_end.model.dto.CommonRequest;
import com.bsz.school_send_back_end.model.dto.errand.ErrandQueryRequest;
import com.bsz.school_send_back_end.model.dto.errand.ErrandStateRequest;
import com.bsz.school_send_back_end.model.dto.errand.ErrandUpdateRequest;
import com.bsz.school_send_back_end.model.vo.ErrandVO;
import jakarta.servlet.http.HttpServletRequest;
/**
* @author xy
*/
public interface ErrandService extends IService<Errand> {
/**
* 校验跑腿
*/
void validErrand (Errand errand, boolean add);
/**
* 添加跑腿
*/
void addErrand (User user, Errand errand);
/**
* 删除跑腿
*/
void deleteErrand (HttpServletRequest request);
/**
* 获取当前登录跑腿
*/
Errand getLoginErrand(HttpServletRequest request);
/**
* 获取查询对象
*/
QueryWrapper<Errand> getQueryWrapper(ErrandQueryRequest queryRequest);
/**
* 修改订单状态
*/
void orderToErrand (ErrandStateRequest errandStateRequest, HttpServletRequest request);
/**
* 修改跑腿
*/
Boolean updateErrand (ErrandUpdateRequest updateRequest);
/**
* 修改跑腿接单量
*/
void updateTotal (Errand errand, boolean add);
/**
* 获取跑腿视图
*/
ErrandVO getErrandVO(Errand errand);
}

View File

@ -0,0 +1,18 @@
package com.bsz.school_send_back_end.service;
import org.springframework.ai.chat.client.AdvisedRequest;
import org.springframework.ai.chat.client.RequestResponseAdvisor;
import java.util.Map;
/**
* @author xy
*/
public class LoggingService implements RequestResponseAdvisor {
@Override
public AdvisedRequest adviseRequest(AdvisedRequest request, Map<String, Object> context) {
System.out.println("Request"+request);
return request;
}
}

View File

@ -0,0 +1,11 @@
package com.bsz.school_send_back_end.service;
import com.bsz.school_send_back_end.model.domain.OrderImage;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @author xy
*/
public interface OrderImageService extends IService<OrderImage> {
}

View File

@ -0,0 +1,11 @@
package com.bsz.school_send_back_end.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bsz.school_send_back_end.model.domain.OrderRefunds;
/**
* @author xy
*/
public interface OrderRefundsService extends IService<OrderRefunds> {
}

View File

@ -0,0 +1,41 @@
package com.bsz.school_send_back_end.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsz.school_send_back_end.contant.CommonConstant;
import com.bsz.school_send_back_end.mapper.BusinessinfoMapper;
import com.bsz.school_send_back_end.model.domain.Businessinfo;
import com.bsz.school_send_back_end.model.dto.businessinfo.InfoQueryRequest;
import com.bsz.school_send_back_end.service.BusinessinfoService;
import com.bsz.school_send_back_end.utils.SqlUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
/**
* @author xy
*/
@Service
public class BusinessinfoServiceImpl extends ServiceImpl<BusinessinfoMapper, Businessinfo>
implements BusinessinfoService {
@Override
public QueryWrapper<Businessinfo> getQueryWrapper(InfoQueryRequest infoQueryRequest) {
Long businessId = infoQueryRequest.getBusinessId();
Date createTime = infoQueryRequest.getCreateTime();
String sortField = infoQueryRequest.getSortField();
String sortOrder = infoQueryRequest.getSortOrder();
QueryWrapper<Businessinfo> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(ObjectUtils.isNotEmpty(businessId), "businessId", businessId);
queryWrapper.le(ObjectUtils.isNotEmpty(createTime), "createTime", createTime);
queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC ), sortField);
return queryWrapper;
}
}

View File

@ -0,0 +1,88 @@
package com.bsz.school_send_back_end.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsz.school_send_back_end.common.ErrorCode;
import com.bsz.school_send_back_end.contant.CommonConstant;
import com.bsz.school_send_back_end.exception.BusinessException;
import com.bsz.school_send_back_end.exception.ThrowUtils;
import com.bsz.school_send_back_end.model.domain.ErrandAuth;
import com.bsz.school_send_back_end.model.dto.errandAtuh.ErrandAuthQueryRequest;
import com.bsz.school_send_back_end.service.ErrandAuthService;
import com.bsz.school_send_back_end.mapper.ErrandAuthMapper;
import com.bsz.school_send_back_end.utils.SqlUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
/**
* @author xy
*/
@Service
public class ErrandAuthServiceImpl extends ServiceImpl<ErrandAuthMapper, ErrandAuth>
implements ErrandAuthService{
@Override
public void validErrandAuth(ErrandAuth errandAuth, boolean add) {
Long errandId = errandAuth.getErrandId();
String bankCard = errandAuth.getBankCard();
String frontIdCard = errandAuth.getFrontIdCard();
String backIdCard = errandAuth.getBackIdCard();
if (add) {
if (StringUtils.isAnyBlank(backIdCard,frontIdCard,bankCard)) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "信息不全");
}
}
else {
LambdaQueryWrapper<ErrandAuth> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ErrandAuth::getErrandId, errandId);
long count = this.count(queryWrapper);
ThrowUtils.throwIf(count == 0, ErrorCode.PARAMS_ERROR, "该用户未关联跑腿");
}
}
@Override
public LambdaUpdateWrapper<ErrandAuth> getUpdateWrapper(ErrandAuth errandAuth) {
Long errandId = errandAuth.getErrandId();
String bankCard = errandAuth.getBankCard();
String backIdCard = errandAuth.getBackIdCard();
String frontIdCard = errandAuth.getFrontIdCard();
LambdaUpdateWrapper<ErrandAuth> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.set(StringUtils.isNotBlank(bankCard), ErrandAuth::getBankCard, bankCard);
updateWrapper.set(StringUtils.isNotBlank(backIdCard), ErrandAuth::getBackIdCard, backIdCard);
updateWrapper.set(StringUtils.isNotBlank(frontIdCard), ErrandAuth::getFrontIdCard, frontIdCard);
updateWrapper.eq(ErrandAuth::getErrandId, errandId);
return updateWrapper;
}
@Override
public QueryWrapper<ErrandAuth> getQueryWrapper(ErrandAuthQueryRequest errandAuthQueryRequest) {
Long id = errandAuthQueryRequest.getId();
Long errandId = errandAuthQueryRequest.getErrandId();
String sortField = errandAuthQueryRequest.getSortField();
String sortOrder = errandAuthQueryRequest.getSortOrder();
QueryWrapper<ErrandAuth> wrapper = new QueryWrapper<>();
wrapper.eq(ObjectUtils.isNotEmpty(id), "id", id);
wrapper.eq(ObjectUtils.isNotEmpty(errandId), "errandId", errandId);
wrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC),
sortField);
return wrapper;
}
@Override
public ErrandAuth getErrandAuth(Long errandId) {
LambdaQueryWrapper<ErrandAuth> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ErrandAuth::getErrandId, errandId);
ErrandAuth errandAuth = this.getOne(queryWrapper);
ThrowUtils.throwIf(errandAuth == null, ErrorCode.PARAMS_ERROR, "当前跑腿id没有认证");
return errandAuth;
}
}

View File

@ -0,0 +1,20 @@
package com.bsz.school_send_back_end.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsz.school_send_back_end.model.domain.ErrandBill;
import com.bsz.school_send_back_end.service.ErrandBillService;
import com.bsz.school_send_back_end.mapper.ErrandBillMapper;
import org.springframework.stereotype.Service;
/**
* @author xy
*/
@Service
public class ErrandBillServiceImpl extends ServiceImpl<ErrandBillMapper, ErrandBill>
implements ErrandBillService{
}

View File

@ -0,0 +1,88 @@
package com.bsz.school_send_back_end.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsz.school_send_back_end.common.ErrorCode;
import com.bsz.school_send_back_end.contant.CommonConstant;
import com.bsz.school_send_back_end.contant.UserConstant;
import com.bsz.school_send_back_end.exception.ThrowUtils;
import com.bsz.school_send_back_end.model.domain.ErrandIncome;
import com.bsz.school_send_back_end.model.domain.Orders;
import com.bsz.school_send_back_end.model.dto.erradnIncome.ErrandIncomeQueryRequest;
import com.bsz.school_send_back_end.service.ErrandIncomeService;
import com.bsz.school_send_back_end.mapper.ErrandIncomeMapper;
import com.bsz.school_send_back_end.utils.SqlUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
/**
* @author xy
*/
@Service
public class ErrandIncomeServiceImpl extends ServiceImpl<ErrandIncomeMapper, ErrandIncome>
implements ErrandIncomeService{
@Override
@Transactional(rollbackFor = Exception.class)
public void addErrandIncome(Orders orders) {
String location = orders.getLocation();
Long errandId = orders.getErrandId();
Long ordersId = orders.getId();
ErrandIncome errandIncome = new ErrandIncome();
errandIncome.setErrandId(errandId);
errandIncome.setOrderId(ordersId);
errandIncome.setIncome(UserConstant.DELIVERY_FEE_MAP.get(location));
boolean save = this.save(errandIncome);
ThrowUtils.throwIf(!save, ErrorCode.OPERATION_ERROR, "添加配送费失败");
}
@Override
public QueryWrapper<ErrandIncome> getWrapper(ErrandIncomeQueryRequest queryRequest) {
Long id = queryRequest.getId();
Long orderId = queryRequest.getOrderId();
Long errandId = queryRequest.getErrandId();
Integer state = queryRequest.getState();
String sortField = queryRequest.getSortField();
String sortOrder = queryRequest.getSortOrder();
QueryWrapper<ErrandIncome> wrapper = new QueryWrapper<>();
wrapper.eq(ObjectUtils.isNotEmpty(id),"id", id);
wrapper.eq(ObjectUtils.isNotEmpty(orderId), "orderId", orderId);
wrapper.eq(ObjectUtils.isNotEmpty(errandId), "errandId",errandId);
wrapper.eq(ObjectUtils.isNotEmpty(state), "state", state);
wrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC),
sortField);
return wrapper;
}
@Override
public LambdaQueryWrapper<ErrandIncome> getQueryWrapper(Long errandId) {
// 获取当前日期的开始和结束时间
LocalDateTime startOfDay = LocalDate.now().atStartOfDay();
LocalDateTime endOfDay = LocalDate.now().atTime(23, 59, 59, 999999999);
// 转换为 Date 对象
Date startDate = Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
Date endDate = Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant());
LambdaQueryWrapper<ErrandIncome> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ErrandIncome::getErrandId, errandId);
queryWrapper.ge(ErrandIncome::getCreateTime, startDate); // 大于等于当天的 00:00:00
queryWrapper.le(ErrandIncome::getCreateTime, endDate); // 小于等于当天的 23:59:59
return queryWrapper;
}
}

View File

@ -0,0 +1,72 @@
package com.bsz.school_send_back_end.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsz.school_send_back_end.contant.UserConstant;
import com.bsz.school_send_back_end.mapper.UserRatingMapper;
import com.bsz.school_send_back_end.model.domain.ErrandLevel;
import com.bsz.school_send_back_end.service.ErrandLevelService;
import com.bsz.school_send_back_end.mapper.ErrandLevelMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import java.math.BigDecimal;
/**
* @author xy
*/
@Service
@Slf4j
public class ErrandLevelServiceImpl extends ServiceImpl<ErrandLevelMapper, ErrandLevel>
implements ErrandLevelService{
@Resource
private ErrandLevelMapper errandLevelMapper;
@Resource
private UserRatingMapper userRatingMapper;
@Override
public void updateErrandLevel(Long errandId) {
Double avg = userRatingMapper.findAvgByRatedEntityId(errandId);
if (avg == null) {
avg = UserConstant.DEFAULT_AVG_SCORE;
log.info("warn: avg没有值将赋初始值1" + avg);
log.info("当前跑腿id" + errandId);
}
int level = calculateLevel(avg);
ErrandLevel errandLevel = errandLevelMapper.selectOne(Wrappers.<ErrandLevel>lambdaQuery()
.eq(ErrandLevel::getErrandId, errandId));
if (errandLevel == null) {
errandLevel = new ErrandLevel();
errandLevel.setErrandId(errandId);
errandLevel.setLevel(UserConstant.DEFAULT_LEVEL);
errandLevel.setAverageScore(BigDecimal.valueOf(1));
}
errandLevel.setAverageScore(BigDecimal.valueOf(avg));
errandLevel.setLevel(level);
this.saveOrUpdate(errandLevel);
}
private int calculateLevel(Double averageScore) {
if (averageScore >= 4.5) {
return 5;
} else if (averageScore >= 4.0) {
return 4;
} else if (averageScore >= 3.0) {
return 3;
} else if (averageScore >= 2.0) {
return 2;
} else {
return 1;
}
}
}

View File

@ -0,0 +1,20 @@
package com.bsz.school_send_back_end.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsz.school_send_back_end.model.domain.ErrandOrder;
import com.bsz.school_send_back_end.service.ErrandOrderService;
import com.bsz.school_send_back_end.mapper.ErrandOrderMapper;
import org.springframework.stereotype.Service;
/**
* @author xy
*/
@Service
public class ErrandOrderServiceImpl extends ServiceImpl<ErrandOrderMapper, ErrandOrder>
implements ErrandOrderService{
}

View File

@ -0,0 +1,279 @@
package com.bsz.school_send_back_end.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.bsz.school_send_back_end.common.ErrorCode;
import com.bsz.school_send_back_end.contant.CommonConstant;
import com.bsz.school_send_back_end.exception.BusinessException;
import com.bsz.school_send_back_end.exception.ThrowUtils;
import com.bsz.school_send_back_end.model.domain.*;
import com.bsz.school_send_back_end.model.dto.errand.ErrandQueryRequest;
import com.bsz.school_send_back_end.model.dto.errand.ErrandStateRequest;
import com.bsz.school_send_back_end.model.dto.errand.ErrandUpdateRequest;
import com.bsz.school_send_back_end.model.vo.ErrandVO;
import com.bsz.school_send_back_end.service.*;
import com.bsz.school_send_back_end.mapper.ErrandMapper;
import com.bsz.school_send_back_end.utils.RegexUtils;
import com.bsz.school_send_back_end.utils.SqlUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Objects;
/**
* @author xy
*/
@Service
@Slf4j
public class ErrandServiceImpl extends ServiceImpl<ErrandMapper, Errand>
implements ErrandService{
@Resource
private UserService userService;
@Resource
private ErrandAuthService errandAuthService;
@Resource
private OrdersService ordersService;
@Resource
private ErrandIncomeService errandIncomeService;
@Resource
private WebsocketService websocketService;
@Resource
private ErrandLevelService errandLevelService;
@Resource
private ErrandOrderService errandOrderService;
@Resource
private OrderImageService orderImageService;
@Override
public void validErrand(Errand errand, boolean add) {
String errandName = errand.getErrandName();
Integer gender = errand.getGender();
String distributionScope = errand.getDistributionScope();
Long userId = errand.getUserId();
String phone = errand.getErrandPhone();
if (add) {
if (StringUtils.isAnyBlank(errandName, phone) || ObjectUtils.isEmpty(gender) || ObjectUtils.isEmpty(distributionScope)) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "信息不全");
}
}
//校验手机号
if (StringUtils.isNotBlank(phone)) {
boolean phoneInvalid = RegexUtils.isPhoneInvalid(phone);
ThrowUtils.throwIf(phoneInvalid, ErrorCode.PARAMS_ERROR, "手机格式不正确");
}
//校验跑腿名
if (StringUtils.isNotBlank(errandName)) {
LambdaQueryWrapper<Errand> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Errand::getUserId, userId);
long count = this.count(queryWrapper);
ThrowUtils.throwIf(count > 0, ErrorCode.PARAMS_ERROR, "跑腿名字重复");
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public synchronized void addErrand(User user, Errand errand) {
boolean save = userService.save(user);
ThrowUtils.throwIf(!save, ErrorCode.SYSTEM_ERROR,"用户添加失败");
errand.setUserId(user.getId());
boolean save1 = this.save(errand);
ThrowUtils.throwIf(!save1, ErrorCode.SYSTEM_ERROR,"跑腿添加失败");
errandLevelService.updateErrandLevel(errand.getId());
}
@Override
@Transactional(rollbackFor = Exception.class)
public synchronized void deleteErrand(HttpServletRequest request) {
User loginUser = userService.getLoginUser(request);
Long userId = loginUser.getId();
LambdaQueryWrapper<Errand> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Errand::getUserId, userId);
Errand errand = this.getOne(queryWrapper);
ThrowUtils.throwIf(errand == null, ErrorCode.NOT_FOUND_ERROR, "该用户没有关联跑腿");
Long errandId = errand.getId();
LambdaQueryWrapper<ErrandAuth> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(ErrandAuth::getErrandId, errandId);
ErrandAuth errandAuth = errandAuthService.getOne(wrapper);
if (errandAuth != null){
boolean remove2 = errandAuthService.removeById(errandAuth.getId());
ThrowUtils.throwIf(!remove2, ErrorCode.SYSTEM_ERROR, "删除跑腿认证失败");
}
boolean remove = userService.removeById(userId);
boolean remove1 = this.removeById(errandId);
ThrowUtils.throwIf(!remove || !remove1, ErrorCode.SYSTEM_ERROR, "删除用户或跑腿失败");
}
@Override
public Errand getLoginErrand(HttpServletRequest request) {
User loginUser = userService.getLoginUser(request);
Long userId = loginUser.getId();
LambdaQueryWrapper<Errand> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Errand::getUserId, userId);
Errand errand = this.getOne(queryWrapper);
ThrowUtils.throwIf(errand == null, ErrorCode.NOT_FOUND_ERROR, "当前用户没有关联跑腿");
return errand;
}
@Override
public QueryWrapper<Errand> getQueryWrapper(ErrandQueryRequest queryRequest) {
Long id = queryRequest.getId();
String errandName = queryRequest.getErrandName();
Integer gender = queryRequest.getGender();
String errandPhone = queryRequest.getErrandPhone();
String distributionScope = queryRequest.getDistributionScope();
Integer state = queryRequest.getState();
String sortOrder = queryRequest.getSortOrder();
String sortField = queryRequest.getSortField();
QueryWrapper<Errand> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(ObjectUtils.isNotEmpty(id),"id", id);
queryWrapper.eq(StringUtils.isNotBlank(errandName), "errandName",errandName);
queryWrapper.eq(ObjectUtils.isNotEmpty(gender), "gender", gender);
queryWrapper.eq(StringUtils.isNotBlank(errandPhone), "errandPhone", errandPhone);
queryWrapper.eq(StringUtils.isNotBlank(distributionScope), "distributionScope", distributionScope);
queryWrapper.eq(ObjectUtils.isNotEmpty(state), "state", state);
queryWrapper.orderBy(SqlUtils.validSortField(sortField),sortOrder.equals(CommonConstant.SORT_ORDER_ASC),
sortField);
return queryWrapper;
}
@Override
public void orderToErrand(ErrandStateRequest errandStateRequest, HttpServletRequest request) {
Long ordersId = errandStateRequest.getOrderId();
Integer errandsState = errandStateRequest.getErrandsState();
String imageAddress = errandStateRequest.getImageAddress();
Errand loginErrand = this.getLoginErrand(request);
Long loginErrandId = loginErrand.getId();
Orders orders = ordersService.getOrderWithPessimisticLock(ordersId);
ThrowUtils.throwIf(orders == null, ErrorCode.PARAMS_ERROR, "订单不存在");
Long errandId = orders.getErrandId();
ThrowUtils.throwIf(!Objects.equals(loginErrandId, errandId), ErrorCode.PARAMS_ERROR, "当前订单不属于该跑腿");
ErrandOrder errandOrder = errandOrderService.getOne(Wrappers.<ErrandOrder>lambdaQuery()
.eq(ErrandOrder::getOrderId, ordersId));
if (errandsState == 5) {
orders.setErrandId(null);
errandOrder.setErrandState(errandsState);//再次抢单
errandOrder.setErrandId(null);
boolean update = ordersService.updateById(orders);
ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "取消订单失败");
log.info("跑腿取消接单订单ID: {}", ordersId);
websocketService.sendOrderToErrand(orders);
}else if (errandsState == 3) {
ThrowUtils.throwIf(orders.getState() != 4, ErrorCode.OPERATION_ERROR, "当前商家未出餐"); //商家未出餐不允许取货
errandOrder.setErrandState(errandsState);// 已取餐
boolean update = ordersService.updateById(orders);
ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "取餐失败");
log.info("订单已取餐订单id" + ordersId);
} else if (errandsState == 4) {
ThrowUtils.throwIf(errandOrder.getErrandState() != 3, ErrorCode.OPERATION_ERROR, "商家未取货");
errandOrder.setErrandState(errandsState);// 订单已送达
boolean update = ordersService.updateById(orders);
ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "订单送达失败");
if (imageAddress == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "请先上传图片");
}
OrderImage orderImage = new OrderImage();
orderImage.setOrderId(ordersId);
orderImage.setImageAddress(imageAddress);
orderImageService.save(orderImage);
log.info("订单已送达订单id" + ordersId);
errandIncomeService.addErrandIncome(orders);
this.updateTotal(loginErrand, false);
}
boolean update = errandOrderService.updateById(errandOrder);
ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "更新跑腿关联失败");
}
@Override
public Boolean updateErrand(ErrandUpdateRequest updateRequest) {
Long id = updateRequest.getId();
String errandName = updateRequest.getErrandName();
String errandPhone = updateRequest.getErrandPhone();
String distributionScope = updateRequest.getDistributionScope();
Integer gender = updateRequest.getGender();
Integer state = updateRequest.getState();
Errand errand = this.getOne(Wrappers.<Errand>lambdaQuery().eq(Errand::getId, id));
ThrowUtils.throwIf(errand == null, ErrorCode.PARAMS_ERROR, "当前跑腿id不正确");
LambdaUpdateWrapper<Errand> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(Errand::getId, id);
updateWrapper.set(StringUtils.isNotBlank(errandName), Errand::getErrandName, errandName);
updateWrapper.set(StringUtils.isNotBlank(errandPhone), Errand::getErrandPhone, errandPhone);
updateWrapper.set(StringUtils.isNotBlank(distributionScope), Errand::getDistributionScope, distributionScope);
updateWrapper.set(ObjectUtils.isNotEmpty(gender), Errand::getGender, gender);
updateWrapper.set(ObjectUtils.isNotEmpty(state), Errand::getState, state);
boolean update = this.update(updateWrapper);
ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "更新跑腿失败");
Long userId = errand.getUserId();
User user = userService.getById(userId);
if (StringUtils.isNotBlank(errand.getErrandPhone())) {
user.setPhone(errand.getErrandPhone());
}
if ((StringUtils.isNotBlank(errand.getErrandName()))) {
user.setUsername(errand.getErrandName());
}
return true;
}
@Override
public void updateTotal(Errand errand, boolean add) {
Integer totalOrders = errand.getTotalOrders();
Integer maxOrders = errand.getMaxOrders();
if (add) {
if (totalOrders >= maxOrders) {
throw new BusinessException(ErrorCode.FORBIDDEN_ERROR, "跑腿员已达到最大接单量,无法接单");
}
errand.setTotalOrders(totalOrders + 1);
} else {
errand.setTotalOrders(totalOrders - 1);
}
boolean update = this.updateById(errand);
ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "更新跑腿订单量失败");
}
@Override
public ErrandVO getErrandVO(Errand errand) {
if (errand == null) {
return null;
}
ErrandVO errandVO = new ErrandVO();
BeanUtils.copyProperties(errand, errandVO);
ErrandLevel level = errandLevelService.getOne(Wrappers.<ErrandLevel>lambdaQuery()
.eq(ErrandLevel::getErrandId, errand.getId()));
errandVO.setLevel(level.getLevel());
return errandVO;
}
}

View File

@ -0,0 +1,20 @@
package com.bsz.school_send_back_end.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsz.school_send_back_end.model.domain.OrderImage;
import com.bsz.school_send_back_end.service.OrderImageService;
import com.bsz.school_send_back_end.mapper.OrderImageMapper;
import org.springframework.stereotype.Service;
/**
* @author xy
*/
@Service
public class OrderImageServiceImpl extends ServiceImpl<OrderImageMapper, OrderImage>
implements OrderImageService{
}

View File

@ -0,0 +1,20 @@
package com.bsz.school_send_back_end.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsz.school_send_back_end.mapper.OrderRefundsMapper;
import com.bsz.school_send_back_end.model.domain.OrderRefunds;
import com.bsz.school_send_back_end.service.OrderRefundsService;
import org.springframework.stereotype.Service;
/**
* @author xy
*/
@Service
public class OrderRefundsServiceImpl extends ServiceImpl<OrderRefundsMapper, OrderRefunds>
implements OrderRefundsService{
}

View File

@ -0,0 +1,55 @@
package com.bsz.school_send_back_end.utils;
import com.alibaba.fastjson.JSON;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.HashMap;
@Component
@Slf4j
public class AliyunSmsUtils {
@Value("${aliyun.sms.sms-access-key-id}")
private String accessKeyId;
@Value("${aliyun.sms.sms-access-key-secret}")
private String accessKeySecret;
@Value("${aliyun.sms.sms-sign-nam}")
private String signName;
@Value("${aliyun.sms.sms-template-cod}")
private String templateCode;
@Value("${aliyun.sms.sms-endpoint}")
private String endpoint;
public boolean sendSms(String phoneNumber, HashMap<String, Object> templateParams) {
try {
DefaultProfile profile = DefaultProfile.getProfile("cn-huhehaote", accessKeyId, accessKeySecret);
DefaultAcsClient client = new DefaultAcsClient(profile);
SendSmsRequest sendSmsRequest = new SendSmsRequest();
sendSmsRequest.setPhoneNumbers(phoneNumber);
sendSmsRequest.setSignName(signName);
sendSmsRequest.setTemplateCode(templateCode);
sendSmsRequest.setTemplateParam(JSON.toJSONString(templateParams));
SendSmsResponse sendSmsResponse = client.getAcsResponse(sendSmsRequest);
log.info("短信响应: Code={}, Message={}", sendSmsResponse.getCode(), sendSmsResponse.getMessage());
return "OK".equalsIgnoreCase(sendSmsResponse.getCode());
} catch (ClientException e) {
log.error("短信发送异常: {}", e.getErrMsg());
return false;
}
}
}

View File

@ -0,0 +1,59 @@
package com.bsz.school_send_back_end.utils;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@Data
@NoArgsConstructor
public class MultiDelayMessage<T> implements Serializable {
/**
* 消息体
*/
private T data;
/**
* 记录延时时间的集合
*/
private List<Long> delayMillis;
public MultiDelayMessage(T data, List<Long> delayMillis) {
this.data = data;
this.delayMillis = delayMillis;
}
public MultiDelayMessage(T data, Long...delayMillis) {
this.data = data;
this.delayMillis = new ArrayList<>(Arrays.asList(delayMillis));
}
/**
* 获取并移除下一个延迟时间
* @return 集合中第一个延迟时间
*/
public Long removeNextDelay() {
return delayMillis.remove(0);
}
/**
* 是否有下一个延迟时间
*/
public boolean hasNextDelay() {
return !delayMillis.isEmpty();
}
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,18 @@
<?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.bsz.school_send_back_end.mapper.BusinessinfoMapper">
<resultMap id="BaseResultMap" type="com.bsz.school_send_back_end.model.domain.Businessinfo">
<id property="id" column="id" jdbcType="BIGINT"/>
<result property="businessId" column="businessId" jdbcType="BIGINT"/>
<result property="content" column="content" jdbcType="VARCHAR"/>
<result property="createTime" column="createTime" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="Base_Column_List">
id,businessId,content,
createTime
</sql>
</mapper>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bsz.school_send_back_end.mapper.ErrandAuthMapper">
<resultMap id="BaseResultMap" type="com.bsz.school_send_back_end.model.domain.ErrandAuth">
<id property="id" column="id" jdbcType="BIGINT"/>
<result property="errandId" column="errandId" jdbcType="BIGINT"/>
<result property="bankCard" column="bankCard" jdbcType="VARCHAR"/>
<result property="frontIdCard" column="frontIdCard" jdbcType="VARCHAR"/>
<result property="backIdCard" column="backIdCard" jdbcType="VARCHAR"/>
<result property="healthCertificate" column="healthCertificate" jdbcType="VARCHAR"/>
<result property="certificateStartTime" column="certificateStartTime" jdbcType="TIMESTAMP"/>
<result property="createTime" column="createTime" jdbcType="TIMESTAMP"/>
<result property="certificateEndTime" column="certificateEndTime" jdbcType="TIMESTAMP"/>
<result property="isDelete" column="isDelete" jdbcType="TINYINT"/>
</resultMap>
<sql id="Base_Column_List">
id,errandId,bankCard,
frontIdCard,backIdCard,healthCertificate,
certificateStartTime,certificateEndTime,createTime,isDelete
</sql>
</mapper>

View File

@ -0,0 +1,20 @@
<?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.bsz.school_send_back_end.mapper.ErrandBillMapper">
<resultMap id="BaseResultMap" type="com.bsz.school_send_back_end.model.domain.ErrandBill">
<id property="id" column="id" jdbcType="BIGINT"/>
<result property="orderId" column="orderId" jdbcType="BIGINT"/>
<result property="username" column="username" jdbcType="VARCHAR"/>
<result property="income" column="income" jdbcType="DECIMAL"/>
<result property="errandState" column="errandState" jdbcType="TINYINT"/>
<result property="orderStartTime" column="orderStartTime" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="Base_Column_List">
id,orderId,username,
income,errandState,orderStartTime
</sql>
</mapper>

View File

@ -0,0 +1,20 @@
<?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.bsz.school_send_back_end.mapper.ErrandIncomeMapper">
<resultMap id="BaseResultMap" type="com.bsz.school_send_back_end.model.domain.ErrandIncome">
<id property="id" column="id" jdbcType="BIGINT"/>
<result property="errandId" column="errandId" jdbcType="BIGINT"/>
<result property="orderId" column="orderId" jdbcType="BIGINT"/>
<result property="income" column="income" jdbcType="DECIMAL"/>
<result property="state" column="state" jdbcType="TINYINT"/>
<result property="createTime" column="createTime" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="Base_Column_List">
id,errandId,orderId,
income,state,createTime
</sql>
</mapper>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bsz.school_send_back_end.mapper.ErrandLevelMapper">
<resultMap id="BaseResultMap" type="com.bsz.school_send_back_end.model.domain.ErrandLevel">
<id property="id" column="id" jdbcType="BIGINT"/>
<result property="errandId" column="errandId" jdbcType="BIGINT"/>
<result property="averageScore" column="averageScore" jdbcType="DECIMAL"/>
<result property="level" column="level" jdbcType="TINYINT"/>
<result property="createTime" column="createTime" jdbcType="TIMESTAMP"/>
<result property="updateTime" column="updateTime" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="Base_Column_List">
id,errandId,
averageScore,level,createTime,
updateTime
</sql>
</mapper>

View File

@ -0,0 +1,30 @@
<?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.bsz.school_send_back_end.mapper.ErrandMapper">
<resultMap id="BaseResultMap" type="com.bsz.school_send_back_end.model.domain.Errand">
<id property="id" column="id" jdbcType="BIGINT"/>
<result property="userId" column="userId" jdbcType="BIGINT"/>
<result property="errandName" column="errandName" jdbcType="VARCHAR"/>
<result property="errandAvatarUrl" column="errandAvatarUrl" jdbcType="VARCHAR"/>
<result property="gender" column="gender" jdbcType="TINYINT"/>
<result property="errandPhone" column="errandPhone" jdbcType="VARCHAR"/>
<result property="distributionScope" column="distributionScope" jdbcType="VARCHAR"/>
<result property="state" column="state" jdbcType="TINYINT"/>
<result property="totalOrders" column="totalOrders" jdbcType="TINYINT"/>
<result property="maxOrders" column="maxOrders" jdbcType="TINYINT"/>
<result property="totalPrice" column="totalPrice" jdbcType="DECIMAL"/>
<result property="createTime" column="createTime" jdbcType="TIMESTAMP"/>
<result property="updateTime" column="updateTime" jdbcType="TIMESTAMP"/>
<result property="isDelete" column="isDelete" jdbcType="TINYINT"/>
</resultMap>
<sql id="Base_Column_List">
id,userId,errandName,errandAvatarUrl,
gender,errandPhone,distributionScope,
state,totalOrders,maxOrders,totalPrice,
createTime,updateTime,isDelete
</sql>
</mapper>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bsz.school_send_back_end.mapper.ErrandOrderMapper">
<resultMap id="BaseResultMap" type="com.bsz.school_send_back_end.model.domain.ErrandOrder">
<id property="id" column="id" jdbcType="BIGINT"/>
<result property="orderId" column="orderId" jdbcType="BIGINT"/>
<result property="errandState" column="errandState" jdbcType="TINYINT"/>
<result property="startTime" column="startTime" jdbcType="TIMESTAMP"/>
<result property="endTime" column="endTime" jdbcType="TIMESTAMP"/>
<result property="errandId" column="errandId" jdbcType="BIGINT"/>
<result property="createTime" column="createTime" jdbcType="TIMESTAMP"/>
<result property="updateTime" column="updateTime" jdbcType="TIMESTAMP"/>
<result property="isDelete" column="isDelete" jdbcType="TINYINT"/>
</resultMap>
<sql id="Base_Column_List">
id,orderId,errandState,
startTime,endTime,errandId,
createTime,updateTime,isDelete
</sql>
</mapper>

View File

@ -0,0 +1,15 @@
<?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.bsz.school_send_back_end.mapper.OrderImageMapper">
<resultMap id="BaseResultMap" type="com.bsz.school_send_back_end.model.domain.OrderImage">
<id property="orderId" column="orderId" jdbcType="BIGINT"/>
<result property="imageAddress" column="imageAddress" jdbcType="VARCHAR"/>
</resultMap>
<sql id="Base_Column_List">
orderId,imageAddress
</sql>
</mapper>

View File

@ -0,0 +1,23 @@
<?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.bsz.school_send_back_end.mapper.OrderRefundsMapper">
<resultMap id="BaseResultMap" type="com.bsz.school_send_back_end.model.domain.OrderRefunds">
<id property="id" column="id" jdbcType="BIGINT"/>
<result property="orderId" column="orderId" jdbcType="BIGINT"/>
<result property="userId" column="userId" jdbcType="BIGINT"/>
<result property="reason" column="reason" jdbcType="VARCHAR"/>
<result property="amount" column="amount" jdbcType="DECIMAL"/>
<result property="status" column="status" jdbcType="TINYINT"/>
<result property="createTime" column="createTime" jdbcType="TIMESTAMP"/>
<result property="updateTime" column="updateTime" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="Base_Column_List">
id,orderId,userId,
reason,amount,status,
createTime,updateTime
</sql>
</mapper>