v3.0.0 springboot3+jdk17版本

This commit is contained in:
hupeng committed 2024-06-01 16:29:28 +08:00
1 parent 3aa2c942dc
commit b3ee447f8e
3676 files changed
+64366 -370384

No files matched your search

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>yshop</artifactId>
<groupId>co.yixiang.boot</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yshop-module-mall</artifactId>
<packaging>pom</packaging>
<name>${project.artifactId}</name>
<description>
商城大模块,由 product 商品、promotion 营销、trade 交易等组成
</description>
<modules>
<module>yshop-module-product-api</module>
<module>yshop-module-product-biz</module>
<module>yshop-module-shop-api</module>
<module>yshop-module-shop-biz</module>
<module>yshop-module-order-api</module>
<module>yshop-module-order-biz</module>
<module>yshop-module-store-api</module>
<module>yshop-module-store-biz</module>
</modules>
</project>
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>co.yixiang.boot</groupId>
<artifactId>yshop-module-mall</artifactId>
<version>${revision}</version>
</parent>
<artifactId>yshop-module-order-api</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>
order 模块 API,暴露给其它模块调用
</description>
<dependencies>
<dependency>
<groupId>co.yixiang.boot</groupId>
<artifactId>yshop-common</artifactId>
</dependency>
<!-- 参数校验 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,38 @@
/**
* Copyright (C) 2018-2022
* All rights reserved, Designed By www.yixiang.co
*/
package co.yixiang.yshop.module.order.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.stream.Stream;
/**
* @author hupeng
* 后台订单相关枚举
*/
@Getter
@AllArgsConstructor
public enum AdminAfterOrderStatusEnum {
STATUS_1(1,"售后中"),
STATUS_2(2,"已完成");
private Integer value;
private String desc;
public static AdminAfterOrderStatusEnum toType(int value) {
return Stream.of(AdminAfterOrderStatusEnum.values())
.filter(p -> p.value == value)
.findAny()
.orElse(null);
}
}
@@ -0,0 +1,43 @@
/**
* Copyright (C) 2018-2022
* All rights reserved, Designed By www.yixiang.co
*/
package co.yixiang.yshop.module.order.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.stream.Stream;
/**
* @author hupeng
* 后台订单相关枚举
*/
@Getter
@AllArgsConstructor
public enum AdminOrderStatusEnum {
STATUS_0(0,"未支付"),
STATUS_1(1,"未发货"),
STATUS_2(2,"待收货"),
STATUS_3(3,"待评价"),
STATUS_4(4,"交易完成"),
STATUS_5(5,"已退款"),
STATUS_6(6,"已删除");
private Integer value;
private String desc;
public static AdminOrderStatusEnum toType(int value) {
return Stream.of(AdminOrderStatusEnum.values())
.filter(p -> p.value == value)
.findAny()
.orElse(null);
}
}
@@ -0,0 +1,23 @@
package co.yixiang.yshop.module.order.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author hupeng
* 售后状态枚举
*/
@Getter
@AllArgsConstructor
public enum AfterChangeTypeEnum {
STATE_0(0,"售后订单生成"),
STATE_1(1,"后台审核成功"),
STATE_2(2,"用户发货"),
STATE_3(3,"打款"),
STATE_4(4,"审核失败"),
STATE_5(5,"用户撤销");
private Integer value;
private String desc;
}
@@ -0,0 +1,39 @@
/**
* Copyright (C) 2018-2022
* All rights reserved, Designed By www.yixiang.co
*/
package co.yixiang.yshop.module.order.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.stream.Stream;
/**
* 售后状态枚举
*
* @author hupeng
* @date 2023/6/23
*/
@Getter
@AllArgsConstructor
public enum AfterSalesStatusEnum {
STATUS_0(0,"已提交等待平台审核"),
STATUS_1(1,"平台已审核,等待用户发货/退款"),
STATUS_2(2,"用户已发货"),
STATUS_3(3,"已完成");
private Integer value;
private String desc;
public static AfterSalesStatusEnum toType(int value) {
return Stream.of(AfterSalesStatusEnum.values())
.filter(p -> p.value == value)
.findAny()
.orElse(null);
}
}
@@ -0,0 +1,20 @@
package co.yixiang.yshop.module.order.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author hupeng
* 售后状态枚举
*/
@Getter
@AllArgsConstructor
public enum AfterStatusEnum {
STATE_0(0,"正常"),
STATE_1(1,"用户取消"),
STATE_2(2,"商家拒绝");
private Integer value;
private String desc;
}
@@ -0,0 +1,21 @@
package co.yixiang.yshop.module.order.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author hupeng
* 售后类型枚举
*/
@Getter
@AllArgsConstructor
public enum AfterTypeEnum {
TYPE_1(1,"同意"),
TYPE_2(2,"拒绝"),
SERVICE_TYPE_0(0,"仅退款"),
SERVICE_TYPE_1(1,"退货退款");
private Integer value;
private String desc;
}
@@ -0,0 +1,32 @@
/**
* Copyright (C) 2018-2022
* All rights reserved, Designed By www.yixiang.co
*/
package co.yixiang.yshop.module.order.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author hupeng
* 应用来源相关枚举
*/
@Getter
@AllArgsConstructor
public enum AppFromEnum {
WEIXIN_H5("weixinh5","weixinh5"),
H5("h5","H5"),
WECHAT("wechat","公众号"),
APP("app","APP"),
PC("pc","PC"),
ROUNTINE("routine","小程序"),
UNIAPPH5("uniappH5","uniappH5");
private String value;
private String desc;
}
@@ -0,0 +1,42 @@
package co.yixiang.yshop.module.order.enums;
import co.yixiang.yshop.framework.common.exception.ErrorCode;
public interface ErrorCodeConstants {
// ========== 订单1008007000==========
ErrorCode STORE_ORDER_NOT_EXISTS = new ErrorCode(1008007000, "订单不存在");
ErrorCode STORE_ORDER_CART_INFO_NOT_EXISTS = new ErrorCode(1008007001, "订单购物详情不存在");
ErrorCode STORE_ORDER_STATUS_NOT_EXISTS = new ErrorCode(1008007002, "订单操作记录不存在");
ErrorCode STORE_AFTER_SALES_NOT_EXISTS = new ErrorCode(1008007003, "售后记录不存在");
ErrorCode STORE_AFTER_SALES_ITEM_NOT_EXISTS = new ErrorCode(1008007004, "售后子不存在");
ErrorCode STORE_AFTER_SALES_STATUS_NOT_EXISTS = new ErrorCode(1008007005, "售后订单操作详情不存在");
ErrorCode INVALID_PRODUCT = new ErrorCode(1008007005, "有失效的商品请重新提交");
ErrorCode VALID_PRODUCT_EMPTY = new ErrorCode(1008007005, "请提交购买的商品");
ErrorCode PARAM_ERROR = new ErrorCode(1008007006, "参数错误");
ErrorCode ORDER_EXPIRED = new ErrorCode(1008007007, "订单已过期,请刷新当前页面");
ErrorCode SELECT_ADDRESS = new ErrorCode(1008007008, "请选择收货地址");
ErrorCode ORDER_GEN_FAIL = new ErrorCode(1008007009, "订单生成失败");
ErrorCode ORDER_PAY_FINISH = new ErrorCode(1008007010, "该订单已支付");
ErrorCode PAY_YUE_NOT = new ErrorCode(1008007011, "余额不足");
ErrorCode ORDER_STATUS_ERROR = new ErrorCode(1008007012, "订单状态错误");
ErrorCode ORDER_STATUS_FINISH = new ErrorCode(1008007023, "订单已经完成,不要重复操作");
ErrorCode COMMENT_PRODUCT_NOT_EXISTS = new ErrorCode(1008007013, "评价产品不存在");
ErrorCode COMMENT_PRODUCT_IN_EXISTS = new ErrorCode(1008007014, "该产品已评价");
ErrorCode ORDER_NOT_DELETE = new ErrorCode(1008007018, "该订单无法删除");
ErrorCode ORDER_STATUS_NOT_EXPRESS_ = new ErrorCode(1008007015, "当前状态不能添加物流信息");
ErrorCode ORDER_REFUND_NOT = new ErrorCode(1008007017, "订单状态不能售后");
ErrorCode ORDER_NOT_REVOKE = new ErrorCode(1008007016, "订单不能撤销");
ErrorCode ORDER_NOT_CANCEL = new ErrorCode(1008007018, "订单不能取消");
ErrorCode ORDER_ADDRESS_REQUERED = new ErrorCode(1008007019, "请输入商家收货人信息");
ErrorCode ORDER_REFUNDING = new ErrorCode(1008007020, "正在申请退款中");
ErrorCode ORDER_REFUNDED = new ErrorCode(1008007021, "订单已退款");
ErrorCode ORDER_PRICE_ERROR = new ErrorCode(1008007022, "退款金额不正确");
// ========== 订单电子面单记录 ==========
ErrorCode STORE_ORDER_ELECTRONICS_NOT_EXISTS = new ErrorCode(1008010000, "订单电子面单记录不存在");
ErrorCode STORE_ORDER_DESK_NOT = new ErrorCode(1008007023, "当前桌号不存在");
}
@@ -0,0 +1,53 @@
package co.yixiang.yshop.module.order.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.stream.Stream;
/**
* @author hupeng
* 订单操作相关枚举
*/
@Getter
@AllArgsConstructor
public enum OrderLogEnum {
ORDER_TAKE_DESK("desk","扫码点餐"),
ORDER_TAKE_OUT("takeout","外卖"),
ORDER_TAKE_IN("takein","自取"),
PINK_ORDER_FAIL_1("ORDER_EXIST","订单生成失败,你已经参加该团了,请先支付订单"),
PINK_ORDER_FAIL_2("ORDER_EXIST","订单生成失败,你已经在该团内不能再参加了"),
REFUND_ORDER_SUCCESS("refund_price_success","退款成功"),
ORDER_EDIT("order_edit","订单改价"),
REMOVE_ORDER("remove_order","删除订单"),
EVAL_ORDER("order_eval","用户评价"),
REFUND_ORDER_APPLY("apply_refund","用户申请退款"),
TAKE_ORDER_DELIVERY("user_take_delivery","用户已收货"),
PAY_ORDER_FAIL("PAY_DEFICIENCY","余额不足"),
PAY_ORDER_SUCCESS("pay_success","用户付款成功"),
CREATE_ORDER_SUCCESS("SUCCESS","订单创建成功"),
CREATE_ORDER("yshop_create_order","订单生成"),
NONE_ORDER("NONE","订单OK"),
DELIVERY_GOODS("delivery_goods", "订单发货"),
OFFLINE_PAY("offline_pay", "线下支付"),
EXTEND_ORDER("EXTEND_ORDER","订单已生成");
private String value;
private String desc;
public static OrderLogEnum toType(String value) {
return Stream.of(OrderLogEnum.values())
.filter(p -> p.value.equals(value))
.findAny()
.orElse(null);
}
public static String getDesc(String value) {
return toType(value) == null ? null : toType(value).desc;
}
}
@@ -0,0 +1,44 @@
/**
* Copyright (C) 2018-2022
* All rights reserved, Designed By www.yixiang.co
*/
package co.yixiang.yshop.module.order.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.stream.Stream;
/**
* @author hupeng
* 订单相关枚举
*/
@Getter
@AllArgsConstructor
public enum OrderStatusEnum {
STATUS__1(-1,"全部订单"),
STATUS_0(0,"未支付"),
STATUS_1(1,"待发货"),
STATUS_2(2,"待收货"),
STATUS_3(3,"待评价"),
STATUS_4(4,"已完成"),
STATUS_MINUS_1(-1,"退款中"),
STATUS_MINUS_2(-2,"已退款"),
STATUS_MINUS_3(-3,"退款");
private Integer value;
private String desc;
public static OrderStatusEnum toType(int value) {
return Stream.of(OrderStatusEnum.values())
.filter(p -> p.value == value)
.findAny()
.orElse(null);
}
}
@@ -0,0 +1,38 @@
/**
* Copyright (C) 2018-2022
* All rights reserved, Designed By www.yixiang.co
*/
package co.yixiang.yshop.module.order.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.stream.Stream;
/**
* @author hupeng
* 支付相关枚举
*/
@Getter
@AllArgsConstructor
public enum PayTypeEnum {
ALI("alipay","支付宝支付"),
WEIXIN("weixin","微信支付"),
YUE("yue","余额支付"),
INTEGRAL("integral","积分兑换");
private String value;
private String desc;
public static PayTypeEnum toType(String value) {
return Stream.of(PayTypeEnum.values())
.filter(p -> p.value.equals(value))
.findAny()
.orElse(null);
}
}
@@ -0,0 +1,20 @@
package co.yixiang.yshop.module.order.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author hupeng
* 运费模板类型枚举
*/
@Getter
@AllArgsConstructor
public enum ShippingTempEnum {
TYPE_1(1,"按件数"),
TYPE_2(2,"按重量"),
TYPE_3(3,"按体积");
private Integer value;
private String desc;
}
@@ -0,0 +1,29 @@
/**
* Copyright (C) 2018-2022
* All rights reserved, Designed By www.yixiang.co
*/
package co.yixiang.yshop.module.order.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author hupeng
* 应用来源相关枚举
*/
@Getter
@AllArgsConstructor
public enum UpdateOrderEnum {
UPDATE_ORDER("updateOrder","修改订单"),
ORDER_SEND("orderSend","订单发货"),
RMARK("remark","备注"),
SEND_INFO("sendInfo","配送信息");
private String value;
private String desc;
}
@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>co.yixiang.boot</groupId>
<artifactId>yshop-module-mall</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yshop-module-order-biz</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>
order 模块,主要实现商品购物车相关功能
</description>
<dependencies>
<dependency>
<groupId>co.yixiang.boot</groupId>
<artifactId>yshop-module-order-api</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>co.yixiang.boot</groupId>
<artifactId>yshop-module-pay-biz</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>co.yixiang.boot</groupId>
<artifactId>yshop-module-message-biz</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>co.yixiang.boot</groupId>
<artifactId>yshop-module-product-biz</artifactId>
<version>${revision}</version>
</dependency>
<!-- 业务组件 -->
<!-- <dependency>-->
<!-- <groupId>co.yixiang.boot</groupId>-->
<!-- <artifactId>yshop-spring-boot-starter-biz-operatelog</artifactId>-->
<!-- </dependency>-->
<!-- Web 相关 -->
<dependency>
<groupId>co.yixiang.boot</groupId>
<artifactId>yshop-spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>co.yixiang.boot</groupId>
<artifactId>yshop-spring-boot-starter-security</artifactId>
</dependency>
<!-- DB 相关 -->
<dependency>
<groupId>co.yixiang.boot</groupId>
<artifactId>yshop-spring-boot-starter-mybatis</artifactId>
</dependency>
<!-- Test 测试相关 -->
<dependency>
<groupId>co.yixiang.boot</groupId>
<artifactId>yshop-spring-boot-starter-test</artifactId>
</dependency>
<!-- 工具类相关 -->
<dependency>
<groupId>co.yixiang.boot</groupId>
<artifactId>yshop-spring-boot-starter-excel</artifactId>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,161 @@
package co.yixiang.yshop.module.order.controller.admin.storeorder;
import co.yixiang.yshop.framework.common.pojo.CommonResult;
import co.yixiang.yshop.framework.common.pojo.PageResult;
import co.yixiang.yshop.framework.excel.core.util.ExcelUtils;
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;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import static co.yixiang.yshop.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 订单")
@RestController
@RequestMapping("/order/store-order")
@Validated
public class StoreOrderController {
@Resource
private StoreOrderService storeOrderService;
@Resource
private StoreOrderStatusService storeOrderStatusService;
@Resource
private AsyncCountRedisDAO asyncCountRedisDAO;
@Resource
private AsyncStoreOrderService asyncStoreOrderService;
@PostMapping("/create")
@Operation(summary = "创建订单")
@PreAuthorize("@ss.hasPermission('order:store-order:create')")
public CommonResult<Long> createStoreOrder(@Valid @RequestBody StoreOrderCreateReqVO createReqVO) {
return success(storeOrderService.createStoreOrder(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新订单")
@PreAuthorize("@ss.hasPermission('order:store-order:update')")
public CommonResult<Boolean> updateStoreOrder(@Valid @RequestBody StoreOrderUpdateReqVO updateReqVO) {
storeOrderService.updateStoreOrder(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除订单")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('order:store-order:delete')")
public CommonResult<Boolean> deleteStoreOrder(@RequestParam("id") Long id) {
storeOrderService.deleteStoreOrder(id);
return success(true);
}
@GetMapping("/pay")
@Operation(summary = "订单线下支付")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('order:store-order:delete')")
public CommonResult<Boolean> payStoreOrder(@RequestParam("id") Long id) {
storeOrderService.payStoreOrder(id);
return success(true);
}
@GetMapping("/take")
@Operation(summary = "确认收货")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('order:store-order:delete')")
public CommonResult<Boolean> takeStoreOrder(@RequestParam("id") Long id) {
storeOrderService.takeStoreOrder(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得订单")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('order:store-order:query')")
public CommonResult<StoreOrderRespVO> getStoreOrder(@RequestParam("id") Long id) {
return success(storeOrderService.getStoreOrder(id));
}
@GetMapping("/list")
@Operation(summary = "获得订单列表")
@Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
@PreAuthorize("@ss.hasPermission('order:store-order:query')")
public CommonResult<List<StoreOrderRespVO>> getStoreOrderList(@RequestParam("ids") Collection<Long> ids) {
List<StoreOrderDO> list = storeOrderService.getStoreOrderList(ids);
return success(StoreOrderConvert.INSTANCE.convertList(list));
}
@GetMapping("/page")
@Operation(summary = "获得订单分页")
@PreAuthorize("@ss.hasPermission('order:store-order:query')")
public CommonResult<PageResult<StoreOrderRespVO>> getStoreOrderPage(@Valid StoreOrderPageReqVO pageVO) {
return success(storeOrderService.getStoreOrderPage(pageVO));
}
@GetMapping("/record-list")
@Operation(summary = "获得订单记录列表")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('order:store-order:query')")
public CommonResult<List<StoreOrderStatusDO>> getStoreOrderRecordList(@RequestParam("id") Long id) {
List<StoreOrderStatusDO> list = storeOrderStatusService.list(new LambdaQueryWrapper<StoreOrderStatusDO>()
.eq(StoreOrderStatusDO::getOid,id));
return success(list);
}
@GetMapping("/export-excel")
@Operation(summary = "导出订单 Excel")
@PreAuthorize("@ss.hasPermission('order:store-order:export')")
public void exportStoreOrderExcel(@Valid StoreOrderExportReqVO exportReqVO,
HttpServletResponse response) throws IOException {
List<StoreOrderDO> list = storeOrderService.getStoreOrderList(exportReqVO);
// 导出 Excel
List<StoreOrderExcelVO> datas = StoreOrderConvert.INSTANCE.convertList02(list);
ExcelUtils.write(response, "订单.xls", "数据", StoreOrderExcelVO.class, datas);
}
@GetMapping("/count")
@Operation(summary = "获得订单统计")
public CommonResult<OrderTimeDataDto> getStoreOrderCount() {
asyncStoreOrderService.getOrderTimeData();
return success(asyncCountRedisDAO.get());
}
@Operation(summary = "退款")
@PostMapping(value = "/refund")
@PreAuthorize("@ss.hasPermission('order:store-order:update')")
public CommonResult<Boolean> refund(@Validated @RequestBody StoreOrderRefundVO updateReqVO) {
storeOrderService.orderRefund(updateReqVO.getId(),updateReqVO.getPayPrice(), 0, null);
return success(true);
}
@Operation(summary = "订单通知")
@GetMapping(value = "/notice")
public CommonResult<Long> refund() {
return success(storeOrderService.orderNotice());
}
}
@@ -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;
}
@@ -0,0 +1,239 @@
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;
import jakarta.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import static co.yixiang.yshop.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 订单 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class StoreOrderBaseVO {
@Schema(description = "订单号", required = true, example = "20527")
@NotNull(message = "订单号不能为空")
private String orderId;
@Schema(description = "额外订单号", example = "12452")
private String extendOrderId;
@Schema(description = "用户id", required = true, example = "8323")
@NotNull(message = "用户id不能为空")
private Long uid;
@Schema(description = "用户姓名", required = true, example = "张三")
//@NotNull(message = "用户姓名不能为空")
private String realName;
//@MobileDesensitize
@Schema(description = "用户电话", required = true)
//@NotNull(message = "用户电话不能为空")
private String userPhone;
@Schema(description = "详细地址", required = true)
// @NotNull(message = "详细地址不能为空")
private String userAddress;
@Schema(description = "购物车id", required = true, example = "23301")
//@NotNull(message = "购物车id不能为空")
private String cartId;
@Schema(description = "运费金额", required = true, example = "637")
//@NotNull(message = "运费金额不能为空")
private BigDecimal freightPrice;
@Schema(description = "订单商品总数", required = true)
//@NotNull(message = "订单商品总数不能为空")
private Integer totalNum;
@Schema(description = "订单总价", required = true, example = "31659")
//@NotNull(message = "订单总价不能为空")
private BigDecimal totalPrice;
@Schema(description = "邮费", required = true)
// @NotNull(message = "邮费不能为空")
private BigDecimal totalPostage;
@Schema(description = "实际支付金额", required = true, example = "19682")
// @NotNull(message = "实际支付金额不能为空")
private BigDecimal payPrice;
@Schema(description = "支付邮费", required = true)
//@NotNull(message = "支付邮费不能为空")
private BigDecimal payPostage;
@Schema(description = "抵扣金额", required = true, example = "16463")
//@NotNull(message = "抵扣金额不能为空")
private BigDecimal deductionPrice;
@Schema(description = "优惠券id", required = true, example = "3299")
//@NotNull(message = "优惠券id不能为空")
private Integer couponId;
@Schema(description = "优惠券金额", required = true, example = "22157")
//@NotNull(message = "优惠券金额不能为空")
private BigDecimal couponPrice;
@Schema(description = "支付状态", required = true, example = "11728")
//@NotNull(message = "支付状态不能为空")
private Integer paid;
@Schema(description = "支付时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime payTime;
@Schema(description = "支付方式", required = true, example = "2")
//@NotNull(message = "支付方式不能为空")
private String payType;
@Schema(description = "订单状态(-1 : 申请退款 -2 : 退货成功 0:待发货;1:待收货;2:已收货;3:已完成;-1:已退款)", required = true, example = "1")
//@NotNull(message = "订单状态(-1 : 申请退款 -2 : 退货成功 0:待发货;1:待收货;2:已收货;3:已完成;-1:已退款)不能为空")
private Integer status;
@Schema(description = "0 未退款 1 申请中 2 已退款", required = true, example = "2")
//@NotNull(message = "0 未退款 1 申请中 2 已退款不能为空")
private Integer refundStatus;
@Schema(description = "退款图片")
private String refundReasonWapImg;
@Schema(description = "退款用户说明")
private String refundReasonWapExplain;
@Schema(description = "退款时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime refundReasonTime;
@Schema(description = "前台退款原因")
private String refundReasonWap;
@Schema(description = "不退款的理由", example = "不喜欢")
private String refundReason;
@Schema(description = "退款金额", required = true, example = "7547")
//@NotNull(message = "退款金额不能为空")
private BigDecimal refundPrice;
@Schema(description = "快递公司编号")
private String deliverySn;
@Schema(description = "快递名称/送货人姓名", example = "张三")
private String deliveryName;
@Schema(description = "发货类型", example = "1")
private String deliveryType;
@Schema(description = "快递单号/手机号", example = "24798")
private String deliveryId;
@Schema(description = "消费赚取积分", required = true)
//@NotNull(message = "消费赚取积分不能为空")
private BigDecimal gainIntegral;
@Schema(description = "使用积分", required = true)
//@NotNull(message = "使用积分不能为空")
private BigDecimal useIntegral;
@Schema(description = "实际支付积分", required = true)
//@NotNull(message = "实际支付积分不能为空")
private BigDecimal payIntegral;
@Schema(description = "给用户退了多少积分")
private BigDecimal backIntegral;
@Schema(description = "备注", required = true)
//@NotNull(message = "备注不能为空")
private String mark;
@Schema(description = "唯一id(md5加密)类似id", required = true)
//@NotNull(message = "唯一id(md5加密)类似id不能为空")
private String unique;
@Schema(description = "管理员备注", example = "随便")
private String remark;
@Schema(description = "商户ID", required = true, example = "8499")
//@NotNull(message = "商户ID不能为空")
private Integer merId;
@Schema(description = "拼团产品id0一般产品", example = "3865")
private Long combinationId;
@Schema(description = "拼团id 0没有拼团", required = true, example = "8463")
//@NotNull(message = "拼团id 0没有拼团不能为空")
private Long pinkId;
@Schema(description = "成本价", required = true)
//@NotNull(message = "成本价不能为空")
private BigDecimal cost;
@Schema(description = "秒杀产品ID", required = true, example = "21525")
//@NotNull(message = "秒杀产品ID不能为空")
private Long seckillId;
@Schema(description = "砍价id", example = "5132")
private Integer bargainId;
@Schema(description = "核销码", required = true)
//@NotNull(message = "核销码不能为空")
private String verifyCode;
@Schema(description = "门店id", required = true, example = "12064")
//@NotNull(message = "门店id不能为空")
private Integer storeId;
@Schema(description = "配送方式 1=快递 ,2=门店自提", required = true, example = "2")
//@NotNull(message = "配送方式 1=快递 ,2=门店自提不能为空")
private Integer shippingType;
@Schema(description = "支付渠道(0微信公众号1微信小程序)")
private Integer isChannel;
@Schema(description = "系统删除")
private Integer isSystemDel;
@Schema(description = "订单类型")
private String orderType;
/**
* 取餐👌
*/
private Long numberId;
/**
* 门店ID
*/
private Long shopId;
/**
* 门店名称
*/
private String shopName;
private LocalDateTime getTime;
/**
* 桌面ID
*/
private Long deskId;
/**
* 桌号
*/
private String deskNumber;
/**
* 就餐人数
*/
private Integer deskPeople;
}
@@ -0,0 +1,14 @@
package co.yixiang.yshop.module.order.controller.admin.storeorder.vo;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.*;
@Schema(description = "管理后台 - 订单创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class StoreOrderCreateReqVO extends StoreOrderBaseVO {
}
@@ -0,0 +1,187 @@
package co.yixiang.yshop.module.order.controller.admin.storeorder.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.ExcelProperty;
/**
* 订单 Excel VO
*
* @author yshop
*/
@Data
public class StoreOrderExcelVO {
@ExcelProperty("订单ID")
private Long id;
@ExcelProperty("订单号")
private String orderId;
@ExcelProperty("额外订单号")
private String extendOrderId;
@ExcelProperty("用户id")
private Long uid;
@ExcelProperty("用户姓名")
private String realName;
@ExcelProperty("用户电话")
private String userPhone;
@ExcelProperty("详细地址")
private String userAddress;
@ExcelProperty("购物车id")
private String cartId;
@ExcelProperty("运费金额")
private BigDecimal freightPrice;
@ExcelProperty("订单商品总数")
private Integer totalNum;
@ExcelProperty("订单总价")
private BigDecimal totalPrice;
@ExcelProperty("邮费")
private BigDecimal totalPostage;
@ExcelProperty("实际支付金额")
private BigDecimal payPrice;
@ExcelProperty("支付邮费")
private BigDecimal payPostage;
@ExcelProperty("抵扣金额")
private BigDecimal deductionPrice;
@ExcelProperty("优惠券id")
private Integer couponId;
@ExcelProperty("优惠券金额")
private BigDecimal couponPrice;
@ExcelProperty("支付状态")
private Integer paid;
@ExcelProperty("支付时间")
private LocalDateTime payTime;
@ExcelProperty("支付方式")
private String payType;
@ExcelProperty("订单状态(-1 : 申请退款 -2 : 退货成功 0:待发货;1:待收货;2:已收货;3:已完成;-1:已退款)")
private Integer status;
@ExcelProperty("0 未退款 1 申请中 2 已退款")
private Integer refundStatus;
@ExcelProperty("退款图片")
private String refundReasonWapImg;
@ExcelProperty("退款用户说明")
private String refundReasonWapExplain;
@ExcelProperty("退款时间")
private LocalDateTime refundReasonTime;
@ExcelProperty("前台退款原因")
private String refundReasonWap;
@ExcelProperty("不退款的理由")
private String refundReason;
@ExcelProperty("退款金额")
private BigDecimal refundPrice;
@ExcelProperty("快递公司编号")
private String deliverySn;
@ExcelProperty("快递名称/送货人姓名")
private String deliveryName;
@ExcelProperty("发货类型")
private String deliveryType;
@ExcelProperty("快递单号/手机号")
private String deliveryId;
@ExcelProperty("消费赚取积分")
private BigDecimal gainIntegral;
@ExcelProperty("使用积分")
private BigDecimal useIntegral;
@ExcelProperty("实际支付积分")
private BigDecimal payIntegral;
@ExcelProperty("给用户退了多少积分")
private BigDecimal backIntegral;
@ExcelProperty("备注")
private String mark;
@ExcelProperty("唯一id(md5加密)类似id")
private String unique;
@ExcelProperty("管理员备注")
private String remark;
@ExcelProperty("商户ID")
private Integer merId;
@ExcelProperty("拼团产品id0一般产品")
private Long combinationId;
@ExcelProperty("拼团id 0没有拼团")
private Long pinkId;
@ExcelProperty("成本价")
private BigDecimal cost;
@ExcelProperty("秒杀产品ID")
private Long seckillId;
@ExcelProperty("砍价id")
private Integer bargainId;
@ExcelProperty("核销码")
private String verifyCode;
@ExcelProperty("门店id")
private Integer storeId;
@ExcelProperty("配送方式 1=快递 ,2=门店自提")
private Integer shippingType;
@ExcelProperty("支付渠道(0微信公众号1微信小程序)")
private Integer isChannel;
@ExcelProperty("系统删除")
private Integer isSystemDel;
@ExcelProperty("添加时间")
private LocalDateTime createTime;
}
@@ -0,0 +1,171 @@
package co.yixiang.yshop.module.order.controller.admin.storeorder.vo;
import lombok.*;
import java.math.BigDecimal;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import co.yixiang.yshop.framework.common.pojo.PageParam;
import java.time.LocalDateTime;
import org.springframework.format.annotation.DateTimeFormat;
import static co.yixiang.yshop.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 订单 Excel 导出 Request VO,参数和 StoreOrderPageReqVO 是一致的")
@Data
public class StoreOrderExportReqVO {
@Schema(description = "订单号", example = "20527")
private String orderId;
@Schema(description = "额外订单号", example = "12452")
private String extendOrderId;
@Schema(description = "用户id", example = "8323")
private Long uid;
@Schema(description = "用户姓名", example = "张三")
private String realName;
@Schema(description = "用户电话")
private String userPhone;
@Schema(description = "详细地址")
private String userAddress;
@Schema(description = "购物车id", example = "23301")
private String cartId;
@Schema(description = "运费金额", example = "637")
private BigDecimal freightPrice;
@Schema(description = "订单商品总数")
private Integer totalNum;
@Schema(description = "订单总价", example = "31659")
private BigDecimal totalPrice;
@Schema(description = "邮费")
private BigDecimal totalPostage;
@Schema(description = "实际支付金额", example = "19682")
private BigDecimal payPrice;
@Schema(description = "支付邮费")
private BigDecimal payPostage;
@Schema(description = "抵扣金额", example = "16463")
private BigDecimal deductionPrice;
@Schema(description = "优惠券id", example = "3299")
private Integer couponId;
@Schema(description = "优惠券金额", example = "22157")
private BigDecimal couponPrice;
@Schema(description = "支付状态", example = "11728")
private Integer paid;
@Schema(description = "支付时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] payTime;
@Schema(description = "支付方式", example = "2")
private String payType;
@Schema(description = "订单状态(-1 : 申请退款 -2 : 退货成功 0:待发货;1:待收货;2:已收货;3:已完成;-1:已退款)", example = "1")
private Integer status;
@Schema(description = "0 未退款 1 申请中 2 已退款", example = "2")
private Integer refundStatus;
@Schema(description = "退款图片")
private String refundReasonWapImg;
@Schema(description = "退款用户说明")
private String refundReasonWapExplain;
@Schema(description = "退款时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] refundReasonTime;
@Schema(description = "前台退款原因")
private String refundReasonWap;
@Schema(description = "不退款的理由", example = "不喜欢")
private String refundReason;
@Schema(description = "退款金额", example = "7547")
private BigDecimal refundPrice;
@Schema(description = "快递公司编号")
private String deliverySn;
@Schema(description = "快递名称/送货人姓名", example = "张三")
private String deliveryName;
@Schema(description = "发货类型", example = "1")
private String deliveryType;
@Schema(description = "快递单号/手机号", example = "24798")
private String deliveryId;
@Schema(description = "消费赚取积分")
private BigDecimal gainIntegral;
@Schema(description = "使用积分")
private BigDecimal useIntegral;
@Schema(description = "实际支付积分")
private BigDecimal payIntegral;
@Schema(description = "给用户退了多少积分")
private BigDecimal backIntegral;
@Schema(description = "备注")
private String mark;
@Schema(description = "唯一id(md5加密)类似id")
private String unique;
@Schema(description = "管理员备注", example = "随便")
private String remark;
@Schema(description = "商户ID", example = "8499")
private Integer merId;
@Schema(description = "拼团产品id0一般产品", example = "3865")
private Long combinationId;
@Schema(description = "拼团id 0没有拼团", example = "8463")
private Long pinkId;
@Schema(description = "成本价")
private BigDecimal cost;
@Schema(description = "秒杀产品ID", example = "21525")
private Long seckillId;
@Schema(description = "砍价id", example = "5132")
private Integer bargainId;
@Schema(description = "核销码")
private String verifyCode;
@Schema(description = "门店id", example = "12064")
private Integer storeId;
@Schema(description = "配送方式 1=快递 ,2=门店自提", example = "2")
private Integer shippingType;
@Schema(description = "支付渠道(0微信公众号1微信小程序)")
private Integer isChannel;
@Schema(description = "系统删除")
private Integer isSystemDel;
@Schema(description = "添加时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}
@@ -0,0 +1,54 @@
package co.yixiang.yshop.module.order.controller.admin.storeorder.vo;
import lombok.*;
import java.math.BigDecimal;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import co.yixiang.yshop.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static co.yixiang.yshop.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 订单分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class StoreOrderPageReqVO extends PageParam {
@Schema(description = "取餐号", example = "20527")
private String numberId;
@Schema(description = "订单号", example = "20527")
private String orderId;
@Schema(description = "用户姓名", example = "张三")
private String realName;
@Schema(description = "用户电话")
private String userPhone;
@Schema(description = "添加时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
@Schema(description = "订单状态搜索值")
private Integer orderStatus;
@Schema(description = "支付状态搜索值")
private String payStatus;
@Schema(description = "工作台订单还是普通订单")
private String type;
@Schema(description = "店铺ID", example = "20527")
private String ShopId;
@Schema(description = "订单类型", example = "desk")
private String orderType;
@Schema(description = "桌面id")
private Integer deskId;
}
@@ -0,0 +1,24 @@
package co.yixiang.yshop.module.order.controller.admin.storeorder.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import jakarta.validation.constraints.NotNull;
import java.math.BigDecimal;
@Schema(description = "管理后台 - 订单退款 Request VO")
@Data
@ToString(callSuper = true)
public class StoreOrderRefundVO {
@Schema(description = "订单ID", required = true, example = "31716")
@NotNull(message = "订单ID不能为空")
private Long id;
@Schema(description = "退款金额", required = true, example = "31716")
@NotNull(message = "退款金额不能为空")
private BigDecimal payPrice;
}
@@ -0,0 +1,33 @@
package co.yixiang.yshop.module.order.controller.admin.storeorder.vo;
import co.yixiang.yshop.module.member.controller.admin.user.vo.UserRespVO;
import co.yixiang.yshop.module.order.dal.dataobject.storeordercartinfo.StoreOrderCartInfoDO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 订单 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class StoreOrderRespVO extends StoreOrderBaseVO {
@Schema(description = "订单ID", required = true, example = "31716")
private Long id;
@Schema(description = "添加时间", required = true)
private LocalDateTime createTime;
@Schema(description = "用户信息", required = true)
private UserRespVO userRespVO;
@Schema(description = "商品信息", required = true)
private List<StoreOrderCartInfoDO> storeOrderCartInfoDOList;
@Schema(description = "订单状态", required = true)
private String StatusStr;
}
@@ -0,0 +1,27 @@
package co.yixiang.yshop.module.order.controller.admin.storeorder.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import jakarta.validation.constraints.*;
@Schema(description = "管理后台 - 订单更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class StoreOrderUpdateReqVO extends StoreOrderBaseVO {
@Schema(description = "订单ID", required = true, example = "31716")
@NotNull(message = "订单ID不能为空")
private Long id;
/**
* updateOrder: '修改订单',
* orderSend: '订单发货',
* remark: '备注',
* sendInfo: '配送信息',
*/
@Schema(description = "更新类型", required = true, example = "31716")
private String updateType;
}
@@ -0,0 +1,241 @@
/**
* Copyright (C) 2018-2022
* All rights reserved, Designed By www.yixiang.co
* 注意:
* 本软件为www.yixiang.co开发研制,未经购买不得使用
* 购买后可获得全部源代码(禁止转卖、分享、上传到码云、github等开源平台)
* 一经发现盗用、分享等行为,将追究法律责任,后果自负
*/
package co.yixiang.yshop.module.order.controller.app.order;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import co.yixiang.yshop.framework.common.enums.OrderInfoEnum;
import co.yixiang.yshop.framework.common.pojo.CommonResult;
import co.yixiang.yshop.framework.security.core.annotations.PreAuthenticated;
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.AppStoreOrderQueryVo;
import co.yixiang.yshop.module.order.dal.dataobject.storeorder.StoreOrderDO;
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.http.HttpRequestNoticeNewParams;
import co.yixiang.yshop.module.store.controller.app.storeshop.vo.AppStoreShopVO;
import co.yixiang.yshop.module.store.convert.storeshop.StoreShopConvert;
import co.yixiang.yshop.module.store.dal.dataobject.storeshop.StoreShopDO;
import co.yixiang.yshop.module.store.service.storeshop.AppStoreShopService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.egzosn.pay.spring.boot.core.PayServiceManager;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
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;
import static co.yixiang.yshop.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static co.yixiang.yshop.module.order.enums.ErrorCodeConstants.PARAM_ERROR;
import static co.yixiang.yshop.module.order.enums.ErrorCodeConstants.STORE_ORDER_NOT_EXISTS;
/**
* <p>
* 订单控制器
* </p>
*
* @author hupeng
* @since 2023-6-23
*/
@Slf4j
@RestController
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Tag(name = "用户 APP - 订单模块")
@RequestMapping("/order")
public class AppOrderController {
private final AppStoreOrderService appStoreOrderService;
private final AsyncOrderRedisDAO asyncOrderRedisDAO;
private final PayServiceManager manager;
private final AppStoreShopService appStoreShopService;
;
/**
* 订单创建
*/
@PreAuthenticated
@PostMapping("/create")
@Operation(summary = "订单创建")
public CommonResult<Map<String, Object>> create(@RequestBody @Valid AppOrderParam param) {
Long uid = getLoginUserId();
return success(appStoreOrderService.createOrder(uid, param));
}
/**
* 订单支付
*/
@PreAuthenticated
@PostMapping(value = "/pay")
@Operation(summary = "订单支付")
public CommonResult<Map<String, Object>> pay(@RequestBody @Valid AppPayParam param) {
Long uid = getLoginUserId();
return success(appStoreOrderService.pay(uid,param));
}
/**
* 支付回调地址
*
* @param request 请求
* @param detailsId 列表id
* @return 支付是否成功
*/
@RequestMapping(value = "/notify/payBack{detailsId}.json")
public String payBack(HttpServletRequest request, @PathVariable String detailsId) {
return manager.payBack(detailsId, new HttpRequestNoticeNewParams(request));
}
/**
* 订单列表
*/
@PreAuthenticated
@GetMapping("/list")
@Operation(summary = "订单列表")
@Parameters({
@Parameter(name = "type", description = "商品状态,-1全部 默认为0未支付 1待发货 2待收货 3待评价 4已完成 5退款中 6已退款 7退款",
required = true, example = "1"),
@Parameter(name = "page", description = "页码,默认为1",
required = true, example = "1"),
@Parameter(name = "limit", description = "页大小,默认为10",
required = true, example = "10 ")
})
public CommonResult<List<AppStoreOrderQueryVo>> orderList(@RequestParam(value = "type", defaultValue = "0") int type,
@RequestParam(value = "page", defaultValue = "1") int page,
@RequestParam(value = "limit", defaultValue = "10") int limit) {
Long uid = getLoginUserId();
return success(appStoreOrderService.orderList(uid, type, page, limit));
}
/**
* 订单详情
*/
@PreAuthenticated
@GetMapping("/detail/{key}")
@Operation(summary = "订单详情")
@Parameter(name = "key", description = "唯一的uni值或者订单号", required = true, example = "10 ")
public CommonResult<AppStoreOrderQueryVo> detail(@PathVariable String key) {
Long uid = getLoginUserId();
if (StrUtil.isEmpty(key)) {
throw exception(PARAM_ERROR);
}
AppStoreOrderQueryVo storeOrder = appStoreOrderService.getOrderInfo(key, uid);
if (ObjectUtil.isNull(storeOrder)) {
throw exception(STORE_ORDER_NOT_EXISTS);
}
return success(appStoreOrderService.handleOrder(storeOrder));
}
/**
* 订单收货
*/
@PreAuthenticated
@PostMapping("/take")
@Operation(summary = "订单收货")
public CommonResult<Boolean> orderTake(@RequestBody @Validated AppDoOrderParam param) {
Long uid = getLoginUserId();
appStoreOrderService.takeOrder(param.getUni(), uid);
return success(true);
}
/**
* 订单退款审核
*/
@PostMapping("/refund")
@Operation(summary = "订单退款审核")
public CommonResult<Boolean> refundVerify(@RequestBody AppRefundParam param) {
Long uid = getLoginUserId();
appStoreOrderService.orderApplyRefund(param.getRefundReasonWapExplain(),
param.getRefundReasonWapImg(),
param.getText(),
param.getUni(), uid);
return success(true);
}
/**
* 订单删除
*/
@PreAuthenticated
@PostMapping("/del")
@Operation(summary = "订单删除")
public CommonResult<Boolean> orderDel(@Validated @RequestBody AppDoOrderParam param) {
Long uid = getLoginUserId();
appStoreOrderService.removeOrder(param.getUni(), uid);
return success(true);
}
/**
* 订单取消 未支付的订单回退积分,回退优惠券,回退库存
*/
@PreAuthenticated
@PostMapping("/cancel")
@Operation(summary = "订单取消")
public CommonResult<Boolean> cancelOrder(@Validated @RequestBody AppHandleOrderParam param) {
Long uid = getLoginUserId();
appStoreOrderService.cancelOrder(param.getId(), uid);
return success(true);
}
/**
* 个人中心订单统计
*/
@PreAuthenticated
@PostMapping("/user_count")
@Operation(summary = "个人中心订单统计")
public CommonResult<AppUserOrderCountVo> countOrder() {
Long uid = getLoginUserId();
AppUserOrderCountVo appUserOrderCountVo = asyncOrderRedisDAO.get(uid);
return success(appUserOrderCountVo);
}
@PreAuthenticated
@GetMapping("/getShop")
@Operation(summary = "获取店铺")
public CommonResult<AppStoreShopVO> getShop(@RequestParam("shopId") Integer shopId) {
StoreShopDO storeShopDO = appStoreShopService.getById(shopId);
AppStoreShopVO appStoreShopVO = StoreShopConvert.INSTANCE.convert02(storeShopDO);
appStoreShopVO.setIsEmpty(true);
return success(appStoreShopVO);
}
}
@@ -0,0 +1,39 @@
package co.yixiang.yshop.module.order.controller.app.order.param;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
/**
* @ClassName ComputeOrderParam
* @Author hupeng <610796224@qq.com>
* @Date 2023/6/19
**/
@Getter
@Setter
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AppComputeOrderParam {
@Schema(description = "地址ID", required = true)
private String addressId;
@Schema(description = "优惠券ID", required = true)
private String couponId;
@Schema(description = "支付方式", required = true)
private String payType;
@Schema(description = "使用积分 1-表示使用", required = true)
private String useIntegral;
@Schema(description = "配送方式 1=快递 ,2=门店自提", required = true)
private String shippingType;
@Schema(description = "拼团ID", required = true)
private String pinkId;
@Schema(description = "拼团产品ID", required = true)
private String combinationId;
}
@@ -0,0 +1,21 @@
package co.yixiang.yshop.module.order.controller.app.order.param;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import jakarta.validation.constraints.NotBlank;
/**
* @ClassName 确认订单ConfirmOrderDTO
* @Author hupeng <610796224@qq.com>
* @Date 2023/6/18
**/
@Getter
@Setter
public class AppConfirmOrderParam {
@NotBlank(message = "请提交购买的商品")
@Schema(description = "购物车ID", required = true)
private String cartId;
}
@@ -0,0 +1,20 @@
package co.yixiang.yshop.module.order.controller.app.order.param;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import jakarta.validation.constraints.NotBlank;
/**
* @ClassName HandleOrderParam
* @Author hupeng <610796224@qq.com>
* @Date 2023/6/21
**/
@Getter
@Setter
public class AppDoOrderParam {
@NotBlank(message = "参数有误")
@Schema(description = "订单ID", required = true)
private String uni;
}
@@ -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;
}
@@ -0,0 +1,21 @@
package co.yixiang.yshop.module.order.controller.app.order.param;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import jakarta.validation.constraints.NotBlank;
/**
* @ClassName HandleOrderParam
* @Author hupeng <610796224@qq.com>
* @Date 2023/6/23
**/
@Getter
@Setter
public class AppHandleOrderParam {
@NotBlank(message = "参数有误")
@Schema(description = "订单ID", required = true)
private String id;
}
@@ -0,0 +1,64 @@
package co.yixiang.yshop.module.order.controller.app.order.param;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import jakarta.validation.constraints.Size;
import java.io.Serializable;
import java.util.List;
/**
* @ClassName OrderParam
* @Author hupeng <610796224@qq.com>
* @Date 2023/8/22
**/
@Data
public class AppOrderParam implements Serializable {
@Schema(description = "地址ID", required = true)
private String addressId;
@Schema(description = "门店ID", required = true)
private String shopId;
@Schema(description = "手机号", required = true)
private String mobile;
@Schema(description = "优惠券ID", required = true)
private String couponId;
@Schema(description = "购买类型:takein=自取,takeout=外卖,desk=扫码点餐", required = true)
private String orderType;
@Size(max = 200,message = "长度超过了限制")
@Schema(description = "备注", required = true)
private String remark;
@Schema(description = "取餐时间", required = true)
private Integer gettime;
@Schema(description = "秒杀产品ID", required = true)
private List<String> productId;
@Schema(description = "规格", required = true)
private List<String> spec;
@Schema(description = "数量", required = true)
private List<String> number;
@Schema(description = "支付类型", required = true)
private String payType;
@Schema(description = "桌面ID", required = true)
private Long deskId;
@Schema(description = "桌号", required = true)
private String deskNumber;
@Schema(description = "就餐人数", required = true)
private Integer deskPeople;
@Schema(description = "订单号", required = true)
private String orderId;
}
@@ -0,0 +1,30 @@
package co.yixiang.yshop.module.order.controller.app.order.param;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* @ClassName PayDto
* @Author hupeng <610796224@qq.com>
* @Date 2013/6/20
**/
@Data
public class AppPayParam implements Serializable {
@Schema(description = "来源", required = true)
private String from;
@NotBlank(message = "选择支付类型 PayTypeEnum类型(alipay weixin yue)")
@Schema(description = "支付类型", required = true)
private String paytype;
@NotBlank(message = "参数错误")
@Schema(description = "订单ID", required = true)
private String uni;
// @Schema(description = "服务商id 当不是余额支付必填1-阿里支付 3-微信支付 这里当编号与数据库id对应", required = true)
// private String detailsId;
}
@@ -0,0 +1,38 @@
package co.yixiang.yshop.module.order.controller.app.order.param;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
/**
* @ClassName ProductReplyParam
* @Author hupeng <610796224@qq.com>
* @Date 2023/6/20
**/
@Getter
@Setter
public class AppProductReplyParam {
@NotBlank(message = "评论不能为空")
@Size(min = 1, max = 200,message = "长度超过了限制")
@Schema(description = "商品评论内容", required = true)
private String comment;
@Schema(description = "商品评论图片地址", required = true)
private String pics;
@NotBlank(message = "请为商品评分")
@Schema(description = "商品评分", required = true)
private String productScore;
@NotBlank(message = "请为商品评分")
@Schema(description = "服务评分", required = true)
private String serviceScore;
@NotBlank(message = "参数有误")
@Schema(description = "参数有误", required = true)
private String unique;
}
@@ -0,0 +1,30 @@
package co.yixiang.yshop.module.order.controller.app.order.param;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* @ClassName RefundParam
* @Author hupeng <610796224@qq.com>
* @Date 2023/6/23
**/
@Data
public class AppRefundParam implements Serializable {
@Schema(description = "退款备注", required = true)
private String refundReasonWapExplain;
@Schema(description = "退款图片", required = true)
private String refundReasonWapImg;
@NotBlank(message = "请填写退款原因")
@Schema(description = "退款原因", required = true)
private String text;
@NotBlank(message = "参数错误")
@Schema(description = "订单号", required = true)
private String uni;
}
@@ -0,0 +1,44 @@
package co.yixiang.yshop.module.order.controller.app.order.vo;
import co.yixiang.yshop.framework.common.serializer.BigDecimalSerializer;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @ClassName ComputeVo
* @Author hupeng <610796224@qq.com>
* @Date 2019/10/27
**/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AppComputeVo implements Serializable {
@JsonSerialize(using = BigDecimalSerializer.class)
private BigDecimal couponPrice;
@JsonSerialize(using = BigDecimalSerializer.class)
private BigDecimal deductionPrice;
@JsonSerialize(using = BigDecimalSerializer.class)
private BigDecimal payPostage;
@JsonSerialize(using = BigDecimalSerializer.class)
private BigDecimal payPrice;
@JsonSerialize(using = BigDecimalSerializer.class)
private BigDecimal totalPrice;
private Double usedIntegral; //使用了多少积分
@JsonSerialize(using = BigDecimalSerializer.class)
private BigDecimal payIntegral;
}
@@ -0,0 +1,63 @@
package co.yixiang.yshop.module.order.controller.app.order.vo;
import co.yixiang.yshop.module.member.controller.app.user.vo.AppUserQueryVo;
import co.yixiang.yshop.module.member.dal.dataobject.useraddress.UserAddressDO;
import co.yixiang.yshop.module.order.service.storeorder.dto.PriceGroupDto;
import co.yixiang.yshop.module.product.controller.app.cart.vo.AppStoreCartQueryVo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
* @ClassName ConfirmOrderVo
* @Author hupeng <610796224@qq.com>
* @Date 2023/6/18
**/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Schema(description = "用户 APP - 订单确认参数参数")
public class AppConfirmOrderVo implements Serializable {
//地址信息
private UserAddressDO addressInfo;
//砍价id
private Integer bargainId;
private Integer combinationId;
//优惠券减
private Boolean deduction;
private Boolean enableIntegral;
private Double enableIntegralNum;
//积分抵扣
private Integer integralRatio;
private String orderKey;
private PriceGroupDto priceGroup;
private Integer seckillId;
//店铺自提
private Integer storeSelfMention;
// private StoreCouponUserVo usableCoupon;
private AppUserQueryVo userInfo;
}
@@ -0,0 +1,210 @@
package co.yixiang.yshop.module.order.controller.app.order.vo;
import co.yixiang.yshop.module.order.dal.dataobject.storeordercartinfo.StoreOrderCartInfoDO;
import co.yixiang.yshop.module.order.service.storeorder.dto.StatusDto;
import co.yixiang.yshop.module.product.controller.app.cart.vo.AppStoreCartQueryVo;
import co.yixiang.yshop.module.store.controller.app.storeshop.vo.AppStoreShopVO;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
/**
* <p>
* 订单表 查询结果对象
* </p>
*
* @author hupeng
* @date 2023-6-19
*/
@Data
@Schema(description = "用户 APP - 订单表查询参数")
public class AppStoreOrderQueryVo implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "订单ID", required = true)
private Long id;
@Schema(description = "订单号", required = true)
private String orderId;
private String extendOrderId;
@Schema(description = "用户id", required = true)
private Long uid;
@Schema(description = "用户姓名", required = true)
private String realName;
@Schema(description = "用户电话", required = true)
private String userPhone;
@Schema(description = "详细地址", required = true)
private String userAddress;
@Schema(description = "购物车id", required = true)
private String cartId;
@Schema(description = "购物车信息", required = true)
private List<StoreOrderCartInfoDO> cartInfo;
@Schema(description = "订单信息合集", required = true)
private StatusDto statusDto;
@Schema(description = "运费金额", required = true)
private BigDecimal freightPrice;
@Schema(description = "订单商品总数", required = true)
private Integer totalNum;
@Schema(description = "订单总价", required = true)
private BigDecimal totalPrice;
@Schema(description = "邮费", required = true)
private BigDecimal totalPostage;
@Schema(description = "实际支付金额", required = true)
private BigDecimal payPrice;
@Schema(description = "实际支付积分", required = true)
private BigDecimal payIntegral;
@Schema(description = "支付邮费", required = true)
private BigDecimal payPostage;
@Schema(description = "抵扣金额", required = true)
private BigDecimal deductionPrice;
@Schema(description = "优惠券id", required = true)
private Integer couponId;
@Schema(description = "优惠券金额", required = true)
private BigDecimal couponPrice;
@Schema(description = "支付状态", required = true)
private Integer paid;
@Schema(description = "支付时间", required = true)
private LocalDateTime payTime;
@Schema(description = "支付方式", required = true)
private String payType;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
@Schema(description = "创建时间", required = true)
private LocalDateTime createTime;
@Schema(description = "订单状态(-1 : 申请退款 -2 : 退货成功 0:待发货;1:待收货;2:已收货;3:待评价;-1:已退款", required = true)
private Integer status;
@Schema(description = "0 未退款 1 申请中 2 已退款", required = true)
private Integer refundStatus;
@Schema(description = "退款图片", required = true)
private String refundReasonWapImg;
@Schema(description = "退款用户说明", required = true)
private String refundReasonWapExplain;
@Schema(description = "退款时间", required = true)
private LocalDateTime refundReasonTime;
@Schema(description = "前台退款原因", required = true)
private String refundReasonWap;
@Schema(description = "不退款的理由", required = true)
private String refundReason;
@Schema(description = "退款金额", required = true)
private BigDecimal refundPrice;
@Schema(description = "快递名称/送货人姓名", required = true)
private String deliveryName;
@Schema(description = "快递公司编号", required = true)
private String deliverySn;
@Schema(description = "发货类型", required = true)
private String deliveryType;
@Schema(description = "快递单号/手机号", required = true)
private String deliveryId;
@Schema(description = "发货时间", required = true)
private LocalDateTime deliveryTime;
@Schema(description = "消费赚取积分", required = true)
private BigDecimal gainIntegral;
@Schema(description = "使用积分", required = true)
private BigDecimal useIntegral;
@Schema(description = "给用户退了多少积分", required = true)
private BigDecimal backIntegral;
@Schema(description = "备注", required = true)
private String mark;
@Schema(description = "确认订单返回的key", required = true)
private String unique;
@Schema(description = "管理员备注", required = true)
private String remark;
@Schema(description = "拼团产品id0一般产品", required = true)
private Long combinationId;
@Schema(description = "拼团id 0没有拼团", required = true)
private Long pinkId;
@Schema(description = "成本价", required = true)
private BigDecimal cost;
@Schema(description = "秒杀产品ID", required = true)
private Long seckillId;
@Schema(description = "配送方式 1=快递 ,2=门店自提\"", required = true)
private Integer shippingType;
@Schema(description = "取餐时间", required = true)
private LocalDateTime getTime;
@Schema(description = "取餐号", required = true)
private Integer numberId;
@Schema(description = "购买类型:takein=自取,takeout=外卖", required = true)
private String orderType;
@Schema(description = "门店", required = true)
private AppStoreShopVO shop;
@Schema(description = "门店id", required = true)
private Long shopId;
@Schema(description = "前面等等的制作数量", required = true)
private Long preNum;
@Schema(description = "店铺名称", required = true)
private String shopName;
@Schema(description = "桌面ID", required = true)
private Long deskId;
@Schema(description = "桌号", required = true)
private String deskNumber;
@Schema(description = "就餐人数", required = true)
private Integer deskPeople;
}
@@ -0,0 +1,39 @@
package co.yixiang.yshop.module.order.convert.storeorder;
import java.util.*;
import co.yixiang.yshop.framework.common.pojo.PageResult;
import co.yixiang.yshop.module.order.controller.app.order.vo.AppStoreOrderQueryVo;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import co.yixiang.yshop.module.order.controller.admin.storeorder.vo.*;
import co.yixiang.yshop.module.order.dal.dataobject.storeorder.StoreOrderDO;
/**
* 订单 Convert
*
* @author yshop
*/
@Mapper
public interface StoreOrderConvert {
StoreOrderConvert INSTANCE = Mappers.getMapper(StoreOrderConvert.class);
StoreOrderDO convert(StoreOrderCreateReqVO bean);
StoreOrderDO convert(StoreOrderUpdateReqVO bean);
StoreOrderRespVO convert(StoreOrderDO bean);
AppStoreOrderQueryVo convert1(StoreOrderDO bean);
List<StoreOrderRespVO> convertList(List<StoreOrderDO> list);
List<AppStoreOrderQueryVo> convertList01(List<StoreOrderDO> list);
PageResult<StoreOrderRespVO> convertPage(PageResult<StoreOrderDO> page);
List<StoreOrderExcelVO> convertList02(List<StoreOrderDO> list);
}
@@ -0,0 +1,16 @@
package co.yixiang.yshop.module.order.convert.storeordercartinfo;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* 订单购物详情 Convert
*
* @author yshop
*/
@Mapper
public interface StoreOrderCartInfoConvert {
StoreOrderCartInfoConvert INSTANCE = Mappers.getMapper(StoreOrderCartInfoConvert.class);
}
@@ -0,0 +1,17 @@
package co.yixiang.yshop.module.order.convert.storeorderstatus;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* 订单操作记录 Convert
*
* @author yshop
*/
@Mapper
public interface StoreOrderStatusConvert {
StoreOrderStatusConvert INSTANCE = Mappers.getMapper(StoreOrderStatusConvert.class);
}
@@ -0,0 +1,37 @@
package co.yixiang.yshop.module.order.dal.dataobject.ordernumber;
import co.yixiang.yshop.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 订单 DO
*
* @author yshop
*/
@TableName("yshop_order_number")
@KeySequence("yshop_order_number_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class OrderNumberDO {
/**
* ID
*/
private Long id;
/**
* 订单号
*/
private String orderId;
}
@@ -0,0 +1,276 @@
package co.yixiang.yshop.module.order.dal.dataobject.storeorder;
import lombok.*;
import java.util.*;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import co.yixiang.yshop.framework.mybatis.core.dataobject.BaseDO;
/**
* 订单 DO
*
* @author yshop
*/
@TableName("yshop_store_order")
@KeySequence("yshop_store_order_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class StoreOrderDO extends BaseDO {
/**
* 订单ID
*/
@TableId
private Long id;
/**
* 订单号
*/
private String orderId;
/**
* 额外订单号
*/
private String extendOrderId;
/**
* 用户id
*/
private Long uid;
/**
* 用户姓名
*/
private String realName;
/**
* 用户电话
*/
private String userPhone;
/**
* 详细地址
*/
private String userAddress;
/**
* 购物车id
*/
private String cartId;
/**
* 运费金额
*/
private BigDecimal freightPrice;
/**
* 订单商品总数
*/
private Integer totalNum;
/**
* 订单总价
*/
private BigDecimal totalPrice;
/**
* 邮费
*/
private BigDecimal totalPostage;
/**
* 实际支付金额
*/
private BigDecimal payPrice;
/**
* 支付邮费
*/
private BigDecimal payPostage;
/**
* 抵扣金额
*/
private BigDecimal deductionPrice;
/**
* 优惠券id
*/
private Integer couponId;
/**
* 优惠券金额
*/
private BigDecimal couponPrice;
/**
* 支付状态
*/
private Integer paid;
/**
* 支付时间
*/
private LocalDateTime payTime;
/**
* 支付方式
*/
private String payType;
/**
* 订单类型 购买类型:takein=自取,takeout=外卖
*/
private String orderType;
/**
* 订单状态(-1 : 申请退款 -2 : 退货成功 0:待发货;1:待收货;2:已收货;3:已完成;-1:已退款)
*/
private Integer status;
/**
* 0 未退款 1 申请中 2 已退款
*/
private Integer refundStatus;
/**
* 退款图片
*/
private String refundReasonWapImg;
/**
* 退款用户说明
*/
private String refundReasonWapExplain;
/**
* 退款时间
*/
private LocalDateTime refundReasonTime;
/**
* 前台退款原因
*/
private String refundReasonWap;
/**
* 不退款的理由
*/
private String refundReason;
/**
* 退款金额
*/
private BigDecimal refundPrice;
/**
* 快递公司编号
*/
private String deliverySn;
/**
* 快递名称/送货人姓名
*/
private String deliveryName;
/**
* 发货类型
*/
private String deliveryType;
/**
* 快递单号/手机号
*/
private String deliveryId;
/**
* 发货时间
*/
private LocalDateTime deliveryTime;
/**
* 消费赚取积分
*/
private BigDecimal gainIntegral;
/**
* 使用积分
*/
private BigDecimal useIntegral;
/**
* 实际支付积分
*/
private BigDecimal payIntegral;
/**
* 给用户退了多少积分
*/
private BigDecimal backIntegral;
/**
* 备注
*/
private String mark;
/**
* 唯一id(md5加密)类似id
*/
@TableField(value = "`unique`")
private String unique;
/**
* 管理员备注
*/
private String remark;
/**
* 商户ID
*/
private Integer merId;
/**
* 拼团产品id0一般产品
*/
private Long combinationId;
/**
* 拼团id 0没有拼团
*/
private Long pinkId;
/**
* 成本价
*/
private BigDecimal cost;
/**
* 秒杀产品ID
*/
private Long seckillId;
/**
* 砍价id
*/
private Integer bargainId;
/**
* 核销码
*/
private String verifyCode;
/**
* 门店id
*/
private Integer storeId;
/**
* 配送方式 1=快递 ,2=门店自提
*/
private Integer shippingType;
/**
* 支付渠道(0微信公众号1微信小程序)
*/
private Integer isChannel;
/**
* 系统删除
*/
private Integer isSystemDel;
/**
* 门店ID
*/
private Long shopId;
/**
* 门店名称
*/
private String shopName;
/**
* 取餐时间
*/
private LocalDateTime getTime;
/**
* 取餐👌
*/
private Long numberId;
}
@@ -0,0 +1,87 @@
package co.yixiang.yshop.module.order.dal.dataobject.storeordercartinfo;
import lombok.*;
import java.math.BigDecimal;
import java.util.*;
import com.baomidou.mybatisplus.annotation.*;
import co.yixiang.yshop.framework.mybatis.core.dataobject.BaseDO;
/**
* 订单购物详情 DO
*
* @author yshop
*/
@TableName("yshop_store_order_cart_info")
@KeySequence("yshop_store_order_cart_info_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class StoreOrderCartInfoDO {
/**
* id
*/
@TableId
private Long id;
/**
* 订单id
*/
private Long oid;
/**
* 订单号
*/
private String orderId;
/**
* 购物车id
*/
private Long cartId;
/**
* 商品ID
*/
private Long productId;
/**
* 购买东西的详细信息
*/
private String cartInfo;
/**
* 唯一id
*/
@TableField(value = "`unique`")
private String unique;
/**
* 是否能售后0不能1能
*/
private Integer isAfterSales;
/**
* 商品名称
*/
private String title;
/**
* 商品图片
*/
private String image;
/**
* 数量
*/
private Integer number;
/**
* 规格
*/
private String spec;
/**
* 价格
*/
private BigDecimal price;
}
@@ -0,0 +1,45 @@
package co.yixiang.yshop.module.order.dal.dataobject.storeorderstatus;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import co.yixiang.yshop.framework.mybatis.core.dataobject.BaseDO;
/**
* 订单操作记录 DO
*
* @author yshop
*/
@TableName("yshop_store_order_status")
@KeySequence("yshop_store_order_status_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class StoreOrderStatusDO {
/**
* id
*/
@TableId
private Long id;
/**
* 订单id
*/
private Long oid;
/**
* 操作类型
*/
private String changeType;
/**
* 操作备注
*/
private String changeMessage;
/**
* 操作时间
*/
private LocalDateTime changeTime;
}
@@ -0,0 +1,15 @@
package co.yixiang.yshop.module.order.dal.mysql.ordernumber;
import co.yixiang.yshop.framework.mybatis.core.mapper.BaseMapperX;
import co.yixiang.yshop.module.order.dal.dataobject.ordernumber.OrderNumberDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 订单 Mapper
*
* @author yshop
*/
@Mapper
public interface OrderNumberMapper extends BaseMapperX<OrderNumberDO> {
}
@@ -0,0 +1,130 @@
package co.yixiang.yshop.module.order.dal.mysql.storeorder;
import java.util.*;
import cn.hutool.core.util.StrUtil;
import co.yixiang.yshop.framework.common.enums.OrderInfoEnum;
import co.yixiang.yshop.framework.common.enums.ShopCommonEnum;
import co.yixiang.yshop.framework.common.pojo.PageResult;
import co.yixiang.yshop.framework.mybatis.core.query.LambdaQueryWrapperX;
import co.yixiang.yshop.framework.mybatis.core.mapper.BaseMapperX;
import co.yixiang.yshop.framework.security.core.util.SecurityFrameworkUtils;
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.OrderLogEnum;
import co.yixiang.yshop.framework.common.enums.OrderTypeEnum;
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;
import org.apache.ibatis.annotations.Select;
/**
* 订单 Mapper
*
* @author yshop
*/
@Mapper
public interface StoreOrderMapper extends BaseMapperX<StoreOrderDO> {
default PageResult<StoreOrderDO> selectPage(StoreOrderPageReqVO reqVO) {
LambdaQueryWrapperX<StoreOrderDO> wrapper = new LambdaQueryWrapperX();
Long shopId = SecurityFrameworkUtils.getLoginUser().getShopId();
if(shopId > 0) {
wrapper.eq(StoreOrderDO::getShopId,shopId);
}
wrapper.eqIfPresent(StoreOrderDO::getOrderId, reqVO.getOrderId())
.eqIfPresent(StoreOrderDO::getNumberId, reqVO.getNumberId())
.eqIfPresent(StoreOrderDO::getShopId, reqVO.getShopId())
.likeIfPresent(StoreOrderDO::getRealName, reqVO.getRealName())
.eqIfPresent(StoreOrderDO::getUserPhone, reqVO.getUserPhone())
.eqIfPresent(StoreOrderDO::getOrderType,reqVO.getOrderType())
.betweenIfPresent(StoreOrderDO::getCreateTime, reqVO.getCreateTime());
//.orderByDesc(StoreOrderDO::getId);
if( OrderTypeEnum.TYPE_WORK.getValue().equals(reqVO.getType())){
wrapper.orderByAsc(StoreOrderDO::getCreateTime);
}else{
wrapper.orderByDesc(StoreOrderDO::getCreateTime);
}
if (reqVO.getOrderStatus() != null) {
switch (AdminOrderStatusEnum.toType(reqVO.getOrderStatus())) {
//未支付
case STATUS_0:
wrapper.eq(StoreOrderDO::getPaid, OrderInfoEnum.PAY_STATUS_0.getValue())
.eq(StoreOrderDO::getRefundStatus, OrderInfoEnum.REFUND_STATUS_0.getValue())
.eq(StoreOrderDO::getStatus, OrderInfoEnum.STATUS_0.getValue());
break;
//待发货
case STATUS_1:
wrapper.eq(StoreOrderDO::getRefundStatus, OrderInfoEnum.REFUND_STATUS_0.getValue())
.eq(StoreOrderDO::getStatus, OrderInfoEnum.STATUS_0.getValue());
if( OrderTypeEnum.TYPE_WORK.getValue().equals(reqVO.getType())){
wrapper.and(i->i.eq(StoreOrderDO::getPaid, OrderInfoEnum.PAY_STATUS_1.getValue())
.or(j->j.eq(StoreOrderDO::getOrderType, OrderLogEnum.ORDER_TAKE_DESK.getValue())
.eq(StoreOrderDO::getPaid, OrderInfoEnum.PAY_STATUS_0.getValue())));
}else {
wrapper.eq(StoreOrderDO::getPaid, OrderInfoEnum.PAY_STATUS_1.getValue());
}
break;
//待收货
case STATUS_2:
wrapper.eq(StoreOrderDO::getPaid, OrderInfoEnum.PAY_STATUS_1.getValue())
.eq(StoreOrderDO::getRefundStatus, OrderInfoEnum.REFUND_STATUS_0.getValue())
.eq(StoreOrderDO::getStatus, OrderInfoEnum.STATUS_1.getValue());
break;
//待评价
case STATUS_3:
wrapper.eq(StoreOrderDO::getPaid, OrderInfoEnum.PAY_STATUS_1.getValue())
.eq(StoreOrderDO::getRefundStatus, OrderInfoEnum.REFUND_STATUS_0.getValue())
.eq(StoreOrderDO::getStatus, OrderInfoEnum.STATUS_2.getValue());
break;
//已完成
case STATUS_4:
wrapper.eq(StoreOrderDO::getPaid, OrderInfoEnum.PAY_STATUS_1.getValue())
.eq(StoreOrderDO::getRefundStatus, OrderInfoEnum.REFUND_STATUS_0.getValue())
.eq(StoreOrderDO::getStatus, OrderInfoEnum.STATUS_3.getValue());
break;
//退款单
case STATUS_5:
String[] strs = {"1", "2"};
wrapper.in(StoreOrderDO::getRefundStatus, strs);
break;
//已删除
case STATUS_6:
wrapper.eq(StoreOrderDO::getIsSystemDel, ShopCommonEnum.DELETE_1.getValue());
break;
default:
}
}
if (StrUtil.isNotEmpty(reqVO.getPayStatus())) {
wrapper.eq(StoreOrderDO::getPayType,reqVO.getPayStatus());
}
return selectPage(reqVO, wrapper);
}
default List<StoreOrderDO> selectList(StoreOrderExportReqVO reqVO) {
return selectList(new LambdaQueryWrapperX<StoreOrderDO>()
.eqIfPresent(StoreOrderDO::getOrderId, reqVO.getOrderId())
.likeIfPresent(StoreOrderDO::getRealName, reqVO.getRealName())
.eqIfPresent(StoreOrderDO::getUserPhone, reqVO.getUserPhone())
.eqIfPresent(StoreOrderDO::getUserAddress, reqVO.getUserAddress())
.betweenIfPresent(StoreOrderDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(StoreOrderDO::getId));
}
@Select("select IFNULL(sum(pay_price),0) from yshop_store_order " +
"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();
}
@@ -0,0 +1,15 @@
package co.yixiang.yshop.module.order.dal.mysql.storeordercartinfo;
import co.yixiang.yshop.framework.mybatis.core.mapper.BaseMapperX;
import co.yixiang.yshop.module.order.dal.dataobject.storeordercartinfo.StoreOrderCartInfoDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 订单购物详情 Mapper
*
* @author yshop
*/
@Mapper
public interface StoreOrderCartInfoMapper extends BaseMapperX<StoreOrderCartInfoDO> {
}
@@ -0,0 +1,16 @@
package co.yixiang.yshop.module.order.dal.mysql.storeorderstatus;
import co.yixiang.yshop.framework.mybatis.core.mapper.BaseMapperX;
import co.yixiang.yshop.module.order.dal.dataobject.storeorderstatus.StoreOrderStatusDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 订单操作记录 Mapper
*
* @author yshop
*/
@Mapper
public interface StoreOrderStatusMapper extends BaseMapperX<StoreOrderStatusDO> {
}
@@ -0,0 +1,37 @@
package co.yixiang.yshop.module.order.dal.redis;
import co.yixiang.yshop.framework.redis.core.RedisKeyDefine;
import co.yixiang.yshop.module.order.service.storeorder.dto.CacheDto;
import static co.yixiang.yshop.framework.redis.core.RedisKeyDefine.KeyTypeEnum.STRING;
/**
* System Redis Key 枚举类
*
* @author yshop
*/
public interface RedisKeyConstants {
RedisKeyDefine YSHOP_ORDER_CACHE_KEY = new RedisKeyDefine("确认订单数据缓存",
"yshop_order_cache:%s", // 参数为访问uid+key
STRING, CacheDto.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC);
RedisKeyDefine YSHOP_ORDER_SALE_STATUS_KEY = new RedisKeyDefine("售后订单数据缓存",
"yshop_after_order_cache:%s", // 参数为访问uid+key
STRING, String.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC);
RedisKeyDefine YSHOP_ORDER_COUNT_CACHE_KEY = new RedisKeyDefine("统计订单数据缓存",
"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);
RedisKeyDefine YSHOP_WEB_PRINT_MECHINE_KEY = new RedisKeyDefine("打印机token",
"yshop_web_print_machine_cache:%s", // 参数为访问shopid
STRING, String.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC);
}
@@ -0,0 +1,45 @@
package co.yixiang.yshop.module.order.dal.redis.ofterorder;
import co.yixiang.yshop.module.order.service.storeorder.dto.CacheDto;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;
import jakarta.annotation.Resource;
import static co.yixiang.yshop.module.order.dal.redis.RedisKeyConstants.YSHOP_ORDER_SALE_STATUS_KEY;
/**
* {@link CacheDto} 的 RedisDAO
*
* @author yshop
*/
@Repository
public class AfterOrderRedisDAO {
@Resource
private StringRedisTemplate stringRedisTemplate;
public String get(String key,Long uid) {
String redisKey = formatKey(key+uid);
return stringRedisTemplate.opsForValue().get(redisKey);
}
public void set(Long uid,String key,String o) {
String redisKey = formatKey(key + uid);
stringRedisTemplate.opsForValue().set(redisKey, o);
}
public void delete(String key,Long uid) {
String redisKey = formatKey(key+uid);
stringRedisTemplate.delete(redisKey);
}
private static String formatKey(String key) {
return String.format(YSHOP_ORDER_SALE_STATUS_KEY.getKeyTemplate(), key);
}
}
@@ -0,0 +1,46 @@
package co.yixiang.yshop.module.order.dal.redis.order;
import co.yixiang.yshop.framework.common.util.json.JsonUtils;
import co.yixiang.yshop.framework.tenant.core.context.TenantContextHolder;
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 jakarta.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 = formatKey();
return JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(redisKey), OrderTimeDataDto.class);
}
public void set(OrderTimeDataDto orderTimeDataDto) {
String redisKey = formatKey();
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() {
return String.format(YSHOP_ADMIN_ORDER_COUNT_CACHE_KEY.getKeyTemplate());
}
}
@@ -0,0 +1,48 @@
package co.yixiang.yshop.module.order.dal.redis.order;
import cn.hutool.core.util.IdUtil;
import co.yixiang.yshop.framework.common.constant.ShopConstants;
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.service.storeorder.dto.CacheDto;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;
import jakarta.annotation.Resource;
import java.util.concurrent.TimeUnit;
import static co.yixiang.yshop.module.order.dal.redis.RedisKeyConstants.YSHOP_ORDER_CACHE_KEY;
import static co.yixiang.yshop.module.order.dal.redis.RedisKeyConstants.YSHOP_ORDER_COUNT_CACHE_KEY;
/**
* {@link AppUserOrderCountVo} 的 RedisDAO
*
* @author yshop
*/
@Repository
public class AsyncOrderRedisDAO {
@Resource
private StringRedisTemplate stringRedisTemplate;
public AppUserOrderCountVo get(Long uid) {
String redisKey = formatKey(""+uid);
return JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(redisKey), AppUserOrderCountVo.class);
}
public void set(AppUserOrderCountVo appUserOrderCountVo, Long uid) {
String redisKey = formatKey("" + uid);
stringRedisTemplate.opsForValue().set(redisKey, JsonUtils.toJsonString(appUserOrderCountVo));
}
public void delete(Long uid) {
String redisKey = formatKey(""+uid);
stringRedisTemplate.delete(redisKey);
}
private static String formatKey(String key) {
return String.format(YSHOP_ORDER_COUNT_CACHE_KEY.getKeyTemplate(), key);
}
}
@@ -0,0 +1,50 @@
package co.yixiang.yshop.module.order.dal.redis.order;
import cn.hutool.core.util.IdUtil;
import co.yixiang.yshop.framework.common.constant.ShopConstants;
import co.yixiang.yshop.framework.common.util.json.JsonUtils;
import co.yixiang.yshop.module.order.service.storeorder.dto.CacheDto;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;
import jakarta.annotation.Resource;
import java.util.concurrent.TimeUnit;
import static co.yixiang.yshop.module.order.dal.redis.RedisKeyConstants.YSHOP_ORDER_CACHE_KEY;
/**
* {@link CacheDto} 的 RedisDAO
*
* @author yshop
*/
@Repository
public class OrderRedisDAO {
@Resource
private StringRedisTemplate stringRedisTemplate;
public CacheDto get(String key,Long uid) {
String redisKey = formatKey(key+uid);
return JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(redisKey), CacheDto.class);
}
public String set(CacheDto cacheDto,Long uid) {
String key = IdUtil.simpleUUID();
String redisKey = formatKey(key + uid);
long time = ShopConstants.YSHOP_ORDER_CACHE_TIME;
stringRedisTemplate.opsForValue().set(redisKey, JsonUtils.toJsonString(cacheDto), time, TimeUnit.SECONDS);
return key;
}
public void delete(String key,Long uid) {
String redisKey = formatKey(key+uid);
stringRedisTemplate.delete(redisKey);
}
private static String formatKey(String key) {
return String.format(YSHOP_ORDER_CACHE_KEY.getKeyTemplate(), key);
}
}
@@ -0,0 +1,46 @@
package co.yixiang.yshop.module.order.dal.redis.order;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;
import jakarta.annotation.Resource;
import java.util.concurrent.TimeUnit;
import static co.yixiang.yshop.module.order.dal.redis.RedisKeyConstants.YSHOP_WEB_PRINT_MECHINE_KEY;
import static co.yixiang.yshop.module.store.dal.redis.RedisKeyConstants.YSHOP_WEB_PRINT_TOKEN_KEY;
/**
*
* @author yshop
*/
@Repository
public class PrintMechinRedisDAO {
@Resource
private StringRedisTemplate stringRedisTemplate;
public String get(Long shopId) {
String redisKey = formatKey(shopId);
return stringRedisTemplate.opsForValue().get(redisKey);
}
public void set(Long shopId,String o) {
String redisKey = formatKey(shopId);
stringRedisTemplate.opsForValue().set(redisKey, o);
}
public void delete(Long shopId) {
String redisKey = formatKey(shopId);
stringRedisTemplate.delete(redisKey);
}
private static String formatKey(Long shopId) {
return String.format(YSHOP_WEB_PRINT_MECHINE_KEY.getKeyTemplate(), shopId);
}
}
@@ -0,0 +1,96 @@
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 jakarta.annotation.PostConstruct;
import jakarta.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 ExecutorTaskUnPay());
executorService.execute(new ExecutorTaskUnConfirm());
}
class ExecutorTaskUnPay implements Runnable {
@SneakyThrows
@Override
public void run() {
RBlockingDeque<String> blockingDeque = redissonClient
.getBlockingDeque(ShopConstants.REDIS_ORDER_OUTTIME_UNPAY_QUEUE);
while (true) {
try {
log.info("======延迟队列监听未支付订单======");
String orderId = blockingDeque.take();
log.info("延迟队列监听未支付订单订单编号:{}", orderId);
if(StrUtil.isNotEmpty(orderId)) {
appStoreOrderService.cancelOrder(orderId,null);
}
} catch (Exception e) {
log.error("Redission延迟队列监测异常中断,忽略此消息:{}", e.getMessage());
return;
}
}
}
}
class ExecutorTaskUnConfirm implements Runnable {
@SneakyThrows
@Override
public void run() {
RBlockingDeque<String> blockingDeque = redissonClient
.getBlockingDeque(ShopConstants.REDIS_ORDER_OUTTIME_UNCONFIRM);
while (true) {
try {
log.info("======延迟队列监听收货超时订单======");
String orderId = blockingDeque.take();
log.info("延迟队列监听收货超时订单订单编号:{}", orderId);
if(StrUtil.isNotEmpty(orderId)) {
appStoreOrderService.takeOrder(orderId,null);
}
} catch (Exception e) {
log.error("Redission延迟队列监测异常中断,忽略此消息:{}", e.getMessage());
return;
}
}
}
}
}
@@ -0,0 +1,27 @@
package co.yixiang.yshop.module.order.mq.consumer;
import co.yixiang.yshop.framework.mq.redis.core.stream.AbstractRedisStreamMessageListener;
import co.yixiang.yshop.module.order.service.storeorder.AppStoreOrderService;
import co.yixiang.yshop.module.pay.mq.message.PayNoticeMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
/**
* 消息队列处理支付消息
*/
@Component
@Slf4j
public class PayNoticeConsumer extends AbstractRedisStreamMessageListener<PayNoticeMessage> {
@Resource
private AppStoreOrderService appStoreOrderService;
@Override
public void onMessage(PayNoticeMessage message) {
log.info("[onMessage][支付消息内容({})]", message);
appStoreOrderService.paySuccess(message.getOrderId(),message.getPayType());
}
}
@@ -0,0 +1,117 @@
package co.yixiang.yshop.module.order.service.storeorder;
import co.yixiang.yshop.module.order.controller.app.order.param.AppComputeOrderParam;
import co.yixiang.yshop.module.order.controller.app.order.param.AppOrderParam;
import co.yixiang.yshop.module.order.controller.app.order.param.AppPayParam;
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.dataobject.storeorder.StoreOrderDO;
import com.baomidou.mybatisplus.extension.service.IService;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
/**
* 订单 Service 接口
*
* @author yshop
*/
public interface AppStoreOrderService extends IService<StoreOrderDO> {
/**
* 订单信息
* @param unique 唯一值或者单号
* @param uid 用户id
* @return YxStoreOrderQueryVo
*/
AppStoreOrderQueryVo getOrderInfo(String unique, Long uid);
/**
* 创建订单
* @param uid 用户uid
* @param param param
* @return map
*/
Map<String, Object> createOrder(Long uid, AppOrderParam param);
/**
* 第三方支付
* @param param 订单
* @param uid 用户id
*/
Map<String, Object> pay(Long uid, AppPayParam param);
/**
* 余额支付
* @param orderId 订单号
* @param uid 用户id
*/
void yuePay(String orderId,Long uid);
/**
* 支付成功后操作
* @param orderId 订单号
* @param payType 支付方式
*/
void paySuccess(String orderId,String payType);
/**
* 订单列表
* @param uid 用户id
* @param type OrderStatusEnum
* @param page page
* @param limit limit
* @return list
*/
List<AppStoreOrderQueryVo> orderList(Long uid, int type, int page, int limit);
/**
* 处理订单返回的状态
* @param order order
* @return YxStoreOrderQueryVo
*/
AppStoreOrderQueryVo handleOrder(AppStoreOrderQueryVo order);
/**
* 订单确认收货
* @param orderId 单号
* @param uid uid
*/
void takeOrder(String orderId,Long uid);
/**
* 申请退款
* @param explain 退款备注
* @param Img 图片
* @param text 理由
* @param orderId 订单号
* @param uid uid
*/
void orderApplyRefund(String explain,String Img,String text,String orderId, Long uid);
/**
* 删除订单
* @param orderId 单号
* @param uid uid
*/
void removeOrder(String orderId,Long uid);
/**
* 未付款取消订单
* @param orderId 订单号
* @param uid 用户id
*/
void cancelOrder(String orderId,Long uid);
}
@@ -0,0 +1,244 @@
package co.yixiang.yshop.module.order.service.storeorder;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
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.controller.app.order.vo.AppStoreOrderQueryVo;
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.dal.redis.order.AsyncCountRedisDAO;
import co.yixiang.yshop.module.order.dal.redis.order.AsyncOrderRedisDAO;
import co.yixiang.yshop.module.order.dal.redis.order.PrintMechinRedisDAO;
import co.yixiang.yshop.module.order.enums.OrderLogEnum;
import co.yixiang.yshop.module.order.service.storeorder.dto.OrderTimeDataDto;
import co.yixiang.yshop.module.product.service.storeproduct.StoreProductService;
import co.yixiang.yshop.module.store.dal.dataobject.storeshop.StoreShopDO;
import co.yixiang.yshop.module.store.dal.mysql.storeshop.StoreShopMapper;
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 jakarta.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* 异步订单 Service 实现类
*
* @author yshop
*/
@Service
@Validated
@Slf4j
public class AsynStoreOrderServiceImpl implements AsyncStoreOrderService {
@Resource
private StoreOrderMapper storeOrderMapper;
@Resource
private AsyncOrderRedisDAO asyncOrderRedisDAO;
@Resource
private AsyncCountRedisDAO asyncCountRedisDAO;
@Resource
private MemberUserService userService;
@Resource
private StoreProductService productService;
@Resource
private PrintMechinRedisDAO printMechinRedisDAO;
@Resource
private StoreShopMapper storeShopMapper;
@Resource
private StoreOrderCartInfoMapper storeOrderCartInfoMapper;
/**
* 获取某个用户的订单统计数据
*
* @param uid uid>0 取用户 否则取所有
* @return
*/
@Override
@Async
public void orderData(Long uid) {
log.info("========获取某个用户的订单统计数据=========");
//订单支付没有退款 数量
LambdaQueryWrapper<StoreOrderDO> wrapperOne = new LambdaQueryWrapper<>();
if (uid != null) {
wrapperOne.eq(StoreOrderDO::getUid, uid);
}
wrapperOne.eq(StoreOrderDO::getRefundStatus, OrderInfoEnum.REFUND_STATUS_0.getValue())
.eq(StoreOrderDO::getPaid, OrderInfoEnum.PAY_STATUS_1.getValue());
Long orderCount = storeOrderMapper.selectCount(wrapperOne);
//订单支付没有退款 支付总金额
double sumPrice = storeOrderMapper.sumPrice(uid);
//订单待支付 数量
LambdaQueryWrapper<StoreOrderDO> wrapperTwo = new LambdaQueryWrapper<>();
if (uid != null) {
wrapperTwo.eq(StoreOrderDO::getUid, uid);
}
wrapperTwo.eq(StoreOrderDO::getPaid, OrderInfoEnum.PAY_STATUS_0.getValue())
.eq(StoreOrderDO::getRefundStatus, OrderInfoEnum.REFUND_STATUS_0.getValue())
.eq(StoreOrderDO::getStatus, OrderInfoEnum.STATUS_0.getValue());
Long unpaidCount = storeOrderMapper.selectCount(wrapperTwo);
//订单待发货 数量
LambdaQueryWrapper<StoreOrderDO> wrapperThree = new LambdaQueryWrapper<>();
if (uid != null) {
wrapperThree.eq(StoreOrderDO::getUid, uid);
}
wrapperThree.eq(StoreOrderDO::getPaid, OrderInfoEnum.PAY_STATUS_1.getValue())
.eq(StoreOrderDO::getRefundStatus, OrderInfoEnum.REFUND_STATUS_0.getValue())
.eq(StoreOrderDO::getStatus, OrderInfoEnum.STATUS_0.getValue());
Long unshippedCount = storeOrderMapper.selectCount(wrapperThree);
//订单待收货 数量
LambdaQueryWrapper<StoreOrderDO> wrapperFour = new LambdaQueryWrapper<>();
if (uid != null) {
wrapperFour.eq(StoreOrderDO::getUid, uid);
}
wrapperFour.eq(StoreOrderDO::getPaid, OrderInfoEnum.PAY_STATUS_1.getValue())
.eq(StoreOrderDO::getRefundStatus, OrderInfoEnum.REFUND_STATUS_0.getValue())
.eq(StoreOrderDO::getStatus, OrderInfoEnum.STATUS_1.getValue());
Long receivedCount = storeOrderMapper.selectCount(wrapperFour);
//订单待评价 数量
LambdaQueryWrapper<StoreOrderDO> wrapperFive = new LambdaQueryWrapper<>();
if (uid != null) {
wrapperFive.eq(StoreOrderDO::getUid, uid);
}
wrapperFive.eq(StoreOrderDO::getPaid, OrderInfoEnum.PAY_STATUS_1.getValue())
.eq(StoreOrderDO::getRefundStatus, OrderInfoEnum.REFUND_STATUS_0.getValue())
.eq(StoreOrderDO::getStatus, OrderInfoEnum.STATUS_2.getValue());
Long evaluatedCount = storeOrderMapper.selectCount(wrapperFive);
//订单已完成 数量
LambdaQueryWrapper<StoreOrderDO> wrapperSix = new LambdaQueryWrapper<>();
if (uid != null) {
wrapperSix.eq(StoreOrderDO::getUid, uid);
}
wrapperSix.eq(StoreOrderDO::getPaid, OrderInfoEnum.PAY_STATUS_1.getValue())
.eq(StoreOrderDO::getRefundStatus, OrderInfoEnum.REFUND_STATUS_0.getValue())
.eq(StoreOrderDO::getStatus, OrderInfoEnum.STATUS_3.getValue());
Long completeCount = storeOrderMapper.selectCount(wrapperSix);
//售后退款
Long salesCount = 0L;
AppUserOrderCountVo appUserOrderCountVo = AppUserOrderCountVo.builder()
.orderCount(orderCount)
.sumPrice(sumPrice)
.unpaidCount(unpaidCount)
.unshippedCount(unshippedCount)
.receivedCount(receivedCount)
.evaluatedCount(evaluatedCount)
.completeCount(completeCount)
.refundCount(salesCount)
.build();
//存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;
}
}
@@ -0,0 +1,32 @@
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.controller.app.order.vo.AppStoreOrderQueryVo;
import co.yixiang.yshop.module.order.dal.dataobject.storeorder.StoreOrderDO;
import co.yixiang.yshop.module.order.service.storeorder.dto.OrderTimeDataDto;
/**
* 异步订单 Service 接口
*
* @author yshop
*/
public interface AsyncStoreOrderService {
/**
* 计算某个用户的订单统计数据
* @param uid uid>0 取用户 否则取所有
* @return UserOrderCountVo
*/
void orderData(Long uid);
/**
* 异步后台数据统计
*/
void getOrderTimeData();
}
@@ -0,0 +1,103 @@
package co.yixiang.yshop.module.order.service.storeorder;
import java.math.BigDecimal;
import java.util.*;
import jakarta.validation.*;
import co.yixiang.yshop.module.order.controller.admin.storeorder.vo.*;
import co.yixiang.yshop.module.order.dal.dataobject.storeorder.StoreOrderDO;
import co.yixiang.yshop.framework.common.pojo.PageResult;
/**
* 订单 Service 接口
*
* @author yshop
*/
public interface StoreOrderService {
/**
* 创建订单
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createStoreOrder(@Valid StoreOrderCreateReqVO createReqVO);
/**
* 更新订单
*
* @param updateReqVO 更新信息
*/
void updateStoreOrder(@Valid StoreOrderUpdateReqVO updateReqVO);
/**
* 删除订单
*
* @param id 编号
*/
void deleteStoreOrder(Long id);
/**
* 订单线下支付
*
* @param id 编号
*/
void payStoreOrder(Long id);
/**
* 确认收货
*
* @param id 编号
*/
void takeStoreOrder(Long id);
/**
* 获得订单
*
* @param id 编号
* @return 订单
*/
StoreOrderRespVO getStoreOrder(Long id);
/**
* 获得订单列表
*
* @param ids 编号
* @return 订单列表
*/
List<StoreOrderDO> getStoreOrderList(Collection<Long> ids);
/**
* 获得订单分页
*
* @param pageReqVO 分页查询
* @return 订单分页
*/
PageResult<StoreOrderRespVO> getStoreOrderPage(StoreOrderPageReqVO pageReqVO);
/**
* 获得订单列表, 用于 Excel 导出
*
* @param exportReqVO 查询条件
* @return 订单列表
*/
List<StoreOrderDO> getStoreOrderList(StoreOrderExportReqVO exportReqVO);
/**
* 确认订单退款
*
* @param id 单号
* @param price 金额
* @param type ShopCommonEnum
* @param salesId 售后id
*/
void orderRefund(Long id, BigDecimal price, Integer type, Long salesId);
/**
* 订单30s内通知
* @return
*/
Long orderNotice();
}
@@ -0,0 +1,413 @@
package co.yixiang.yshop.module.order.service.storeorder;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import co.yixiang.yshop.framework.common.constant.ShopConstants;
import co.yixiang.yshop.framework.common.enums.OrderInfoEnum;
import co.yixiang.yshop.framework.common.enums.PayIdEnum;
import co.yixiang.yshop.framework.common.enums.ShopCommonEnum;
import co.yixiang.yshop.framework.common.exception.ErrorCode;
import co.yixiang.yshop.framework.common.pojo.PageResult;
import co.yixiang.yshop.framework.security.core.util.SecurityFrameworkUtils;
import co.yixiang.yshop.framework.tenant.core.context.TenantContextHolder;
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.enums.BillDetailEnum;
import co.yixiang.yshop.module.member.service.user.MemberUserService;
import co.yixiang.yshop.module.member.service.userbill.UserBillService;
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.convert.storeorder.StoreOrderConvert;
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.OrderLogEnum;
import co.yixiang.yshop.module.order.enums.PayTypeEnum;
import co.yixiang.yshop.module.order.enums.UpdateOrderEnum;
import co.yixiang.yshop.module.order.service.storeorderstatus.StoreOrderStatusService;
import co.yixiang.yshop.module.product.service.storeproduct.AppStoreProductService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.egzosn.pay.common.bean.RefundOrder;
import com.egzosn.pay.common.bean.RefundResult;
import com.egzosn.pay.spring.boot.core.PayServiceManager;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBlockingDeque;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.math.BigDecimal;
import java.time.LocalDateTime;
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.member.enums.ErrorCodeConstants.USER_NOT_EXISTS;
import static co.yixiang.yshop.module.order.enums.ErrorCodeConstants.*;
/**
* 订单 Service 实现类
*
* @author yshop
*/
@Slf4j
@Service
@Validated
public class StoreOrderServiceImpl implements StoreOrderService {
@Resource
private StoreOrderMapper storeOrderMapper;
@Resource
private MemberUserMapper memberUserMapper;
@Resource
private StoreOrderCartInfoMapper storeOrderCartInfoMapper;
@Resource
private StoreOrderStatusService storeOrderStatusService;
@Resource
private AppStoreOrderService appStoreOrderService;
@Resource
private MemberUserService userService;
@Resource
private WeixinNoticeProducer weixinNoticeProducer;
@Resource
private RedissonClient redissonClient;
@Resource
private UserBillService billService;
@Resource
private AppStoreProductService appStoreProductService;
@Resource
private PayServiceManager manager;
@Resource
private AsyncStoreOrderService asyncStoreOrderService;
@Value("${yshop.demo}")
private Boolean isDemo;
@Override
public Long createStoreOrder(StoreOrderCreateReqVO createReqVO) {
// 插入
StoreOrderDO storeOrder = StoreOrderConvert.INSTANCE.convert(createReqVO);
storeOrderMapper.insert(storeOrder);
// 返回
return storeOrder.getId();
}
@Override
public void updateStoreOrder(StoreOrderUpdateReqVO updateReqVO) {
// 校验存在
// 更新
StoreOrderDO updateObj = StoreOrderConvert.INSTANCE.convert(updateReqVO);
StoreOrderDO updateObj2 = storeOrderMapper.selectById(updateReqVO.getId());
if (updateObj2 == null) {
throw exception(STORE_ORDER_NOT_EXISTS);
}
//发货自取模式 直接收货
if(UpdateOrderEnum.ORDER_SEND.getValue().equals(updateReqVO.getUpdateType())
&& updateObj.getOrderType().equals(OrderLogEnum.ORDER_TAKE_IN.getValue())){
this.takeStoreOrder(updateObj.getId());
//todo 异步打印小票 商业版本才有 官网购买:https://www.yixiang.co
return;
}
//发货-外卖模式
if(UpdateOrderEnum.ORDER_SEND.getValue().equals(updateReqVO.getUpdateType())
&& updateObj.getOrderType().equals(OrderLogEnum.ORDER_TAKE_OUT.getValue())){
updateObj.setStatus(OrderInfoEnum.STATUS_1.getValue());
//todo 异步打印小票 商业版本才有 官网购买:https://www.yixiang.co
}
//堂食模式
if(UpdateOrderEnum.ORDER_SEND.getValue().equals(updateReqVO.getUpdateType())
&& updateObj.getOrderType().equals(OrderLogEnum.ORDER_TAKE_DESK.getValue())){
//todo 异步打印小票 商业版本才有 官网购买:https://www.yixiang.co
}
storeOrderMapper.updateById(updateObj);
if(UpdateOrderEnum.ORDER_SEND.getValue().equals(updateReqVO.getUpdateType())){
//增加状态
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());
// }
//延时队列 1小时候自动收货
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.MINUTES);
String s = TimeUnit.SECONDS.toSeconds(ShopConstants.ORDER_OUTTIME_UNCONFIRM) + "分钟";
log.info("添加延时队列成功 ,延迟时间:" + s);
} catch (Exception e) {
log.error(e.getMessage());
}
}
}
@Override
public void deleteStoreOrder(Long id) {
// 校验存在
validateStoreOrderExists(id);
// 删除
StoreOrderDO storeOrderDO = StoreOrderDO.builder()
.isSystemDel(ShopCommonEnum.DELETE_1.getValue())
.id(id)
.build();
storeOrderMapper.updateById(storeOrderDO);
}
@Override
public void payStoreOrder(Long id) {
// 校验存在
validateStoreOrderExists(id);
StoreOrderDO storeOrderDO = storeOrderMapper.selectById(id);
storeOrderDO.setPaid(OrderInfoEnum.PAY_STATUS_1.getValue());
storeOrderDO.setPayTime(LocalDateTime.now());
storeOrderMapper.updateById(storeOrderDO);
//增加状态
storeOrderStatusService.create(storeOrderDO.getUid(),storeOrderDO.getId(), OrderLogEnum.OFFLINE_PAY.getValue(),
OrderLogEnum.OFFLINE_PAY.getDesc());
}
@Override
public void takeStoreOrder(Long id) {
StoreOrderDO storeOrderDO = storeOrderMapper.selectById(id);
appStoreOrderService.takeOrder(storeOrderDO.getOrderId(),storeOrderDO.getUid());
}
private void validateStoreOrderExists(Long id) {
if (storeOrderMapper.selectById(id) == null) {
throw exception(STORE_ORDER_NOT_EXISTS);
}
}
@Override
public StoreOrderRespVO getStoreOrder(Long id) {
StoreOrderDO storeOrderDO = storeOrderMapper.selectById(id);
StoreOrderRespVO storeOrderRespVO = StoreOrderConvert.INSTANCE.convert(storeOrderDO);
MemberUserDO memberUserDO = memberUserMapper.selectById(storeOrderRespVO.getUid());
UserRespVO userRespVO = UserConvert.INSTANCE.convert4(memberUserDO);
storeOrderRespVO.setUserRespVO(userRespVO);
LambdaQueryWrapper<StoreOrderCartInfoDO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(StoreOrderCartInfoDO::getOid,storeOrderDO.getId());
List<StoreOrderCartInfoDO> storeOrderCartInfoDOList = storeOrderCartInfoMapper.selectList(wrapper);
storeOrderRespVO.setStoreOrderCartInfoDOList(storeOrderCartInfoDOList);
storeOrderRespVO.setStatusStr(this.handleOrderStatus(storeOrderRespVO.getPaid()
,storeOrderRespVO.getStatus(),storeOrderRespVO.getRefundStatus(),storeOrderRespVO.getIsSystemDel()));
return storeOrderRespVO;
}
@Override
public List<StoreOrderDO> getStoreOrderList(Collection<Long> ids) {
return storeOrderMapper.selectBatchIds(ids);
}
/**
* 订单查询
* @param pageReqVO 分页查询
* @return
*/
@Override
public PageResult<StoreOrderRespVO> getStoreOrderPage(StoreOrderPageReqVO pageReqVO) {
PageResult<StoreOrderDO> pageResult = storeOrderMapper.selectPage(pageReqVO);
PageResult<StoreOrderRespVO> storeOrderRespVO = StoreOrderConvert.INSTANCE.convertPage(pageResult);
for (StoreOrderRespVO storeOrderRespVO1 : storeOrderRespVO.getList()) {
LambdaQueryWrapper<StoreOrderCartInfoDO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(StoreOrderCartInfoDO::getOid,storeOrderRespVO1.getId());
List<StoreOrderCartInfoDO> storeOrderCartInfoDOList = storeOrderCartInfoMapper.selectList(wrapper);
MemberUserDO memberUserDO = memberUserMapper.selectById(storeOrderRespVO1.getUid());
UserRespVO userRespVO = UserConvert.INSTANCE.convert4(memberUserDO);
storeOrderRespVO1.setStoreOrderCartInfoDOList(storeOrderCartInfoDOList);
storeOrderRespVO1.setUserRespVO(userRespVO);
storeOrderRespVO1.setStatusStr(this.handleOrderStatus(storeOrderRespVO1.getPaid()
,storeOrderRespVO1.getStatus(),storeOrderRespVO1.getRefundStatus(),storeOrderRespVO1.getIsSystemDel()));
}
return storeOrderRespVO;
}
@Override
public List<StoreOrderDO> getStoreOrderList(StoreOrderExportReqVO exportReqVO) {
return storeOrderMapper.selectList(exportReqVO);
}
/**
* 确认订单退款
*
* @param id 单号
* @param price 金额
* @param type ShopCommonEnum
* @param salesId 售后id
*/
@Override
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void orderRefund(Long id, BigDecimal price, Integer type, Long salesId) {
StoreOrderDO storeOrderDO = storeOrderMapper.selectById(id);
if (storeOrderDO == null) {
throw exception(STORE_ORDER_NOT_EXISTS);
}
MemberUserDO userQueryVo = userService.getById(storeOrderDO.getUid());
if (ObjectUtil.isNull(userQueryVo)) {
throw exception(USER_NOT_EXISTS);
}
if (OrderInfoEnum.REFUND_STATUS_2.getValue().equals(storeOrderDO.getRefundStatus())) {
throw exception(ORDER_REFUNDED);
}
if (storeOrderDO.getPayPrice().compareTo(price) < 0) {
throw exception(ORDER_PRICE_ERROR);
}
storeOrderDO.setRefundStatus(OrderInfoEnum.REFUND_STATUS_2.getValue());
storeOrderDO.setRefundPrice(price);
storeOrderMapper.updateById(storeOrderDO);
//生成分布式唯一值用于退款订单
String orderSn = IdUtil.getSnowflake(0, 0).nextIdStr();
BigDecimal balance = userQueryVo.getNowMoney();
//根据支付类型不同退款不同
if (PayTypeEnum.YUE.getValue().equals(storeOrderDO.getPayType())) {
//退款到余额
userService.incMoney(storeOrderDO.getUid(), price);
balance = balance.add(price);
} else if (PayTypeEnum.WEIXIN.getValue().equals(storeOrderDO.getPayType())) {
if(isDemo){
throw exception(new ErrorCode(888888,"演示模式没有配置证书无法微信退款的哦!"));
}
log.error("{},{},{},{}",orderSn,storeOrderDO.getOrderId(),price,storeOrderDO.getTotalPrice());
RefundOrder refundOrder = new RefundOrder(orderSn,"",storeOrderDO.getOrderId(),price,storeOrderDO.getTotalPrice());
RefundResult refundResult = manager.refund(PayIdEnum.WX_MINIAPP.getValue(), refundOrder);
if(refundResult.getCode().equals("FAIL")){
log.error("支付退款错误:{}",refundResult.getMsg());
throw exception(new ErrorCode(999999,refundResult.getMsg()));
}else {
if(refundResult.getResultCode().equals("FAIL")){
log.error("支付退款错误:{}",refundResult.getResultMsg());
throw exception(new ErrorCode(999998,refundResult.getResultMsg()));
}
}
}else if (PayTypeEnum.ALI.getValue().equals(storeOrderDO.getPayType())){
throw exception(new ErrorCode(999997,"支付宝暂时不支持退款"));
}
//增加流水
billService.income(storeOrderDO.getUid(), "商品退款", BillDetailEnum.CATEGORY_1.getValue(),
BillDetailEnum.TYPE_5.getValue(),
price.doubleValue(),
balance.doubleValue(),
"订单退款到余额" + price + "元", storeOrderDO.getId().toString(),orderSn);
storeOrderStatusService.create(storeOrderDO.getUid(), storeOrderDO.getId(),
OrderLogEnum.REFUND_ORDER_SUCCESS.getValue(), "退款给用户:" + price + "元");
//退库存
this.regressionStock(storeOrderDO,0);
}
/**
* 订单30s内通知
* @return
*/
@Override
public Long orderNotice() {
LambdaQueryWrapper<StoreOrderDO> wrapper = new LambdaQueryWrapper();
Long shopId = SecurityFrameworkUtils.getLoginUser().getShopId();
if(shopId > 0) {
wrapper.eq(StoreOrderDO::getShopId,shopId);
}
wrapper.eq(StoreOrderDO::getPaid, OrderInfoEnum.PAY_STATUS_1.getValue());
LocalDateTime nowTime = LocalDateTime.now();
wrapper.ge(StoreOrderDO::getCreateTime,nowTime.minusSeconds(30));
return storeOrderMapper.selectCount(wrapper);
}
/**
* 退回库存
*
* @param order 订单
*/
private void regressionStock(StoreOrderDO order, Integer type) {
LambdaQueryWrapper<StoreOrderCartInfoDO> wrapper = new LambdaQueryWrapper<>();
wrapper.in(StoreOrderCartInfoDO::getOid, order.getId());
List<StoreOrderCartInfoDO> cartInfoList = storeOrderCartInfoMapper.selectList(wrapper);
for (StoreOrderCartInfoDO cartInfo : cartInfoList) {
appStoreProductService.incProductStock(cartInfo.getNumber(), cartInfo.getProductId(), cartInfo.getSpec(),
0L, null);
}
}
/**
* 处理订单状态
* @param payStatus
* @param status
* @param refundStatus
* @param del
* @return
*/
private String handleOrderStatus(Integer payStatus,Integer status,Integer refundStatus,Integer del) {
String statusName = "";
if (del == 1){
statusName = "已删除";
}else if (payStatus == 0 && status == 0) {
statusName = "未支付";
} else if (payStatus == 1 && status == 0 && refundStatus == 0) {
statusName = "未发货";
} else if (payStatus == 1 && status == 1 && refundStatus == 0) {
statusName = "待收货";
} else if (payStatus == 1 && status == 2 && refundStatus == 0) {
statusName = "待评价";
} else if (payStatus == 1 && status == 3 && refundStatus == 0) {
statusName = "已完成";
} else if (payStatus == 1 && refundStatus == 2) {
statusName = "已退款";
}
else if (payStatus == 1 && refundStatus == 1) {
statusName = "退款中";
}
return statusName;
}
}
@@ -0,0 +1,16 @@
package co.yixiang.yshop.module.order.service.storeorder.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @ClassName CacheDto
* @Author hupeng <610796224@qq.com>
* @Date 2023/6/19
**/
@Data
public class CacheDto implements Serializable {
private PriceGroupDto priceGroup;
private OtherDto other;
}
@@ -0,0 +1,21 @@
/**
* Copyright (C) 2018-2022
* All rights reserved, Designed By www.yixiang.co
*/
package co.yixiang.yshop.module.order.service.storeorder.dto;
import lombok.Data;
/**
* @ClassName ChartDataDTO
* @Author hupeng <610796224@qq.com>
* @Date 2019/11/25
**/
@Data
public class ChartDataDto {
// @Value("#{target.adminCount}")
private Double num;
private String time;
}
@@ -0,0 +1,14 @@
/**
* Copyright (C) 2018-2022
* All rights reserved, Designed By www.yixiang.co
*/
package co.yixiang.yshop.module.order.service.storeorder.dto;
import lombok.Data;
@Data
public class CountDto {
private String catename;
}
@@ -0,0 +1,26 @@
/**
* Copyright (C) 2018-2022
* All rights reserved, Designed By www.yixiang.co
*/
package co.yixiang.yshop.module.order.service.storeorder.dto;
import lombok.Data;
import java.util.List;
@Data
public class OrderCountDto {
private List<String> column;
private List<OrderCountData> orderCountDatas;
@Data
public static class OrderCountData{
private String name;
private Integer value;
}
}
@@ -0,0 +1,31 @@
package co.yixiang.yshop.module.order.service.storeorder.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Map;
/**
* @ClassName OrderExtendDto
* @Author hupeng <610796224@qq.com>
* @Date 2023/6/19
**/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class OrderExtendDto implements Serializable {
@Schema(description = "唯一的key", required = true)
private String key;
@Schema(description = "订单ID", required = true)
private String orderId;
@Schema(description = "微信相关配置", required = true)
private Map<String,String> jsConfig;
}
@@ -0,0 +1,33 @@
/**
* Copyright (C) 2018-2022
* All rights reserved, Designed By www.yixiang.co
*/
package co.yixiang.yshop.module.order.service.storeorder.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @ClassName OrderTimeDataDTO
* @Author hupeng <610796224@qq.com>
* @Date 2019/11/25
**/
@Data
public class OrderTimeDataDto implements Serializable {
private Double todayPrice; //今日成交额
private Integer todayCount; //今日订单数
private Double proPrice; //昨日成交额
private Integer proCount;//昨日订单数
private Double monthPrice;//本月成交额
private Integer monthCount;//本月订单数
private Integer lastWeekCount;//上周
private Double lastWeekPrice; //上周
private Long userCount;
private Long orderCount;
private Double priceCount;
private Long goodsCount;
}
@@ -0,0 +1,25 @@
package co.yixiang.yshop.module.order.service.storeorder.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @ClassName OtherDto
* @Author hupeng <610796224@qq.com>
* @Date 2019/10/27
**/
@Data
public class OtherDto implements Serializable {
//线下包邮
private String offlinePostage;
//积分抵扣
private String integralRatio;
//最大
private String integralMax;
//满多少
private String integralFull;
}
@@ -0,0 +1,27 @@
package co.yixiang.yshop.module.order.service.storeorder.dto;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Data;
import java.math.BigDecimal;
/**
* @ClassName PriceGroup
* @Author hupeng <610796224@qq.com>
* @Date 2023/6/18
**/
@Data
public class PriceGroupDto {
private BigDecimal costPrice;
private BigDecimal storeFreePostage;
private BigDecimal storePostage;
private BigDecimal totalPrice;
private BigDecimal vipPrice;
private BigDecimal payIntegral;
}
@@ -0,0 +1,22 @@
package co.yixiang.yshop.module.order.service.storeorder.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @ClassName ProductAttrDto
* @Author hupeng <610796224@qq.com>
* @Date 2023/6/27
**/
@Data
public class ProductAttrDto implements Serializable {
private Long productId;
private String sku;
private Double price;
private String image;
}
@@ -0,0 +1,23 @@
package co.yixiang.yshop.module.order.service.storeorder.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @ClassName ProductVo
* @Author hupeng <610796224@qq.com>
* @Date 20123/6/27
**/
@Data
public class ProductDto implements Serializable {
private String image;
private Double price;
private String storeName;
private ProductAttrDto attrInfo;
}
@@ -0,0 +1,19 @@
package co.yixiang.yshop.module.order.service.storeorder.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @ClassName StatusDto
* @Author hupeng <610796224@qq.com>
* @Date 2024/1/19
**/
@Data
public class StatusDto implements Serializable {
private String yClass;
private String msg;
private String payType;
private String title;
private String type;
}
@@ -0,0 +1,40 @@
/**
* Copyright (C) 2018-2022
* All rights reserved, Designed By www.yixiang.co
*/
package co.yixiang.yshop.module.order.service.storeorder.dto;
import lombok.Data;
import java.util.Map;
/**
* @ClassName StoreOrderCartInfo
* @Author hupeng <610796224@qq.com>
* @Date 2019/10/14
**/
@Data
public class StoreOrderCartInfoDto {
private Integer id;
private Integer oid;
private Integer cartId;
private String cartInfo;
private String unique;
private Map<String,Object> cartInfoMap;
}
@@ -0,0 +1,26 @@
package co.yixiang.yshop.module.order.service.storeorder.dto;
import lombok.*;
import java.math.BigDecimal;
/**
* @ClassName TemplateDTO
* @Author hupeng <610796224@qq.com>
* @Date 2024/2/17
**/
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class TemplateDto {
private Double number;
private BigDecimal price;
private Double first;
private BigDecimal firstPrice;
private Double yContinue;
private BigDecimal continuePrice;
private Integer tempId;
private Integer cityId;
}
@@ -0,0 +1,33 @@
/**
* Copyright (C) 2018-2022
* All rights reserved, Designed By www.yixiang.co
*/
package co.yixiang.yshop.module.order.service.storeorder.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @author hupeng
* @date 2020-05-12
*/
@Data
public class YxExpressDto implements Serializable {
/** 快递公司id */
private Integer id;
/** 快递公司简称 */
private String code;
/** 快递公司全称 */
private String name;
/** 排序 */
private Integer sort;
/** 是否显示 */
private Integer isShow;
}
@@ -0,0 +1,35 @@
package co.yixiang.yshop.module.order.service.storeorder.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* @author :LionCity
* @date :Created in 2020-05-29 11:16
* @description:
* @modified By:
* @version:
*/
@Data
public class YxOrderNowOrderStatusDto implements Serializable {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date cacheKeyCreateOrder;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date paySuccess;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date deliveryGoods;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date orderVerific;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date userTakeDelivery;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date checkOrderOver;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date applyRefund;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date refundOrderSuccess;
private int size;
}
@@ -0,0 +1,40 @@
/**
* Copyright (C) 2018-2022
* All rights reserved, Designed By www.yixiang.co
*/
package co.yixiang.yshop.module.order.service.storeorder.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @author hupeng
* @date 2020-05-12
*/
@Data
public class YxStoreOrderCartInfoDto implements Serializable {
private Integer id;
/** 订单id */
private Integer oid;
/**
* 订单号
*/
private String orderId;
/** 购物车id */
private Integer cartId;
/** 商品ID */
private Integer productId;
/** 购买东西的详细信息 */
private String cartInfo;
/** 唯一id */
private String unique;
}
@@ -0,0 +1,37 @@
/**
* Copyright (C) 2018-2022
* All rights reserved, Designed By www.yixiang.co
*/
package co.yixiang.yshop.module.order.service.storeorder.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* @author hupeng
* @date 2020-05-12
*/
@Data
public class YxStoreOrderStatusDto implements Serializable {
private Integer id;
/** 订单id */
private Integer oid;
/** 操作类型 */
private String changeType;
/** 操作备注 */
private String changeMessage;
/** 操作时间 */
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date changeTime;
}
@@ -0,0 +1,29 @@
package co.yixiang.yshop.module.order.service.storeordercartinfo;
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.product.controller.app.cart.vo.AppStoreCartQueryVo;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* 订单购物详情 Service 接口
*
* @author yshop
*/
public interface StoreOrderCartInfoService extends IService<StoreOrderCartInfoDO> {
/**
* 添加购物车商品信息
* @param oid 订单id
* @param orderId 订单号
* @param productIds 商品id
* @param numbers 商品数量
* @param specs 商品规格
*/
void saveCartInfo(Long oid, String orderId,List<String> productIds,List<String> numbers,List<String> specs);
}
@@ -0,0 +1,83 @@
package co.yixiang.yshop.module.order.service.storeordercartinfo;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import co.yixiang.yshop.module.order.dal.dataobject.storeordercartinfo.StoreOrderCartInfoDO;
import co.yixiang.yshop.module.order.dal.mysql.storeordercartinfo.StoreOrderCartInfoMapper;
import co.yixiang.yshop.module.product.dal.dataobject.storeproduct.StoreProductDO;
import co.yixiang.yshop.module.product.dal.dataobject.storeproductattrvalue.StoreProductAttrValueDO;
import co.yixiang.yshop.module.product.service.storeproduct.AppStoreProductService;
import co.yixiang.yshop.module.product.service.storeproductattrvalue.StoreProductAttrValueService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.util.ArrayList;
import java.util.List;
/**
* 订单购物详情 Service 实现类
*
* @author yshop
*/
@Slf4j
@Service
@Validated
public class StoreOrderCartInfoServiceImpl extends ServiceImpl<StoreOrderCartInfoMapper, StoreOrderCartInfoDO> implements StoreOrderCartInfoService {
@Resource
private AppStoreProductService appStoreProductService;
@Resource
private StoreProductAttrValueService storeProductAttrValueService;
/**
* 添加购物车商品信息
* @param oid 订单id
* @param orderId
* @param productIds 商品id
* @param numbers 商品数量
* @param specs 商品规格
*/
@Async
@Override
public void saveCartInfo(Long oid, String orderId, List<String> productIds,List<String> numbers,List<String> specs) {
log.info("==========添加购物车商品信息start===========");
List<StoreOrderCartInfoDO> list = new ArrayList<>();
for (int i = 0;i < productIds.size();i++){
String newSku = StrUtil.replace(specs.get(i),"|",",");
StoreProductDO storeProductDO = appStoreProductService.getById(productIds.get(i));
StoreProductAttrValueDO storeProductAttrValue = storeProductAttrValueService
.getOne(Wrappers.<StoreProductAttrValueDO>lambdaQuery()
.eq(StoreProductAttrValueDO::getSku, newSku)
.eq(StoreProductAttrValueDO::getProductId, productIds.get(i)));
StoreOrderCartInfoDO info = new StoreOrderCartInfoDO();
info.setOid(oid);
info.setOrderId(orderId);
info.setCartId(0L);
info.setProductId(Long.valueOf(productIds.get(i)));
info.setCartInfo("");
info.setUnique(IdUtil.simpleUUID());
info.setIsAfterSales(1);
info.setTitle(storeProductDO.getStoreName());
info.setImage(storeProductDO.getImage());
info.setNumber(Integer.valueOf(numbers.get(i)));
info.setSpec(specs.get(i));
info.setPrice(storeProductAttrValue.getPrice());
list.add(info);
}
this.saveBatch(list);
}
}
@@ -0,0 +1,21 @@
package co.yixiang.yshop.module.order.service.storeorderstatus;
import co.yixiang.yshop.module.order.dal.dataobject.storeorderstatus.StoreOrderStatusDO;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* 订单操作记录 Service 接口
*
* @author yshop
*/
public interface StoreOrderStatusService extends IService<StoreOrderStatusDO> {
/**
* 添加订单操作记录
* @param oid 订单id
* @param changetype 操作状态
* @param changeMessage 操作内容
*/
void create(Long uid,Long oid,String changetype,String changeMessage);
}
@@ -0,0 +1,47 @@
package co.yixiang.yshop.module.order.service.storeorderstatus;
import co.yixiang.yshop.module.order.dal.dataobject.storeorderstatus.StoreOrderStatusDO;
import co.yixiang.yshop.module.order.dal.mysql.storeorderstatus.StoreOrderStatusMapper;
import co.yixiang.yshop.module.order.service.storeorder.AsyncStoreOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import jakarta.annotation.Resource;
/**
* 订单操作记录 Service 实现类
*
* @author yshop
*/
@Service
@Validated
public class StoreOrderStatusServiceImpl extends ServiceImpl<StoreOrderStatusMapper, StoreOrderStatusDO> implements StoreOrderStatusService {
@Resource
private StoreOrderStatusMapper storeOrderStatusMapper;
@Resource
private AsyncStoreOrderService asyncStoreOrderService;
/**
* 添加订单操作记录
* @param oid 订单id
* @param changetype 操作状态
* @param changeMessage 操作内容
*/
@Override
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void create(Long uid,Long oid, String changetype, String changeMessage) {
StoreOrderStatusDO storeOrderStatus = new StoreOrderStatusDO();
storeOrderStatus.setOid(oid);
storeOrderStatus.setChangeType(changetype);
storeOrderStatus.setChangeMessage(changeMessage);
this.baseMapper.insert(storeOrderStatus);
//异步统计
asyncStoreOrderService.orderData(uid);
}
}
@@ -0,0 +1,12 @@
<?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="co.yixiang.yshop.module.order.dal.mysql.express.ExpressMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见:https://www.yixiang.co/MyBatis/x-plugins/
-->
</mapper>
@@ -0,0 +1,12 @@
<?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="co.yixiang.yshop.module.order.dal.mysql.storeorder.StoreOrderMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见:https://www.yixiang.co/MyBatis/x-plugins/
-->
</mapper>
@@ -0,0 +1,12 @@
<?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="co.yixiang.yshop.module.order.dal.mysql.storeordercartinfo.StoreOrderCartInfoMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见:https://www.yixiang.co/MyBatis/x-plugins/
-->
</mapper>
@@ -0,0 +1,6 @@
<?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="co.yixiang.yshop.module.order.dal.mysql.storeorderstatus.StoreOrderStatusMapper">
</mapper>
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>co.yixiang.boot</groupId>
<artifactId>yshop-module-mall</artifactId>
<version>${revision}</version>
</parent>
<artifactId>yshop-module-product-api</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>
product 模块 API,暴露给其它模块调用
</description>
<dependencies>
<dependency>
<groupId>co.yixiang.boot</groupId>
<artifactId>yshop-common</artifactId>
</dependency>
<!-- 参数校验 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
<version>2.2.8</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,4 @@
/**
* 占位
*/
package co.yixiang.yshop.module.product.api;
@@ -0,0 +1,14 @@
package co.yixiang.yshop.module.product.api.product;
import java.util.List;
public interface ProductApi {
// /**
// * 检测商品/秒杀/砍价/拼团库存
// * @param uid 用户ID
// * @param productId 产品ID
// * @param cartNum 购买数量
// * @param productAttrUnique 商品属性Unique
// */
// void checkProductStock(Long uid, Long productId, Integer cartNum, String productAttrUnique);
}
@@ -0,0 +1,23 @@
package co.yixiang.yshop.module.product.api.property;
import co.yixiang.yshop.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
import java.util.Collection;
import java.util.List;
/**
* 商品属性值 API 接口
*
* @author yshop
*/
public interface ProductPropertyValueApi {
/**
* 根据编号数组,获得属性值列表
*
* @param ids 编号数组
* @return 属性值明细列表
*/
List<ProductPropertyValueDetailRespDTO> getPropertyValueDetailList(Collection<Long> ids);
}
@@ -0,0 +1,33 @@
package co.yixiang.yshop.module.product.api.property.dto;
import lombok.Data;
/**
* 商品属性项的明细 Response DTO
*
* @author yshop
*/
@Data
public class ProductPropertyValueDetailRespDTO {
/**
* 属性的编号
*/
private Long propertyId;
/**
* 属性的名称
*/
private String propertyName;
/**
* 属性值的编号
*/
private Long valueId;
/**
* 属性值的名称
*/
private String valueName;
}
@@ -0,0 +1,51 @@
package co.yixiang.yshop.module.product.enums;
import co.yixiang.yshop.framework.common.exception.ErrorCode;
/**
* Product 错误码枚举类
*
* product 系统,使用 1-008-000-000 段
*/
public interface ErrorCodeConstants {
ErrorCode PARAM_ERROR = new ErrorCode(1008001000, "参数非法");
// ========== 商品分类相关 1008001000 ============
ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(1008001000, "商品分类不存在");
ErrorCode CATEGORY_PARENT_NOT_EXISTS = new ErrorCode(1008001001, "父分类不存在");
ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1008001002, "分类最多只有二级哦");
ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001003, "存在子分类,无法删除");
ErrorCode CATEGORY_DISABLED = new ErrorCode(1008001004, "商品分类({})已禁用,无法使用");
// ========== 商品品牌相关编号 1008002000 ==========
ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在");
ErrorCode BRAND_DISABLED = new ErrorCode(1008002001, "品牌不存在");
ErrorCode BRAND_NAME_EXISTS = new ErrorCode(1008002002, "品牌名称已存在");
// ========== 商品 1008003000 ==========
ErrorCode STORE_PRODUCT_NOT_EXISTS = new ErrorCode(1008003000, "商品不存在");
ErrorCode STORE_PRODUCT_ATTR_NOT_EXISTS = new ErrorCode(1008003001, "商品属性不存在");
ErrorCode STORE_PRODUCT_ATTR_RESULT_NOT_EXISTS = new ErrorCode(1008003002, "商品属性详情不存在");
ErrorCode STORE_PRODUCT_ATTR_VALUE_NOT_EXISTS = new ErrorCode(1008003003, "商品属性值不存在");
ErrorCode STORE_PRODUCT_RULE_NOT_EXISTS = new ErrorCode(1008003004, "商品规则值(规格)不存在");
ErrorCode STORE_PRODUCT_RULE_NEED = new ErrorCode(1008003005, "请至少添加一个规格值哦");
ErrorCode STORE_PRODUCT_RULE_RE = new ErrorCode(1008003006, "规格值里包含'-',请重新添加");
ErrorCode STORE_PRODUCT_STOCK_ERROR = new ErrorCode(1008003007, "库存不能低于0");
ErrorCode STORE_PRODUCT_SLIDER_ERROR = new ErrorCode(1008003008, "请上传轮播图");
ErrorCode STORE_PRODUCT_ATTR_NEED = new ErrorCode(1008003009, "请设置至少一个属性");
// ========== 运费模板 1008004000 ==========
ErrorCode SHIPPING_TEMPLATES_NOT_EXISTS = new ErrorCode(1008004000, "运费模板不存在");
ErrorCode SHIPPING_TEMPLATES_FREE_NOT_EXISTS = new ErrorCode(1008004001, "请添加包邮区域");
ErrorCode SHIPPING_TEMPLATES_REGION_NOT_EXISTS = new ErrorCode(1008004002, "请添加区域");
ErrorCode SHIPPING_TEMPLATES_FREE_NEED = new ErrorCode(1008004000, "请指定包邮地区");
// ========== 评论 1008005000 ==========
ErrorCode STORE_PRODUCT_REPLY_NOT_EXISTS = new ErrorCode(1008005000, "评论不存在");
ErrorCode STORE_PRODUCT_RELATION_NOT_EXISTS = new ErrorCode(1008005001, "商品点赞和收藏不存在");
ErrorCode STORE_PRODUCT_RELATION_EXISTS = new ErrorCode(1008005002, "已经收藏过");
ErrorCode PRODUCT_STOCK_LESS = new ErrorCode(1008005003, "商品库存不足");
}
@@ -0,0 +1,16 @@
package co.yixiang.yshop.module.product.enums;
import co.yixiang.yshop.framework.common.exception.ErrorCode;
/**
* Product 错误码枚举类
*
* product 系统,使用 1-008-000-000 段
*/
public interface ProductConstants {
String NO_COMMENT_CONTENT = "此用户没有填写评价";
String FREE_POSTAGE = "全国包邮";
String POSTAGE_TEMP_NOT = "运费模板不存在";
}
@@ -0,0 +1,38 @@
package co.yixiang.yshop.module.product.enums.comment;
import co.yixiang.yshop.framework.common.core.IntArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 商品评论的审批状态枚举
*
* @author yshop
*/
@Getter
@AllArgsConstructor
public enum ProductCommentAuditStatusEnum implements IntArrayValuable {
NONE(1, "待审核"),
APPROVE(2, "审批通过"),
REJECT(2, "审批不通过"),;
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductCommentAuditStatusEnum::getStatus).toArray();
/**
* 审批状态
*/
private final Integer status;
/**
* 状态名
*/
private final String name;
@Override
public int[] array() {
return ARRAYS;
}
}
@@ -0,0 +1,38 @@
package co.yixiang.yshop.module.product.enums.delivery;
import co.yixiang.yshop.framework.common.core.IntArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 配送方式枚举
*
* @author yshop
*/
@Getter
@AllArgsConstructor
public enum DeliveryTypeEnum implements IntArrayValuable {
// TODO yshop:英文单词,需要再想下;
EXPRESS(1, "快递发货"),
USER(2, "用户自提"),;
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(DeliveryTypeEnum::getMode).toArray();
/**
* 配送方式
*/
private final Integer mode;
/**
* 状态名
*/
private final String name;
@Override
public int[] array() {
return ARRAYS;
}
}
@@ -0,0 +1,38 @@
package co.yixiang.yshop.module.product.enums.group;
import co.yixiang.yshop.framework.common.core.IntArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 商品分组的样式枚举
*
* @author yshop
*/
@Getter
@AllArgsConstructor
public enum ProductGroupStyleEnum implements IntArrayValuable {
ONE(1, "每列一个"),
TWO(2, "每列两个"),
THREE(2, "每列三个"),;
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductGroupStyleEnum::getStyle).toArray();
/**
* 列表样式
*/
private final Integer style;
/**
* 状态名
*/
private final String name;
@Override
public int[] array() {
return ARRAYS;
}
}
@@ -0,0 +1,18 @@
package co.yixiang.yshop.module.product.enums.product;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author hupeng
* 产品相关规格类型枚举
*/
@Getter
@AllArgsConstructor
public enum DefaultEnum {
DEFAULT_0(0,"默认值0"),
DEFAULT_1(1,"默认值1");
private Integer value;
private String desc;
}
Loaded 100 of 3676 files, more files were not shown because too many files have changed in this diff. Show more