27 files added
37 files modified
2076 ■■■■ changed files
oying-common/src/main/java/com/oying/utils/enums/OrderStatusEnum.java 1 ●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/AppRun.java 4 ●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/hwc/service/impl/CallbackServiceImpl.java 3 ●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/message/common/OrderStatusEnum.java 52 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/message/domain/dto/MessageOrderSellerDTO.java 5 ●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/message/mapper/MessageOrderSellerMapper.java 2 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/message/rest/MessageOrderSellerController.java 26 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/message/service/MessageOrderSellerService.java 8 ●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/message/service/impl/MessageOrderSellerServiceImpl.java 50 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/common/core/constrant/AuditStatusEnum.java 86 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/common/core/constrant/Constants.java 10 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/product/domain/ProductAudit.java 59 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/product/domain/dto/ProductAuditData.java 13 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/product/domain/dto/ProductAuditQueryCriteria.java 29 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/product/domain/dto/ProductRevisionRecord.java 32 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/product/domain/enums/ProductChangeTypeEnum.java 7 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/product/domain/enums/ProductStatusEnum.java 6 ●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/product/events/ProductAuditVerdictEvent.java 14 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/product/mapper/ProductAuditMapper.java 23 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/product/rest/ProductAuditController.java 72 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/product/service/ProductAuditService.java 76 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/product/service/ProductMerchantService.java 2 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/product/service/impl/ProductAuditServiceImpl.java 114 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/product/service/impl/ProductMerchantServiceImpl.java 62 ●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/domain/Store.java 13 ●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/domain/StoreAudit.java 60 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/domain/dto/StoreAuditData.java 12 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/domain/dto/StoreAuditQueryCriteria.java 29 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/domain/dto/StoreFieldUpdateRequest.java 6 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/domain/dto/StoreQueryCriteria.java 5 ●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/domain/dto/StoreRevisionRecord.java 31 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/domain/enums/StoreChangeTypeEnum.java 9 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/domain/enums/StoreStatusEnum.java 6 ●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/events/StoreAuditVerdictEvent.java 14 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/mapper/StoreAuditMapper.java 22 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/mapper/StoreMapper.java 4 ●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/rest/StoreAuditController.java 73 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/rest/StoreController.java 5 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/rest/StoreCustomerController.java 4 ●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/rest/StoreMerchantController.java 96 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/service/StoreAuditService.java 78 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/service/StoreMerchantService.java 16 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/service/StoreQualificationService.java 2 ●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/service/StoreService.java 17 ●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/service/impl/StoreAuditServiceImpl.java 122 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/service/impl/StoreCreateServiceImpl.java 6 ●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/service/impl/StoreMerchantServiceImpl.java 229 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/service/impl/StoreQualificationServiceImpl.java 2 ●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/service/impl/StoreQueryServiceImpl.java 25 ●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/pc/store/service/impl/StoreServiceImpl.java 173 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/sh/domain/request/StatusOrder.java 18 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/sh/domain/vo/OrderResponse.java 2 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/sh/mapper/OrderMapper.java 2 ●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/sh/rest/OrderController.java 9 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/sh/service/OrderOperationLogService.java 12 ●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/sh/service/OrderService.java 6 ●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/sh/service/impl/OrderOperationLogServiceImpl.java 50 ●●●●● patch | view | raw | blame | history
oying-system/src/main/java/com/oying/modules/sh/service/impl/OrderServiceImpl.java 44 ●●●●● patch | view | raw | blame | history
oying-system/src/main/resources/config/application.yml 2 ●●● patch | view | raw | blame | history
oying-system/src/main/resources/mapper/message/MessageOrderSellerMapper.xml 5 ●●●●● patch | view | raw | blame | history
oying-system/src/main/resources/mapper/pc/product/ProductAuditMapper.xml 37 ●●●●● patch | view | raw | blame | history
oying-system/src/main/resources/mapper/pc/store/StoreAuditMapper.xml 37 ●●●●● patch | view | raw | blame | history
oying-system/src/main/resources/mapper/pc/store/StoreMapper.xml 32 ●●●● patch | view | raw | blame | history
oying-system/src/main/resources/mapper/sh/OrderMapper.xml 5 ●●●●● patch | view | raw | blame | history
oying-common/src/main/java/com/oying/utils/enums/OrderStatusEnum.java
@@ -16,6 +16,7 @@
    SIX(6, "骑手已取货,正在送货"),
    SEVEN(7, "商品已送达"),
    EIGHT(8, "订单已完成"),
    NINE(9, "用户取消订单"),
    UNKNOWN(99, "未知枚举");
    private final Integer key;
oying-system/src/main/java/com/oying/AppRun.java
@@ -30,8 +30,8 @@
        springApplication.addListeners(new ApplicationPidFileWriter());
        springApplication.run(args);
        log.info("---------------------------------------------");
        log.info("Local: {}", "http://localhost:8088");
        log.info("Swagger: {}", "http://localhost:8088/doc.html");
        log.info("Local: {}", "http://localhost:8000");
        log.info("Swagger: {}", "http://localhost:8000/doc.html");
        log.info("---------------------------------------------");
    }
oying-system/src/main/java/com/oying/modules/hwc/service/impl/CallbackServiceImpl.java
@@ -9,6 +9,7 @@
import com.oying.modules.sh.domain.vo.OrderResponse;
import com.oying.modules.sh.service.OrderReturnService;
import com.oying.modules.sh.service.OrderService;
import com.oying.utils.enums.OrderStatusEnum;
import com.oying.utils.enums.PayStateEnum;
import com.oying.utils.enums.PayTypeEnum;
import lombok.RequiredArgsConstructor;
@@ -61,7 +62,7 @@
                                    PayStateEnum stateEnum = PayStateEnum.NOTPAY;
                                    if ("0".equals(map.get("pay_result"))) {
                                        stateEnum = PayStateEnum.SUCCESS;
                                        orderService.paySuccess(order);
                                        orderService.operationLog(order, OrderStatusEnum.TWO);
                                    }
                                    orderService.updatePayStatus(map.get("out_trade_no"), stateEnum, map.get("pay_info"), map.get("time_end"));
                                    // 处理成功
oying-system/src/main/java/com/oying/modules/message/common/OrderStatusEnum.java
New file
@@ -0,0 +1,52 @@
package com.oying.modules.message.common;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
 * 订单状态枚举
 *
 * @author leomon
 * @date 2025-05-20
 */
@Getter
@AllArgsConstructor
public enum OrderStatusEnum {
    ZERO(0, "订单已提交"),
    ONE(1, "支付成功"),
    TWO(2, "商家已接单"),
    THREE(3, "骑手已接单"),
    FOUR(4, "商家已备货"),
    FIVE(5, "骑手已到店"),
    SIX(6, "骑手已取货"),
    SEVEN(7, "商品已送达"),
    EIGHT(8, "订单已完成"),
    NINE(9, "订单已取消");
    private final Integer key;
    private final String  value;
    /* ========== 工具方法 ========== */
    /** 根据 key 获取枚举 */
    public static OrderStatusEnum of(Integer key) {
        return key == null ? null : MAP.get(key);
    }
    /** 根据 key 获取描述 */
    public static String descOf(Integer key) {
        OrderStatusEnum e = of(key);
        return e == null ? "" : e.getValue();
    }
    /** 反向映射,提升查找速度 */
    private static final Map<Integer, OrderStatusEnum> MAP =
            Arrays.stream(values())
                    .collect(Collectors.toMap(OrderStatusEnum::getKey, Function.identity()));
}
oying-system/src/main/java/com/oying/modules/message/domain/dto/MessageOrderSellerDTO.java
@@ -8,10 +8,13 @@
@Data
public class MessageOrderSellerDTO {
    //加一个主键
    private Integer id;
    private Integer orderId;
    private String messageType;
//    private String messageType;
    private String messageContent;
oying-system/src/main/java/com/oying/modules/message/mapper/MessageOrderSellerMapper.java
@@ -25,4 +25,6 @@
    Boolean updateMessageOrderSellerRead(Integer orderId);
    boolean saveMessageOrderSellerByOrderIdAndStoreId(MessageOrderSeller resources);
    boolean updateReadStatusById(Integer id);
}
oying-system/src/main/java/com/oying/modules/message/rest/MessageOrderSellerController.java
@@ -102,16 +102,22 @@
    }
    //让前端标记已读
    @PostMapping("/read/{order_id}")
    @ApiOperation("让前端标记已读 按条")
    public R<String> getMessageOrderSellerRead(@PathVariable Integer order_id) {
             if(messageOrderSellerService.updateMessageOrderSellerRead(order_id)){
                 return R.success("已读");
             }else{
                 return R.fail("id不存在");
             }
    //修改逻辑 主键为条件  而不是订单号,有些订单号可能重复 含多条信息 已弃用
//    @PostMapping("/readByorderid/{order_id}")
//    @ApiOperation("让前端标记已读 按条")
//    public R<String> getMessageOrderSellerRead(@PathVariable Integer order_id) {
//             if(messageOrderSellerService.updateMessageOrderSellerRead(order_id)){
//                 return R.success("已读");
//             }else{
//                 return R.fail("id不存在");
//             }
//    }
    //让前端标记已读   主键为条件
    @PostMapping("/read/{id}")
    @ApiOperation("标记单条消息为已读(按主键 id)")
    public R<String> markReadByPrimaryKey(@PathVariable Integer id) {
        boolean updated = messageOrderSellerService.updateReadStatusById(id);
        return updated ? R.success("已读") : R.fail("消息 id 不存在");
    }
    @Beta//重复值处理
    //让后端队友更新我的表
oying-system/src/main/java/com/oying/modules/message/service/MessageOrderSellerService.java
@@ -77,8 +77,8 @@
     * </p>
     * <p>
     * 可选字段:
     * - messageType:消息类型 :     供流程使用  订单状态: 1-待取货 2-配送中 3-已完成 4-商家取消 5-骑手取消 6-客户取消 7-系统取消"
     * - messageContent:消息内容 :  "订单已提交"   :"支付成功"   商家已接单   骑手已接单"
     * - messageType:消息类型 :  暂未使用
     * - messageContent:消息内容 :  "订单已提交"   :"支付成功"   商家已接单   骑手已接单" 即com.oying.modules.message.common.OrderStatusEnum
     * - link:链接
     * - flag:标志字段(默认值为未读 0)
     * </p>
@@ -88,4 +88,8 @@
     */
    @Beta
    boolean saveMessageOrderSellerByOrderIdAndStoreId(MessageOrderSeller resources);
    boolean updateReadStatusById(Integer id);
//    public void saveMessage(MessageOrderSeller resources) ;
}
oying-system/src/main/java/com/oying/modules/message/service/impl/MessageOrderSellerServiceImpl.java
@@ -9,6 +9,7 @@
import com.oying.modules.message.service.MessageOrderSellerService;
import com.oying.modules.message.domain.dto.MessageOrderSellerQueryCriteria;
import com.oying.modules.message.mapper.MessageOrderSellerMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.util.Beta;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -25,11 +26,15 @@
* @author 李萌
* @date 2025-05-20
**/
@Slf4j
@Service
@RequiredArgsConstructor
public class MessageOrderSellerServiceImpl extends ServiceImpl<MessageOrderSellerMapper, MessageOrderSeller> implements MessageOrderSellerService {
    private final MessageOrderSellerMapper messageOrderSellerMapper;
    @Override
    public PageResult<MessageOrderSeller> queryAll(MessageOrderSellerQueryCriteria criteria, Page<Object> page){
@@ -104,19 +109,56 @@
     * </p>
     * <p>
     * 可选字段:
     * - messageType:消息类型 :     供流程使用  订单状态: 1-待取货 2-配送中 3-已完成 4-商家取消 5-骑手取消 6-客户取消 7-系统取消"
     * - messageContent:消息内容 :  "订单已提交"   :"支付成功"   商家已接单   骑手已接单"
     * - messageType:消息类型 : 暂时不用
     * - messageContent:消息内容 :  "订单已提交"   :"支付成功"   商家已接单   骑手已接单".......com.oying.modules.message.common.OrderStatusEnum
     * - link:链接
     * - flag:标志字段(默认值为未读 0)
     * </p>
     *
     * @param resources MessageOrderSeller 对象,包含需要保存或更新的数据。
     * @return true 表示保存成功,false 表示保存失败。
     *
     * 目前插入orderId   storeId messageContent即可,其他保留---------
     */
    @Beta
    @Override
    public boolean saveMessageOrderSellerByOrderIdAndStoreId(MessageOrderSeller resources) {
        return messageOrderSellerMapper.saveMessageOrderSellerByOrderIdAndStoreId(resources);
        try {
            // 1. 判断重复的记录是否存在
//            // messageType此处不用
            long count = this.lambdaQuery()
                    .eq(MessageOrderSeller::getOrderId, resources.getOrderId())
                    .eq(MessageOrderSeller::getStoreId,   resources.getStoreId())
                    .eq(MessageOrderSeller::getMessageContent, resources.getMessageContent())
                    .eq(MessageOrderSeller::getFlag, 0)       // 未读
                    .count();
            //存在  不插入
            if (count > 0) {
                log.warn("消息已存在,跳过保存:{}",
                        resources);
                return false;
            }else{
                return messageOrderSellerMapper.saveMessageOrderSellerByOrderIdAndStoreId(resources);
            }
        } catch (Exception e) {
            log.error("保存消息异常",
                    e);
            return false;
        }
    }
    @Override
    public boolean updateReadStatusById(Integer id) {
        return messageOrderSellerMapper.updateReadStatusById(id);
    }
}
oying-system/src/main/java/com/oying/modules/pc/common/core/constrant/AuditStatusEnum.java
New file
@@ -0,0 +1,86 @@
package com.oying.modules.pc.common.core.constrant;
import lombok.Getter;
import java.util.EnumSet;
import java.util.Optional;
@Getter
public enum AuditStatusEnum {
    DRAFT(1000, "草稿"),
    PENDING(1001, "待审核"),
    UNDER_REVIEW(1002, "审核中"),
    REJECTED(1003, "拒绝"),
    APPROVED(1004, "同意"),
    CANCELLED(1005, "取消");
    private final Integer value;
    private final String reasonPhrase;
    AuditStatusEnum(Integer value, String reasonPhrase) {
        this.value = value;
        this.reasonPhrase = reasonPhrase;
    }
    public static AuditStatusEnum get(Integer code) {
        return getOrDefault(code, null);
    }
    public static AuditStatusEnum getOrDefault(Integer code, AuditStatusEnum defaultStatus) {
        for (AuditStatusEnum value : values()) {
            if (value.value.equals(code)) {
                return value;
            }
        }
        return defaultStatus;
    }
    public static boolean isApproved(Integer code) {
        return Optional.ofNullable(get(code)).map(i -> i.equals(APPROVED)).orElse(false);
    }
    public static boolean isCompleted(Integer code) {
        return EnumSet.of(REJECTED, APPROVED, CANCELLED).contains(get(code));
    }
    public static AuditStatusEnum get(String name) {
        return AuditStatusEnum.valueOf(name);
    }
    public static EnumSet<AuditStatusEnum> getNext(AuditStatusEnum status) {
        switch (status) {
            case DRAFT:
                return EnumSet.of(PENDING);
            case PENDING:
                return EnumSet.of(UNDER_REVIEW, APPROVED, REJECTED, CANCELLED);
            case UNDER_REVIEW:
                return EnumSet.of(APPROVED, REJECTED);
            case APPROVED:
            case REJECTED:
            case CANCELLED:
            default:
                return EnumSet.noneOf(AuditStatusEnum.class);
        }
    }
    public static boolean hasNext(AuditStatusEnum status) {
        return !getNext(status).isEmpty();
    }
    public EnumSet<AuditStatusEnum> getNext() {
        return getNext(this);
    }
    public boolean nextContains(AuditStatusEnum status) {
        return getNext().contains(status);
    }
    public boolean nextContains(String status) {
        return nextContains(get(status));
    }
    public boolean hasNext() {
        return hasNext(this);
    }
}
oying-system/src/main/java/com/oying/modules/pc/common/core/constrant/Constants.java
@@ -47,4 +47,14 @@
     * https请求
     */
    public static final String HTTPS = "https://";
    /**
     * 否
     */
    public static final Integer NOT = 0;
    /**
     * 是
     */
    public static final Integer YES = 1;
}
oying-system/src/main/java/com/oying/modules/pc/product/domain/ProductAudit.java
New file
@@ -0,0 +1,59 @@
package com.oying.modules.pc.product.domain;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.oying.base.BaseEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;
/**
* @description /
* @author lzp
* @date 2025-07-01
**/
@Getter
@Setter
@TableName("pc_product_audit")
public class ProductAudit extends BaseEntity implements Serializable {
    @TableId(value = "audit_id", type = IdType.AUTO)
    @ApiModelProperty(value = "审核ID")
    private Long auditId;
    @NotNull
    @ApiModelProperty(value = "商品ID")
    private Long productId;
    @NotBlank
    @ApiModelProperty(value = "类型")
    private String type;
    @ApiModelProperty(value = "审核状态")
    private Integer status;
    @ApiModelProperty(value = "审核原因")
    private String reason;
    @ApiModelProperty(value = "审核人")
    private String auditor;
    @ApiModelProperty(value = "审核时间")
    private Date auditTime;
    @NotBlank
    @ApiModelProperty(value = "审核内容")
    private String data;
    public void copy(ProductAudit source){
        BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true));
    }
}
oying-system/src/main/java/com/oying/modules/pc/product/domain/dto/ProductAuditData.java
New file
@@ -0,0 +1,13 @@
package com.oying.modules.pc.product.domain.dto;
import com.oying.modules.pc.store.domain.Store;
import com.oying.modules.pc.store.domain.dto.StoreRevisionRecord;
import lombok.Data;
@Data
public class ProductAuditData {
    private Store store;
    private StoreRevisionRecord revisionRecord;
}
oying-system/src/main/java/com/oying/modules/pc/product/domain/dto/ProductAuditQueryCriteria.java
New file
@@ -0,0 +1,29 @@
package com.oying.modules.pc.product.domain.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* @author lzp
* @date 2025-07-01
**/
@Data
public class ProductAuditQueryCriteria {
    @NotNull
    @ApiModelProperty(value = "商品ID")
    private Long productId;
    @NotBlank
    @ApiModelProperty(value = "类型")
    private String type;
    @ApiModelProperty(value = "页码", example = "1")
    private Integer page = 1;
    @ApiModelProperty(value = "每页数据量", example = "10")
    private Integer size = 10;
}
oying-system/src/main/java/com/oying/modules/pc/product/domain/dto/ProductRevisionRecord.java
New file
@@ -0,0 +1,32 @@
package com.oying.modules.pc.product.domain.dto;
import com.oying.modules.pc.store.domain.StoreQualification;
import com.oying.modules.pc.store.domain.dto.StoreQualificationUpdateRequest;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class ProductRevisionRecord {
    @ApiModelProperty(value = "店铺ID")
    private Long storeId;
    @ApiModelProperty(value = "店铺名称")
    private String storeName;
    @ApiModelProperty(value = "资质")
    private List<StoreQualification> qualifications = new ArrayList<>();
    @ApiModelProperty(value = "删除的资质")
    private List<Long> deletedQualificationIds = new ArrayList<>();
    @ApiModelProperty(value = "修改的资质")
    private List<StoreQualificationUpdateRequest> updatedQualifications = new ArrayList<>();
    @ApiModelProperty(value = "新增的资质")
    private List<StoreQualification> newQualifications = new ArrayList<>();
}
oying-system/src/main/java/com/oying/modules/pc/product/domain/enums/ProductChangeTypeEnum.java
New file
@@ -0,0 +1,7 @@
package com.oying.modules.pc.product.domain.enums;
public enum ProductChangeTypeEnum {
    PUT_ON_SHELF
}
oying-system/src/main/java/com/oying/modules/pc/product/domain/enums/ProductStatusEnum.java
@@ -23,11 +23,15 @@
    }
    public static ProductStatusEnum get(Integer code) {
        return getOrDefault(code, null);
    }
    public static ProductStatusEnum getOrDefault(Integer code, ProductStatusEnum productStatusEnum) {
        for (ProductStatusEnum value : values()) {
            if (value.value.equals(code)) {
                return value;
            }
        }
        return null;
        return productStatusEnum;
    }
}
oying-system/src/main/java/com/oying/modules/pc/product/events/ProductAuditVerdictEvent.java
New file
@@ -0,0 +1,14 @@
package com.oying.modules.pc.product.events;
import lombok.Data;
@Data
public class ProductAuditVerdictEvent {
    private Long auditId;
    public ProductAuditVerdictEvent(Long auditId) {
        this.auditId = auditId;
    }
}
oying-system/src/main/java/com/oying/modules/pc/product/mapper/ProductAuditMapper.java
New file
@@ -0,0 +1,23 @@
package com.oying.modules.pc.product.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.oying.modules.pc.product.domain.ProductAudit;
import com.oying.modules.pc.product.domain.dto.ProductAuditQueryCriteria;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
 * @author lzp
 * @date 2025-07-01
 **/
@Mapper
public interface ProductAuditMapper extends BaseMapper<ProductAudit> {
    IPage<ProductAudit> findAll(@Param("criteria") ProductAuditQueryCriteria criteria, Page<Object> page);
    List<ProductAudit> findAll(@Param("criteria") ProductAuditQueryCriteria criteria);
}
oying-system/src/main/java/com/oying/modules/pc/product/rest/ProductAuditController.java
New file
@@ -0,0 +1,72 @@
package com.oying.modules.pc.product.rest;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.oying.annotation.Log;
import com.oying.modules.pc.product.domain.ProductAudit;
import com.oying.modules.pc.product.domain.dto.ProductAuditQueryCriteria;
import com.oying.modules.pc.product.service.ProductAuditService;
import com.oying.utils.PageResult;
import com.oying.utils.R;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
 * @author lzp
 * @date 2025-07-01
 **/
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/pc/product/audit")
public class ProductAuditController {
    private final ProductAuditService auditService;
    @GetMapping
    @ApiOperation("查询审批信息")
    //@PreAuthorize("@el.check('productAudit:list')")
    public ResponseEntity<?> queryProductAudit(ProductAuditQueryCriteria criteria) {
        Page<Object> page = new Page<>(criteria.getPage(), criteria.getSize());
        return ResponseEntity.ok(R.success(auditService.queryAll(criteria, page)));
    }
    @PostMapping
    @Log("新增审批信息")
    @ApiOperation("新增审批信息")
    //@PreAuthorize("@el.check('productAudit:add')")
    public ResponseEntity<Object> createProductAudit(@Validated @RequestBody ProductAudit resources) {
        auditService.create(resources);
        return ResponseEntity.status(HttpStatus.CREATED).build();
    }
    @PutMapping
    @Log("修改审批信息")
    @ApiOperation("修改审批信息")
    //@PreAuthorize("@el.check('productAudit:edit')")
    public ResponseEntity<Object> updateProductAudit(@Validated @RequestBody ProductAudit resources) {
        auditService.update(resources, false);
        return ResponseEntity.noContent().build();
    }
    @PostMapping(value = "/verdict")
    @ApiOperation("处理审核")
    public ResponseEntity<?> submitAuditVerdict(@RequestBody ProductAudit resources) {
        auditService.processVerdict(resources);
        return ResponseEntity.noContent().build();
    }
    @DeleteMapping
    @Log("删除审批信息")
    @ApiOperation("删除审批信息")
    //@PreAuthorize("@el.check('productAudit:del')")
    public ResponseEntity<Object> deleteProductAudit(@ApiParam(value = "传ID数组[]") @RequestBody List<Long> ids) {
        auditService.deleteAll(ids);
        return ResponseEntity.noContent().build();
    }
}
oying-system/src/main/java/com/oying/modules/pc/product/service/ProductAuditService.java
New file
@@ -0,0 +1,76 @@
package com.oying.modules.pc.product.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.oying.modules.pc.product.domain.ProductAudit;
import com.oying.modules.pc.product.domain.dto.ProductAuditQueryCriteria;
import com.oying.utils.PageResult;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
/**
 * @author lzp
 * @description 服务接口
 * @date 2025-07-01
 **/
public interface ProductAuditService extends IService<ProductAudit> {
    /**
     * 查询数据分页
     *
     * @param criteria 条件
     * @param page     分页参数
     * @return PageResult
     */
    PageResult<ProductAudit> queryAll(ProductAuditQueryCriteria criteria, Page<Object> page);
    /**
     * 查询所有数据不分页
     *
     * @param criteria 条件参数
     * @return List<StoreRevisionDto>
     */
    List<ProductAudit> queryAll(ProductAuditQueryCriteria criteria);
    /**
     * 商品ID查询修订数据,
     *
     * @param productId 必须的参数,不能为null
     * @return 查询到的结果
     */
    ProductAudit getByProductId(Long productId);
    /**
     * 创建
     *
     * @param resources /
     */
    void create(ProductAudit resources);
    /**
     * 编辑
     *
     * @param resources /
     */
    void update(ProductAudit resources, boolean isDirectUpdate);
    /**
     * 多选删除
     *
     * @param ids /
     */
    void deleteAll(List<Long> ids);
    /**
     * 导出数据
     *
     * @param all      待导出的数据
     * @param response /
     * @throws IOException /
     */
    void download(List<ProductAudit> all, HttpServletResponse response) throws IOException;
    void processVerdict(ProductAudit resources);
}
oying-system/src/main/java/com/oying/modules/pc/product/service/ProductMerchantService.java
@@ -2,6 +2,7 @@
import com.oying.modules.pc.product.domain.dto.ProductMerchantCreateRequest;
import com.oying.modules.pc.product.domain.dto.ProductMerchantUpdateRequest;
import com.oying.modules.pc.product.events.ProductAuditVerdictEvent;
import java.util.List;
@@ -14,5 +15,6 @@
    void batchDelete(List<Long> ids);
    void putOnShelf(Long productId);
    void takeOffShelf(Long productId);
    void handleAuditVerdictEvent(ProductAuditVerdictEvent event);
}
oying-system/src/main/java/com/oying/modules/pc/product/service/impl/ProductAuditServiceImpl.java
New file
@@ -0,0 +1,114 @@
package com.oying.modules.pc.product.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.oying.exception.BadRequestException;
import com.oying.modules.pc.common.core.constrant.AuditStatusEnum;
import com.oying.modules.pc.product.domain.ProductAudit;
import com.oying.modules.pc.product.domain.dto.ProductAuditQueryCriteria;
import com.oying.modules.pc.product.events.ProductAuditVerdictEvent;
import com.oying.modules.pc.product.mapper.ProductAuditMapper;
import com.oying.modules.pc.product.service.ProductAuditService;
import com.oying.utils.FileUtil;
import com.oying.utils.PageResult;
import com.oying.utils.PageUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
 * @author lzp
 * @description 服务实现
 * @date 2025-07-01
 **/
@Service
@RequiredArgsConstructor
public class ProductAuditServiceImpl extends ServiceImpl<ProductAuditMapper, ProductAudit> implements ProductAuditService {
    private final ApplicationEventPublisher eventPublisher;
    private final ProductAuditMapper productAuditMapper;
    @Override
    public PageResult<ProductAudit> queryAll(ProductAuditQueryCriteria criteria, Page<Object> page) {
        return PageUtil.toPage(productAuditMapper.findAll(criteria, page));
    }
    @Override
    public List<ProductAudit> queryAll(ProductAuditQueryCriteria criteria) {
        return productAuditMapper.findAll(criteria);
    }
    @Override
    public ProductAudit getByProductId(Long productId) {
        LambdaQueryWrapper<ProductAudit> wrapper = new LambdaQueryWrapper<ProductAudit>()
                .eq(ProductAudit::getProductId, productId);
        return productAuditMapper.selectOne(wrapper);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(ProductAudit resources) {
        productAuditMapper.insert(resources);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(ProductAudit resources, boolean isDirectUpdate) {
        if (isDirectUpdate) {
            productAuditMapper.updateById(resources);
        } else {
            ProductAudit existingRevision = this.getById(resources.getAuditor());
            existingRevision.copy(resources);
            productAuditMapper.updateById(existingRevision);
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void processVerdict(ProductAudit resources) {
        AuditStatusEnum newAuditStatus = AuditStatusEnum.get(resources.getStatus());
        ProductAudit existingAudit = this.getById(resources.getAuditId());
        AuditStatusEnum existingAuditStatus = AuditStatusEnum.getOrDefault(existingAudit.getStatus(), AuditStatusEnum.DRAFT);
        if (!existingAuditStatus.nextContains(newAuditStatus)) {
            throw new BadRequestException("审核状态错误");
        }
        existingAudit.copy(resources);
        productAuditMapper.updateById(existingAudit);
        eventPublisher.publishEvent(new ProductAuditVerdictEvent(existingAudit.getAuditId()));
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAll(List<Long> ids) {
        productAuditMapper.deleteBatchIds(ids);
    }
    @Override
    public void download(List<ProductAudit> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (ProductAudit productAudit : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("审核ID", productAudit.getAuditId());
            map.put("商品ID", productAudit.getProductId());
            map.put("审批ID", productAudit.getAuditId());
            map.put("类型", productAudit.getType());
            map.put("新数据", productAudit.getData());
            map.put("创建人", productAudit.getCreateBy());
            map.put("创建时间", productAudit.getCreateTime());
            map.put("修改人", productAudit.getUpdateBy());
            map.put("修改时间", productAudit.getUpdateTime());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }
}
oying-system/src/main/java/com/oying/modules/pc/product/service/impl/ProductMerchantServiceImpl.java
@@ -3,32 +3,36 @@
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.oying.exception.EntityExistException;
import com.oying.exception.BadRequestException;
import com.oying.exception.EntityNotFoundException;
import com.oying.modules.pc.common.core.constrant.AuditStatusEnum;
import com.oying.modules.pc.product.converter.ProductImageAssembler;
import com.oying.modules.pc.product.converter.ProductLabelAssembler;
import com.oying.modules.pc.product.domain.Product;
import com.oying.modules.pc.product.domain.ProductAudit;
import com.oying.modules.pc.product.domain.ProductImage;
import com.oying.modules.pc.product.domain.ProductLabel;
import com.oying.modules.pc.product.domain.dto.ProductImageCreateRequest;
import com.oying.modules.pc.product.domain.dto.ProductLabelCreateRequest;
import com.oying.modules.pc.product.domain.dto.ProductMerchantCreateRequest;
import com.oying.modules.pc.product.domain.dto.ProductMerchantUpdateRequest;
import com.oying.modules.pc.product.domain.enums.ProductChangeTypeEnum;
import com.oying.modules.pc.product.domain.enums.ProductStatusEnum;
import com.oying.modules.pc.product.service.ProductImageService;
import com.oying.modules.pc.product.service.ProductLabelService;
import com.oying.modules.pc.product.service.ProductMerchantService;
import com.oying.modules.pc.product.service.ProductService;
import com.oying.modules.pc.product.events.ProductAuditVerdictEvent;
import com.oying.modules.pc.product.service.*;
import com.oying.modules.pc.utils.ImageUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@Slf4j
@Service
@RequiredArgsConstructor
public class ProductMerchantServiceImpl implements ProductMerchantService {
@@ -36,6 +40,7 @@
    private final ProductService productService;
    private final ProductImageService productImageService;
    private final ProductLabelService productLabelService;
    private final ProductAuditService productAuditService;
    @Override
    @Transactional(rollbackFor = Exception.class)
@@ -71,6 +76,7 @@
    @Transactional(rollbackFor = Exception.class)
    public void update(ProductMerchantUpdateRequest request) {
        Product existingProduct = this.findOrThrow(request.getProductId());
        this.validateApprovedStatus(existingProduct.getStatus());
        this.processImagesUpdate(request);
        this.processLabelsUpdate(request);
        BeanUtils.copyProperties(request, existingProduct);
@@ -80,6 +86,8 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateImages(ProductMerchantUpdateRequest request) {
        Product existingProduct = this.findOrThrow(request.getProductId());
        this.validateApprovedStatus(existingProduct.getStatus());
        this.findOrThrow(request.getProductId());
        this.processImagesUpdate(request);
    }
@@ -87,6 +95,8 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateLabels(ProductMerchantUpdateRequest request) {
        Product existingProduct = this.findOrThrow(request.getProductId());
        this.validateApprovedStatus(existingProduct.getStatus());
        this.findOrThrow(request.getProductId());
        this.processImagesUpdate(request);
    }
@@ -99,9 +109,14 @@
    @Override
    public void putOnShelf(Long productId) {
        ProductAudit audit = new ProductAudit();
        audit.setProductId(productId);
        audit.setType(ProductChangeTypeEnum.PUT_ON_SHELF.name());
        audit.setStatus(AuditStatusEnum.PENDING.getValue());
        productAuditService.create(audit);
        LambdaUpdateWrapper<Product> wrapper = new LambdaUpdateWrapper<Product>()
                .eq(Product::getProductId, productId)
                .set(Product::getStatus, ProductStatusEnum.AVAILABLE.getValue());
                .set(Product::getStatus, ProductStatusEnum.PENDING.getValue());
        productService.update(wrapper);
    }
@@ -111,6 +126,21 @@
                .eq(Product::getProductId, productId)
                .set(Product::getStatus, ProductStatusEnum.NO_AVAILABLE.getValue());
        productService.update(wrapper);
    }
    @Override
    @EventListener
    @Transactional(rollbackFor = Exception.class)
    public void handleAuditVerdictEvent(ProductAuditVerdictEvent event) {
        try {
            ProductAudit audit = productAuditService.getById(event.getAuditId());
            ProductChangeTypeEnum changeType = ProductChangeTypeEnum.valueOf(audit.getType());
            if (changeType == ProductChangeTypeEnum.PUT_ON_SHELF) {
                this.handlePutOnShelfAuditEvent(audit);
            }
        } catch (Exception e) {
            log.error("处理商品审核结果异常", e);
        }
    }
    private Product findOrThrow(Long productId) {
@@ -146,4 +176,22 @@
            productLabelService.batchCreate(newLabels);
        }
    }
    private void handlePutOnShelfAuditEvent(ProductAudit audit) {
        AuditStatusEnum auditStatus = AuditStatusEnum.get(audit.getStatus());
        if (AuditStatusEnum.APPROVED.equals(auditStatus)) {
            Product existingProduct = productService.getById(audit.getProductId());
            existingProduct.setStatus(auditStatus.getValue());
            productService.updateById(existingProduct);
        }
    }
    private void validateApprovedStatus(Integer status) {
        Set<ProductStatusEnum> statusEnumSet = CollectionUtil.newHashSet(ProductStatusEnum.PENDING,
                ProductStatusEnum.UNDER_REVIEW, ProductStatusEnum.AVAILABLE);
        ProductStatusEnum existingStatus = ProductStatusEnum.getOrDefault(status, ProductStatusEnum.DRAFT);
        if (statusEnumSet.contains(existingStatus)) {
            throw new BadRequestException("在售商品无法修改");
        }
    }
}
oying-system/src/main/java/com/oying/modules/pc/store/domain/Store.java
@@ -18,6 +18,7 @@
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalTime;
import java.util.Date;
import java.util.List;
/**
@@ -92,6 +93,9 @@
    @ApiModelProperty(value = "营业结束时间")
    private LocalTime closeTime;
    @ApiModelProperty(value = "营业状态")
    private Integer businessStatus;
    @ApiModelProperty(value = "省级代码")
    private String provinceCode;
@@ -128,9 +132,8 @@
    @ApiModelProperty(value = "是否支持自提")
    private Integer selfPickup;
    @NotNull
    @ApiModelProperty(value = "版本号")
    private Long version;
    @ApiModelProperty(value = "审核状态")
    private Integer auditStatus;
    @TableField(exist = false)
    @ApiModelProperty(value = "评分")
@@ -152,6 +155,10 @@
    @ApiModelProperty(value = "月销售量")
    private Integer monthlyUnitsSold = 0;
    @NotNull
    @ApiModelProperty(value = "版本号")
    private Long version;
    @TableField(exist = false)
    @ApiModelProperty(value = "资质")
    private List<StoreQualification> qualifications;
oying-system/src/main/java/com/oying/modules/pc/store/domain/StoreAudit.java
New file
@@ -0,0 +1,60 @@
package com.oying.modules.pc.store.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.oying.base.BaseEntity;
import cn.hutool.core.bean.BeanUtil;
import io.swagger.annotations.ApiModelProperty;
import cn.hutool.core.bean.copier.CopyOptions;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter;
import lombok.Setter;
/**
* @description /
* @author lzp
* @date 2025-07-01
**/
@Getter
@Setter
@TableName("pc_store_audit")
public class StoreAudit extends BaseEntity implements Serializable {
    @TableId(value = "audit_id", type = IdType.AUTO)
    @ApiModelProperty(value = "审核ID")
    private Long auditId;
    @NotNull
    @ApiModelProperty(value = "店铺ID")
    private Long storeId;
    @NotBlank
    @ApiModelProperty(value = "类型")
    private String type;
    @ApiModelProperty(value = "审核状态")
    private Integer status;
    @ApiModelProperty(value = "审核原因")
    private String reason;
    @ApiModelProperty(value = "审核人")
    private String auditor;
    @ApiModelProperty(value = "审核时间")
    private Date auditTime;
    @NotBlank
    @ApiModelProperty(value = "审核内容")
    private String data;
    public void copy(StoreAudit source){
        BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true));
    }
}
oying-system/src/main/java/com/oying/modules/pc/store/domain/dto/StoreAuditData.java
New file
@@ -0,0 +1,12 @@
package com.oying.modules.pc.store.domain.dto;
import com.oying.modules.pc.store.domain.Store;
import lombok.Data;
@Data
public class StoreAuditData {
    private Store store;
    private StoreRevisionRecord revisionRecord;
}
oying-system/src/main/java/com/oying/modules/pc/store/domain/dto/StoreAuditQueryCriteria.java
New file
@@ -0,0 +1,29 @@
package com.oying.modules.pc.store.domain.dto;
import lombok.Data;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* @author lzp
* @date 2025-07-01
**/
@Data
public class StoreAuditQueryCriteria {
    @NotNull
    @ApiModelProperty(value = "店铺ID")
    private Long storeId;
    @NotBlank
    @ApiModelProperty(value = "类型")
    private String type;
    @ApiModelProperty(value = "页码", example = "1")
    private Integer page = 1;
    @ApiModelProperty(value = "每页数据量", example = "10")
    private Integer size = 10;
}
oying-system/src/main/java/com/oying/modules/pc/store/domain/dto/StoreFieldUpdateRequest.java
@@ -34,11 +34,17 @@
    @NotNull(groups = UpdateStoreBusinessStatusGroup.class)
    private Integer businessStatus;
    @ApiModelProperty(value = "店铺logo图片")
    private Long logoImageId;
    public interface UpdateStoreLogoImageGroup{}
    @NotBlank(groups = UpdateStoreLogoImageGroup.class)
    private String logoImageUploadId;
    @ApiModelProperty(value = "店铺封面图")
    private Long coverImageId;
    public interface UpdateStoreCoverImageGroup{}
    @NotBlank(groups = UpdateStoreCoverImageGroup.class)
oying-system/src/main/java/com/oying/modules/pc/store/domain/dto/StoreQueryCriteria.java
@@ -25,13 +25,15 @@
    private Integer status;
    private Integer businessStatus;
    private String blurry;
    private Double longitude; // 中心点经度
    private Double latitude;  // 中心点纬度
    private Integer radius = 10000; // 搜索半径(米)
    private Integer radius = 50000000; // 搜索半径(米)
    private Integer limit = 20; // 返回数量限制
@@ -48,6 +50,7 @@
        baseKeyJoiner.add("platformCategoryId=" + platformCategoryId);
        baseKeyJoiner.add("storeName=" + storeName);
        baseKeyJoiner.add("status=" + status);
        baseKeyJoiner.add("businessStatus=" + businessStatus);
        baseKeyJoiner.add("blurry=" + blurry);
        baseKeyJoiner.add("longitude=" + longitude);
        baseKeyJoiner.add("latitude=" + latitude);
oying-system/src/main/java/com/oying/modules/pc/store/domain/dto/StoreRevisionRecord.java
New file
@@ -0,0 +1,31 @@
package com.oying.modules.pc.store.domain.dto;
import com.oying.modules.pc.store.domain.StoreQualification;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class StoreRevisionRecord {
    @ApiModelProperty(value = "店铺ID")
    private Long storeId;
    @ApiModelProperty(value = "店铺名称")
    private String storeName;
    @ApiModelProperty(value = "资质")
    private List<StoreQualification> qualifications = new ArrayList<>();
    @ApiModelProperty(value = "删除的资质")
    private List<Long> deletedQualificationIds = new ArrayList<>();
    @ApiModelProperty(value = "修改的资质")
    private List<StoreQualificationUpdateRequest> updatedQualifications = new ArrayList<>();
    @ApiModelProperty(value = "新增的资质")
    private List<StoreQualification> newQualifications = new ArrayList<>();
}
oying-system/src/main/java/com/oying/modules/pc/store/domain/enums/StoreChangeTypeEnum.java
New file
@@ -0,0 +1,9 @@
package com.oying.modules.pc.store.domain.enums;
public enum StoreChangeTypeEnum {
    NEW_STORE,
    STORE_UPDATE,
    STORE_NAME_UPDATE
}
oying-system/src/main/java/com/oying/modules/pc/store/domain/enums/StoreStatusEnum.java
@@ -23,11 +23,15 @@
    }
    public static StoreStatusEnum get(Integer code) {
        return getOrDefault(code, null);
    }
    public static StoreStatusEnum getOrDefault(Integer code, StoreStatusEnum defaultStatus) {
        for (StoreStatusEnum value : values()) {
            if (value.value.equals(code)) {
                return value;
            }
        }
        return null;
        return defaultStatus;
    }
}
oying-system/src/main/java/com/oying/modules/pc/store/events/StoreAuditVerdictEvent.java
New file
@@ -0,0 +1,14 @@
package com.oying.modules.pc.store.events;
import lombok.Data;
@Data
public class StoreAuditVerdictEvent {
    private Long auditId;
    public StoreAuditVerdictEvent(Long auditId) {
        this.auditId = auditId;
    }
}
oying-system/src/main/java/com/oying/modules/pc/store/mapper/StoreAuditMapper.java
New file
@@ -0,0 +1,22 @@
package com.oying.modules.pc.store.mapper;
import com.oying.modules.pc.store.domain.StoreAudit;
import com.oying.modules.pc.store.domain.dto.StoreAuditQueryCriteria;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
/**
* @author lzp
* @date 2025-07-01
**/
@Mapper
public interface StoreAuditMapper extends BaseMapper<StoreAudit> {
    IPage<StoreAudit> findAll(@Param("criteria") StoreAuditQueryCriteria criteria, Page<Object> page);
    List<StoreAudit> findAll(@Param("criteria") StoreAuditQueryCriteria criteria);
}
oying-system/src/main/java/com/oying/modules/pc/store/mapper/StoreMapper.java
@@ -10,6 +10,8 @@
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
/**
@@ -35,4 +37,6 @@
    List<Store> queryUserStores(@Param("userId") Long userId);
    List<Store> queryByIds(@Param("ids") Collection<? extends Serializable> idList);
}
oying-system/src/main/java/com/oying/modules/pc/store/rest/StoreAuditController.java
New file
@@ -0,0 +1,73 @@
package com.oying.modules.pc.store.rest;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.oying.annotation.Log;
import com.oying.modules.pc.store.domain.StoreAudit;
import com.oying.modules.pc.store.domain.dto.StoreAuditQueryCriteria;
import com.oying.modules.pc.store.service.StoreAuditService;
import com.oying.utils.PageResult;
import com.oying.utils.R;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
 * @author lzp
 * @date 2025-07-01
 **/
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/pc/store/audit")
public class StoreAuditController {
    private final StoreAuditService auditService;
    @GetMapping
    @ApiOperation("查询审批信息")
    //@PreAuthorize("@el.check('storeAudit:list')")
    public ResponseEntity<?> queryStoreAudit(StoreAuditQueryCriteria criteria) {
        Page<Object> page = new Page<>(criteria.getPage(), criteria.getSize());
        return ResponseEntity.ok(R.success(auditService.queryAll(criteria, page)));
    }
    @PostMapping
    @Log("新增审批信息")
    @ApiOperation("新增审批信息")
    //@PreAuthorize("@el.check('storeAudit:add')")
    public ResponseEntity<Object> createStoreAudit(@Validated @RequestBody StoreAudit resources) {
        auditService.create(resources);
        return new ResponseEntity<>(HttpStatus.CREATED);
    }
    @PutMapping
    @Log("修改审批信息")
    @ApiOperation("修改审批信息")
    //@PreAuthorize("@el.check('storeAudit:edit')")
    public ResponseEntity<Object> updateStoreAudit(@Validated @RequestBody StoreAudit resources) {
        auditService.update(resources, false);
        return ResponseEntity.noContent().build();
    }
    @PutMapping(value = "/verdict")
    @ApiOperation("处理审核")
    //@PreAuthorize("@el.check('merchant:store:create')")
    public ResponseEntity<?> submitAuditVerdict(@RequestBody StoreAudit resources) {
        auditService.processVerdict(resources);
        return ResponseEntity.noContent().build();
    }
    @DeleteMapping
    @Log("删除审批信息")
    @ApiOperation("删除审批信息")
    //@PreAuthorize("@el.check('storeAudit:del')")
    public ResponseEntity<Object> deleteStoreAudit(@ApiParam(value = "传ID数组[]") @RequestBody List<Long> ids) {
        auditService.deleteAll(ids);
        return ResponseEntity.noContent().build();
    }
}
oying-system/src/main/java/com/oying/modules/pc/store/rest/StoreController.java
@@ -54,6 +54,11 @@
        return ResponseEntity.ok(R.success(storeService.getById(storeId)));
    }
    @GetMapping(value = "/{storeId}/name-check")
    public ResponseEntity<?> checkStoreName(@RequestParam String storeName) {
        return ResponseEntity.ok(R.success(storeService.existsStoreName(storeName)));
    }
    @PostMapping
    @ApiOperation("创建店铺")
    public ResponseEntity<?> create(@RequestBody StoreCreateRequest request) {
oying-system/src/main/java/com/oying/modules/pc/store/rest/StoreCustomerController.java
@@ -7,6 +7,7 @@
import com.oying.modules.pc.product.service.ProductService;
import com.oying.modules.pc.store.domain.Store;
import com.oying.modules.pc.store.domain.dto.StoreQueryCriteria;
import com.oying.modules.pc.store.domain.enums.StoreStatusEnum;
import com.oying.modules.pc.store.service.StoreQualificationService;
import com.oying.modules.pc.store.service.StoreQueryService;
import com.oying.modules.pc.store.service.StoreService;
@@ -47,6 +48,7 @@
    @ApiOperation("查询店铺")
    public ResponseEntity<?> getStoresByPage(StoreQueryCriteria criteria) {
        criteria.setLimit(1000);
        criteria.setBusinessStatus(StoreStatusEnum.OPEN.getValue());
        PageResult<Store> pagedStores = storeQueryService.findPagedStores(criteria);
        pagedStores.getContent().forEach(store -> store.setProducts(this.getProductsByStoreId(store.getStoreId())));
        return ResponseEntity.ok(R.success(pagedStores));
@@ -67,7 +69,7 @@
    public ResponseEntity<?> getStoreDetailsById(@PathVariable("storeId") Long storeId) {
        Store store = storeService.getById(storeId);
        if (ObjUtil.isNotEmpty(store)) {
            store.setQualifications(storeQualificationService.queryByStoreId(storeId));
            store.setQualifications(storeQualificationService.getByStoreId(storeId));
        }
        return ResponseEntity.ok(R.success(store));
    }
oying-system/src/main/java/com/oying/modules/pc/store/rest/StoreMerchantController.java
@@ -2,20 +2,18 @@
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import com.oying.modules.pc.store.domain.dto.StoreUpdateRequest;
import com.oying.modules.pc.store.service.StoreQualificationService;
import com.oying.utils.R;
import com.oying.exception.BadRequestException;
import com.oying.modules.pc.store.domain.Store;
import com.oying.modules.pc.store.domain.dto.StoreCreateRequest;
import com.oying.modules.pc.store.domain.dto.StoreFieldUpdateRequest;
import com.oying.modules.pc.store.domain.dto.StoreQueryCriteria;
import com.oying.modules.pc.store.service.StoreCreateService;
import com.oying.modules.pc.store.service.StoreService;
import com.oying.modules.pc.store.domain.dto.*;
import com.oying.modules.pc.store.domain.enums.StoreStatusEnum;
import com.oying.modules.pc.store.service.*;
import com.oying.modules.pc.store.view.StoreMerchantView;
import com.oying.modules.pc.store.view.StoreSimpleView;
import com.oying.utils.R;
import com.oying.utils.SecurityUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -23,12 +21,12 @@
import org.springframework.beans.BeanUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
/**
@@ -46,12 +44,14 @@
    private final StoreService storeService;
    private final StoreCreateService storeCreateService;
    private final StoreQualificationService storeQualificationService;
    private final StoreQueryService storeQueryService;
    private final StoreMerchantService storeMerchantService;
    @GetMapping(value = "/list")
    @ApiOperation("查询所有店铺")
    //@PreAuthorize("@el.check('merchant:store:list')")
    public ResponseEntity<?> getList() {
        List<Store> stores = Optional.ofNullable(storeService.queryUserStores(SecurityUtils.getCurrentUserId())).orElse(ListUtil.empty());
        List<Store> stores = Optional.ofNullable(storeService.getUserStores(SecurityUtils.getCurrentUserId())).orElse(ListUtil.empty());
        return ResponseEntity.ok(R.success(stores));
    }
@@ -59,7 +59,7 @@
    @ApiOperation("查询所有店铺")
    //@PreAuthorize("@el.check('merchant:store:list')")
    public ResponseEntity<?> getSimpleStores() {
        List<Store> stores = Optional.ofNullable(storeService.queryUserStores(SecurityUtils.getCurrentUserId())).orElse(ListUtil.empty());
        List<Store> stores = Optional.ofNullable(storeService.getUserStores(SecurityUtils.getCurrentUserId())).orElse(ListUtil.empty());
        List<StoreSimpleView> storeViewList = stores.stream().map(i -> {
            StoreSimpleView view = new StoreSimpleView();
            BeanUtil.copyProperties(i, view, CopyOptions.create().setIgnoreNullValue(true));
@@ -84,7 +84,7 @@
    public ResponseEntity<?> getStoreDetailsById(@PathVariable Long storeId) {
        Store store = storeService.getById(storeId);
        if (ObjUtil.isNotEmpty(store)) {
            store.setQualifications(storeQualificationService.queryByStoreId(storeId));
            store.setQualifications(storeQualificationService.getByStoreId(storeId));
        }
        return ResponseEntity.ok(R.success(store));
    }
@@ -93,19 +93,27 @@
    @ApiOperation("创建店铺")
    //@PreAuthorize("@el.check('merchant:store:create')")
    public ResponseEntity<?> create(@RequestBody StoreCreateRequest request) {
        return ResponseEntity.status(HttpStatus.CREATED).body(storeCreateService.create(request));
        return ResponseEntity.status(HttpStatus.CREATED).body(storeMerchantService.createStore(request));
    }
    @PostMapping(value = "/{storeId}/audit/submit")
    @ApiOperation("提交审核")
    //@PreAuthorize("@el.check('merchant:store:create')")
    public ResponseEntity<?> submitAudit(@PathVariable Long storeId) {
        storeMerchantService.submitStoreAudit(storeId);
        return ResponseEntity.noContent().build();
    }
    /**
     * 修改店铺信息
     */
    @PostMapping(value = "/{storeId}")
    @PutMapping(value = "/{storeId}")
    @ApiOperation("修改店铺")
    //@PreAuthorize("@el.check('merchant:store:update')" +
    //        " and @storeMerchantOwnershipService.check(#storeId)")
    public ResponseEntity<?> update(@PathVariable("storeId") Long storeId, @RequestBody StoreUpdateRequest request) {
        request.setStoreId(ObjectUtil.defaultIfNull(request.getStoreId(), storeId));
        storeService.update(request);
        storeMerchantService.updateStore(request);
        return ResponseEntity.noContent().build();
    }
@@ -119,7 +127,8 @@
    public ResponseEntity<?> updateLogo(@PathVariable("storeId") Long storeId,
                           @Validated(value = StoreFieldUpdateRequest.UpdateStoreLogoImageGroup.class)
                           @RequestBody StoreFieldUpdateRequest request) {
        storeService.updateLogo(storeId, request.getLogoImageUploadId(), request.getVersion());
        Long logeImageId = Optional.ofNullable(request.getLogoImageId()).orElse(Long.getLong(request.getLogoImageUploadId()));
        storeService.updateLogo(storeId, logeImageId, request.getVersion());
        return ResponseEntity.noContent().build();
    }
@@ -133,7 +142,11 @@
    public ResponseEntity<?> updateName(@PathVariable("storeId") Long storeId,
                           @Validated(value = StoreFieldUpdateRequest.UpdateStoreNameGroup.class)
                           @RequestBody StoreFieldUpdateRequest request) {
        storeService.updateName(storeId, request.getStoreName(), request.getVersion());
        StoreUpdateRequest updateRequest = new StoreUpdateRequest();
        updateRequest.setStoreId(storeId);
        updateRequest.setStoreName(request.getStoreName());
        storeMerchantService.updateStore(updateRequest);
        //storeMerchantService.saveRevisionStore(request, StoreRevisionTypeEnum.NAME_UPDATE);
        return ResponseEntity.noContent().build();
    }
@@ -156,8 +169,8 @@
     */
    @PatchMapping(value = "/{storeId}/contactPhone")
    @ApiOperation("修改店铺联系电话")
    @PreAuthorize("@el.check('merchant:store:list')" +
            " and @storeMerchantOwnershipService.check(#storeId)")
    /*@PreAuthorize("@el.check('merchant:store:list')" +
            " and @storeMerchantOwnershipService.check(#storeId)")*/
    public ResponseEntity<?> updateContactPhone(@PathVariable("storeId") Long storeId,
                                   @Validated(value = StoreFieldUpdateRequest.UpdateStoreContactPhoneGroup.class)
                                   @RequestBody StoreFieldUpdateRequest request) {
@@ -170,8 +183,8 @@
     */
    @PatchMapping(value = "/{storeId}/address")
    @ApiOperation("修改店铺地址")
    @PreAuthorize("@el.check('merchant:store:address')" +
            " and @storeMerchantOwnershipService.check(#storeId)")
    /*@PreAuthorize("@el.check('merchant:store:address')" +
            " and @storeMerchantOwnershipService.check(#storeId)")*/
    public ResponseEntity<?> updateAddress(@PathVariable("storeId") Long storeId,
                              @Validated(value = StoreFieldUpdateRequest.UpdateStoreAddressGroup.class)
                              @RequestBody StoreFieldUpdateRequest request) {
@@ -184,8 +197,8 @@
     */
    @PatchMapping(value = "/{storeId}/location")
    @ApiOperation("修改店铺坐标")
    @PreAuthorize("@el.check('merchant:store:location')" +
            " and @storeMerchantOwnershipService.check(#storeId)")
    /*@PreAuthorize("@el.check('merchant:store:location')" +
            " and @storeMerchantOwnershipService.check(#storeId)")*/
    public ResponseEntity<?> updateLocation(@PathVariable("storeId") Long storeId,
                               @Validated(value = StoreFieldUpdateRequest.UpdateStoreLocationGroup.class)
                               @RequestBody StoreFieldUpdateRequest request) {
@@ -198,8 +211,8 @@
     */
    @PatchMapping(value = "/{storeId}/radius")
    @ApiOperation("修改店铺配送范围")
    @PreAuthorize("@el.check('merchant:store:radius')" +
            " and @storeMerchantOwnershipService.check(#storeId)")
    /*@PreAuthorize("@el.check('merchant:store:radius')" +
            " and @storeMerchantOwnershipService.check(#storeId)")*/
    public ResponseEntity<?> updateRadius(@PathVariable("storeId") Long storeId,
                             @Validated(value = StoreFieldUpdateRequest.UpdateStoreRadiusGroup.class)
                             @RequestBody StoreFieldUpdateRequest request) {
@@ -212,8 +225,8 @@
     */
    @PatchMapping(value = "/{storeId}/platformCategory")
    @ApiOperation("修改店铺绑定的经营类目")
    @PreAuthorize("@el.check('merchant:store:platformCategory')" +
            " and @storeMerchantOwnershipService.check(#storeId)")
    /*@PreAuthorize("@el.check('merchant:store:platformCategory')" +
            " and @storeMerchantOwnershipService.check(#storeId)")*/
    public ResponseEntity<?> updatePlatformCategory(@PathVariable("storeId") Long storeId,
                                       @Validated(value = StoreFieldUpdateRequest.UpdateStorePlatformCategoryGroup.class)
                                       @RequestBody StoreFieldUpdateRequest request) {
@@ -226,8 +239,8 @@
     */
    @PatchMapping(value = "/{storeId}/businessHours")
    @ApiOperation("修改店铺营业时间")
    @PreAuthorize("@el.check('merchant:store:businessHours')" +
            " and @storeMerchantOwnershipService.check(#storeId)")
    /*@PreAuthorize("@el.check('merchant:store:businessHours')" +
            " and @storeMerchantOwnershipService.check(#storeId)")*/
    public ResponseEntity<?> updateBusinessHours(@PathVariable("storeId") Long storeId,
                                    @Validated(value = StoreFieldUpdateRequest.UpdateStoreBusinessHoursGroup.class)
                                    @RequestBody StoreFieldUpdateRequest request) {
@@ -240,8 +253,8 @@
     */
    @PatchMapping(value = "/{storeId}/deliveryMinimum")
    @ApiOperation("修改起送金额")
    @PreAuthorize("@el.check('merchant:store:deliveryMinimum')" +
            " and @storeMerchantOwnershipService.check(#storeId)")
    /*@PreAuthorize("@el.check('merchant:store:deliveryMinimum')" +
            " and @storeMerchantOwnershipService.check(#storeId)")*/
    public ResponseEntity<?> updateDeliveryMinimum(@PathVariable("storeId") Long storeId,
                                      @Validated(value = StoreFieldUpdateRequest.UpdateStoreDeliveryMinimumGroup.class)
                                      @RequestBody StoreFieldUpdateRequest request) {
@@ -254,8 +267,8 @@
     */
    @PatchMapping(value = "/{storeId}/deliveryFee")
    @ApiOperation("修改配送费用")
    @PreAuthorize("@el.check('merchant:store:deliveryFee')" +
            " and @storeMerchantOwnershipService.check(#storeId)")
    /*@PreAuthorize("@el.check('merchant:store:deliveryFee')" +
            " and @storeMerchantOwnershipService.check(#storeId)")*/
    public ResponseEntity<?> updateDeliveryFee(@PathVariable("storeId") Long storeId,
                                  @Validated(value = StoreFieldUpdateRequest.UpdateStoreDeliveryFeeGroup.class)
                                  @RequestBody StoreFieldUpdateRequest request) {
@@ -267,13 +280,22 @@
     * 修改状态
     */
    @PatchMapping(value = "/{storeId}/businessStatus")
    @ApiOperation("修改状态")
    @PreAuthorize("@el.check('merchant:store:businessStatus')" +
            " and @storeMerchantOwnershipService.check(#storeId)")
    @ApiOperation("修改营业状态")
    /*@PreAuthorize("@el.check('merchant:store:businessStatus')" +
            " and @storeMerchantOwnershipService.check(#storeId)")*/
    public ResponseEntity<?> businessStatus(@PathVariable("storeId") Long storeId,
                               @Validated(value = StoreFieldUpdateRequest.UpdateStoreBusinessStatusGroup.class)
                               @RequestBody StoreFieldUpdateRequest request) {
        storeService.updateStatus(storeId, request.getBusinessStatus(), request.getVersion());
        //storeService.updateStatus(storeId, request.getBusinessStatus(), request.getVersion());
        Store store = new Store();
        store.setStoreId(storeId);
        store.setStatus(request.getBusinessStatus());
        store.setBusinessStatus(request.getBusinessStatus());
        Set<Integer> statusEnumSet = CollectionUtil.newHashSet(StoreStatusEnum.OPEN.getValue(), StoreStatusEnum.CLOSED.getValue());
        if (!statusEnumSet.contains(request.getBusinessStatus())) {
            throw new BadRequestException("状态错误");
        }
        storeMerchantService.updateBusinessStatus(store);
        return ResponseEntity.noContent().build();
    }
}
oying-system/src/main/java/com/oying/modules/pc/store/service/StoreAuditService.java
New file
@@ -0,0 +1,78 @@
package com.oying.modules.pc.store.service;
import com.oying.modules.pc.store.domain.StoreAudit;
import com.oying.modules.pc.store.domain.dto.StoreAuditQueryCriteria;
import java.util.List;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.oying.utils.PageResult;
/**
* @description 服务接口
* @author lzp
* @date 2025-07-01
**/
public interface StoreAuditService extends IService<StoreAudit> {
    /**
    * 查询数据分页
    * @param criteria 条件
    * @param page 分页参数
    * @return PageResult
    */
    PageResult<StoreAudit> queryAll(StoreAuditQueryCriteria criteria, Page<Object> page);
    /**
    * 查询所有数据不分页
    * @param criteria 条件参数
    * @return List<StoreRevisionDto>
    */
    List<StoreAudit> queryAll(StoreAuditQueryCriteria criteria);
    /**
     * 店铺ID查询修订数据,
     *
     * @param storeId 必须的参数,不能为null
     * @return 查询到的结果
     */
    StoreAudit getByStoreId(Long storeId);
    /**
     * 是否有待审记录
     *
     * @param storeId 必须的参数,不能为null
     * @return 查询到的结果
     */
    boolean hasPendingByStoreId(Long storeId);
    /**
    * 创建
    * @param resources /
    */
    void create(StoreAudit resources);
    /**
    * 编辑
    * @param resources /
    */
    void update(StoreAudit resources, boolean isDirectUpdate);
    /**
    * 多选删除
    * @param ids /
    */
    void deleteAll(List<Long> ids);
    /**
    * 导出数据
    * @param all 待导出的数据
    * @param response /
    * @throws IOException /
    */
    void download(List<StoreAudit> all, HttpServletResponse response) throws IOException;
    void processVerdict(StoreAudit resources);
}
oying-system/src/main/java/com/oying/modules/pc/store/service/StoreMerchantService.java
New file
@@ -0,0 +1,16 @@
package com.oying.modules.pc.store.service;
import com.oying.modules.pc.store.domain.Store;
import com.oying.modules.pc.store.domain.dto.StoreCreateRequest;
import com.oying.modules.pc.store.domain.dto.StoreUpdateRequest;
import com.oying.modules.pc.store.events.StoreAuditVerdictEvent;
public interface StoreMerchantService {
    Store createStore(StoreCreateRequest request);
    void updateStore(StoreUpdateRequest request);
    void updateBusinessStatus(Store resources);
    void submitStoreAudit(Long storeId);
    void handleStoreAudit(StoreAuditVerdictEvent event);
}
oying-system/src/main/java/com/oying/modules/pc/store/service/StoreQualificationService.java
@@ -44,7 +44,7 @@
     * @param storeId 条件参数
     * @return List<StoreQualification>
     */
    List<StoreQualification> queryByStoreId(Long storeId);
    List<StoreQualification> getByStoreId(Long storeId);
    /**
    * 创建
oying-system/src/main/java/com/oying/modules/pc/store/service/StoreService.java
@@ -10,6 +10,7 @@
import java.math.BigDecimal;
import java.time.LocalTime;
import java.util.List;
import java.util.Set;
/**
 * 店铺基础信息Service接口
@@ -23,15 +24,25 @@
    List<Store> queryAll(StoreQueryCriteria criteria);
    List<Long> queryStoreIds(StoreQueryCriteria criteria);
    Store getMerchantStore(Long merchantId);
    List<Store> queryUserStores(Long userId);
    List<Store> getStoresByIds(Set<Long> ids);
    List<Store> getUserStores(Long userId);
    Store getOrThrow(Long storeId, Long version);
    void create(Store resources);
    Store create(StoreCreateRequest request);
    boolean update(Store resources, boolean isDirectUpdate);
    boolean update(StoreUpdateRequest request);
    boolean updateLogo(Long storeId, String logo, Long version);
    boolean updateLogo(Long storeId, Long logoImageId, Long version);
    boolean updateName(Long storeId, String storeName, Long version);
@@ -58,4 +69,6 @@
    boolean existsByIdAndMerchantId(Long storeId, Long merchantId);
    boolean existsStoreName(String storeName);
    boolean bindUser(Long store);
}
oying-system/src/main/java/com/oying/modules/pc/store/service/impl/StoreAuditServiceImpl.java
New file
@@ -0,0 +1,122 @@
package com.oying.modules.pc.store.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.oying.exception.BadRequestException;
import com.oying.modules.pc.common.core.constrant.AuditStatusEnum;
import com.oying.modules.pc.store.domain.StoreAudit;
import com.oying.modules.pc.store.domain.dto.StoreAuditQueryCriteria;
import com.oying.modules.pc.store.events.StoreAuditVerdictEvent;
import com.oying.modules.pc.store.mapper.StoreAuditMapper;
import com.oying.modules.pc.store.service.StoreAuditService;
import com.oying.utils.FileUtil;
import com.oying.utils.PageResult;
import com.oying.utils.PageUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
 * @author lzp
 * @description 服务实现
 * @date 2025-07-01
 **/
@Service
@RequiredArgsConstructor
public class StoreAuditServiceImpl extends ServiceImpl<StoreAuditMapper, StoreAudit> implements StoreAuditService {
    private final ApplicationEventPublisher eventPublisher;
    private final StoreAuditMapper storeAuditMapper;
    @Override
    public PageResult<StoreAudit> queryAll(StoreAuditQueryCriteria criteria, Page<Object> page) {
        return PageUtil.toPage(storeAuditMapper.findAll(criteria, page));
    }
    @Override
    public List<StoreAudit> queryAll(StoreAuditQueryCriteria criteria) {
        return storeAuditMapper.findAll(criteria);
    }
    @Override
    public StoreAudit getByStoreId(Long storeId) {
        LambdaQueryWrapper<StoreAudit> wrapper = new LambdaQueryWrapper<StoreAudit>()
                .eq(StoreAudit::getStoreId, storeId);
        return storeAuditMapper.selectOne(wrapper);
    }
    @Override
    public boolean hasPendingByStoreId(Long storeId) {
        LambdaQueryWrapper<StoreAudit> wrapper = new LambdaQueryWrapper<StoreAudit>()
                .eq(StoreAudit::getStoreId, storeId)
                .eq(StoreAudit::getStatus, AuditStatusEnum.PENDING.getValue());
        return storeAuditMapper.selectCount(wrapper) > 0;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(StoreAudit resources) {
        storeAuditMapper.insert(resources);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(StoreAudit resources, boolean isDirectUpdate) {
        if (isDirectUpdate) {
            storeAuditMapper.updateById(resources);
        } else {
            StoreAudit existingRevision = this.getById(resources.getAuditor());
            existingRevision.copy(resources);
            storeAuditMapper.updateById(existingRevision);
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void processVerdict(StoreAudit resources) {
        AuditStatusEnum newAuditStatus = AuditStatusEnum.get(resources.getStatus());
        StoreAudit existingAudit = this.getById(resources.getAuditId());
        AuditStatusEnum existingAuditStatus = AuditStatusEnum.getOrDefault(existingAudit.getStatus(), AuditStatusEnum.DRAFT);
        if (!existingAuditStatus.nextContains(newAuditStatus)) {
            throw new BadRequestException("审核状态错误");
        }
        existingAudit.copy(resources);
        storeAuditMapper.updateById(existingAudit);
        eventPublisher.publishEvent(new StoreAuditVerdictEvent(existingAudit.getAuditId()));
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAll(List<Long> ids) {
        storeAuditMapper.deleteBatchIds(ids);
    }
    @Override
    public void download(List<StoreAudit> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (StoreAudit storeRevision : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("审核ID", storeRevision.getAuditId());
            map.put("店铺ID", storeRevision.getStoreId());
            map.put("审批ID", storeRevision.getAuditId());
            map.put("类型", storeRevision.getType());
            map.put("新数据", storeRevision.getData());
            map.put("创建人", storeRevision.getCreateBy());
            map.put("创建时间", storeRevision.getCreateTime());
            map.put("修改人", storeRevision.getUpdateBy());
            map.put("修改时间", storeRevision.getUpdateTime());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }
}
oying-system/src/main/java/com/oying/modules/pc/store/service/impl/StoreCreateServiceImpl.java
@@ -3,7 +3,7 @@
import com.oying.modules.pc.store.domain.Store;
import com.oying.modules.pc.store.domain.dto.StoreCreateRequest;
import com.oying.modules.pc.store.service.StoreCreateService;
import com.oying.modules.pc.store.service.StoreService;
import com.oying.modules.pc.store.service.StoreMerchantService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -14,10 +14,10 @@
@RequiredArgsConstructor
public class StoreCreateServiceImpl implements StoreCreateService {
    private final StoreService storeService;
    private final StoreMerchantService storeMerchantService;
    @Transactional(rollbackFor = Exception.class)
    public Store create(StoreCreateRequest request) {
        return storeService.create(request);
        return storeMerchantService.createStore(request);
    }
}
oying-system/src/main/java/com/oying/modules/pc/store/service/impl/StoreMerchantServiceImpl.java
New file
@@ -0,0 +1,229 @@
package com.oying.modules.pc.store.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.oying.exception.BadRequestException;
import com.oying.modules.pc.common.ValueUpdate;
import com.oying.modules.pc.common.core.constrant.AuditStatusEnum;
import com.oying.modules.pc.store.converter.StoreAssembler;
import com.oying.modules.pc.store.converter.StoreQualificationAssembler;
import com.oying.modules.pc.store.domain.Store;
import com.oying.modules.pc.store.domain.StoreAudit;
import com.oying.modules.pc.store.domain.StoreQualification;
import com.oying.modules.pc.store.domain.dto.*;
import com.oying.modules.pc.store.domain.enums.StoreChangeTypeEnum;
import com.oying.modules.pc.store.domain.enums.StoreStatusEnum;
import com.oying.modules.pc.store.events.StoreAuditVerdictEvent;
import com.oying.modules.pc.store.service.StoreAuditService;
import com.oying.modules.pc.store.service.StoreMerchantService;
import com.oying.modules.pc.store.service.StoreQualificationService;
import com.oying.modules.pc.store.service.StoreService;
import com.oying.service.BucketStorageService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Slf4j
@Service
@RequiredArgsConstructor
public class StoreMerchantServiceImpl implements StoreMerchantService {
    private final BucketStorageService bucketStorageService;
    private final StoreService storeService;
    private final StoreQualificationService qualificationService;
    private final StoreAuditService auditService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Store createStore(StoreCreateRequest request) {
        Store store = StoreAssembler.to(request);
        storeService.create(store);
        this.processQualificationCreate(store, request.getQualificationList());
        storeService.bindUser(store.getStoreId());
        return store;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateStore(StoreUpdateRequest request) {
        Store existingStore = storeService.getOrThrow(request.getStoreId(), request.getVersion());
        AuditStatusEnum existingStatus = AuditStatusEnum.getOrDefault(existingStore.getAuditStatus(), AuditStatusEnum.DRAFT);
        if (AuditStatusEnum.DRAFT.equals(existingStatus)) {
            this.processStoreImagesUpdate(request, existingStore);
            this.processQualificationUpdate(request.getDeletedQualificationIds(), request.getUpdatedQualifications(), request.getNewQualifications());
            BeanUtil.copyProperties(request, existingStore, CopyOptions.create().setIgnoreNullValue(true));
            storeService.update(existingStore, true);
        } else if (AuditStatusEnum.APPROVED.equals(existingStatus)) {
            Store newStore = new Store();
            newStore.setQualifications(ListUtil.of());
            BeanUtil.copyProperties(request, newStore, CopyOptions.create().setIgnoreNullValue(true));
            List<StoreQualification> existingQualifications = qualificationService.getByStoreId(request.getStoreId());
            if (CollectionUtil.isNotEmpty(request.getDeletedQualificationIds())) {
                List<StoreQualification> filteredQualifications = existingQualifications.stream()
                        .filter(qualification -> !request.getDeletedQualificationIds().contains(qualification.getQualificationId()))
                        .collect(Collectors.toList());
                newStore.getQualifications().addAll(filteredQualifications);
            }
            List<StoreQualification> updatedQualifications = ListUtil.of();
            if (CollectionUtil.isNotEmpty(request.getUpdatedQualifications())) {
                Set<Long> updatedQualificationIdSet = request.getUpdatedQualifications().stream().map(StoreQualificationUpdateRequest::getQualificationId).collect(Collectors.toSet());
                List<StoreQualification> filteredQualifications = newStore.getQualifications().stream()
                        .filter(qualification -> !updatedQualificationIdSet.contains(qualification.getQualificationId()))
                        .collect(Collectors.toList());
                newStore.setQualifications(filteredQualifications);
                request.getUpdatedQualifications().forEach(i -> {
                    StoreQualification qualificationUpdate = new StoreQualification();
                    BeanUtil.copyProperties(i, qualificationUpdate, CopyOptions.create().setIgnoreNullValue(true));
                    newStore.getQualifications().add(qualificationUpdate);
                    updatedQualifications.add(qualificationUpdate);
                });
            }
            if (CollectionUtil.isNotEmpty(request.getNewQualifications())) {
                newStore.getQualifications().addAll(request.getNewQualifications());
            }
            StoreRevisionRecord revisionRecord = new StoreRevisionRecord();
            BeanUtil.copyProperties(request, revisionRecord, CopyOptions.create().setIgnoreNullValue(true));
            StoreAuditData auditData = new StoreAuditData();
            auditData.setStore(newStore);
            auditData.setRevisionRecord(revisionRecord);
            this.createLatestModification(request.getStoreId(), StoreChangeTypeEnum.STORE_UPDATE, auditData);
        }
    }
    @Override
    public void updateBusinessStatus(Store resources) {
        StoreStatusEnum businessStatus = StoreStatusEnum.getOrDefault(resources.getBusinessStatus(), StoreStatusEnum.DRAFT);
        Store existingStore = storeService.getOrThrow(resources.getStoreId(), resources.getVersion());
        AuditStatusEnum existingStatus = AuditStatusEnum.getOrDefault(existingStore.getAuditStatus(), AuditStatusEnum.DRAFT);
        if (StoreStatusEnum.OPEN.equals(businessStatus) && !AuditStatusEnum.APPROVED.equals(existingStatus)) {
            throw new BadRequestException("店铺未审核");
        }
        storeService.updateStatus(existingStore.getStoreId(), businessStatus.getValue(), existingStore.getVersion());
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submitStoreAudit(Long storeId) {
        Store existingStore = storeService.getById(storeId);
        // 更新店铺状态
        existingStore.setStatus(AuditStatusEnum.PENDING.getValue());
        existingStore.setAuditStatus(AuditStatusEnum.PENDING.getValue());
        storeService.update(existingStore, true);
        // 创建新的审核
        existingStore.setQualifications(qualificationService.getByStoreId(existingStore.getStoreId()));
        StoreRevisionRecord revisionRecord = new StoreRevisionRecord();
        BeanUtil.copyProperties(existingStore, revisionRecord, CopyOptions.create().setIgnoreNullValue(true));
        StoreAuditData auditData = new StoreAuditData();
        auditData.setStore(existingStore);
        auditData.setRevisionRecord(revisionRecord);
        this.createLatestModification(existingStore.getStoreId(), StoreChangeTypeEnum.NEW_STORE, auditData);
    }
    @Override
    @EventListener
    @Transactional(rollbackFor = Exception.class)
    public void handleStoreAudit(StoreAuditVerdictEvent event) {
        try {
            StoreAudit audit = auditService.getById(event.getAuditId());
            StoreChangeTypeEnum changeType = StoreChangeTypeEnum.valueOf(audit.getType());
            switch (changeType) {
                case NEW_STORE:
                    this.handleNewStoreAuditEvent(audit);
                    return;
                case STORE_UPDATE:
                    this.handleStoreUpdateAuditEvent(audit);
            }
        } catch (Exception e) {
            log.error("处理店铺审核结果异常", e);
        }
    }
    private void processQualificationCreate(Store store, List<StoreQualificationCreateRequest> qualificationRequests) {
        if (CollectionUtil.isNotEmpty(qualificationRequests)) {
            List<StoreQualification> storeQualificationList = qualificationRequests.stream().map(i -> {
                i.setStoreId(store.getStoreId());
                return StoreQualificationAssembler.to(i);
            }).collect(Collectors.toList());
            storeQualificationList.forEach(i -> i.setStoreId(store.getStoreId()));
            qualificationService.batchCreate(storeQualificationList);
            store.setQualifications(storeQualificationList);
        }
    }
    private List<Long> getDeleteImageIds(List<ValueUpdate<Long>> imageValues) {
        List<Long> deleteImageIds = new ArrayList<>();
        for (ValueUpdate<Long> imageValue : imageValues) {
            if (imageValue.isChangeAndOldValueNotEmpty()) {
                deleteImageIds.add(imageValue.getOldValue());
            }
        }
        return deleteImageIds;
    }
    private void processStoreImagesUpdate(StoreUpdateRequest request, Store existingStore) {
        List<ValueUpdate<Long>> imageValues = ListUtil.toList(
                new ValueUpdate<>(request.getLogoImageId(), existingStore.getLogoImageId()),
                new ValueUpdate<>(request.getCoverImageId(), existingStore.getCoverImageId())
        );
        List<Long> ids = this.getDeleteImageIds(imageValues);
        if (CollectionUtil.isNotEmpty(ids)) {
            bucketStorageService.deleteAll(ids);
        }
    }
    private void processQualificationUpdate(List<Long> ids, List<StoreQualificationUpdateRequest> updateRequests,
                                            List<StoreQualification> newQualifications) {
        if (CollectionUtil.isNotEmpty(ids)) {
            qualificationService.deleteAll(ids);
        }
        if (CollectionUtil.isNotEmpty(updateRequests)) {
            qualificationService.batchUpdate(updateRequests);
        }
        if (CollectionUtil.isNotEmpty(newQualifications)) {
            qualificationService.batchCreate(newQualifications);
        }
    }
    private void createLatestModification(Long storeId, StoreChangeTypeEnum changeType, StoreAuditData auditData) {
        if (auditService.hasPendingByStoreId(storeId)) {
            throw new BadRequestException("已有审核的内容");
        }
        StoreAudit storeAudit = new StoreAudit();
        storeAudit.setStoreId(storeId);
        storeAudit.setType(changeType.name());
        storeAudit.setData(JSON.toJSONString(auditData));
        storeAudit.setStatus(AuditStatusEnum.PENDING.getValue());
        auditService.create(storeAudit);
    }
    private void handleNewStoreAuditEvent(StoreAudit audit) {
        Store existingStore = storeService.getById(audit.getStoreId());
        existingStore.setStatus(audit.getStatus());
        existingStore.setAuditStatus(audit.getStatus());
        storeService.updateById(existingStore);
    }
    private void handleStoreUpdateAuditEvent(StoreAudit audit) {
        AuditStatusEnum auditStatus = AuditStatusEnum.get(audit.getStatus());
        if (AuditStatusEnum.APPROVED.equals(auditStatus)) {
            StoreAuditData data = JSONObject.parseObject(audit.getData(), StoreAuditData.class);
            Store existingStore = storeService.getById(audit.getStoreId());
            StoreRevisionRecord revisionRecord = data.getRevisionRecord();
            BeanUtil.copyProperties(revisionRecord, existingStore, CopyOptions.create().setIgnoreNullValue(true));
            storeService.updateById(existingStore);
            this.processQualificationUpdate(revisionRecord.getDeletedQualificationIds(), revisionRecord.getUpdatedQualifications(),
                    revisionRecord.getNewQualifications());
        }
    }
}
oying-system/src/main/java/com/oying/modules/pc/store/service/impl/StoreQualificationServiceImpl.java
@@ -57,7 +57,7 @@
    }
    @Override
    public List<StoreQualification> queryByStoreId(Long storeId) {
    public List<StoreQualification> getByStoreId(Long storeId) {
        LambdaQueryWrapper<StoreQualification> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StoreQualification::getStoreId, storeId);
        return storeQualificationMapper.selectList(wrapper);
oying-system/src/main/java/com/oying/modules/pc/store/service/impl/StoreQueryServiceImpl.java
@@ -1,10 +1,9 @@
package com.oying.modules.pc.store.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.NumberUtil;
import com.oying.modules.pc.store.domain.Store;
import com.oying.modules.pc.store.domain.dto.StoreQueryCriteria;
import com.oying.modules.pc.store.mapper.StoreMapper;
import com.oying.modules.pc.store.service.StoreQueryService;
import com.oying.modules.pc.store.service.StoreService;
import com.oying.utils.PageResult;
@@ -27,7 +26,6 @@
    private final RedisTemplate<Object, Object> redisTemplate;
    private final StoreService storeService;
    private final StoreMapper storeMapper;
    @Override
    public PageResult<Store> findPagedStores(StoreQueryCriteria criteria) {
@@ -39,7 +37,7 @@
        Long total = redisTemplate.opsForZSet().size(setKey);
        if (total == null || total == 0) {
            // 初始化缓存
            List<Long> ids = storeMapper.queryStoreIds(criteria);
            List<Long> ids = storeService.queryStoreIds(criteria);
            int index = 0;
            for (Long id : ids) {
                redisTemplate.opsForZSet().add(setKey, id, index++);
@@ -56,17 +54,32 @@
        Set<Long> storeIds = Optional.ofNullable(redisTemplate.opsForZSet().range(setKey, offset, end))
                .orElse(Collections.emptySet())
                .stream()
                .map(i-> (Long) i)
                .map(i -> (Long) i)
                .collect(Collectors.toSet());
        // 3. 获取详情数据]
        List<Store> stores = Optional.of(storeIds)
                .filter(CollectionUtil::isNotEmpty)
                .map(storeService::listByIds)
                .map(storeService::getStoresByIds)
                .orElse(ListUtil.toList());
        stores.forEach(u -> u.setDeliveryDuration(distanceCalculation(criteria.getLatitude(), criteria.getLongitude(), u.getLatitude(), u.getLongitude())));
        page.setContent(stores);
        page.setTotalElements(total);
        return page;
    }
    private Integer distanceCalculation(double lat1, double lon1, double lat2, double lon2) {
        // 地球半径(千米)
        final int R = 6371;
        // 将纬度、经度从度转换为弧度
        double latDistance = Math.toRadians(lat2 - lat1);
        double lonDistance = Math.toRadians(lon2 - lon1);
        double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
                + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
                * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        return new Double(R * c * 1000).intValue();
    }
}
oying-system/src/main/java/com/oying/modules/pc/store/service/impl/StoreServiceImpl.java
@@ -1,7 +1,5 @@
package com.oying.modules.pc.store.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -9,21 +7,15 @@
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.oying.exception.BadRequestException;
import com.oying.exception.EntityNotFoundException;
import com.oying.modules.pc.common.ValueUpdate;
import com.oying.modules.pc.store.converter.StoreAssembler;
import com.oying.modules.pc.store.converter.StoreQualificationAssembler;
import com.oying.modules.pc.store.domain.Store;
import com.oying.modules.pc.store.domain.StoreQualification;
import com.oying.modules.pc.store.domain.StoreUser;
import com.oying.modules.pc.store.domain.dto.StoreCreateRequest;
import com.oying.modules.pc.store.domain.dto.StoreQualificationCreateRequest;
import com.oying.modules.pc.store.domain.dto.StoreQueryCriteria;
import com.oying.modules.pc.store.domain.dto.StoreUpdateRequest;
import com.oying.modules.pc.store.mapper.StoreMapper;
import com.oying.modules.pc.store.mapper.StoreUserMapper;
import com.oying.modules.pc.store.service.StoreQualificationService;
import com.oying.modules.pc.store.service.StoreService;
import com.oying.service.BucketStorageService;
import com.oying.utils.PageResult;
import com.oying.utils.PageUtil;
import com.oying.utils.SecurityUtils;
@@ -35,11 +27,10 @@
import java.math.BigDecimal;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.Set;
/**
 * 店铺Service业务层处理
@@ -54,8 +45,6 @@
    private final StoreMapper storeMapper;
    private final StoreUserMapper storeUserMapper;
    private final StoreQualificationService qualificationService;
    private final BucketStorageService bucketStorageService;
    @Override
    public PageResult<Store> queryByPage(StoreQueryCriteria criteria) {
@@ -69,13 +58,44 @@
    }
    @Override
    public List<Long> queryStoreIds(StoreQueryCriteria criteria) {
        return storeMapper.queryStoreIds(criteria);
    }
    @Override
    public Store getMerchantStore(Long merchantId) {
        return storeMapper.selectStoreByMerchantId(merchantId);
    }
    @Override
    public List<Store> queryUserStores(Long userId) {
    public List<Store> getStoresByIds(Set<Long> ids) {
        return storeMapper.queryByIds(ids);
    }
    @Override
    public List<Store> getUserStores(Long userId) {
        return storeMapper.queryUserStores(userId);
    }
    @Override
    public Store getOrThrow(Long storeId, Long version) {
        Objects.requireNonNull(storeId, String.format("方法 '%s' 调用失败:参数 'storeId'(店铺ID)不能为 null", "findOrThrow"));
        LambdaQueryWrapper<Store> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Store::getStoreId, storeId);
        if (ObjUtil.isNotEmpty(version)) {
            wrapper.eq(Store::getVersion, version);
        }
        Store existingStore = storeMapper.selectOne(wrapper);
        if (ObjUtil.isEmpty(existingStore)) {
            throw new EntityNotFoundException(Store.class, "storeId", storeId.toString());
        }
        return existingStore;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(Store resources) {
        storeMapper.insert(resources);
    }
    @Override
@@ -88,17 +108,26 @@
        // 创建店铺
        Store store = StoreAssembler.to(request);
        storeMapper.insert(store);
        this.processQualificationCreate(store, request.getQualificationList());
        this.bindUser(store.getStoreId());
        return store;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean update(Store resources, boolean isDirectUpdate) {
        LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(resources.getStoreId(), resources.getVersion());
        if (isDirectUpdate) {
            return this.update(resources, wrapper);
        } else {
            Store existingStore = this.getById(resources.getStoreId());
            existingStore.copy(resources);
            return this.update(existingStore, wrapper);
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean update(StoreUpdateRequest request) {
        Store existingStore = this.findOrThrow(request);
        this.processImagesUpdate(request, existingStore);
        this.processQualificationUpdate(request);
        Store existingStore = this.getOrThrow(request.getStoreId(), request.getVersion());
        existingStore.copy(StoreAssembler.to(request));
        LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(existingStore.getStoreId(), existingStore.getVersion());
        return this.update(existingStore, wrapper);
@@ -106,16 +135,16 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateLogo(Long storeId, String logo, Long version) {
        Store existingStore = this.findOrThrow(storeId, version);
    public boolean updateLogo(Long storeId, Long logoImageId, Long version) {
        Store existingStore = this.getOrThrow(storeId, version);
        LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion())
                .set(Store::getLogoImageId, logo);
                .set(Store::getLogoImageId, logoImageId);
        return update(wrapper);
    }
    @Override
    public boolean updateName(Long storeId, String storeName, Long version) {
        Store existingStore = this.findOrThrow(storeId, version);
        Store existingStore = this.getOrThrow(storeId, version);
        LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion())
                .set(Store::getStoreName, storeName);
        return update(wrapper);
@@ -123,7 +152,7 @@
    @Override
    public boolean updateDescription(Long storeId, String description, Long version) {
        Store existingStore = this.findOrThrow(storeId, version);
        Store existingStore = this.getOrThrow(storeId, version);
        LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion())
                .set(Store::getDescription, description);
        return update(wrapper);
@@ -131,7 +160,7 @@
    @Override
    public boolean updateContactPhone(Long storeId, String contactPhone, Long version) {
        Store existingStore = this.findOrThrow(storeId, version);
        Store existingStore = this.getOrThrow(storeId, version);
        LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion())
                .set(Store::getContactPhone, contactPhone);
        return update(wrapper);
@@ -139,7 +168,7 @@
    @Override
    public boolean updateAddress(Long storeId, String address, Long version) {
        Store existingStore = this.findOrThrow(storeId, version);
        Store existingStore = this.getOrThrow(storeId, version);
        LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion())
                .set(Store::getAddress, address);
        return update(wrapper);
@@ -147,7 +176,7 @@
    @Override
    public boolean updateLocation(Long storeId, Double longitude, Double latitude, Long version) {
        Store existingStore = this.findOrThrow(storeId, version);
        Store existingStore = this.getOrThrow(storeId, version);
        LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion())
                .set(Store::getLongitude, longitude)
                .set(Store::getLatitude, latitude);
@@ -156,7 +185,7 @@
    @Override
    public boolean updateRadius(Long storeId, Integer radius, Long version) {
        Store existingStore = this.findOrThrow(storeId, version);
        Store existingStore = this.getOrThrow(storeId, version);
        LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion())
                .set(Store::getRadius, radius);
        return update(wrapper);
@@ -164,7 +193,7 @@
    @Override
    public boolean updatePlatformCategory(Long storeId, Long platformCategory, Long version) {
        Store existingStore = this.findOrThrow(storeId, version);
        Store existingStore = this.getOrThrow(storeId, version);
        LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion())
                .set(Store::getPlatformCategoryId, platformCategory);
        return update(wrapper);
@@ -172,7 +201,7 @@
    @Override
    public boolean updateBusinessHours(Long storeId, LocalTime openTime, LocalTime endTime, Long version) {
        Store existingStore = this.findOrThrow(storeId, version);
        Store existingStore = this.getOrThrow(storeId, version);
        LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion())
                .set(Store::getOpenTime, openTime)
                .set(Store::getCloseTime, endTime);
@@ -181,7 +210,7 @@
    @Override
    public boolean updateDeliveryMinimum(Long storeId, BigDecimal deliveryMinimum, Long version) {
        Store existingStore = this.findOrThrow(storeId, version);
        Store existingStore = this.getOrThrow(storeId, version);
        LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion())
                .set(Store::getDeliveryMinimum, deliveryMinimum);
        return update(wrapper);
@@ -189,7 +218,7 @@
    @Override
    public boolean updateDeliveryFee(Long storeId, BigDecimal deliveryFee, Long version) {
        Store existingStore = this.findOrThrow(storeId, version);
        Store existingStore = this.getOrThrow(storeId, version);
        LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion())
                .set(Store::getDeliveryFee, deliveryFee);
        return update(wrapper);
@@ -197,7 +226,7 @@
    @Override
    public boolean updateStatus(Long storeId, Integer status, Long version) {
        Store existingStore = this.findOrThrow(storeId, version);
        Store existingStore = this.getOrThrow(storeId, version);
        LambdaUpdateWrapper<Store> wrapper = this.createLambdaUpdateWrapper(storeId, existingStore.getVersion())
                .set(Store::getStatus, status);
        return update(wrapper);
@@ -214,32 +243,23 @@
    }
    @Override
    public boolean existsByIdAndMerchantId(Long storeId, Long merchantId) {
        if (storeId == null || merchantId == null) {
            return false;
        }
        Store store = getById(storeId);
        return Optional.ofNullable(store).map(i -> merchantId.equals(i.getMerchantId())).orElse(false);
    }
    private void processQualificationCreate(Store store, List<StoreQualificationCreateRequest> qualificationRequests) {
        if (CollectionUtil.isNotEmpty(qualificationRequests)) {
            List<StoreQualification> storeQualificationList = qualificationRequests.stream().map(i -> {
                i.setStoreId(store.getStoreId());
                return StoreQualificationAssembler.to(i);
            }).collect(Collectors.toList());
            storeQualificationList.forEach(i -> i.setStoreId(store.getStoreId()));
            qualificationService.batchCreate(storeQualificationList);
        }
    }
    private void bindUser(Long storeId) {
    public boolean bindUser(Long storeId) {
        StoreUser storeUser = new StoreUser();
        storeUser.setStoreId(storeId);
        storeUser.setUserId(SecurityUtils.getCurrentUserId());
        storeUser.setRoleType("");
        storeUser.setPermissions("");
        storeUserMapper.insert(storeUser);
        return true;
    }
    @Override
    public boolean existsByIdAndMerchantId(Long storeId, Long merchantId) {
        if (storeId == null || merchantId == null) {
            return false;
        }
        Store store = getById(storeId);
        return Optional.ofNullable(store).map(i -> merchantId.equals(i.getMerchantId())).orElse(false);
    }
    private LambdaUpdateWrapper<Store> createLambdaUpdateWrapper(Long storeId, Long version) {
@@ -250,55 +270,6 @@
            updateWrapper.eq(Store::getVersion, version);
            updateWrapper.set(Store::getVersion, version + 1);
        }
        updateWrapper.set(Store::getUpdateBy, SecurityUtils.getCurrentUserId());
        return updateWrapper;
    }
    private Store findOrThrow(StoreUpdateRequest request) {
        return this.findOrThrow(request.getStoreId(), request.getVersion());
    }
    private Store findOrThrow(Long storeId, Long version) {
        Objects.requireNonNull(storeId, String.format("方法 '%s' 调用失败:参数 'storeId'(店铺ID)不能为 null", "findOrThrow"));
        LambdaQueryWrapper<Store> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Store::getStoreId, storeId);
        if (ObjUtil.isNotEmpty(version)) {
            wrapper.eq(Store::getVersion, version);
        }
        Store existingStore = storeMapper.selectOne(wrapper);
        if (ObjUtil.isEmpty(existingStore)) {
            throw new EntityNotFoundException(Store.class, "storeId", storeId.toString());
        }
        return existingStore;
    }
    private List<Long> getDeleteImageIds(List<ValueUpdate<Long>> imageValues) {
        List<Long> deleteImageIds = new ArrayList<>();
        for (ValueUpdate<Long> imageValue : imageValues) {
            if (imageValue.isChangeAndOldValueNotEmpty()) {
                deleteImageIds.add(imageValue.getOldValue());
            }
        }
        return deleteImageIds;
    }
    private void processImagesUpdate(StoreUpdateRequest request, Store existingStore) {
        List<ValueUpdate<Long>> imageValues = ListUtil.toList(
                new ValueUpdate<>(request.getLogoImageId(), existingStore.getLogoImageId()),
                new ValueUpdate<>(request.getCoverImageId(), existingStore.getCoverImageId())
        );
        bucketStorageService.deleteAll(this.getDeleteImageIds(imageValues));
    }
    private void processQualificationUpdate(StoreUpdateRequest request) {
        if (CollectionUtil.isNotEmpty(request.getDeletedQualificationIds())) {
            qualificationService.deleteAll(request.getDeletedQualificationIds());
        }
        if (CollectionUtil.isNotEmpty(request.getUpdatedQualifications())) {
            qualificationService.batchUpdate(request.getUpdatedQualifications());
        }
        if (CollectionUtil.isNotEmpty(request.getNewQualifications())) {
            qualificationService.batchCreate(request.getNewQualifications());
        }
    }
}
oying-system/src/main/java/com/oying/modules/sh/domain/request/StatusOrder.java
New file
@@ -0,0 +1,18 @@
package com.oying.modules.sh.domain.request;
import com.oying.utils.enums.OrderStatusEnum;
import lombok.Getter;
import lombok.Setter;
/**
 * @author xin
 * @description
 * @date 2025/7/15 14:41
 */
@Getter
@Setter
public class StatusOrder {
    private String orderNum;
    private OrderStatusEnum status;
}
oying-system/src/main/java/com/oying/modules/sh/domain/vo/OrderResponse.java
@@ -3,6 +3,7 @@
import com.oying.modules.sh.domain.Order;
import com.oying.modules.sh.domain.OrderAddressSnapshot;
import com.oying.modules.sh.domain.OrderOperationLog;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
@@ -15,6 +16,7 @@
 */
@Getter
@Setter
@AllArgsConstructor
public class OrderResponse {
    private Order order;
oying-system/src/main/java/com/oying/modules/sh/mapper/OrderMapper.java
@@ -28,7 +28,7 @@
    void updatePayStatus(String orderNum, String payState, String payMessage, String payTime);
    void updateCloseStatus(String orderNum, String payState);
    void updateCloseStatus(String orderNum, String payState, String payMessage);
    void updateOrderStatus(String orderNum, Integer key, String value);
}
oying-system/src/main/java/com/oying/modules/sh/rest/OrderController.java
@@ -3,6 +3,7 @@
import com.oying.annotation.Log;
import com.oying.modules.sh.domain.Order;
import com.oying.modules.sh.domain.request.GeneratorOrder;
import com.oying.modules.sh.domain.request.StatusOrder;
import com.oying.modules.sh.domain.request.SubmitOrder;
import com.oying.modules.sh.service.OrderService;
import com.oying.modules.sh.domain.dto.OrderQueryCriteria;
@@ -76,6 +77,14 @@
        return new ResponseEntity<>(R.success(orderService.generatorOrder(generator)), HttpStatus.CREATED);
    }
    @PostMapping("status")
    @Log("更新订单状态")
    @ApiOperation("更新订单状态")
    public ResponseEntity<Object> statusOrder(@Validated @RequestBody StatusOrder statusOrder) {
        orderService.statusOrder(statusOrder);
        return new ResponseEntity<>(R.success(), HttpStatus.CREATED);
    }
    @PostMapping("submit")
    @Log("小程序:提交订单")
    @ApiOperation("小程序:提交订单")
oying-system/src/main/java/com/oying/modules/sh/service/OrderOperationLogService.java
@@ -1,7 +1,5 @@
package com.oying.modules.sh.service;
import com.oying.modules.sh.domain.Order;
import com.oying.modules.sh.domain.OrderAddressSnapshot;
import com.oying.modules.sh.domain.OrderOperationLog;
import com.oying.modules.sh.domain.dto.OrderOperationLogQueryCriteria;
import java.util.List;
@@ -9,7 +7,9 @@
import javax.servlet.http.HttpServletResponse;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.oying.modules.sh.domain.vo.OrderResponse;
import com.oying.utils.PageResult;
import com.oying.utils.enums.OrderStatusEnum;
/**
* @description 服务接口
@@ -34,15 +34,9 @@
    List<OrderOperationLog> queryAll(OrderOperationLogQueryCriteria criteria);
    /**
    * 创建
    * @param resources /
    */
    void create(OrderOperationLog resources);
    /**
     * 创建
     */
    void create(Order order, OrderAddressSnapshot addressSnapshot);
    void create(OrderResponse response, OrderStatusEnum statusEnum);
    /**
    * 编辑
oying-system/src/main/java/com/oying/modules/sh/service/OrderService.java
@@ -11,10 +11,12 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.oying.modules.sh.domain.request.GeneratorOrder;
import com.oying.modules.sh.domain.request.StatusOrder;
import com.oying.modules.sh.domain.request.SubmitOrder;
import com.oying.modules.sh.domain.vo.OrderInfo;
import com.oying.modules.sh.domain.vo.OrderResponse;
import com.oying.utils.PageResult;
import com.oying.utils.enums.OrderStatusEnum;
import com.oying.utils.enums.PayStateEnum;
/**
@@ -47,7 +49,7 @@
    OrderResponse getByOrderNum(String orderNum);
    void paySuccess(OrderResponse order);
    void operationLog(OrderResponse order, OrderStatusEnum stateEnum);
    void updatePayStatus(String outTradeNo, PayStateEnum stateEnum, String payInfo, String timeEnd);
@@ -82,4 +84,6 @@
    void download(List<Order> all, HttpServletResponse response) throws IOException;
    void closeOrder(String orderNum);
    void statusOrder(StatusOrder statusOrder);
}
oying-system/src/main/java/com/oying/modules/sh/service/impl/OrderOperationLogServiceImpl.java
@@ -1,9 +1,9 @@
package com.oying.modules.sh.service.impl;
import com.alibaba.fastjson2.JSON;
import com.oying.modules.sh.domain.Order;
import com.oying.modules.sh.domain.OrderAddressSnapshot;
import com.oying.modules.sh.domain.OrderOperationLog;
import com.oying.modules.sh.domain.vo.OrderResponse;
import com.oying.modules.sh.mapper.OrderMapper;
import com.oying.utils.*;
import com.oying.utils.enums.OrderStatusEnum;
import lombok.RequiredArgsConstructor;
@@ -33,6 +33,7 @@
public class OrderOperationLogServiceImpl extends ServiceImpl<OrderOperationLogMapper, OrderOperationLog> implements OrderOperationLogService {
    private final OrderOperationLogMapper orderOperationLogMapper;
    private final OrderMapper orderMapper;
    @Override
    public PageResult<OrderOperationLog> queryAll(OrderOperationLogQueryCriteria criteria, Page<Object> page) {
@@ -51,27 +52,40 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(OrderOperationLog resources) {
        orderOperationLogMapper.insert(resources);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(Order order, OrderAddressSnapshot addressSnapshot) {
        Map<String, Object> map = new LinkedHashMap<>();
        map.put("order", order);
        map.put("address", addressSnapshot);
    public void create(OrderResponse response, OrderStatusEnum statusEnum) {
        String userType = ConstantsKey.BUYER;
        switch (statusEnum) {
            case ZERO:
            case ONE:
            case EIGHT:
            case NINE:
                userType = ConstantsKey.BUYER;
                break;
            case TWO:
            case FOUR:
                userType = ConstantsKey.MERCHANT;
                break;
            case THREE:
            case FIVE:
            case SIX:
            case SEVEN:
                userType = ConstantsKey.RIDER;
                break;
            default:
        }
        String username = SecurityUtils.getCurrentUsername();
        Timestamp time = new Timestamp(System.currentTimeMillis());
        OrderOperationLog resources = new OrderOperationLog();
        resources.setOrderNum(order.getOrderNum());
        resources.setOrderNum(response.getOrder().getOrderNum());
        resources.setUsername(username);
        resources.setUserType(ConstantsKey.BUYER);
        resources.setOperation(OrderStatusEnum.ZERO.getKey());
        resources.setOperationDescribe(OrderStatusEnum.ZERO.getValue());
        resources.setRemark(username + ":" + time + ">" + OrderStatusEnum.ZERO.getValue() + ":" + order.getOrderNum());
        resources.setSnapshotData(JSON.toJSONString(map));
        resources.setUserType(userType);
        resources.setOperation(statusEnum.getKey());
        resources.setOperationDescribe(statusEnum.getValue());
        resources.setRemark(username + ":" + time + ">" + statusEnum.getValue() + ":" + response.getOrder().getOrderNum());
        resources.setSnapshotData(JSON.toJSONString(response));
        resources.setOperationTime(time);
        orderOperationLogMapper.insert(resources);
        orderMapper.updateOrderStatus(response.getOrder().getOrderNum(), statusEnum.getKey(), statusEnum.getValue());
    }
    @Override
oying-system/src/main/java/com/oying/modules/sh/service/impl/OrderServiceImpl.java
@@ -12,6 +12,7 @@
import com.oying.modules.sh.domain.*;
import com.oying.modules.sh.domain.request.GeneratorOrder;
import com.oying.modules.sh.domain.request.ProductOrder;
import com.oying.modules.sh.domain.request.StatusOrder;
import com.oying.modules.sh.domain.request.SubmitOrder;
import com.oying.modules.sh.domain.vo.OrderInfo;
import com.oying.modules.sh.domain.vo.OrderResponse;
@@ -173,7 +174,9 @@
        productSnapshotService.saveBatch(snapshots);
        order.setProductSnapshots(new HashSet<>(snapshots));
        operationLogService.create(order, addressSnapshot);
        OrderResponse response = new OrderResponse(order, addressSnapshot, null);
        operationLogService.create(response, OrderStatusEnum.ZERO);
        return order;
    }
@@ -235,18 +238,22 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderResponse getByOrderNum(String orderNum) {
        OrderResponse response = new OrderResponse();
        response.setOrder(orderMapper.getByOrderNum(orderNum));
        response.setAddress(addressSnapshotService.queryByOrderNum(orderNum));
        response.setOperation(operationLogService.getByOrderNum(orderNum));
        return response;
    public void statusOrder(StatusOrder statusOrder) {
        operationLog(getByOrderNum(statusOrder.getOrderNum()), statusOrder.getStatus());
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void paySuccess(OrderResponse order) {
        orderMapper.updateOrderStatus(order.getOrder().getOrderNum(), OrderStatusEnum.TWO.getKey(), OrderStatusEnum.TWO.getValue());
    public OrderResponse getByOrderNum(String orderNum) {
        return new OrderResponse(orderMapper.getByOrderNum(orderNum),
                addressSnapshotService.queryByOrderNum(orderNum),
                operationLogService.getByOrderNum(orderNum));
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void operationLog(OrderResponse order, OrderStatusEnum stateEnum) {
        operationLogService.create(order, stateEnum);
    }
    @Override
@@ -258,25 +265,30 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void closeOrder(String orderNum) {
        Order order = orderMapper.getByOrderNum(orderNum);
        OrderResponse response = getByOrderNum(orderNum);
        Order order = response.getOrder();
        if (order == null) {
            throw new BadRequestException("订单不存在");
        }
        if (!SecurityUtils.getCurrentUserId().equals(order.getUserId())) {
            throw new BadRequestException("不能修改他人订单");
        }
        if (!order.getPayState().equals(PayStateEnum.NOTPAY.getKey())) {
            throw new BadRequestException(PayStateEnum.getValue(order.getPayState()));
        }
        PayTypeEnum anEnum = PayTypeEnum.find(order.getPayType());
        switch (anEnum) {
            case HWC:
            case HWC2:
                JSONObject object = swiftPassService.query(orderNum, anEnum);
                if (object.getString("trade_state").equals(PayStateEnum.SUCCESS.getKey())) {
                    throw new BadRequestException("订单已支付");
                }
                if (object.getString("trade_state").equals(PayStateEnum.CLOSED.getKey())) {
                    throw new BadRequestException("订单已关闭");
                if (object.getString("trade_state").equals(PayStateEnum.NOTPAY.getKey())) {
                    throw new BadRequestException(PayStateEnum.getValue(order.getPayState()));
                }
                swiftPassService.closeOrder(orderNum, anEnum);
                break;
        }
        orderMapper.updateCloseStatus(orderNum, PayStateEnum.CLOSED.getKey());
        operationLogService.create(response, OrderStatusEnum.NINE);
        orderMapper.updateCloseStatus(orderNum, PayStateEnum.CLOSED.getKey(), PayStateEnum.CLOSED.getValue());
    }
    @Override
oying-system/src/main/resources/config/application.yml
@@ -34,7 +34,7 @@
  redis:
    #数据库索引
    database: 0
    host: 192.168.18.13
    host: 127.0.0.1
    port: 6379
    password:
    #连接超时时间
oying-system/src/main/resources/mapper/message/MessageOrderSellerMapper.xml
@@ -63,6 +63,11 @@
        set flag = 1
        where order_id = #{orderId}
    </update>
    <update id="updateReadStatusById">
        update message_order_seller
        set flag = 1
        where id = #{id}
    </update>
</mapper>
oying-system/src/main/resources/mapper/pc/product/ProductAuditMapper.xml
New file
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.oying.modules.pc.product.mapper.ProductAuditMapper">
    <resultMap id="BaseResultMap" type="com.oying.modules.pc.product.domain.ProductAudit">
        <id column="audit_id" property="auditId"/>
        <result column="product_id" property="productId"/>
        <result column="type" property="type"/>
        <result column="status" property="status"/>
        <result column="data" property="data"/>
        <result column="reason" property="reason"/>
        <result column="auditor" property="auditor"/>
        <result column="audit_time" property="auditTime"/>
        <result column="create_by" property="createBy"/>
        <result column="create_time" property="createTime"/>
        <result column="update_by" property="updateBy"/>
        <result column="update_time" property="updateTime"/>
    </resultMap>
    <sql id="Base_Column_List">
        audit_id, product_id, type, status, reason, auditor, audit_time, data, create_by, create_time, update_by, update_time
    </sql>
    <select id="findAll" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List"/>
        from pc_product_audit
        <where>
            <if test="criteria.productId != null">
                and product_id = #{criteria.productId}
            </if>
            <if test="criteria.type != null and criteria.type != ''">
                and type = #{criteria.type}
            </if>
        </where>
        order by audit_id desc
    </select>
</mapper>
oying-system/src/main/resources/mapper/pc/store/StoreAuditMapper.xml
New file
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.oying.modules.pc.store.mapper.StoreAuditMapper">
    <resultMap id="BaseResultMap" type="com.oying.modules.pc.store.domain.StoreAudit">
        <id column="audit_id" property="auditId"/>
        <result column="store_id" property="storeId"/>
        <result column="type" property="type"/>
        <result column="status" property="status"/>
        <result column="data" property="data"/>
        <result column="reason" property="reason"/>
        <result column="auditor" property="auditor"/>
        <result column="audit_time" property="auditTime"/>
        <result column="create_by" property="createBy"/>
        <result column="create_time" property="createTime"/>
        <result column="update_by" property="updateBy"/>
        <result column="update_time" property="updateTime"/>
    </resultMap>
    <sql id="Base_Column_List">
        audit_id, store_id, type, status, reason, auditor, audit_time, data, create_by, create_time, update_by, update_time
    </sql>
    <select id="findAll" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List"/>
        from pc_store_audit
        <where>
            <if test="criteria.storeId != null">
                and store_id = #{criteria.storeId}
            </if>
            <if test="criteria.type != null and criteria.type != ''">
                and type = #{criteria.type}
            </if>
        </where>
        order by audit_id desc
    </select>
</mapper>
oying-system/src/main/resources/mapper/pc/store/StoreMapper.xml
@@ -13,8 +13,12 @@
        <result property="storeName" column="store_name"/>
        <result property="businessScope" column="business_scope"/>
        <result property="status" column="status"/>
        <result property="businessStatus" column="business_status"/>
        <result property="auditStatus" column="audit_status"/>
        <result property="logoImageId" column="logo_image_id"/>
        <result property="logoImageUrl" column="logo_image_url"/>
        <result property="coverImageId" column="cover_image_id"/>
        <result property="coverImageUrl" column="cover_image_url"/>
        <result property="description" column="description"/>
        <result property="tags" column="tags"/>
        <result property="deliveryFee" column="delivery_fee"/>
@@ -28,25 +32,25 @@
        <result property="geoHash" column="geo_hash"/>
        <result property="coordinateSystem" column="coordinate_system"/>
        <result property="radius" column="radius"/>
        <result column="returns" property="returns"/>
        <result column="self_pickup" property="selfPickup"/>
        <result property="returns" column="returns" />
        <result property="selfPickup" column="self_pickup"/>
        <result property="createBy" column="create_by"/>
        <result property="createTime" column="create_time"/>
        <result property="updateBy" column="update_by"/>
        <result property="updateTime" column="update_time"/>
        <result column="version" property="version"/>
        <result property="version" column="version"/>
    </resultMap>
    <sql id="store_column_list">
        store_id, merchant_id, platform_category_id, store_type, store_code, store_name, business_scope, status, logo_image_id,
        cover_image_id, description, tags, delivery_fee, delivery_minimum, contact_phone, open_time, close_time,
        store_id, merchant_id, platform_category_id, store_type, store_code, store_name, business_scope, status, business_status, audit_status, logo_image_id, logo_image_url,
        cover_image_id, cover_image_url, description, tags, delivery_fee, delivery_minimum, contact_phone, open_time, close_time,
        address, longitude, latitude, geo_hash, geo_point, coordinate_system, radius, returns, self_pickup, create_by, create_time, update_by, update_time, version
    </sql>
    <sql id="selectStoreVo">
        select
        store_id, merchant_id, platform_category_id, store_type, store_code, store_name, business_scope, status, logo_image_id,
        cover_image_id, description, tags, delivery_fee, delivery_minimum, contact_phone, open_time, close_time,
        store_id, merchant_id, platform_category_id, store_type, store_code, store_name, business_scope, status, business_status, audit_status, logo_image_id, logo_image_url,
        cover_image_id, cover_image_url, description, tags, delivery_fee, delivery_minimum, contact_phone, open_time, close_time,
        address, longitude, latitude, geo_hash, geo_point, coordinate_system, radius, returns, self_pickup, create_by, create_time, update_by, update_time, version from pc_store
    </sql>
@@ -126,8 +130,8 @@
            </if>
            <!-- 营业状态 -->
            <if test="criteria.status != null">
                AND s.status = #{criteria.status}
            <if test="criteria.businessStatus != null">
                AND s.business_status = #{criteria.businessStatus}
            </if>
            <!-- 类目ID -->
@@ -140,6 +144,16 @@
        </if>
    </select>
    <select id="queryByIds" resultMap="StoreResult">
        SELECT
            <include refid="store_column_list"/>
        FROM pc_store
        WHERE store_id IN
        <foreach collection="ids" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
    </select>
    <select id="queryUserStores" parameterType="java.lang.Long" resultMap="StoreResult">
        SELECT s.*
        FROM sys_user_store u INNER JOIN pc_store s ON u.store_id = s.store_id
oying-system/src/main/resources/mapper/sh/OrderMapper.xml
@@ -136,13 +136,14 @@
    <update id="updateCloseStatus">
        update sh_order
        set pay_state = #{payState}
        set pay_state   = #{payState},
            pay_message = #{payMessage}
        where order_num = #{orderNum}
    </update>
    <update id="updateOrderStatus">
        update sh_order
        set order_status = #{key},
        set order_status          = #{key},
            order_status_describe = #{value}
        where order_num = #{orderNum}
    </update>