1.0 完成
This commit is contained in:
10
README.md
10
README.md
@ -1,3 +1,11 @@
|
||||
**yshop-pro**
|
||||
<h1 style="text-align: center">yshop-pro意向电商商城系统</h1>
|
||||
|
||||
|
||||
#### 项目简介
|
||||
YSHOP-PRO 技术特色:移动端uniapp全新的ui、vue3全新全家桶、高并发高性能支持消息队列、异步任务、分布式锁、限流、冥等性等、支持多种支付(微信、支付宝)、支持批量上传商品、支持电子面单、支持微信统一登录各端等新特性!!! 其他新特性尽情期待;
|
||||
|
||||
|
||||
|
||||
#### 官网地址:https://www.yixiang.co
|
||||
|
||||
|
||||
|
@ -3,7 +3,7 @@ set -e
|
||||
|
||||
DATE=$(date +%Y%m%d%H%M)
|
||||
# 基础路径
|
||||
BASE_PATH=/work/projects/yshop-server
|
||||
BASE_PATH=/work/projects/yshop-pro-server
|
||||
# 编译后 jar 的地址。部署时,Jenkins 会上传 jar 包到该目录下
|
||||
SOURCE_PATH=$BASE_PATH/build
|
||||
# 服务名称。同时约定部署服务的 jar 包名字也为它。
|
||||
@ -18,12 +18,6 @@ HEAP_ERROR_PATH=$BASE_PATH/heapError
|
||||
# JVM 参数
|
||||
JAVA_OPS="-Xms512m -Xmx512m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$HEAP_ERROR_PATH"
|
||||
|
||||
# SkyWalking Agent 配置
|
||||
#export SW_AGENT_NAME=$SERVER_NAME
|
||||
#export SW_AGENT_COLLECTOR_BACKEND_SERVICES=192.168.0.84:11800
|
||||
#export SW_GRPC_LOG_SERVER_HOST=192.168.0.84
|
||||
#export SW_AGENT_TRACE_IGNORE_PATH="Redisson/PING,/actuator/**,/admin/**"
|
||||
#export JAVA_AGENT=-javaagent:/work/skywalking/apache-skywalking-apm-bin/agent/skywalking-agent.jar
|
||||
|
||||
# 备份
|
||||
function backup() {
|
||||
|
3
pom.xml
3
pom.xml
@ -20,7 +20,6 @@
|
||||
<module>yshop-module-mp</module>
|
||||
<module>yshop-module-mall</module>
|
||||
<!-- 示例项目 -->
|
||||
<module>yshop-sso-example</module>
|
||||
<module>yshop-module-express</module>
|
||||
<module>yshop-module-message</module>
|
||||
</modules>
|
||||
@ -30,7 +29,7 @@
|
||||
|
||||
|
||||
<properties>
|
||||
<revision>1.7.2-snapshot</revision>
|
||||
<revision>1.0.0</revision>
|
||||
<!-- Maven 相关 -->
|
||||
<java.version>1.8</java.version>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
|
@ -14,7 +14,7 @@
|
||||
<url>https://github.com/guchengwuyue/yshop-pro</url>
|
||||
|
||||
<properties>
|
||||
<revision>1.7.2-snapshot</revision>
|
||||
<revision>1.0.0</revision>
|
||||
<!-- 统一依赖管理 -->
|
||||
<spring.boot.version>2.7.10</spring.boot.version>
|
||||
<!-- Web 相关 -->
|
||||
|
@ -23,7 +23,7 @@ public interface ShopConstants {
|
||||
/**
|
||||
* redis订单未付款key
|
||||
*/
|
||||
String REDIS_ORDER_OUTTIME_UNPAY = "order:unpay:";
|
||||
String REDIS_ORDER_OUTTIME_UNPAY_QUEUE = "order-unpay-cancel-queue";
|
||||
/**
|
||||
* redis订单收货key
|
||||
*/
|
||||
|
@ -28,10 +28,6 @@ public class BannerApplicationRunner implements ApplicationRunner {
|
||||
"http://localhost/doc.html",
|
||||
"https://www.yixiang.co");
|
||||
|
||||
// 商城
|
||||
if (isNotPresent("co.yixiang.yshop.module.trade.framework.web.config.TradeWebConfiguration")) {
|
||||
System.out.println("[商城系统 yshop-module-mall -需要购买才有哦,我们开源的是整个商城后台管理系统,移动端需要购买才有");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ public class ExpressController {
|
||||
}
|
||||
|
||||
@PostMapping("/set")
|
||||
@Operation(summary = "获得快递鸟配置")
|
||||
@Operation(summary = "快递鸟配置")
|
||||
public CommonResult<Boolean> postExpressSet(@RequestBody KdniaoApiBaseDTO kdniaoApiBaseDTO) {
|
||||
expressRedisDAO.set(kdniaoApiBaseDTO);
|
||||
return success(true);
|
||||
|
@ -33,6 +33,12 @@
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Job 定时任务相关 -->
|
||||
<dependency>
|
||||
<groupId>co.yixiang.boot</groupId>
|
||||
<artifactId>yshop-spring-boot-starter-job</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 业务组件 -->
|
||||
<dependency>
|
||||
<groupId>co.yixiang.boot</groupId>
|
||||
|
@ -64,6 +64,7 @@ public class AppCartController {
|
||||
@PreAuthenticated
|
||||
@PostMapping("/add")
|
||||
@Operation(summary = "添加购物车")
|
||||
|
||||
public CommonResult<Map<String,Object>> add(@Validated @RequestBody AppCartParam cartParam){
|
||||
Map<String,Object> map = new LinkedHashMap<>();
|
||||
Long uid = getLoginUserId();
|
||||
|
@ -20,6 +20,10 @@ import co.yixiang.yshop.module.product.service.storeproductattrvalue.StoreProduc
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@ -40,6 +44,7 @@ import static co.yixiang.yshop.module.cart.enums.ErrorCodeConstants.STORE_CART_N
|
||||
*
|
||||
* @author yshop
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@Validated
|
||||
public class AppStoreCartServiceImpl extends ServiceImpl<StoreCartMapper,StoreCartDO> implements AppStoreCartService {
|
||||
@ -53,6 +58,7 @@ public class AppStoreCartServiceImpl extends ServiceImpl<StoreCartMapper,StoreCa
|
||||
@Resource
|
||||
private StoreProductAttrValueService storeProductAttrValueService;
|
||||
|
||||
|
||||
/**
|
||||
* 返回当前用户购物车总数量
|
||||
*
|
||||
@ -119,7 +125,7 @@ public class AppStoreCartServiceImpl extends ServiceImpl<StoreCartMapper,StoreCa
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测商品库存
|
||||
* 检测商品库存 库存加锁
|
||||
*
|
||||
* @param uid 用户ID
|
||||
* @param productId 产品ID
|
||||
@ -271,9 +277,11 @@ public class AppStoreCartServiceImpl extends ServiceImpl<StoreCartMapper,StoreCa
|
||||
* 修改购物车支付状态
|
||||
* @param cartIds
|
||||
*/
|
||||
@Async
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
|
||||
//@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
|
||||
public void updateCartPayStatus(List<String> cartIds) {
|
||||
log.info("==========修改购物车支付状态start===========");
|
||||
StoreCartDO cartObj = new StoreCartDO();
|
||||
cartObj.setIsPay(OrderInfoEnum.PAY_STATUS_1.getValue());
|
||||
storeCartMapper.update(cartObj, Wrappers.<StoreCartDO>lambdaQuery()
|
||||
|
@ -78,11 +78,7 @@
|
||||
<artifactId>yshop-spring-boot-starter-excel</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Job 定时任务相关 -->
|
||||
<dependency>
|
||||
<groupId>co.yixiang.boot</groupId>
|
||||
<artifactId>yshop-spring-boot-starter-job</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@ -8,7 +8,10 @@ import co.yixiang.yshop.module.order.controller.admin.storeorder.vo.*;
|
||||
import co.yixiang.yshop.module.order.convert.storeorder.StoreOrderConvert;
|
||||
import co.yixiang.yshop.module.order.dal.dataobject.storeorder.StoreOrderDO;
|
||||
import co.yixiang.yshop.module.order.dal.dataobject.storeorderstatus.StoreOrderStatusDO;
|
||||
import co.yixiang.yshop.module.order.dal.redis.order.AsyncCountRedisDAO;
|
||||
import co.yixiang.yshop.module.order.service.storeorder.AsyncStoreOrderService;
|
||||
import co.yixiang.yshop.module.order.service.storeorder.StoreOrderService;
|
||||
import co.yixiang.yshop.module.order.service.storeorder.dto.OrderTimeDataDto;
|
||||
import co.yixiang.yshop.module.order.service.storeorderstatus.StoreOrderStatusService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
@ -39,6 +42,10 @@ public class StoreOrderController {
|
||||
private StoreOrderService storeOrderService;
|
||||
@Resource
|
||||
private StoreOrderStatusService storeOrderStatusService;
|
||||
@Resource
|
||||
private AsyncCountRedisDAO asyncCountRedisDAO;
|
||||
@Resource
|
||||
private AsyncStoreOrderService asyncStoreOrderService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建订单")
|
||||
@ -140,5 +147,13 @@ public class StoreOrderController {
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/count")
|
||||
@Operation(summary = "获得订单统计")
|
||||
public CommonResult<OrderTimeDataDto> getStoreOrderCount() {
|
||||
asyncStoreOrderService.getOrderTimeData();
|
||||
return success(asyncCountRedisDAO.get());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,38 @@
|
||||
package co.yixiang.yshop.module.order.controller.admin.storeorder.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @ClassName OrderTimeDataDTO
|
||||
* @Author hupeng <610796224@qq.com>
|
||||
* @Date 2023/7/26
|
||||
**/
|
||||
@Data
|
||||
public class ShoperOrderTimeDataVo implements Serializable {
|
||||
|
||||
/**今日成交额*/
|
||||
private Double todayPrice;
|
||||
|
||||
/**今日订单数*/
|
||||
private Long todayCount;
|
||||
|
||||
/**昨日成交额*/
|
||||
private Double proPrice;
|
||||
|
||||
/**昨日订单数*/
|
||||
private Long proCount;
|
||||
|
||||
/**本月成交额*/
|
||||
private Double monthPrice;
|
||||
|
||||
/**本月订单数*/
|
||||
private Long monthCount;
|
||||
|
||||
/**上周订单数*/
|
||||
private Long lastWeekCount;
|
||||
|
||||
/**上周成交额*/
|
||||
private Double lastWeekPrice;
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package co.yixiang.yshop.module.order.controller.admin.storeorder.vo;
|
||||
|
||||
import co.yixiang.yshop.framework.desensitize.core.slider.annotation.MobileDesensitize;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
@ -32,6 +33,7 @@ public class StoreOrderBaseVO {
|
||||
@NotNull(message = "用户姓名不能为空")
|
||||
private String realName;
|
||||
|
||||
@MobileDesensitize
|
||||
@Schema(description = "用户电话", required = true)
|
||||
@NotNull(message = "用户电话不能为空")
|
||||
private String userPhone;
|
||||
|
@ -12,13 +12,17 @@ import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import co.yixiang.yshop.framework.common.pojo.CommonResult;
|
||||
import co.yixiang.yshop.framework.security.core.annotations.PreAuthenticated;
|
||||
import co.yixiang.yshop.module.express.dal.redis.express.ExpressRedisDAO;
|
||||
import co.yixiang.yshop.module.express.kdniao.model.dto.KdniaoApiBaseDTO;
|
||||
import co.yixiang.yshop.module.express.kdniao.model.dto.KdniaoApiDTO;
|
||||
import co.yixiang.yshop.module.express.kdniao.model.vo.KdniaoApiVO;
|
||||
import co.yixiang.yshop.module.express.kdniao.util.KdniaoUtil;
|
||||
import co.yixiang.yshop.module.member.controller.app.user.vo.AppUserOrderCountVo;
|
||||
import co.yixiang.yshop.module.order.controller.app.order.param.*;
|
||||
import co.yixiang.yshop.module.order.controller.app.order.vo.AppConfirmOrderVo;
|
||||
import co.yixiang.yshop.module.order.controller.app.order.vo.AppStoreOrderQueryVo;
|
||||
import co.yixiang.yshop.module.order.dal.redis.order.AsyncOrderRedisDAO;
|
||||
import co.yixiang.yshop.module.order.service.storeorder.AppStoreOrderService;
|
||||
import co.yixiang.yshop.module.pay.mq.producer.PayNoticeProducer;
|
||||
import com.egzosn.pay.spring.boot.core.PayServiceManager;
|
||||
import com.egzosn.pay.web.support.HttpRequestNoticeParams;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
@ -34,7 +38,8 @@ import org.springframework.web.bind.annotation.*;
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static co.yixiang.yshop.framework.common.pojo.CommonResult.success;
|
||||
@ -61,18 +66,8 @@ public class AppOrderController {
|
||||
private final AsyncOrderRedisDAO asyncOrderRedisDAO;
|
||||
private final PayServiceManager manager;
|
||||
|
||||
|
||||
@Resource
|
||||
private PayNoticeProducer payNoticeProducer;
|
||||
|
||||
// @Autowired
|
||||
// private MerchantDetailsManager<PaymentPlatformMerchantDetails> merchantDetailsManager;
|
||||
|
||||
|
||||
// @GetMapping("merchantExists")
|
||||
// public Map<String, Object> merchantExists() {
|
||||
// return new MapGen<String, Object>("exist", merchantDetailsManager.merchantExists("1")).getAttr();
|
||||
// }
|
||||
private ExpressRedisDAO expressRedisDAO;
|
||||
|
||||
|
||||
|
||||
@ -109,45 +104,7 @@ public class AppOrderController {
|
||||
public CommonResult<Map<String, Object>> create(@Valid @RequestBody AppOrderParam param,
|
||||
@PathVariable String key) {
|
||||
Long uid = getLoginUserId();
|
||||
// ComputeOrderParam computeOrderParam = new ComputeOrderParam();
|
||||
// BeanUtil.copyProperties(param, computeOrderParam);
|
||||
// Map<String, Object> map = orderSupplyService.check(yxUser.getUid(), key, computeOrderParam);
|
||||
// if (OrderLogEnum.EXTEND_ORDER.getValue().equals(map.get("status"))
|
||||
// || OrderLogEnum.PINK_ORDER_FAIL_2.getValue().equals(map.get("status"))
|
||||
// || OrderLogEnum.PINK_ORDER_FAIL_1.getValue().equals(map.get("status"))) {
|
||||
// return ApiResult.ok(map, map.get("msg").toString());
|
||||
// }
|
||||
//
|
||||
//
|
||||
// //创建订单
|
||||
// YxStoreOrder order = appStoreOrderService.createOrder(uid, key, param);
|
||||
|
||||
return success(appStoreOrderService.createOrder(uid, key, param));
|
||||
|
||||
// if (ObjectUtil.isNull(order)) {
|
||||
// throw new YshopException("订单生成失败");
|
||||
// }
|
||||
//
|
||||
// String orderId = order.getOrderId();
|
||||
//
|
||||
// OrderExtendDto orderDTO = new OrderExtendDto();
|
||||
// orderDTO.setKey(key);
|
||||
// orderDTO.setOrderId(orderId);
|
||||
// map.put("status", OrderLogEnum.CREATE_ORDER_SUCCESS.getValue());
|
||||
// map.put("result", orderDTO);
|
||||
// map.put("createTime", order.getCreateTime());
|
||||
|
||||
//开始处理支付
|
||||
//处理金额为0的情况
|
||||
// if(order.getPayPrice().compareTo(BigDecimal.ZERO) <= 0&&!param.getPayType().equals(PayTypeEnum.INTEGRAL.getValue())){
|
||||
// storeOrderService.yuePay(orderId,yxUser.getUid());
|
||||
// map.put("payMsg","支付成功");
|
||||
// return ApiResult.ok(map,"支付成功");
|
||||
// }
|
||||
//
|
||||
// orderSupplyService.goPay(map,orderId,yxUser.getUid(),
|
||||
// param.getPayType(),param.getFrom(),orderDTO);
|
||||
// return ApiResult.ok(map, map.get("payMsg").toString());
|
||||
}
|
||||
|
||||
|
||||
@ -293,47 +250,28 @@ public class AppOrderController {
|
||||
|
||||
|
||||
|
||||
// /**
|
||||
// * 获取物流信息
|
||||
// */
|
||||
// @AuthCheck
|
||||
// @PostMapping("/order/express")
|
||||
// @ApiOperation(value = "获取物流信息", notes = "获取物流信息")
|
||||
// public ApiResult<ExpressInfo> express(@RequestBody ExpressParam expressInfoDo) {
|
||||
//
|
||||
// //顺丰轨迹查询处理
|
||||
// String lastFourNumber = "";
|
||||
// if (expressInfoDo.getShipperCode().equals(ShipperCodeEnum.SF.getValue())) {
|
||||
// YxStoreOrderQueryVo yxStoreOrderDto;
|
||||
// yxStoreOrderDto = storeOrderService.getOrderInfo(expressInfoDo.getOrderCode(),null);
|
||||
// lastFourNumber = yxStoreOrderDto.getUserPhone();
|
||||
// if (lastFourNumber.length() == 11) {
|
||||
// lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// ExpressService expressService = ExpressAutoConfiguration.expressService();
|
||||
// ExpressInfo expressInfo = expressService.getExpressInfo(expressInfoDo.getOrderCode(),
|
||||
// expressInfoDo.getShipperCode(), expressInfoDo.getLogisticCode(), lastFourNumber);
|
||||
// if (!expressInfo.isSuccess()) {
|
||||
// throw new YshopException(expressInfo.getReason());
|
||||
// }
|
||||
// return ApiResult.ok(expressInfo);
|
||||
// }
|
||||
/**
|
||||
* 获取物流信息
|
||||
*/
|
||||
@PreAuthenticated
|
||||
@PostMapping("/order/express")
|
||||
@Operation(summary = "获取物流信息")
|
||||
public CommonResult<KdniaoApiVO> express(@RequestBody AppExpressParam appExpressParam) {
|
||||
|
||||
KdniaoApiBaseDTO kdniaoApiBaseDTO = expressRedisDAO.get();
|
||||
KdniaoApiDTO params = new KdniaoApiDTO();
|
||||
params.setLogisticCode(appExpressParam.getLogisticCode());
|
||||
params.setShipperCode(appExpressParam.getShipperCode());
|
||||
params.setApiKey(kdniaoApiBaseDTO.getApiKey());
|
||||
params.setEBusinessID(kdniaoApiBaseDTO.getEBusinessID());
|
||||
//此处注意 这个地方分收费与免费当 目前用当免费免费当只支持圆通 申通 百世 如果是收费当 改里面RequestType参数 函数里有说明
|
||||
return success(KdniaoUtil.getLogisticInfo(params));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// @AuthCheck
|
||||
// @GetMapping("/order/getSubscribeTemplate")
|
||||
// @ApiOperation(value = "获取订阅消息模板ID", notes = "获取订阅消息模板ID")
|
||||
// public ApiResult<List<String>> getSubscribeTemplate() {
|
||||
// List<YxWechatTemplate> yxWechatTemplate = yxWechatTemplateService.lambdaQuery()
|
||||
// .eq(YxWechatTemplate::getType, "subscribe")
|
||||
// .eq(YxWechatTemplate::getStatus, ShopCommonEnum.IS_STATUS_1.getValue()).list();
|
||||
// List<String> temId = yxWechatTemplate.stream().map(tem -> tem.getTempid()).collect(Collectors.toList());
|
||||
// return ApiResult.ok(temId);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,24 @@
|
||||
package co.yixiang.yshop.module.order.controller.app.order.param;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @ClassName ExpressParam
|
||||
* @Author hupeng <610796224@qq.com>
|
||||
* @Date 2023/7/26
|
||||
**/
|
||||
@Data
|
||||
public class AppExpressParam implements Serializable {
|
||||
|
||||
@Schema(description = "订单编号", required = true)
|
||||
private String orderCode;
|
||||
|
||||
@Schema(description = "快递公司编码", required = true)
|
||||
private String shipperCode;
|
||||
|
||||
@Schema(description = "物流单号", required = true)
|
||||
private String logisticCode;
|
||||
}
|
@ -11,6 +11,8 @@ import co.yixiang.yshop.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import co.yixiang.yshop.module.order.dal.dataobject.storeorder.StoreOrderDO;
|
||||
import co.yixiang.yshop.module.order.enums.AdminOrderStatusEnum;
|
||||
import co.yixiang.yshop.module.order.enums.OrderStatusEnum;
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import co.yixiang.yshop.module.order.controller.admin.storeorder.vo.*;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
@ -98,4 +100,12 @@ public interface StoreOrderMapper extends BaseMapperX<StoreOrderDO> {
|
||||
"where paid=1 and deleted=0 and refund_status=0 and uid=#{uid}")
|
||||
double sumPrice(@Param("uid") Long uid);
|
||||
|
||||
@Select("SELECT IFNULL(sum(pay_price),0) " +
|
||||
" FROM yshop_store_order ${ew.customSqlSegment}")
|
||||
Double todayPrice(@Param(Constants.WRAPPER) Wrapper<StoreOrderDO> wrapper);
|
||||
|
||||
@Select( "select IFNULL(sum(pay_price),0) from yshop_store_order " +
|
||||
"where refund_status=0 and deleted=0 and paid=1")
|
||||
Double sumTotalPrice();
|
||||
|
||||
}
|
||||
|
@ -25,5 +25,9 @@ public interface RedisKeyConstants {
|
||||
"yshop_order_count_cache:%s", // 参数为访问uid
|
||||
STRING, CacheDto.class, RedisKeyDefine.TimeoutTypeEnum.FOREVER);
|
||||
|
||||
RedisKeyDefine YSHOP_ADMIN_ORDER_COUNT_CACHE_KEY = new RedisKeyDefine("后台统计订单数据缓存",
|
||||
"yshop_admin_order_count_cache:", // 参数为访问uid
|
||||
STRING, CacheDto.class, RedisKeyDefine.TimeoutTypeEnum.FOREVER);
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,45 @@
|
||||
package co.yixiang.yshop.module.order.dal.redis.order;
|
||||
|
||||
import co.yixiang.yshop.framework.common.util.json.JsonUtils;
|
||||
import co.yixiang.yshop.module.member.controller.app.user.vo.AppUserOrderCountVo;
|
||||
import co.yixiang.yshop.module.order.controller.admin.storeorder.vo.ShoperOrderTimeDataVo;
|
||||
import co.yixiang.yshop.module.order.service.storeorder.dto.OrderTimeDataDto;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import static co.yixiang.yshop.module.order.dal.redis.RedisKeyConstants.YSHOP_ADMIN_ORDER_COUNT_CACHE_KEY;
|
||||
|
||||
/**
|
||||
* {@link AppUserOrderCountVo} 的 RedisDAO
|
||||
*
|
||||
* @author yshop
|
||||
*/
|
||||
@Repository
|
||||
public class AsyncCountRedisDAO {
|
||||
|
||||
@Resource
|
||||
private StringRedisTemplate stringRedisTemplate;
|
||||
|
||||
public OrderTimeDataDto get() {
|
||||
String redisKey = YSHOP_ADMIN_ORDER_COUNT_CACHE_KEY.getKeyTemplate();
|
||||
return JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(redisKey), OrderTimeDataDto.class);
|
||||
}
|
||||
|
||||
public void set(OrderTimeDataDto orderTimeDataDto) {
|
||||
String redisKey = YSHOP_ADMIN_ORDER_COUNT_CACHE_KEY.getKeyTemplate();
|
||||
stringRedisTemplate.opsForValue().set(redisKey, JsonUtils.toJsonString(orderTimeDataDto));
|
||||
}
|
||||
|
||||
public void delete(Long uid) {
|
||||
String redisKey = YSHOP_ADMIN_ORDER_COUNT_CACHE_KEY.getKeyTemplate();
|
||||
stringRedisTemplate.delete(redisKey);
|
||||
}
|
||||
|
||||
|
||||
private static String formatKey(String key) {
|
||||
return String.format(YSHOP_ADMIN_ORDER_COUNT_CACHE_KEY.getKeyTemplate(), key);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package co.yixiang.yshop.module.order.handle;
|
||||
|
||||
import cn.hutool.core.thread.ExecutorBuilder;
|
||||
import cn.hutool.core.thread.ThreadFactoryBuilder;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import co.yixiang.yshop.framework.common.constant.ShopConstants;
|
||||
import co.yixiang.yshop.module.order.service.storeorder.AppStoreOrderService;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.redisson.api.RBlockingDeque;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.Resource;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
/**
|
||||
* 延时队列消费
|
||||
* @author hupeng
|
||||
* @date 2023.7.27
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class RedisDelayHandle {
|
||||
@Resource
|
||||
private RedissonClient redissonClient;
|
||||
@Resource
|
||||
private AppStoreOrderService appStoreOrderService;
|
||||
|
||||
@PostConstruct
|
||||
public void startJobTimer() {
|
||||
ThreadFactory threadFactory = new ThreadFactoryBuilder().setNamePrefix("delay-job-service").build();
|
||||
log.info("========延时队列开始=========");
|
||||
ExecutorService executorService = ExecutorBuilder.create()
|
||||
.setCorePoolSize(2)
|
||||
.setMaxPoolSize(10)
|
||||
.setKeepAliveTime(0)
|
||||
.setThreadFactory(threadFactory)
|
||||
.build();
|
||||
|
||||
executorService.execute(new ExecutorTask());
|
||||
}
|
||||
|
||||
class ExecutorTask implements Runnable {
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public void run() {
|
||||
RBlockingDeque<String> blockingDeque = redissonClient
|
||||
.getBlockingDeque(ShopConstants.REDIS_ORDER_OUTTIME_UNPAY_QUEUE);
|
||||
RBlockingDeque<String> blockingDeque2 = redissonClient
|
||||
.getBlockingDeque(ShopConstants.REDIS_ORDER_OUTTIME_UNCONFIRM);
|
||||
while (true) {
|
||||
String orderId = "";
|
||||
String orderId2 = "";
|
||||
try {
|
||||
orderId = blockingDeque.take();
|
||||
orderId2 = blockingDeque2.take();
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
if(StrUtil.isNotEmpty(orderId)) {
|
||||
appStoreOrderService.cancelOrder(orderId,null);
|
||||
}
|
||||
if(StrUtil.isNotEmpty(orderId2)) {
|
||||
appStoreOrderService.takeOrder(orderId,null);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -8,6 +8,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
import co.yixiang.yshop.framework.common.constant.ShopConstants;
|
||||
import co.yixiang.yshop.framework.common.enums.OrderInfoEnum;
|
||||
import co.yixiang.yshop.framework.common.enums.ShopCommonEnum;
|
||||
import co.yixiang.yshop.framework.common.exception.ErrorCode;
|
||||
import co.yixiang.yshop.module.cart.service.storecart.AppStoreCartService;
|
||||
import co.yixiang.yshop.module.member.controller.app.user.vo.AppUserQueryVo;
|
||||
import co.yixiang.yshop.module.member.dal.dataobject.user.MemberUserDO;
|
||||
@ -57,6 +58,12 @@ import com.egzosn.pay.common.bean.RefundResult;
|
||||
import com.egzosn.pay.spring.boot.core.PayServiceManager;
|
||||
import com.egzosn.pay.spring.boot.core.bean.MerchantPayOrder;
|
||||
import com.google.common.collect.Maps;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.redisson.api.RBlockingDeque;
|
||||
import org.redisson.api.RDelayedQueue;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@ -66,6 +73,7 @@ import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
@ -77,6 +85,7 @@ import static co.yixiang.yshop.module.order.enums.ErrorCodeConstants.*;
|
||||
*
|
||||
* @author yshop
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@Validated
|
||||
public class AppStoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper,StoreOrderDO> implements AppStoreOrderService {
|
||||
@ -111,6 +120,11 @@ public class AppStoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper,Store
|
||||
private PayServiceManager manager;
|
||||
@Resource
|
||||
private WeixinNoticeProducer weixinNoticeProducer;
|
||||
@Resource
|
||||
private RedissonClient redissonClient;
|
||||
|
||||
private static final String LOCK_KEY = "cart:check:stock:lock";
|
||||
private static final String STOCK_LOCK_KEY = "cart:do:stock:lock";
|
||||
|
||||
|
||||
|
||||
@ -286,12 +300,23 @@ public class AppStoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper,Store
|
||||
CacheDto cacheDTO = orderRedisDAO.get(key, uid);
|
||||
List<AppStoreCartQueryVo> cartInfo = cacheDTO.getCartInfo();
|
||||
|
||||
for (AppStoreCartQueryVo cart : cartInfo) {
|
||||
//检测库存
|
||||
appStoreCartService.checkProductStock(uid, cart.getProductId(), cart.getCartNum(), cart.getProductAttrUnique());
|
||||
//对库存检查加锁
|
||||
RLock lock = redissonClient.getLock(LOCK_KEY);
|
||||
if (lock.tryLock()){
|
||||
try {
|
||||
for (AppStoreCartQueryVo cart : cartInfo) {
|
||||
//检测库存
|
||||
appStoreCartService.checkProductStock(uid, cart.getProductId(), cart.getCartNum(), cart.getProductAttrUnique());
|
||||
|
||||
cartIds.add(cart.getId().toString());
|
||||
totalNum += cart.getCartNum();
|
||||
cartIds.add(cart.getId().toString());
|
||||
totalNum += cart.getCartNum();
|
||||
}
|
||||
}catch (Exception ex) {
|
||||
log.error("[checkProductStock][执行异常]", ex);
|
||||
throw exception(new ErrorCode(999999,ex.getMessage()));
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -336,11 +361,11 @@ public class AppStoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper,Store
|
||||
this.deStockIncSale(cartInfo);
|
||||
|
||||
|
||||
//保存购物车商品信息
|
||||
//保存购物车商品信息,异步执行
|
||||
storeOrderCartInfoService.saveCartInfo(storeOrder.getId(), storeOrder.getOrderId(),cartInfo);
|
||||
|
||||
|
||||
//购物车状态修改
|
||||
//购物车状态修改异步执行
|
||||
appStoreCartService.updateCartPayStatus(cartIds);
|
||||
|
||||
|
||||
@ -352,11 +377,16 @@ public class AppStoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper,Store
|
||||
OrderLogEnum.CREATE_ORDER.getDesc());
|
||||
|
||||
|
||||
//加入redis,30分钟自动取消 todo 延时队列
|
||||
// String redisKey = String.valueOf(StrUtil.format("{}{}",
|
||||
// ShopConstants.REDIS_ORDER_OUTTIME_UNPAY, storeOrder.getId()));
|
||||
// redisTemplate.opsForValue().set(redisKey, storeOrder.getOrderId(),
|
||||
// ShopConstants.ORDER_OUTTIME_UNPAY, TimeUnit.MINUTES);
|
||||
//加入延时队列,30分钟自动取消
|
||||
try {
|
||||
RBlockingDeque<Object> blockingDeque = redissonClient.getBlockingDeque(ShopConstants.REDIS_ORDER_OUTTIME_UNPAY_QUEUE);
|
||||
RDelayedQueue<Object> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);
|
||||
delayedQueue.offer(orderSn, ShopConstants.ORDER_OUTTIME_UNPAY, TimeUnit.MINUTES);
|
||||
String s = TimeUnit.SECONDS.toSeconds(ShopConstants.ORDER_OUTTIME_UNPAY) + "分钟";
|
||||
log.info("添加延时队列成功 ,延迟时间:" + s);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
|
||||
OrderExtendDto orderDTO = new OrderExtendDto();
|
||||
orderDTO.setKey(key);
|
||||
@ -522,9 +552,21 @@ public class AppStoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper,Store
|
||||
*/
|
||||
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
|
||||
public void deStockIncSale(List<AppStoreCartQueryVo> cartInfo) {
|
||||
for (AppStoreCartQueryVo storeCartVO : cartInfo) {
|
||||
appStoreProductService.decProductStock(storeCartVO.getCartNum(), storeCartVO.getProductId(),
|
||||
storeCartVO.getProductAttrUnique(), 0L, "");
|
||||
log.info("========减库存增加销量start=========");
|
||||
//对库存加锁
|
||||
RLock lock = redissonClient.getLock(STOCK_LOCK_KEY);
|
||||
if (lock.tryLock()) {
|
||||
try {
|
||||
for (AppStoreCartQueryVo storeCartVO : cartInfo) {
|
||||
appStoreProductService.decProductStock(storeCartVO.getCartNum(), storeCartVO.getProductId(),
|
||||
storeCartVO.getProductAttrUnique(), 0L, "");
|
||||
}
|
||||
}catch (Exception ex) {
|
||||
log.error("[deStockIncSale][执行异常]", ex);
|
||||
throw exception(new ErrorCode(999999,ex.getMessage()));
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -714,7 +756,7 @@ public class AppStoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper,Store
|
||||
this.updateById(storeOrder);
|
||||
|
||||
//增加状态
|
||||
storeOrderStatusService.create(uid,order.getId(), OrderLogEnum.TAKE_ORDER_DELIVERY.getValue(), OrderLogEnum.TAKE_ORDER_DELIVERY.getDesc());
|
||||
storeOrderStatusService.create(order.getUid(),order.getId(), OrderLogEnum.TAKE_ORDER_DELIVERY.getValue(), OrderLogEnum.TAKE_ORDER_DELIVERY.getDesc());
|
||||
|
||||
//奖励积分
|
||||
this.gainUserIntegral(order);
|
||||
@ -817,6 +859,7 @@ public class AppStoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper,Store
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
|
||||
public void cancelOrder(String orderId, Long uid) {
|
||||
log.info("订单取消:({})",orderId);
|
||||
AppStoreOrderQueryVo order = this.getOrderInfo(orderId, uid);
|
||||
if (ObjectUtil.isNull(order)) {
|
||||
throw exception(STORE_ORDER_NOT_EXISTS);
|
||||
|
@ -1,19 +1,28 @@
|
||||
package co.yixiang.yshop.module.order.service.storeorder;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import co.yixiang.yshop.framework.common.enums.OrderInfoEnum;
|
||||
import co.yixiang.yshop.module.member.controller.app.user.vo.AppUserOrderCountVo;
|
||||
import co.yixiang.yshop.module.member.service.user.MemberUserService;
|
||||
import co.yixiang.yshop.module.order.controller.admin.storeorder.vo.ShoperOrderTimeDataVo;
|
||||
import co.yixiang.yshop.module.order.dal.dataobject.storeaftersales.StoreAfterSalesDO;
|
||||
import co.yixiang.yshop.module.order.dal.dataobject.storeorder.StoreOrderDO;
|
||||
import co.yixiang.yshop.module.order.dal.mysql.storeorder.StoreOrderMapper;
|
||||
import co.yixiang.yshop.module.order.dal.redis.order.AsyncCountRedisDAO;
|
||||
import co.yixiang.yshop.module.order.dal.redis.order.AsyncOrderRedisDAO;
|
||||
import co.yixiang.yshop.module.order.service.storeaftersales.AppStoreAfterSalesService;
|
||||
import co.yixiang.yshop.module.order.service.storeorder.dto.OrderTimeDataDto;
|
||||
import co.yixiang.yshop.module.product.service.storeproduct.StoreProductService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@ -23,6 +32,7 @@ import java.util.Objects;
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class AsynStoreOrderServiceImpl implements AsyncStoreOrderService {
|
||||
|
||||
@Resource
|
||||
@ -31,6 +41,12 @@ public class AsynStoreOrderServiceImpl implements AsyncStoreOrderService {
|
||||
private AppStoreAfterSalesService appStoreAfterSalesService;
|
||||
@Resource
|
||||
private AsyncOrderRedisDAO asyncOrderRedisDAO;
|
||||
@Resource
|
||||
private AsyncCountRedisDAO asyncCountRedisDAO;
|
||||
@Resource
|
||||
private MemberUserService userService;
|
||||
@Resource
|
||||
private StoreProductService productService;
|
||||
|
||||
/**
|
||||
* 获取某个用户的订单统计数据
|
||||
@ -41,6 +57,7 @@ public class AsynStoreOrderServiceImpl implements AsyncStoreOrderService {
|
||||
@Override
|
||||
@Async
|
||||
public void orderData(Long uid) {
|
||||
log.info("========获取某个用户的订单统计数据=========");
|
||||
//订单支付没有退款 数量
|
||||
LambdaQueryWrapper<StoreOrderDO> wrapperOne = new LambdaQueryWrapper<>();
|
||||
if (uid != null) {
|
||||
@ -103,15 +120,6 @@ public class AsynStoreOrderServiceImpl implements AsyncStoreOrderService {
|
||||
.eq(StoreOrderDO::getStatus, OrderInfoEnum.STATUS_3.getValue());
|
||||
Long completeCount = storeOrderMapper.selectCount(wrapperSix);
|
||||
|
||||
//订单退款
|
||||
// LambdaQueryWrapper<StoreOrderDO> wrapperSeven = new LambdaQueryWrapper<>();
|
||||
// if (uid != null) {
|
||||
// wrapperSeven.eq(StoreOrderDO::getUid, uid);
|
||||
// }
|
||||
// String[] strArr = {"1", "2"};
|
||||
// wrapperSeven.eq(StoreOrderDO::getPaid, OrderInfoEnum.PAY_STATUS_1.getValue())
|
||||
// .in(StoreOrderDO::getRefundStatus, Arrays.asList(strArr));
|
||||
// Long refundCount = storeOrderMapper.selectCount(wrapperSeven);
|
||||
//售后退款
|
||||
Long salesCount = appStoreAfterSalesService.lambdaQuery()
|
||||
.eq(Objects.nonNull(uid), StoreAfterSalesDO::getUserId, uid)
|
||||
@ -130,6 +138,91 @@ public class AsynStoreOrderServiceImpl implements AsyncStoreOrderService {
|
||||
|
||||
//存redis
|
||||
asyncOrderRedisDAO.set(appUserOrderCountVo,uid);
|
||||
|
||||
this.getOrderTimeData();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 首页订单/用户等统计
|
||||
*
|
||||
* @return OrderTimeDataDto
|
||||
*/
|
||||
@Async
|
||||
@Override
|
||||
public void getOrderTimeData() {
|
||||
OrderTimeDataDto orderTimeDataDto = new OrderTimeDataDto();
|
||||
|
||||
ShoperOrderTimeDataVo shoperOrderTimeData = this.getShoperOrderTimeData();
|
||||
|
||||
BeanUtil.copyProperties(shoperOrderTimeData, orderTimeDataDto);
|
||||
|
||||
|
||||
orderTimeDataDto.setUserCount(userService.count());
|
||||
orderTimeDataDto.setOrderCount(storeOrderMapper.selectCount());
|
||||
orderTimeDataDto.setPriceCount(storeOrderMapper.sumTotalPrice());
|
||||
orderTimeDataDto.setGoodsCount(productService.count());
|
||||
|
||||
asyncCountRedisDAO.set(orderTimeDataDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步后台统计
|
||||
*/
|
||||
public ShoperOrderTimeDataVo getShoperOrderTimeData() {
|
||||
|
||||
Date today = DateUtil.beginOfDay(new Date());
|
||||
Date yesterday = DateUtil.beginOfDay(DateUtil.yesterday());
|
||||
Date nowMonth = DateUtil.beginOfMonth(new Date());
|
||||
Date lastWeek = DateUtil.beginOfDay(DateUtil.lastWeek());
|
||||
|
||||
ShoperOrderTimeDataVo orderTimeDataVo = new ShoperOrderTimeDataVo();
|
||||
|
||||
//今日成交额
|
||||
LambdaQueryWrapper<StoreOrderDO> wrapperOne = new LambdaQueryWrapper<>();
|
||||
wrapperOne
|
||||
.ge(StoreOrderDO::getPayTime, today)
|
||||
.eq(StoreOrderDO::getPaid, OrderInfoEnum.PAY_STATUS_1.getValue())
|
||||
.eq(StoreOrderDO::getRefundStatus, OrderInfoEnum.REFUND_STATUS_0.getValue());
|
||||
orderTimeDataVo.setTodayPrice(storeOrderMapper.todayPrice(wrapperOne));
|
||||
//今日订单数
|
||||
orderTimeDataVo.setTodayCount(storeOrderMapper.selectCount(wrapperOne));
|
||||
|
||||
//昨日成交额
|
||||
LambdaQueryWrapper<StoreOrderDO> wrapperTwo = new LambdaQueryWrapper<>();
|
||||
wrapperTwo
|
||||
.lt(StoreOrderDO::getPayTime, today)
|
||||
.ge(StoreOrderDO::getPayTime, yesterday)
|
||||
.eq(StoreOrderDO::getPaid, OrderInfoEnum.PAY_STATUS_1.getValue())
|
||||
.eq(StoreOrderDO::getRefundStatus, OrderInfoEnum.REFUND_STATUS_0.getValue());
|
||||
orderTimeDataVo.setProPrice(storeOrderMapper.todayPrice(wrapperTwo));
|
||||
//昨日订单数
|
||||
orderTimeDataVo.setProCount(storeOrderMapper.selectCount(wrapperTwo));
|
||||
|
||||
//本月成交额
|
||||
LambdaQueryWrapper<StoreOrderDO> wrapperThree = new LambdaQueryWrapper<>();
|
||||
wrapperThree
|
||||
.ge(StoreOrderDO::getPayTime, nowMonth)
|
||||
.eq(StoreOrderDO::getPaid, OrderInfoEnum.PAY_STATUS_1.getValue())
|
||||
.eq(StoreOrderDO::getRefundStatus, OrderInfoEnum.REFUND_STATUS_0.getValue());
|
||||
orderTimeDataVo.setMonthPrice(storeOrderMapper.todayPrice(wrapperThree));
|
||||
//本月订单数
|
||||
orderTimeDataVo.setMonthCount(storeOrderMapper.selectCount(wrapperThree));
|
||||
|
||||
//上周成交额
|
||||
LambdaQueryWrapper<StoreOrderDO> wrapperLastWeek = new LambdaQueryWrapper<>();
|
||||
wrapperLastWeek
|
||||
.lt(StoreOrderDO::getPayTime, today)
|
||||
.ge(StoreOrderDO::getPayTime, lastWeek)
|
||||
.eq(StoreOrderDO::getPaid, OrderInfoEnum.PAY_STATUS_1.getValue())
|
||||
.eq(StoreOrderDO::getRefundStatus, OrderInfoEnum.REFUND_STATUS_0.getValue());
|
||||
orderTimeDataVo.setLastWeekPrice(storeOrderMapper.todayPrice(wrapperLastWeek));
|
||||
//上周订单数
|
||||
orderTimeDataVo.setLastWeekCount(storeOrderMapper.selectCount(wrapperLastWeek));
|
||||
|
||||
|
||||
return orderTimeDataVo;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
package co.yixiang.yshop.module.order.service.storeorder;
|
||||
|
||||
import co.yixiang.yshop.module.member.controller.app.user.vo.AppUserOrderCountVo;
|
||||
import co.yixiang.yshop.module.order.controller.admin.storeorder.vo.ShoperOrderTimeDataVo;
|
||||
import co.yixiang.yshop.module.order.service.storeorder.dto.OrderTimeDataDto;
|
||||
|
||||
/**
|
||||
* 异步订单 Service 接口
|
||||
@ -16,4 +18,11 @@ public interface AsyncStoreOrderService {
|
||||
*/
|
||||
void orderData(Long uid);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 异步后台数据统计
|
||||
*/
|
||||
void getOrderTimeData();
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package co.yixiang.yshop.module.order.service.storeorder;
|
||||
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import co.yixiang.yshop.framework.common.constant.ShopConstants;
|
||||
import co.yixiang.yshop.framework.common.enums.OrderInfoEnum;
|
||||
import co.yixiang.yshop.framework.common.enums.ShopCommonEnum;
|
||||
import co.yixiang.yshop.framework.common.exception.ErrorCode;
|
||||
@ -22,6 +23,9 @@ import co.yixiang.yshop.module.member.controller.admin.user.vo.UserRespVO;
|
||||
import co.yixiang.yshop.module.member.convert.user.UserConvert;
|
||||
import co.yixiang.yshop.module.member.dal.dataobject.user.MemberUserDO;
|
||||
import co.yixiang.yshop.module.member.dal.mysql.user.MemberUserMapper;
|
||||
import co.yixiang.yshop.module.member.service.user.MemberUserService;
|
||||
import co.yixiang.yshop.module.message.enums.WechatTempateEnum;
|
||||
import co.yixiang.yshop.module.message.mq.producer.WeixinNoticeProducer;
|
||||
import co.yixiang.yshop.module.order.controller.admin.storeorder.vo.*;
|
||||
import co.yixiang.yshop.module.order.controller.admin.storeorderelectronics.vo.StoreOrderElectronicsCreateReqVO;
|
||||
import co.yixiang.yshop.module.order.convert.storeorder.StoreOrderConvert;
|
||||
@ -29,6 +33,7 @@ import co.yixiang.yshop.module.order.dal.dataobject.storeorder.StoreOrderDO;
|
||||
import co.yixiang.yshop.module.order.dal.dataobject.storeordercartinfo.StoreOrderCartInfoDO;
|
||||
import co.yixiang.yshop.module.order.dal.mysql.storeorder.StoreOrderMapper;
|
||||
import co.yixiang.yshop.module.order.dal.mysql.storeordercartinfo.StoreOrderCartInfoMapper;
|
||||
import co.yixiang.yshop.module.order.enums.AppFromEnum;
|
||||
import co.yixiang.yshop.module.order.enums.OrderLogEnum;
|
||||
import co.yixiang.yshop.module.order.enums.UpdateOrderEnum;
|
||||
import co.yixiang.yshop.module.order.service.storeorderelectronics.StoreOrderElectronicsService;
|
||||
@ -36,6 +41,10 @@ import co.yixiang.yshop.module.order.service.storeorderstatus.StoreOrderStatusSe
|
||||
import co.yixiang.yshop.module.product.controller.app.cart.vo.AppStoreCartQueryVo;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.redisson.api.RBlockingDeque;
|
||||
import org.redisson.api.RDelayedQueue;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
@ -45,6 +54,7 @@ import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static co.yixiang.yshop.module.order.enums.ErrorCodeConstants.STORE_ORDER_NOT_EXISTS;
|
||||
@ -54,6 +64,7 @@ import static co.yixiang.yshop.module.order.enums.ErrorCodeConstants.STORE_ORDER
|
||||
*
|
||||
* @author yshop
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@Validated
|
||||
public class StoreOrderServiceImpl implements StoreOrderService {
|
||||
@ -76,6 +87,12 @@ public class StoreOrderServiceImpl implements StoreOrderService {
|
||||
private ExpressRedisDAO expressRedisDAO;
|
||||
@Resource
|
||||
private StoreOrderElectronicsService storeOrderElectronicsService;
|
||||
@Resource
|
||||
private MemberUserService userService;
|
||||
@Resource
|
||||
private WeixinNoticeProducer weixinNoticeProducer;
|
||||
@Resource
|
||||
private RedissonClient redissonClient;
|
||||
|
||||
@Override
|
||||
public Long createStoreOrder(StoreOrderCreateReqVO createReqVO) {
|
||||
@ -102,6 +119,32 @@ public class StoreOrderServiceImpl implements StoreOrderService {
|
||||
//增加状态
|
||||
storeOrderStatusService.create(updateObj.getUid(),updateObj.getId(), OrderLogEnum.DELIVERY_GOODS.getValue(),
|
||||
"已发货 快递公司:" + updateObj.getDeliveryName() + "快递单号:" + updateObj.getDeliveryId());
|
||||
|
||||
MemberUserDO userInfo = userService.getUser(updateObj.getUid());
|
||||
//发送消息队列进行推送消息
|
||||
if(userInfo.getLoginType().equals(AppFromEnum.ROUNTINE.getValue())){
|
||||
weixinNoticeProducer.sendNoticeMessage(updateObj.getUid(), WechatTempateEnum.DELIVERY_SUCCESS.getValue(),
|
||||
WechatTempateEnum.SUBSCRIBE.getValue(),updateObj.getOrderId(),
|
||||
updateObj.getPayPrice().toString(),"",updateObj.getDeliveryName(),
|
||||
updateObj.getDeliveryId());
|
||||
}else if(userInfo.getLoginType().equals(AppFromEnum.WECHAT.getValue())){
|
||||
weixinNoticeProducer.sendNoticeMessage(updateObj.getUid(),WechatTempateEnum.PAY_SUCCESS.getValue(),
|
||||
WechatTempateEnum.TEMPLATES.getValue(),updateObj.getOrderId(),
|
||||
updateObj.getPayPrice().toString(),"",updateObj.getDeliveryName(),
|
||||
updateObj.getDeliveryId());
|
||||
}
|
||||
|
||||
//延时队列 七天自动收货
|
||||
try {
|
||||
RBlockingDeque<Object> blockingDeque = redissonClient.getBlockingDeque(ShopConstants.REDIS_ORDER_OUTTIME_UNCONFIRM);
|
||||
RDelayedQueue<Object> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);
|
||||
delayedQueue.offer(updateReqVO.getOrderId(), ShopConstants.ORDER_OUTTIME_UNCONFIRM, TimeUnit.DAYS);
|
||||
String s = TimeUnit.SECONDS.toSeconds(ShopConstants.ORDER_OUTTIME_UNCONFIRM) + "天";
|
||||
log.info("添加延时队列成功 ,延迟时间:" + s);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ import co.yixiang.yshop.module.order.dal.mysql.storeordercartinfo.StoreOrderCart
|
||||
import co.yixiang.yshop.module.product.controller.app.cart.vo.AppStoreCartQueryVo;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@ -19,6 +21,7 @@ import java.util.List;
|
||||
*
|
||||
* @author yshop
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@Validated
|
||||
public class StoreOrderCartInfoServiceImpl extends ServiceImpl<StoreOrderCartInfoMapper, StoreOrderCartInfoDO> implements StoreOrderCartInfoService {
|
||||
@ -29,10 +32,11 @@ public class StoreOrderCartInfoServiceImpl extends ServiceImpl<StoreOrderCartInf
|
||||
* @param orderId
|
||||
* @param cartInfo 购物车信息
|
||||
*/
|
||||
@Async
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
|
||||
//@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
|
||||
public void saveCartInfo(Long oid, String orderId, List<AppStoreCartQueryVo> cartInfo) {
|
||||
|
||||
log.info("==========添加购物车商品信息start===========");
|
||||
List<StoreOrderCartInfoDO> list = new ArrayList<>();
|
||||
for (AppStoreCartQueryVo cart : cartInfo) {
|
||||
StoreOrderCartInfoDO info = new StoreOrderCartInfoDO();
|
||||
|
@ -31,22 +31,17 @@ public interface StoreProductMapper extends BaseMapperX<StoreProductDO> {
|
||||
.eqIfPresent(StoreProductDO::getIsPostage, reqVO.getIsPostage())
|
||||
.orderByDesc(StoreProductDO::getId);
|
||||
|
||||
//if(ShopCommonEnum.SHOW_1.getValue().equals(Convert.toInt(reqVO.getIsShow()))){
|
||||
wrapper.eq(StoreProductDO::getIsShow,Convert.toInt(reqVO.getIsShow()));
|
||||
// }
|
||||
wrapper.eq(StoreProductDO::getIsShow,Convert.toInt(reqVO.getIsShow()));
|
||||
if(DefaultEnum.DEFAULT_0.getValue().equals(Convert.toInt(reqVO.getStock()))){
|
||||
wrapper.eq(StoreProductDO::getStock,DefaultEnum.DEFAULT_0.getValue());
|
||||
}
|
||||
// CollUtil.isNotEmpty()
|
||||
|
||||
if(CollUtil.isNotEmpty(reqVO.getCatIds())){
|
||||
wrapper.in(StoreProductDO::getCateId,reqVO.getCatIds());
|
||||
}
|
||||
|
||||
return selectPage(reqVO, wrapper);
|
||||
// return selectPage(reqVO, new LambdaQueryWrapperX<StoreProductDO>()
|
||||
// .likeIfPresent(StoreProductDO::getStoreName, reqVO.getStoreName())
|
||||
// .eqIfPresent(StoreProductDO::getIsPostage, reqVO.getIsPostage())
|
||||
// .orderByDesc(StoreProductDO::getId));
|
||||
|
||||
}
|
||||
|
||||
default List<StoreProductDO> selectList(StoreProductExportReqVO reqVO) {
|
||||
@ -70,4 +65,14 @@ public interface StoreProductMapper extends BaseMapperX<StoreProductDO> {
|
||||
" where id=#{productId}")
|
||||
int incStockDecSales(@Param("num") Integer num,@Param("productId") Long productId);
|
||||
|
||||
/**
|
||||
* 正常商品库存 减库存 加销量
|
||||
* @param num
|
||||
* @param productId
|
||||
* @return
|
||||
*/
|
||||
@Update("update yshop_store_product set stock=stock-#{num}, sales=sales+#{num}" +
|
||||
" where id=#{productId} and stock >= #{num}")
|
||||
int decStockIncSales(@Param("num") Integer num,@Param("productId") Long productId);
|
||||
|
||||
}
|
||||
|
@ -122,7 +122,6 @@ public class AppStoreProductServiceImpl extends ServiceImpl<StoreProductMapper,S
|
||||
|
||||
LambdaQueryWrapper<StoreProductDO> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(StoreProductDO::getIsShow, ShopCommonEnum.SHOW_1.getValue());
|
||||
// wrapper.eq(YxStoreProduct::getIsIntegral, CommonEnum.SHOW_STATUS_1.getValue());
|
||||
|
||||
if(productQueryParam.getIsIntegral()!=null){
|
||||
wrapper.eq(StoreProductDO::getIsIntegral, productQueryParam.getIsIntegral());
|
||||
@ -281,41 +280,16 @@ public class AppStoreProductServiceImpl extends ServiceImpl<StoreProductMapper,S
|
||||
|
||||
|
||||
int res = 0;
|
||||
// if(ProductTypeEnum.COMBINATION.getValue().equals(type)){
|
||||
// res = yxStoreProductAttrValueMapper.decCombinationStockIncSales(num,productId,unique);
|
||||
// }else if(ProductTypeEnum.SECKILL.getValue().equals(type)){
|
||||
// res = yxStoreProductAttrValueMapper.decSeckillStockIncSales(num,productId,unique);
|
||||
// }else {
|
||||
res = storeProductAttrValueMapper.decStockIncSales(num,productId,unique);
|
||||
// }
|
||||
res = storeProductAttrValueMapper.decStockIncSales(num,productId,unique);
|
||||
|
||||
if(res == 0) {
|
||||
throw exception(PRODUCT_STOCK_LESS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// //处理属性sku
|
||||
// if (StrUtil.isNotEmpty(unique)) {
|
||||
// yxStoreProductAttrService.decProductAttrStock(num, productId, unique, type);
|
||||
// }
|
||||
// //先处理商品库存,活动商品也要处理,因为共享库存
|
||||
// int product = storeProductMapper.decStockIncSales(num, productId);
|
||||
// if (product == 0) {
|
||||
// throw new YshopException("共享商品库存不足");
|
||||
// }
|
||||
// //处理商品外层显示的库存
|
||||
// if (ProductTypeEnum.COMBINATION.getValue().equals(type)) {
|
||||
// int combinationRes = storeProductMapper.decCombinationStockIncSales(num, productId, activityId);
|
||||
// if (combinationRes == 0) {
|
||||
// throw new YshopException("拼团商品库存不足");
|
||||
// }
|
||||
// } else if (ProductTypeEnum.SECKILL.getValue().equals(type)) {
|
||||
// int seckillRes = storeProductMapper.decSeckillStockIncSales(num, productId, activityId);
|
||||
// if (seckillRes == 0) {
|
||||
// throw new YshopException("秒杀商品库存不足");
|
||||
// }
|
||||
// }
|
||||
int product = this.baseMapper.decStockIncSales(num, productId);
|
||||
if (product == 0) {
|
||||
throw exception(PRODUCT_STOCK_LESS);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -70,6 +70,11 @@
|
||||
<artifactId>yshop-spring-boot-starter-redis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>co.yixiang.boot</groupId>
|
||||
<artifactId>yshop-spring-boot-starter-desensitize</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 消息队列相关 -->
|
||||
<dependency>
|
||||
<groupId>co.yixiang.boot</groupId>
|
||||
@ -87,6 +92,7 @@
|
||||
<artifactId>yshop-spring-boot-starter-biz-ip</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- 工具类相关 -->
|
||||
</dependencies>
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package co.yixiang.yshop.module.member.controller.admin.useraddress.vo;
|
||||
|
||||
import co.yixiang.yshop.framework.desensitize.core.slider.annotation.MobileDesensitize;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
@ -22,6 +23,7 @@ public class UserAddressBaseVO {
|
||||
@NotNull(message = "收货人姓名不能为空")
|
||||
private String realName;
|
||||
|
||||
@MobileDesensitize
|
||||
@Schema(description = "收货人电话", required = true)
|
||||
@NotNull(message = "收货人电话不能为空")
|
||||
private String phone;
|
||||
|
@ -1,51 +0,0 @@
|
||||
### 请求 /login 接口 => 成功
|
||||
POST {{appApi}}/member/auth/login
|
||||
Content-Type: application/json
|
||||
tenant-id: {{appTenentId}}
|
||||
|
||||
{
|
||||
"mobile": "15601691300",
|
||||
"password": "admin123"
|
||||
}
|
||||
|
||||
### 请求 /send-sms-code 接口 => 成功
|
||||
POST {{appApi}}/member/auth/send-sms-code
|
||||
Content-Type: application/json
|
||||
tenant-id: {{appTenentId}}
|
||||
|
||||
{
|
||||
"mobile": "15601691399",
|
||||
"scene": 1
|
||||
}
|
||||
|
||||
### 请求 /sms-login 接口 => 成功
|
||||
POST {{appApi}}/member/auth/sms-login
|
||||
Content-Type: application/json
|
||||
tenant-id: {{appTenentId}}
|
||||
|
||||
{
|
||||
"mobile": "15601691301",
|
||||
"code": 9999
|
||||
}
|
||||
|
||||
### 请求 /weixin-mini-app-login 接口 => 成功
|
||||
POST {{appApi}}/member/auth/weixin-mini-app-login
|
||||
Content-Type: application/json
|
||||
tenant-id: {{appTenentId}}
|
||||
|
||||
{
|
||||
"phoneCode": "618e6412e0c728f5b8fc7164497463d0158a923c9e7fd86af8bba393b9decbc5",
|
||||
"loginCode": "001frTkl21JUf94VGxol2hSlff1frTkR"
|
||||
}
|
||||
|
||||
|
||||
### 请求 /logout 接口 => 成功
|
||||
POST {{appApi}}/member/auth/logout
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer c1b76bdaf2c146c581caa4d7fd81ee66
|
||||
tenant-id: {{appTenentId}}
|
||||
|
||||
### 请求 /auth/refresh-token 接口 => 成功
|
||||
POST {{appApi}}/member/auth/refresh-token?refreshToken=bc43d929094849a28b3a69f6e6940d70
|
||||
Content-Type: application/json
|
||||
tenant-id: {{appTenentId}}
|
@ -14,9 +14,6 @@ public class YshopServerApplication {
|
||||
public static void main(String[] args) {
|
||||
|
||||
SpringApplication.run(YshopServerApplication.class, args);
|
||||
// new SpringApplicationBuilder(YshopServerApplication.class)
|
||||
// .applicationStartup(new BufferingApplicationStartup(20480))
|
||||
// .run(args);
|
||||
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user