peng
2025-07-07 cffb16b1767f5a5282e953cce8e674bade546178
添加改价记录功能 修改结算流程 添加定时任务
10个文件已修改
36个文件已添加
2726 ■■■■■ 已修改文件
buyer-api/src/main/java/cn/lili/controller/order/AfterSaleBuyerController.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
buyer-api/src/main/java/cn/lili/controller/store/StoreBuyerController.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/goods/service/GoodsSkuService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/domain/entity/CommissionRecord.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/domain/entity/PriceChange.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/domain/form/CommissionRecordForm.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/domain/form/PriceChangeForm.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/domain/query/CommissionRecordQuery.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/domain/query/PriceChangeQuery.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/domain/vo/CommissionRecordVO.java 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/domain/vo/PriceChangeVO.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/enums/general/ChangePriceAudioStatusEnum.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/enums/general/ChangePriceOperationTypeEnum.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/mapper/CommissionRecordMapper.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/mapper/PriceChangeMapper.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/service/CommissionRecordService.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/service/PriceChangeService.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/service/impl/CommissionRecordServiceImpl.java 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/lmk/service/impl/PriceChangeServiceImpl.java 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/order/cart/render/impl/CommissionRender.java 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/order/order/entity/dos/OrderItem.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/java/cn/lili/modules/order/order/serviceimpl/StoreFlowServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/resources/mapper/lmk/CommissionRecordMapper.xml 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
framework/src/main/resources/mapper/lmk/PriceChangeMapper.xml 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lmk-job/src/main/java/cn/lili/handler/EveryDayExecute.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lmk-job/src/main/java/cn/lili/handler/EveryHourExecute.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lmk-job/src/main/java/cn/lili/handler/EveryMinuteExecute.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lmk-job/src/main/java/cn/lili/handler/impl/broadcast/BroadcastExecute.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lmk-job/src/main/java/cn/lili/handler/impl/coupon/CouponExecute.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lmk-job/src/main/java/cn/lili/handler/impl/goods/GoodsExecute.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lmk-job/src/main/java/cn/lili/handler/impl/hotwords/HotWordsEveryDayTaskExecute.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lmk-job/src/main/java/cn/lili/handler/impl/order/CancelOrderTaskExecute.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lmk-job/src/main/java/cn/lili/handler/impl/order/OrderEveryDayTaskExecute.java 287 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lmk-job/src/main/java/cn/lili/handler/impl/order/RechargeOrderTaskExecute.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lmk-job/src/main/java/cn/lili/handler/impl/promotion/MemberCouponSignEverydayExecute.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lmk-job/src/main/java/cn/lili/handler/impl/promotion/PromotionEverydayExecute.java 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lmk-job/src/main/java/cn/lili/handler/impl/statistics/MemberStatisticsExecute.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lmk-job/src/main/java/cn/lili/handler/impl/statistics/OnlineMemberStatistics.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lmk-job/src/main/java/cn/lili/handler/impl/store/StoreExecute.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lmk-job/src/main/java/cn/lili/handler/impl/store/StoreRatingExecute.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lmk-job/src/main/java/cn/lili/handler/impl/view/PageViewStatisticsExecute.java 195 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
lmk-job/src/main/java/cn/lili/job/TimedTaskJobHandler.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
seller-api/src/main/java/cn/lili/controller/order/OrderStoreController.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
buyer-api/src/main/java/cn/lili/controller/order/AfterSaleBuyerController.java
@@ -3,6 +3,7 @@
import cn.lili.common.aop.annotation.PreventDuplicateSubmissions;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.security.OperationalJudgment;
import cn.lili.common.utils.StringUtils;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.order.aftersale.entity.dos.AfterSale;
import cn.lili.modules.order.aftersale.entity.dos.AfterSaleLog;
@@ -15,6 +16,7 @@
import cn.lili.modules.order.aftersale.service.AfterSaleReasonService;
import cn.lili.modules.order.aftersale.service.AfterSaleService;
import cn.lili.modules.store.entity.dto.StoreAfterSaleAddressDTO;
import cn.lili.utils.COSUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
@@ -55,6 +57,8 @@
    @Autowired
    private AfterSaleLogService afterSaleLogService;
    @Autowired
    private COSUtil cosUtil;
    @ApiOperation(value = "查看售后服务详情")
    @ApiImplicitParam(name = "sn", value = "售后单号", required = true, paramType = "path")
    @GetMapping(value = "/get/{sn}")
@@ -66,7 +70,14 @@
    @ApiOperation(value = "分页获取售后服务")
    @GetMapping(value = "/page")
    public ResultMessage<IPage<AfterSaleVO>> getByPage(AfterSaleSearchParams searchParams) {
        return ResultUtil.data(afterSaleService.getAfterSalePages(searchParams));
        IPage<AfterSaleVO> afterSalePages = afterSaleService.getAfterSalePages(searchParams);
        afterSalePages.getRecords().forEach(item->{
            String goodsImage = item.getGoodsImage();
            if (StringUtils.isNotBlank(goodsImage)&&!goodsImage.contains("http")) {
                item.setGoodsImage(cosUtil.getPreviewUrl(goodsImage));
            }
        });
        return ResultUtil.data(afterSalePages);
    }
    @ApiOperation(value = "获取申请售后页面信息")
buyer-api/src/main/java/cn/lili/controller/store/StoreBuyerController.java
@@ -3,6 +3,7 @@
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.security.AuthUser;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.utils.StringUtils;
import cn.lili.common.vo.PageVO;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.goods.entity.vos.StoreGoodsLabelVO;
@@ -14,6 +15,7 @@
import cn.lili.modules.store.entity.vos.*;
import cn.lili.modules.store.service.StoreDetailService;
import cn.lili.modules.store.service.StoreService;
import cn.lili.utils.COSUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
@@ -52,6 +54,8 @@
     */
    @Autowired
    private StoreDetailService storeDetailService;
    @Autowired
    private COSUtil cosUtil;
    @ApiOperation(value = "获取店铺列表分页")
    @GetMapping
@@ -77,7 +81,11 @@
    @ApiImplicitParam(name = "id", value = "店铺ID", required = true, paramType = "path")
    @GetMapping(value = "/get/detail/{id}")
    public ResultMessage<StoreBasicInfoVO> detail(@NotNull @PathVariable String id) {
        return ResultUtil.data(storeDetailService.getStoreBasicInfoDTO(id));
        StoreBasicInfoVO storeBasicInfoDTO = storeDetailService.getStoreBasicInfoDTO(id);
        if (StringUtils.isNotBlank(storeBasicInfoDTO.getStoreLogo())&&!storeBasicInfoDTO.getStoreLogo().contains("http")) {
            storeBasicInfoDTO.setStoreLogo(cosUtil.getPreviewUrl(storeBasicInfoDTO.getStoreLogo()));
        }
        return ResultUtil.data(storeBasicInfoDTO);
    }
    @ApiOperation(value = "通过id获取店铺详细信息-营业执照")
framework/src/main/java/cn/lili/modules/goods/service/GoodsSkuService.java
@@ -60,7 +60,7 @@
     * @param goods             商品信息
     * @param goodsOperationDTO 商品操作信息
     */
    void update(Goods goods, GoodsOperationDTO goodsOperationDTO);
    void update(Goods goods, GoodsOperationDTO goodsOperationDTO,Goods previousGoods);
    /**
     * 更新商品sku
framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsServiceImpl.java
@@ -47,7 +47,6 @@
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
@@ -218,10 +217,11 @@
        if (goodsOperationDTO.getGoodsParamsDTOList() != null && !goodsOperationDTO.getGoodsParamsDTOList().isEmpty()) {
            goods.setParams(JSONUtil.toJsonStr(goodsOperationDTO.getGoodsParamsDTOList()));
        }
        Goods previousGoods = this.getById(goodsId);
        //修改商品
        this.updateById(goods);
        //修改商品sku信息
        this.goodsSkuService.update(goods, goodsOperationDTO);
        this.goodsSkuService.update(goods, goodsOperationDTO,previousGoods);
        //添加相册
        if (goodsOperationDTO.getGoodsGalleryList() != null && !goodsOperationDTO.getGoodsGalleryList().isEmpty()) {
            this.goodsGalleryService.add(goodsOperationDTO.getGoodsGalleryList(), goods.getId());
framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java
@@ -37,7 +37,11 @@
import cn.lili.modules.goods.service.WholesaleService;
import cn.lili.modules.goods.sku.GoodsSkuBuilder;
import cn.lili.modules.goods.sku.render.SalesModelRender;
import cn.lili.modules.lmk.domain.entity.PriceChange;
import cn.lili.modules.lmk.enums.general.ChangePriceAudioStatusEnum;
import cn.lili.modules.lmk.enums.general.ChangePriceOperationTypeEnum;
import cn.lili.modules.lmk.enums.general.ViewTypeEnum;
import cn.lili.modules.lmk.service.PriceChangeService;
import cn.lili.modules.member.entity.dos.FootPrint;
import cn.lili.modules.promotion.entity.dos.Coupon;
import cn.lili.modules.promotion.entity.dos.PromotionGoods;
@@ -56,6 +60,7 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.poi.ss.usermodel.*;
@@ -73,8 +78,10 @@
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
@@ -137,6 +144,9 @@
    @Autowired
    private List<SalesModelRender> salesModelRenders;
    @Autowired
    private PriceChangeService priceChangeService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(Goods goods, GoodsOperationDTO goodsOperationDTO) {
@@ -151,12 +161,29 @@
        if (!goodsSkus.isEmpty()) {
            this.saveOrUpdateBatch(goodsSkus);
            this.updateGoodsStock(goodsSkus);
            //记录价格变动
            List<PriceChange> priceChangeList = goodsSkus.stream().map(item -> {
                PriceChange priceChange = new PriceChange();
                priceChange.setCurrentPrice(BigDecimal.valueOf(item.getPrice()));
                priceChange.setSkuId(item.getId());
                priceChange.setGoodsId(item.getGoodsId());
                priceChange.setPreviousPrice(BigDecimal.ZERO);
                priceChange.setPreviousCommission(BigDecimal.ZERO);
                priceChange.setCurrentCommission(goods.getCommission());
                priceChange.setOperatorType(ChangePriceOperationTypeEnum.STORE.name());
                priceChange.setExamineStatus(ChangePriceAudioStatusEnum.APPLY.name());
                priceChange.setOperatorId(UserContext.getCurrentUser().getId());
                priceChange.setOperatorName(UserContext.getCurrentUser().getNickName());
                priceChange.setStoreId(item.getStoreId());
                return priceChange;
            }).collect(Collectors.toList());
            priceChangeService.saveBatch(priceChangeList);
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Goods goods, GoodsOperationDTO goodsOperationDTO) {
    public void update(Goods goods, GoodsOperationDTO goodsOperationDTO,Goods previousGoods) {
        // 是否存在规格
        if (goodsOperationDTO.getSkuList() == null || goodsOperationDTO.getSkuList().isEmpty()) {
            throw new ServiceException(ResultCode.MUST_HAVE_GOODS_SKU);
@@ -199,9 +226,41 @@
            unnecessarySkuIdsQuery.eq(GoodsSku::getGoodsId, goods.getId());
            unnecessarySkuIdsQuery.notIn(GoodsSku::getId,
                    skuList.stream().map(BaseEntity::getId).collect(Collectors.toList()));
            LambdaQueryWrapper<GoodsSku> skuIdsQuery = new LambdaQueryWrapper<>();
            skuIdsQuery.eq(GoodsSku::getGoodsId, goods.getId());
            skuIdsQuery.in(GoodsSku::getId,
                    skuList.stream().map(BaseEntity::getId).collect(Collectors.toList()));
            Map<String, GoodsSku> skuMap = this.list(skuIdsQuery).stream().collect(Collectors.toMap(GoodsSku::getId, Function.identity()));
            this.remove(unnecessarySkuIdsQuery);
            this.saveOrUpdateBatch(skuList);
            this.updateGoodsStock(skuList);
            //记录价格变动
            //删除当前审核状态为申请的改价的商品 店铺id一致商品id一致且为申请状态的移除
            LambdaQueryWrapper<PriceChange> needRemove = Wrappers.<PriceChange>lambdaQuery()
                    .eq(PriceChange::getGoodsId, goods.getId())
                    .eq(PriceChange::getStoreId, goods.getStoreId())
                    .eq(PriceChange::getExamineStatus, ChangePriceAudioStatusEnum.APPLY.name());
            priceChangeService.remove(needRemove);
            //重新添加改价商品
            List<PriceChange> priceChangeList = skuList.stream().map(item -> {
                PriceChange priceChange = new PriceChange();
                priceChange.setCurrentPrice(BigDecimal.valueOf(item.getPrice()));
                GoodsSku goodsSku = skuMap.get(item.getId());
                priceChange.setSkuId(item.getId());
                priceChange.setGoodsId(item.getGoodsId());
                if (Objects.nonNull(goodsSku)) {
                    priceChange.setPreviousPrice(BigDecimal.valueOf(goodsSku.getPrice()));
                }
                priceChange.setPreviousCommission(previousGoods.getCommission());
                priceChange.setCurrentCommission(goods.getCommission());
                priceChange.setOperatorType(ChangePriceOperationTypeEnum.STORE.name());
                priceChange.setExamineStatus(ChangePriceAudioStatusEnum.APPLY.name());
                priceChange.setOperatorId(UserContext.getCurrentUser().getId());
                priceChange.setOperatorName(UserContext.getCurrentUser().getNickName());
                priceChange.setStoreId(item.getStoreId());
                return priceChange;
            }).collect(Collectors.toList());
            priceChangeService.saveBatch(priceChangeList);
        }
    }
@@ -389,6 +448,17 @@
        updateWrapper.set(GoodsSku::getDeleteFlag, goods.getDeleteFlag());
        boolean update = this.update(updateWrapper);
        if (Boolean.TRUE.equals(update)) {
            //修改订单改价状态为通过或者失败
            LambdaUpdateWrapper<PriceChange> updatePriceChange = Wrappers.<PriceChange>lambdaUpdate()
                    .eq(PriceChange::getGoodsId, goods.getId())
                    .eq(PriceChange::getStoreId, goods.getStoreId())
                    .eq(PriceChange::getExamineStatus, ChangePriceAudioStatusEnum.APPLY.name());
            if (GoodsAuthEnum.PASS.name().equals(goods.getAuthFlag())) {
                updatePriceChange.set(PriceChange::getExamineStatus, ChangePriceAudioStatusEnum.PASS.name());
            }else {
                updatePriceChange.set(PriceChange::getExamineStatus, ChangePriceAudioStatusEnum.REFUSE.name());
            }
            priceChangeService.update(updatePriceChange);
            List<GoodsSku> goodsSkus = this.getGoodsSkuListByGoodsId(goods.getId());
            for (GoodsSku sku : goodsSkus) {
                cache.remove(GoodsSkuService.getCacheKeys(sku.getId()));
framework/src/main/java/cn/lili/modules/lmk/domain/entity/CommissionRecord.java
New file
@@ -0,0 +1,92 @@
package cn.lili.modules.lmk.domain.entity;
import cn.lili.mybatis.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
 * 抽成记录表
 *
 * @author peng
 * @since 2025-07-04
 */
@Data
@TableName("lmk_commission_record")
public class CommissionRecord extends BaseEntity {
    private static final long serialVersionUID = 1L;
    @TableField("store_id")
    /** 店铺id */
    private Long storeId;
    @TableField("goods_id")
    /** 商品id */
    private Long goodsId;
    @TableField("sku_id")
    /** skuId */
    private Long skuId;
    @TableField("goods_name")
    /** 商品名称 */
    private String goodsName;
    @TableField("img_url")
    /** 商品图片地址 */
    private String imgUrl;
    @TableField("price")
    /** 商品单价 */
    private BigDecimal price;
    @TableField("num")
    /** 商品数量 */
    private BigDecimal num;
    @TableField("sum_price")
    /** 商品总价 */
    private BigDecimal sumPrice;
    @TableField("commission")
    /** 当前抽成比例 */
    private BigDecimal commission;
    @TableField("commission_price")
    /** 平台抽成金额 */
    private BigDecimal commissionPrice;
    @TableField("remain_money")
    /** 扣除平台抽成金额 */
    private BigDecimal remainMoney;
    @TableField("settlement_status")
    /** 结算订单状态 */
    private String settlementStatus;
    @TableField("can_settlement_time")
    /** 可以结算时间 */
    private LocalDateTime canSettlementTime;
    @TableField("trade_sn")
    /** 交易单号 */
    private String tradeSn;
    @TableField("sn")
    /** 子订单号 */
    private String sn;
    @TableField("type")
    /** 抽成类型(退款退佣金) */
    private String type;
    @TableField("delivery_status")
    /** 否确认收货 */
    private String deliveryStatus;
}
framework/src/main/java/cn/lili/modules/lmk/domain/entity/PriceChange.java
New file
@@ -0,0 +1,72 @@
package cn.lili.modules.lmk.domain.entity;
import cn.lili.modules.lmk.enums.general.ChangePriceAudioStatusEnum;
import cn.lili.mybatis.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
/**
 * 价格变动表
 *
 * @author peng
 * @since 2025-07-03
 */
@Data
@TableName("lmk_price_change")
public class PriceChange extends BaseEntity {
    private static final long serialVersionUID = 1L;
    @TableField("store_id")
    /** 店铺id */
    private String storeId;
    @TableField("goods_id")
    /** 商品id */
    private String goodsId;
    @TableField("sku_id")
    /** 最小销售单元id */
    private String skuId;
    @TableField("previous_price")
    /** 原价 */
    private BigDecimal previousPrice;
    @TableField("current_price")
    /** 现价 */
    private BigDecimal currentPrice;
    @TableField("previous_commission")
    /** 原抽成比例 */
    private BigDecimal previousCommission;
    @TableField("current_commission")
    /** 现在抽成比例 */
    private BigDecimal currentCommission;
    @TableField("operator_name")
    /** 操作人员姓名 */
    private String operatorName;
    @TableField("operator_id")
    /** 操作人员id */
    private String operatorId;
    @TableField("examine_status")
    /**
     * 审核状态
     *
     * @see  ChangePriceAudioStatusEnum
     * */
    private String examineStatus;
    @TableField("operator_type")
    /** 操作人员类型 */
    private String operatorType;
}
framework/src/main/java/cn/lili/modules/lmk/domain/form/CommissionRecordForm.java
New file
@@ -0,0 +1,104 @@
package cn.lili.modules.lmk.domain.form;
import cn.lili.base.AbsForm;
import cn.lili.group.Add;
import cn.lili.group.Update;
import cn.lili.modules.lmk.domain.entity.CommissionRecord;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.beans.BeanUtils;
import org.springframework.lang.NonNull;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.Date;
/**
 * 抽成记录表表单
 *
 * @author peng
 * @since 2025-07-04
 */
@Data
@ApiModel(value = "CommissionRecord表单", description = "抽成记录表表单")
public class CommissionRecordForm extends AbsForm {
    @NotNull(message = "店铺id不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("店铺id")
    private Long storeId;
    @NotNull(message = "商品id不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("商品id")
    private Long goodsId;
    @NotNull(message = "skuId不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("skuId")
    private Long skuId;
    @NotBlank(message = "商品名称不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("商品名称")
    private String goodsName;
    @NotBlank(message = "商品图片地址不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("商品图片地址")
    private String imgUrl;
    @NotNull(message = "商品单价不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("商品单价")
    private BigDecimal price;
    @NotNull(message = "商品数量不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("商品数量")
    private BigDecimal num;
    @NotNull(message = "商品总价不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("商品总价")
    private BigDecimal sumPrice;
    @NotNull(message = "当前抽成比例不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("当前抽成比例")
    private BigDecimal commission;
    @NotNull(message = "平台抽成金额不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("平台抽成金额")
    private BigDecimal commissionPrice;
    @NotNull(message = "扣除平台抽成金额不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("扣除平台抽成金额")
    private BigDecimal remainMoney;
    @NotBlank(message = "结算订单状态不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("结算订单状态")
    private String settlementStatus;
    @NotNull(message = "可以结算时间不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("可以结算时间")
    private Date canSettlementTime;
    @NotBlank(message = "交易单号不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("交易单号")
    private String tradeSn;
    @NotBlank(message = "子订单号不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("子订单号")
    private String sn;
    @NotBlank(message = "抽成类型(退款退佣金)不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("抽成类型(退款退佣金)")
    private String type;
    @NotBlank(message = "否确认收货不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("否确认收货")
    private String deliveryStatus;
    public static CommissionRecord getEntityByForm(@NonNull CommissionRecordForm form, CommissionRecord entity) {
        if(entity == null) {
          entity = new CommissionRecord();
        }
        BeanUtils.copyProperties(form, entity);
        return entity;
    }
}
framework/src/main/java/cn/lili/modules/lmk/domain/form/PriceChangeForm.java
New file
@@ -0,0 +1,79 @@
package cn.lili.modules.lmk.domain.form;
import cn.lili.base.AbsForm;
import cn.lili.group.Add;
import cn.lili.group.Update;
import cn.lili.modules.lmk.domain.entity.PriceChange;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.beans.BeanUtils;
import org.springframework.lang.NonNull;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
 * 价格变动表表单
 *
 * @author peng
 * @since 2025-07-03
 */
@Data
@ApiModel(value = "PriceChange表单", description = "价格变动表表单")
public class PriceChangeForm extends AbsForm {
    @NotNull(message = "店铺id不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("店铺id")
    private Long storeId;
    @NotNull(message = "商品id不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("商品id")
    private Long goodsId;
    @NotNull(message = "最小销售单元id不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("最小销售单元id")
    private Long skuId;
    @NotNull(message = "原价不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("原价")
    private BigDecimal previousPrice;
    @NotNull(message = "现价不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("现价")
    private BigDecimal currentPrice;
    @NotNull(message = "原抽成比例不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("原抽成比例")
    private BigDecimal previousCommission;
    @NotNull(message = "现在抽成比例不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("现在抽成比例")
    private BigDecimal currentCommission;
    @NotBlank(message = "操作人员姓名不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("操作人员姓名")
    private String operatorName;
    @NotNull(message = "操作人员id不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("操作人员id")
    private Long operatorId;
    @NotBlank(message = "审核状态不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("审核状态")
    private String examineStatus;
    @NotBlank(message = "操作人员类型不能为空", groups = {Add.class, Update.class})
    @ApiModelProperty("操作人员类型")
    private String operatorType;
    public static PriceChange getEntityByForm(@NonNull PriceChangeForm form, PriceChange entity) {
        if(entity == null) {
          entity = new PriceChange();
        }
        BeanUtils.copyProperties(form, entity);
        return entity;
    }
}
framework/src/main/java/cn/lili/modules/lmk/domain/query/CommissionRecordQuery.java
New file
@@ -0,0 +1,17 @@
package cn.lili.modules.lmk.domain.query;
import cn.lili.base.AbsQuery;
import io.swagger.annotations.ApiModel;
import lombok.Data;
/**
 * 抽成记录表查询
 *
 * @author peng
 * @since 2025-07-04
 */
@Data
@ApiModel(value = "CommissionRecord查询参数", description = "抽成记录表查询参数")
public class CommissionRecordQuery extends AbsQuery {
}
framework/src/main/java/cn/lili/modules/lmk/domain/query/PriceChangeQuery.java
New file
@@ -0,0 +1,17 @@
package cn.lili.modules.lmk.domain.query;
import cn.lili.base.AbsQuery;
import io.swagger.annotations.ApiModel;
import lombok.Data;
/**
 * 价格变动表查询
 *
 * @author peng
 * @since 2025-07-03
 */
@Data
@ApiModel(value = "PriceChange查询参数", description = "价格变动表查询参数")
public class PriceChangeQuery extends AbsQuery {
}
framework/src/main/java/cn/lili/modules/lmk/domain/vo/CommissionRecordVO.java
New file
@@ -0,0 +1,100 @@
package cn.lili.modules.lmk.domain.vo;
import cn.lili.base.AbsVo;
import cn.lili.modules.lmk.domain.entity.CommissionRecord;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.beans.BeanUtils;
import org.springframework.lang.NonNull;
import java.math.BigDecimal;
import java.util.Date;
/**
 * 抽成记录表展示
 *
 * @author peng
 * @since 2025-07-04
 */
@Data
@ApiModel(value = "抽成记录表响应数据", description = "抽成记录表响应数据")
public class CommissionRecordVO extends AbsVo {
    /** 店铺id */
    @ApiModelProperty("店铺id")
    private Long storeId;
    /** 商品id */
    @ApiModelProperty("商品id")
    private Long goodsId;
    /** skuId */
    @ApiModelProperty("skuId")
    private Long skuId;
    /** 商品名称 */
    @ApiModelProperty("商品名称")
    private String goodsName;
    /** 商品图片地址 */
    @ApiModelProperty("商品图片地址")
    private String imgUrl;
    /** 商品单价 */
    @ApiModelProperty("商品单价")
    private BigDecimal price;
    /** 商品数量 */
    @ApiModelProperty("商品数量")
    private BigDecimal num;
    /** 商品总价 */
    @ApiModelProperty("商品总价")
    private BigDecimal sumPrice;
    /** 当前抽成比例 */
    @ApiModelProperty("当前抽成比例")
    private BigDecimal commission;
    /** 平台抽成金额 */
    @ApiModelProperty("平台抽成金额")
    private BigDecimal commissionPrice;
    /** 扣除平台抽成金额 */
    @ApiModelProperty("扣除平台抽成金额")
    private BigDecimal remainMoney;
    /** 结算订单状态 */
    @ApiModelProperty("结算订单状态")
    private String settlementStatus;
    /** 可以结算时间 */
    @ApiModelProperty("可以结算时间")
    private Date canSettlementTime;
    /** 交易单号 */
    @ApiModelProperty("交易单号")
    private String tradeSn;
    /** 子订单号 */
    @ApiModelProperty("子订单号")
    private String sn;
    /** 抽成类型(退款退佣金) */
    @ApiModelProperty("抽成类型(退款退佣金)")
    private String type;
    /** 否确认收货 */
    @ApiModelProperty("否确认收货")
    private String deliveryStatus;
    public static CommissionRecordVO getVoByEntity(@NonNull CommissionRecord entity, CommissionRecordVO vo) {
        if(vo == null) {
            vo = new CommissionRecordVO();
        }
        BeanUtils.copyProperties(entity, vo);
        return vo;
    }
}
framework/src/main/java/cn/lili/modules/lmk/domain/vo/PriceChangeVO.java
New file
@@ -0,0 +1,75 @@
package cn.lili.modules.lmk.domain.vo;
import cn.lili.base.AbsVo;
import cn.lili.modules.lmk.domain.entity.PriceChange;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.beans.BeanUtils;
import org.springframework.lang.NonNull;
import java.math.BigDecimal;
/**
 * 价格变动表展示
 *
 * @author peng
 * @since 2025-07-03
 */
@Data
@ApiModel(value = "价格变动表响应数据", description = "价格变动表响应数据")
public class PriceChangeVO extends AbsVo {
    /** 店铺id */
    @ApiModelProperty("店铺id")
    private Long storeId;
    /** 商品id */
    @ApiModelProperty("商品id")
    private Long goodsId;
    /** 最小销售单元id */
    @ApiModelProperty("最小销售单元id")
    private Long skuId;
    /** 原价 */
    @ApiModelProperty("原价")
    private BigDecimal previousPrice;
    /** 现价 */
    @ApiModelProperty("现价")
    private BigDecimal currentPrice;
    /** 原抽成比例 */
    @ApiModelProperty("原抽成比例")
    private BigDecimal previousCommission;
    /** 现在抽成比例 */
    @ApiModelProperty("现在抽成比例")
    private BigDecimal currentCommission;
    /** 操作人员姓名 */
    @ApiModelProperty("操作人员姓名")
    private String operatorName;
    /** 操作人员id */
    @ApiModelProperty("操作人员id")
    private Long operatorId;
    /** 审核状态 */
    @ApiModelProperty("审核状态")
    private String examineStatus;
    /** 操作人员类型 */
    @ApiModelProperty("操作人员类型")
    private String operatorType;
    public static PriceChangeVO getVoByEntity(@NonNull PriceChange entity, PriceChangeVO vo) {
        if(vo == null) {
            vo = new PriceChangeVO();
        }
        BeanUtils.copyProperties(entity, vo);
        return vo;
    }
}
framework/src/main/java/cn/lili/modules/lmk/enums/general/ChangePriceAudioStatusEnum.java
New file
@@ -0,0 +1,29 @@
package cn.lili.modules.lmk.enums.general;
/**
 * 商品价格改动记录表审核状态
 *
 * @author peng
 * @since 2025-07-03 15:00
 */
public enum ChangePriceAudioStatusEnum {
    /**
     * 商品价格改动记录表审核状态
     */
    APPLY("申请中"),
    PASS("已通过"),
    REFUSE("已拒绝");
    private final String description;
    ChangePriceAudioStatusEnum(String description) {
        this.description = description;
    }
    public String description() {
        return description;
    }
}
framework/src/main/java/cn/lili/modules/lmk/enums/general/ChangePriceOperationTypeEnum.java
New file
@@ -0,0 +1,28 @@
package cn.lili.modules.lmk.enums.general;
/**
 * 商品价格改动记录表操作人员类型
 *
 * @author peng
 * @since 2025-07-03 15:00
 */
public enum ChangePriceOperationTypeEnum {
    /**
     * 商品价格改动记录表操作人员类型
     */
    PLATFORM("平台"),
    STORE("商家");
    private final String description;
    ChangePriceOperationTypeEnum(String description) {
        this.description = description;
    }
    public String description() {
        return description;
    }
}
framework/src/main/java/cn/lili/modules/lmk/mapper/CommissionRecordMapper.java
New file
@@ -0,0 +1,32 @@
package cn.lili.modules.lmk.mapper;
import cn.lili.modules.lmk.domain.entity.CommissionRecord;
import cn.lili.modules.lmk.domain.query.CommissionRecordQuery;
import cn.lili.modules.lmk.domain.vo.CommissionRecordVO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
 * 抽成记录表 Mapper 接口
 *
 * @author peng
 * @since 2025-07-04
 */
@Mapper
public interface CommissionRecordMapper extends BaseMapper<CommissionRecord> {
    /**
     * id查找抽成记录表
     * @param id
     * @return
     */
    CommissionRecordVO getById(String id);
    /**
    *  分页
    */
    IPage getPage(IPage page, @Param("query") CommissionRecordQuery query);
}
framework/src/main/java/cn/lili/modules/lmk/mapper/PriceChangeMapper.java
New file
@@ -0,0 +1,32 @@
package cn.lili.modules.lmk.mapper;
import cn.lili.modules.lmk.domain.entity.PriceChange;
import cn.lili.modules.lmk.domain.query.PriceChangeQuery;
import cn.lili.modules.lmk.domain.vo.PriceChangeVO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
 * 价格变动表 Mapper 接口
 *
 * @author peng
 * @since 2025-07-03
 */
@Mapper
public interface PriceChangeMapper extends BaseMapper<PriceChange> {
    /**
     * id查找价格变动表
     * @param id
     * @return
     */
    PriceChangeVO getById(String id);
    /**
    *  分页
    */
    IPage getPage(IPage page, @Param("query") PriceChangeQuery query);
}
framework/src/main/java/cn/lili/modules/lmk/service/CommissionRecordService.java
New file
@@ -0,0 +1,65 @@
package cn.lili.modules.lmk.service;
import cn.lili.modules.lmk.domain.entity.CommissionRecord;
import com.baomidou.mybatisplus.extension.service.IService;
import cn.lili.base.Result;
import cn.lili.modules.lmk.domain.form.CommissionRecordForm;
import cn.lili.modules.lmk.domain.query.CommissionRecordQuery;
import java.util.List;
/**
 * 抽成记录表 服务类
 *
 * @author peng
 * @since 2025-07-04
 */
public interface CommissionRecordService extends IService<CommissionRecord> {
    /**
     * 添加
     * @param form
     * @return
     */
    Result add(CommissionRecordForm form);
    /**
     * 修改
     * @param form
     * @return
     */
    Result update(CommissionRecordForm form);
    /**
     * 批量删除
     * @param ids
     * @return
     */
    Result remove(List<String> ids);
    /**
     * id删除
     * @param id
     * @return
     */
    Result removeById(String id);
    /**
     * 分页查询
     * @param query
     * @return
     */
    Result page(CommissionRecordQuery query);
    /**
     * 根据id查找
     * @param id
     * @return
     */
    Result detail(String id);
    /**
     * 列表
     * @return
     */
    Result all();
}
framework/src/main/java/cn/lili/modules/lmk/service/PriceChangeService.java
New file
@@ -0,0 +1,65 @@
package cn.lili.modules.lmk.service;
import cn.lili.modules.lmk.domain.entity.PriceChange;
import com.baomidou.mybatisplus.extension.service.IService;
import cn.lili.base.Result;
import cn.lili.modules.lmk.domain.form.PriceChangeForm;
import cn.lili.modules.lmk.domain.query.PriceChangeQuery;
import java.util.List;
/**
 * 价格变动表 服务类
 *
 * @author peng
 * @since 2025-07-03
 */
public interface PriceChangeService extends IService<PriceChange> {
    /**
     * 添加
     * @param form
     * @return
     */
    Result add(PriceChangeForm form);
    /**
     * 修改
     * @param form
     * @return
     */
    Result update(PriceChangeForm form);
    /**
     * 批量删除
     * @param ids
     * @return
     */
    Result remove(List<String> ids);
    /**
     * id删除
     * @param id
     * @return
     */
    Result removeById(String id);
    /**
     * 分页查询
     * @param query
     * @return
     */
    Result page(PriceChangeQuery query);
    /**
     * 根据id查找
     * @param id
     * @return
     */
    Result detail(String id);
    /**
     * 列表
     * @return
     */
    Result all();
}
framework/src/main/java/cn/lili/modules/lmk/service/impl/CommissionRecordServiceImpl.java
New file
@@ -0,0 +1,119 @@
package cn.lili.modules.lmk.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import cn.lili.modules.lmk.domain.entity.CommissionRecord;
import cn.lili.modules.lmk.mapper.CommissionRecordMapper;
import cn.lili.modules.lmk.service.CommissionRecordService;
import cn.lili.base.Result;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.lili.modules.lmk.domain.form.CommissionRecordForm;
import cn.lili.modules.lmk.domain.vo.CommissionRecordVO;
import cn.lili.modules.lmk.domain.query.CommissionRecordQuery;
import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
import cn.lili.utils.PageUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.util.Assert;
import java.util.List;
import java.util.stream.Collectors;
/**
 * 抽成记录表 服务实现类
 *
 * @author peng
 * @since 2025-07-04
 */
@Service
@RequiredArgsConstructor
public class CommissionRecordServiceImpl extends ServiceImpl<CommissionRecordMapper, CommissionRecord> implements CommissionRecordService {
    private final CommissionRecordMapper commissionRecordMapper;
    /**
     * 添加
     * @param form
     * @return
     */
    @Override
    public Result add(CommissionRecordForm form) {
        CommissionRecord entity = CommissionRecordForm.getEntityByForm(form, null);
        baseMapper.insert(entity);
        return Result.ok("添加成功");
    }
    /**
     * 修改
     * @param form
     * @return
     */
    @Override
    public Result update(CommissionRecordForm form) {
        CommissionRecord entity = baseMapper.selectById(form.getId());
        // 为空抛IllegalArgumentException,做全局异常处理
        Assert.notNull(entity, "记录不存在");
        BeanUtils.copyProperties(form, entity);
        baseMapper.updateById(entity);
        return Result.ok("修改成功");
    }
    /**
     * 批量删除
     * @param ids
     * @return
     */
    @Override
    public Result remove(List<String> ids) {
        baseMapper.deleteBatchIds(ids);
        return Result.ok("删除成功");
    }
    /**
     * id删除
     * @param id
     * @return
     */
    @Override
    public Result removeById(String id) {
        baseMapper.deleteById(id);
        return Result.ok("删除成功");
    }
    /**
     * 分页查询
     * @param query
     * @return
     */
    @Override
    public Result page(CommissionRecordQuery query) {
        IPage<CommissionRecordVO> page = PageUtil.getPage(query, CommissionRecordVO.class);
        baseMapper.getPage(page, query);
        return Result.ok().data(page.getRecords()).total(page.getTotal());
    }
    /**
     * 根据id查找
     * @param id
     * @return
     */
    @Override
    public Result detail(String id) {
        CommissionRecordVO vo = baseMapper.getById(id);
        Assert.notNull(vo, "记录不存在");
        return Result.ok().data(vo);
    }
    /**
     * 列表
     * @return
     */
    @Override
    public Result all() {
        List<CommissionRecord> entities = baseMapper.selectList(null);
        List<CommissionRecordVO> vos = entities.stream()
                .map(entity -> CommissionRecordVO.getVoByEntity(entity, null))
                .collect(Collectors.toList());
        return Result.ok().data(vos);
    }
}
framework/src/main/java/cn/lili/modules/lmk/service/impl/PriceChangeServiceImpl.java
New file
@@ -0,0 +1,119 @@
package cn.lili.modules.lmk.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import cn.lili.modules.lmk.domain.entity.PriceChange;
import cn.lili.modules.lmk.mapper.PriceChangeMapper;
import cn.lili.modules.lmk.service.PriceChangeService;
import cn.lili.base.Result;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.lili.modules.lmk.domain.form.PriceChangeForm;
import cn.lili.modules.lmk.domain.vo.PriceChangeVO;
import cn.lili.modules.lmk.domain.query.PriceChangeQuery;
import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
import cn.lili.utils.PageUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.util.Assert;
import java.util.List;
import java.util.stream.Collectors;
/**
 * 价格变动表 服务实现类
 *
 * @author peng
 * @since 2025-07-03
 */
@Service
@RequiredArgsConstructor
public class PriceChangeServiceImpl extends ServiceImpl<PriceChangeMapper, PriceChange> implements PriceChangeService {
    private final PriceChangeMapper priceChangeMapper;
    /**
     * 添加
     * @param form
     * @return
     */
    @Override
    public Result add(PriceChangeForm form) {
        PriceChange entity = PriceChangeForm.getEntityByForm(form, null);
        baseMapper.insert(entity);
        return Result.ok("添加成功");
    }
    /**
     * 修改
     * @param form
     * @return
     */
    @Override
    public Result update(PriceChangeForm form) {
        PriceChange entity = baseMapper.selectById(form.getId());
        // 为空抛IllegalArgumentException,做全局异常处理
        Assert.notNull(entity, "记录不存在");
        BeanUtils.copyProperties(form, entity);
        baseMapper.updateById(entity);
        return Result.ok("修改成功");
    }
    /**
     * 批量删除
     * @param ids
     * @return
     */
    @Override
    public Result remove(List<String> ids) {
        baseMapper.deleteBatchIds(ids);
        return Result.ok("删除成功");
    }
    /**
     * id删除
     * @param id
     * @return
     */
    @Override
    public Result removeById(String id) {
        baseMapper.deleteById(id);
        return Result.ok("删除成功");
    }
    /**
     * 分页查询
     * @param query
     * @return
     */
    @Override
    public Result page(PriceChangeQuery query) {
        IPage<PriceChangeVO> page = PageUtil.getPage(query, PriceChangeVO.class);
        baseMapper.getPage(page, query);
        return Result.ok().data(page.getRecords()).total(page.getTotal());
    }
    /**
     * 根据id查找
     * @param id
     * @return
     */
    @Override
    public Result detail(String id) {
        PriceChangeVO vo = baseMapper.getById(id);
        Assert.notNull(vo, "记录不存在");
        return Result.ok().data(vo);
    }
    /**
     * 列表
     * @return
     */
    @Override
    public Result all() {
        List<PriceChange> entities = baseMapper.selectList(null);
        List<PriceChangeVO> vos = entities.stream()
                .map(entity -> PriceChangeVO.getVoByEntity(entity, null))
                .collect(Collectors.toList());
        return Result.ok().data(vos);
    }
}
framework/src/main/java/cn/lili/modules/order/cart/render/impl/CommissionRender.java
@@ -1,11 +1,12 @@
package cn.lili.modules.order.cart.render.impl;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.lili.common.enums.PromotionTypeEnum;
import cn.lili.common.utils.CurrencyUtil;
import cn.lili.modules.goods.entity.dos.Goods;
import cn.lili.modules.goods.service.CategoryService;
import cn.lili.modules.goods.service.GoodsService;
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
import cn.lili.modules.order.cart.entity.enums.CartTypeEnum;
import cn.lili.modules.order.cart.entity.enums.RenderStepEnums;
@@ -38,6 +39,8 @@
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private GoodsService goodsService;
    @Override
    public RenderStepEnums step() {
        return RenderStepEnums.PLATFORM_COMMISSION;
@@ -64,11 +67,17 @@
                PriceDetailDTO priceDetailDTO = cartSkuVO.getPriceDetailDTO();
                //平台佣金根据分类计算
                String categoryId = cartSkuVO.getGoodsSku().getCategoryPath()
                        .substring(cartSkuVO.getGoodsSku().getCategoryPath().lastIndexOf(",") + 1);
                if (CharSequenceUtil.isNotEmpty(categoryId)) {
                    Double commissionRate = categoryService.getCategoryById(categoryId).getCommissionRate();
                    priceDetailDTO.setPlatFormCommissionPoint(commissionRate);
                //根据商品抽成进行计算佣金
                String goodsId = cartSkuVO.getGoodsSku().getGoodsId();
                Goods goods = goodsService.getById(goodsId);
//                String categoryId = cartSkuVO.getGoodsSku().getCategoryPath()
//                        .substring(cartSkuVO.getGoodsSku().getCategoryPath().lastIndexOf(",") + 1);
//                if (CharSequenceUtil.isNotEmpty(categoryId)) {
//                    Double commissionRate = categoryService.getCategoryById(categoryId).getCommissionRate();
//                    priceDetailDTO.setPlatFormCommissionPoint(commissionRate);
//                }
                if (goods != null&&goods.getCommission()!=null) {
                    priceDetailDTO.setPlatFormCommissionPoint(Double.valueOf(goods.getCommission().toString()));
                }
                //如果积分订单 积分订单,单独操作订单结算金额和商家结算字段
framework/src/main/java/cn/lili/modules/order/order/entity/dos/OrderItem.java
@@ -22,6 +22,7 @@
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.stream.Collectors;
/**
@@ -129,6 +130,9 @@
    @ApiModelProperty(value = "已发货数量")
    private Integer deliverNumber;
    @ApiModelProperty(value = "抽成比例")
    private BigDecimal commission;
    public Integer getDeliverNumber() {
        if(deliverNumber == null){
            return 0;
framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java
@@ -5,7 +5,6 @@
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.poi.excel.ExcelReader;
@@ -205,6 +204,12 @@
                    UserContext.getCurrentUser().getUsername(), message));
            item.getCheckedSkuList().forEach(
                    sku -> {
//                        OrderItem e = new OrderItem(sku, item, tradeDTO);
//                        String goodsId = e.getGoodsId();
//                        Goods goods = goodsService.getById(goodsId);
//                        item.getPriceDetailDTO().setPlatFormCommissionPoint(Double.valueOf(goods.getCommission().toString()));
//                        e.setPriceDetailDTO(item.getPriceDetailDTO());
//                        orderItems.add(e);
                        orderItems.add(new OrderItem(sku, item, tradeDTO));
                        currentOrderItems.add(new OrderItem(sku, item, tradeDTO));
                    }
@@ -454,7 +459,25 @@
        //记录店铺订单支付流水
        storeFlowService.payOrder(orderSn);
        //todo 生成订单记录表
//        //获取子订单数据
//        List<OrderItem> orderItems = orderItemService.getByOrderSn(orderSn);
//        List<String> goodsIds = orderItems.stream().map(OrderItem::getGoodsId).distinct().collect(Collectors.toList());
//
//        Map<String, OrderItem> orderItem = orderItems.stream()
//                .collect(Collectors.toMap(OrderItem::getGoodsId, Function.identity()
//                        ,(oldValue, newValue) -> oldValue));
//        //根据订单item项创建抽成流水订单
//        List<CommissionRecord> commissionRecords = new ArrayList<>();
//        CommissionRecord commissionRecord;
//        for (OrderItem item : orderItems) {
//            commissionRecord = new CommissionRecord();
//            commissionRecord.setSn(item.getSn());
//            BigDecimal commission = item.getCommission();
//            commissionRecord.setCommission(commission);
//            commissionRecord.setCommissionPrice();
//
//        }
        //发送订单已付款消息
        OrderMessage orderMessage = new OrderMessage();
        orderMessage.setOrderSn(order.getSn());
framework/src/main/java/cn/lili/modules/order/order/serviceimpl/StoreFlowServiceImpl.java
@@ -26,7 +26,6 @@
import cn.lili.modules.store.entity.vos.StoreFlowPayDownloadVO;
import cn.lili.modules.store.entity.vos.StoreFlowRefundDownloadVO;
import cn.lili.modules.store.service.BillService;
import cn.lili.modules.system.entity.dto.payment.WechatPaymentSetting;
import cn.lili.mybatis.util.PageUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
framework/src/main/resources/mapper/lmk/CommissionRecordMapper.xml
New file
@@ -0,0 +1,86 @@
<?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="cn.lili.modules.lmk.mapper.CommissionRecordMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="cn.lili.modules.lmk.domain.vo.CommissionRecordVO">
        <id column="id" property="id"/>
        <result column="store_id" property="storeId" />
        <result column="goods_id" property="goodsId" />
        <result column="sku_id" property="skuId" />
        <result column="goods_name" property="goodsName" />
        <result column="img_url" property="imgUrl" />
        <result column="price" property="price" />
        <result column="num" property="num" />
        <result column="sum_price" property="sumPrice" />
        <result column="commission" property="commission" />
        <result column="commission_price" property="commissionPrice" />
        <result column="remain_money" property="remainMoney" />
        <result column="settlement_status" property="settlementStatus" />
        <result column="can_settlement_time" property="canSettlementTime" />
        <result column="trade_sn" property="tradeSn" />
        <result column="sn" property="sn" />
        <result column="type" property="type" />
        <result column="delivery_status" property="deliveryStatus" />
    </resultMap>
    <select id="getById" resultMap="BaseResultMap">
        SELECT
            LCR.store_id,
            LCR.goods_id,
            LCR.sku_id,
            LCR.goods_name,
            LCR.img_url,
            LCR.price,
            LCR.num,
            LCR.sum_price,
            LCR.commission,
            LCR.commission_price,
            LCR.remain_money,
            LCR.settlement_status,
            LCR.can_settlement_time,
            LCR.trade_sn,
            LCR.sn,
            LCR.type,
            LCR.delivery_status,
            LCR.id
        FROM
            lmk_commission_record LCR
        WHERE
            LCR.id = #{id} AND LCR.delete_flag = 0
    </select>
    <select id="getPage" resultMap="BaseResultMap">
        SELECT
            LCR.store_id,
            LCR.goods_id,
            LCR.sku_id,
            LCR.goods_name,
            LCR.img_url,
            LCR.price,
            LCR.num,
            LCR.sum_price,
            LCR.commission,
            LCR.commission_price,
            LCR.remain_money,
            LCR.settlement_status,
            LCR.can_settlement_time,
            LCR.trade_sn,
            LCR.sn,
            LCR.type,
            LCR.delivery_status,
            LCR.id
        FROM
            lmk_commission_record LCR
        WHERE
            LCR.delete_flag = 0
    </select>
</mapper>
framework/src/main/resources/mapper/lmk/PriceChangeMapper.xml
New file
@@ -0,0 +1,68 @@
<?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="cn.lili.modules.lmk.mapper.PriceChangeMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="cn.lili.modules.lmk.domain.vo.PriceChangeVO">
        <id column="id" property="id"/>
        <result column="store_id" property="storeId" />
        <result column="goods_id" property="goodsId" />
        <result column="sku_id" property="skuId" />
        <result column="previous_price" property="previousPrice" />
        <result column="current_price" property="currentPrice" />
        <result column="previous_commission" property="previousCommission" />
        <result column="current_commission" property="currentCommission" />
        <result column="operator_name" property="operatorName" />
        <result column="operator_id" property="operatorId" />
        <result column="examine_status" property="examineStatus" />
        <result column="operator_type" property="operatorType" />
    </resultMap>
    <select id="getById" resultMap="BaseResultMap">
        SELECT
            LPC.store_id,
            LPC.goods_id,
            LPC.sku_id,
            LPC.previous_price,
            LPC.current_price,
            LPC.previous_commission,
            LPC.current_commission,
            LPC.operator_name,
            LPC.operator_id,
            LPC.examine_status,
            LPC.operator_type,
            LPC.id
        FROM
            lmk_price_change LPC
        WHERE
            LPC.id = #{id} AND LPC.delete_flag = 0
    </select>
    <select id="getPage" resultMap="BaseResultMap">
        SELECT
            LPC.store_id,
            LPC.goods_id,
            LPC.sku_id,
            LPC.previous_price,
            LPC.current_price,
            LPC.previous_commission,
            LPC.current_commission,
            LPC.operator_name,
            LPC.operator_id,
            LPC.examine_status,
            LPC.operator_type,
            LPC.id
        FROM
            lmk_price_change LPC
        WHERE
            LPC.delete_flag = 0
    </select>
</mapper>
lmk-job/src/main/java/cn/lili/handler/EveryDayExecute.java
New file
@@ -0,0 +1,18 @@
package cn.lili.handler;
/**
 * 每日任务
 * 每日凌晨1点执行
 *
 * @author Chopper
 * @since 2020/12/24 11:52
 */
public interface EveryDayExecute {
    /**
     * 执行每日任务
     */
    void execute();
}
lmk-job/src/main/java/cn/lili/handler/EveryHourExecute.java
New file
@@ -0,0 +1,17 @@
package cn.lili.handler;
/**
 * 每小时任务
 *
 * @author Chopper
 * @since 2020/12/24 11:52
 */
public interface EveryHourExecute {
    /**
     * 执行
     */
    void execute();
}
lmk-job/src/main/java/cn/lili/handler/EveryMinuteExecute.java
New file
@@ -0,0 +1,17 @@
package cn.lili.handler;
/**
 * 每分钟任务
 *
 * @author Chopper
 * @since 2020/12/24 11:52
 */
public interface EveryMinuteExecute {
    /**
     * 执行
     */
    void execute();
}
lmk-job/src/main/java/cn/lili/handler/impl/broadcast/BroadcastExecute.java
New file
@@ -0,0 +1,25 @@
package cn.lili.handler.impl.broadcast;
import cn.lili.handler.EveryHourExecute;
import cn.lili.modules.goods.service.CommodityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
 * 小程序直播状态获取
 *
 * @author Bulbasaur
 * @since 2021/5/20 2:52 下午
 */
@Component
public class BroadcastExecute implements EveryHourExecute {
    @Autowired
    private CommodityService commodityService;
    @Override
    public void execute() {
        //同步直播商品状态
        commodityService.getGoodsWareHouse();
    }
}
lmk-job/src/main/java/cn/lili/handler/impl/coupon/CouponExecute.java
New file
@@ -0,0 +1,55 @@
package cn.lili.handler.impl.coupon;
import cn.lili.modules.promotion.entity.dos.MemberCoupon;
import cn.lili.modules.promotion.entity.enums.MemberCouponStatusEnum;
import cn.lili.modules.promotion.service.MemberCouponService;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Calendar;
import java.util.Date;
/**
 * 优惠券状态监测
 *
 * @author Bulbasaur
 * @since 2021/5/24 10:08 上午
 */
@Component
public class CouponExecute implements EveryDayExecute {
    /**
     * 过期常量,过期后或者使用后一定时间内,删除无效的优惠券,物理删除
     */
    static final int EXPIRATION_DAY = 3;
    @Autowired
    private MemberCouponService memberCouponService;
    /**
     * 检测优惠券的使用时间,超期未使用则失效
     * 此方法用于领取*天后失效优惠券使用
     */
    @Override
    public void execute() {
        //将过期优惠券变更为过期状态
        LambdaUpdateWrapper<MemberCoupon> updateWrapper = new LambdaUpdateWrapper<MemberCoupon>()
                .eq(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.NEW.name())
                .le(MemberCoupon::getEndTime, new Date())
                .set(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.EXPIRE.name());
        this.memberCouponService.update(updateWrapper);
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) - EXPIRATION_DAY);
        Date removeTime = calendar.getTime();
        //删除过期/已使用的优惠券
        LambdaUpdateWrapper<MemberCoupon> deleteWrapper = new LambdaUpdateWrapper<MemberCoupon>()
                //如果结束时间小于 当前时间增加指定删除日期,则删除
                .le(MemberCoupon::getEndTime, removeTime);
        this.memberCouponService.remove(deleteWrapper);
    }
}
lmk-job/src/main/java/cn/lili/handler/impl/goods/GoodsExecute.java
New file
@@ -0,0 +1,48 @@
package cn.lili.handler.impl.goods;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.lili.handler.EveryDayExecute;
import cn.lili.modules.goods.service.GoodsService;
import cn.lili.modules.member.service.MemberEvaluationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
/**
 * 商品定时器
 *
 * @author Chopper
 * @since 2021/3/18 3:23 下午
 */
@Component
public class GoodsExecute implements EveryDayExecute {
    /**
     * 会员评价
     */
    @Autowired
    private MemberEvaluationService memberEvaluationService;
    /**
     * 商品
     */
    @Autowired
    private GoodsService goodsService;
    /**
     * 查询已上架的商品的评价数量并赋值
     */
    @Override
    public void execute() {
        //查询上次统计到本次的评价数量
        List<Map<String, Object>> list = memberEvaluationService.memberEvaluationNum(DateUtil.yesterday(), new DateTime());
        for (Map<String, Object> map : list) {
            goodsService.addGoodsCommentNum(Convert.toInt(map.get("num").toString()), map.get("goods_id").toString());
        }
    }
}
lmk-job/src/main/java/cn/lili/handler/impl/hotwords/HotWordsEveryDayTaskExecute.java
New file
@@ -0,0 +1,86 @@
package cn.lili.handler.impl.hotwords;
import cn.hutool.json.JSONUtil;
import cn.lili.cache.Cache;
import cn.lili.cache.CachePrefix;
import cn.lili.handler.EveryDayExecute;
import cn.lili.modules.search.entity.dos.HotWordsHistory;
import cn.lili.modules.search.service.HotWordsHistoryService;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.system.entity.dto.HotWordsSetting;
import cn.lili.modules.system.entity.dto.HotWordsSettingItem;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.service.SettingService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Set;
/**
 * @author paulG
 * @since 2021/3/11
 **/
@Slf4j
@Component
public class HotWordsEveryDayTaskExecute implements EveryDayExecute {
    @Autowired
    private Cache cache;
    @Autowired
    private HotWordsHistoryService hotWordsHistoryService;
    @Autowired
    private SettingService settingService;
    /**
     * 执行每日任务
     */
    @Override
    public void execute() {
        //获取大于0分的热词
        Set<DefaultTypedTuple> tuples = cache.zRangeByScore(CachePrefix.HOT_WORD.getPrefix(), 1, Integer.MAX_VALUE);
        //如果任务不为空
        if (!CollectionUtils.isEmpty(tuples)) {
            //因为是第二天统计第一天的数据,所以这里获取昨天凌晨的时间
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.HOUR_OF_DAY, 0);
            calendar.set(Calendar.SECOND, 0);
            calendar.set(Calendar.MILLISECOND, 0);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) - 1);
            //批量保存热词
            List<HotWordsHistory> hotWordsHistories = new ArrayList<>();
            for (DefaultTypedTuple tuple : tuples) {
                String keywords = (String) tuple.getValue();
                Double score = tuple.getScore();
                hotWordsHistories.add(new HotWordsHistory(keywords, score.intValue(), calendar.getTime()));
            }
            hotWordsHistoryService.saveBatch(hotWordsHistories);
        }
        //移除昨日的热搜词
        cache.remove(CachePrefix.HOT_WORD.getPrefix());
        //设置今日默认热词
        Setting setting = settingService.get(SettingEnum.HOT_WORDS.name());
        if (setting == null) {
            return;
        }
        HotWordsSetting hotWordsSetting = JSONUtil.toBean(setting.getSettingValue(), HotWordsSetting.class);
        List<HotWordsSettingItem> hotWordsSettingItems = hotWordsSetting.getHotWordsSettingItems();
        if (hotWordsSettingItems != null && !hotWordsSettingItems.isEmpty()) {
            for (HotWordsSettingItem hotWordsSettingItem : hotWordsSettingItems) {
                cache.zAdd(CachePrefix.HOT_WORD.getPrefix(), hotWordsSettingItem.getScore(), hotWordsSettingItem.getKeywords());
            }
        }
    }
}
lmk-job/src/main/java/cn/lili/handler/impl/order/CancelOrderTaskExecute.java
New file
@@ -0,0 +1,61 @@
package cn.lili.handler.impl.order;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import cn.lili.handler.EveryMinuteExecute;
import cn.lili.modules.order.order.entity.dos.Order;
import cn.lili.modules.order.order.entity.enums.OrderStatusEnum;
import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.system.entity.dto.OrderSetting;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.service.SettingService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.stream.Collectors;
/**
 * 订单自动取消(每分钟执行)
 *
 * @author paulG
 * @since 2021/3/11
 **/
@Slf4j
@Component
public class CancelOrderTaskExecute implements EveryMinuteExecute {
    /**
     * 订单
     */
    @Autowired
    private OrderService orderService;
    /**
     * 设置
     */
    @Autowired
    private SettingService settingService;
    @Override
    public void execute() {
        Setting setting = settingService.get(SettingEnum.ORDER_SETTING.name());
        OrderSetting orderSetting = JSONUtil.toBean(setting.getSettingValue(), OrderSetting.class);
        if (orderSetting != null && orderSetting.getAutoCancel() != null) {
            //订单自动取消时间 = 当前时间 - 自动取消时间分钟数
            DateTime cancelTime = DateUtil.offsetMinute(DateUtil.date(), -orderSetting.getAutoCancel());
            LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Order::getOrderStatus, OrderStatusEnum.UNPAID.name());
            //订单创建时间 <= 订单自动取消时间
            queryWrapper.le(Order::getCreateTime, cancelTime);
            List<Order> list = orderService.list(queryWrapper);
            List<String> cancelSnList = list.stream().map(Order::getSn).collect(Collectors.toList());
            for (String sn : cancelSnList) {
                orderService.systemCancel(sn, "超时未支付自动取消",false);
            }
        }
    }
}
lmk-job/src/main/java/cn/lili/handler/impl/order/OrderEveryDayTaskExecute.java
New file
@@ -0,0 +1,287 @@
package cn.lili.handler.impl.order;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.handler.EveryDayExecute;
import cn.lili.modules.distribution.service.DistributionOrderService;
import cn.lili.modules.member.entity.dto.MemberEvaluationDTO;
import cn.lili.modules.member.entity.enums.EvaluationGradeEnum;
import cn.lili.modules.member.service.MemberEvaluationService;
import cn.lili.modules.order.order.entity.dos.Order;
import cn.lili.modules.order.order.entity.dos.OrderItem;
import cn.lili.modules.order.order.entity.dto.OrderItemOperationDTO;
import cn.lili.modules.order.order.entity.enums.CommentStatusEnum;
import cn.lili.modules.order.order.entity.enums.OrderComplaintStatusEnum;
import cn.lili.modules.order.order.entity.enums.OrderItemAfterSaleStatusEnum;
import cn.lili.modules.order.order.entity.enums.OrderStatusEnum;
import cn.lili.modules.order.order.service.OrderItemService;
import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.order.order.service.StoreFlowService;
import cn.lili.modules.store.entity.dto.StoreSettlementDay;
import cn.lili.modules.store.service.BillService;
import cn.lili.modules.store.service.StoreDetailService;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.system.entity.dto.OrderSetting;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.service.SettingService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.stream.Collectors;
/**
 * @author paulG
 * @since 2021/3/11
 **/
@Slf4j
@Component
public class OrderEveryDayTaskExecute implements EveryDayExecute {
    /**
     * 订单
     */
    @Autowired
    private OrderService orderService;
    /**
     * 订单货物
     */
    @Autowired
    private OrderItemService orderItemService;
    /**
     * 设置
     */
    @Autowired
    private SettingService settingService;
    /**
     * 会员评价
     */
    @Autowired
    private MemberEvaluationService memberEvaluationService;
    @Autowired
    private DistributionOrderService distributionOrderService;
    @Autowired
    private StoreFlowService storeFlowService;
    /**
     * 结算单
     */
    @Autowired
    private BillService billService;
    /**
     * 店铺详情
     */
    @Autowired
    private StoreDetailService storeDetailService;
    /**
     * 执行每日任务
     */
    @Override
    public void execute() {
        Setting setting = settingService.get(SettingEnum.ORDER_SETTING.name());
        //订单设置
        OrderSetting orderSetting = JSONUtil.toBean(setting.getSettingValue(), OrderSetting.class);
        if (orderSetting == null) {
            throw new ServiceException(ResultCode.ORDER_SETTING_ERROR);
        }
        try {
            //自动确认收货
            completedOrder(orderSetting);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        try {
            //自动好评
            memberEvaluation(orderSetting);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        try {
            //关闭允许售后申请
            this.closeAfterSale(orderSetting);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        try {
            //关闭允许投诉
            closeComplaint(orderSetting);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        //修改分账状态
        try {
            storeFlowService.updateProfitSharingStatus();
        } catch (Exception e) {
            log.error("修改分账状态失败", e);
        }
        //生成店铺结算单
        try {
            createBill();
        } catch (Exception e) {
            log.error("生成店铺结算单", e);
        }
    }
    /**
     * 自动确认收获,订单完成
     *
     * @param orderSetting 订单设置
     */
    private void completedOrder(OrderSetting orderSetting) {
        //订单自动收货时间 = 当前时间 - 自动收货时间天数
        DateTime receiveTime = DateUtil.offsetDay(DateUtil.date(), -orderSetting.getAutoReceive());
        LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Order::getOrderStatus, OrderStatusEnum.DELIVERED.name());
        //订单发货时间 >= 订单自动收货时间
        queryWrapper.le(Order::getLogisticsTime, receiveTime);
        List<Order> list = orderService.list(queryWrapper);
        try {
            //判断是否有符合条件的订单,进行订单完成处理
            if (!list.isEmpty()) {
                List<String> receiveSnList = list.stream().map(Order::getSn).collect(Collectors.toList());
                for (String orderSn : receiveSnList) {
                    orderService.systemComplete(orderSn);
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }
    /**
     * 自动好评
     *
     * @param orderSetting 订单设置
     */
    private void memberEvaluation(OrderSetting orderSetting) {
        //订单自动收货时间 = 当前时间 - 自动收货时间天数
        DateTime receiveTime = DateUtil.offsetDay(DateUtil.date(), -orderSetting.getAutoEvaluation());
        //订单完成时间 <= 订单自动好评时间
        OrderItemOperationDTO orderItemOperationDTO =
            OrderItemOperationDTO.builder().receiveTime(receiveTime).commentStatus(CommentStatusEnum.UNFINISHED.name())
                .build();
        List<OrderItem> orderItems = orderItemService.waitOperationOrderItem(orderItemOperationDTO);
        //判断是否有符合条件的订单,进行自动评价处理
        if (!orderItems.isEmpty()) {
            for (OrderItem orderItem : orderItems) {
                MemberEvaluationDTO memberEvaluationDTO = new MemberEvaluationDTO();
                memberEvaluationDTO.setOrderItemSn(orderItem.getSn());
                memberEvaluationDTO.setContent("系统默认好评");
                memberEvaluationDTO.setGoodsId(orderItem.getGoodsId());
                memberEvaluationDTO.setSkuId(orderItem.getSkuId());
                memberEvaluationDTO.setGrade(EvaluationGradeEnum.GOOD.name());
                memberEvaluationDTO.setDeliveryScore(5);
                memberEvaluationDTO.setDescriptionScore(5);
                memberEvaluationDTO.setServiceScore(5);
                try {
                    memberEvaluationService.addMemberEvaluation(memberEvaluationDTO, false);
                } catch (Exception e) {
                    // 修改订单货物评价状态为已评价避免无限调用评价异常
                    orderItemService.updateCommentStatus(orderItem.getSn(), CommentStatusEnum.FINISHED);
                    log.error(e.getMessage(), e);
                }
            }
        }
    }
    /**
     * 关闭允许售后申请
     *
     * @param orderSetting 订单设置
     */
    @Transactional(rollbackFor = Exception.class)
    public void closeAfterSale(OrderSetting orderSetting) {
        //订单关闭售后申请时间 = 当前时间 - 自动关闭售后申请天数
        DateTime receiveTime = DateUtil.offsetDay(DateUtil.date(), -orderSetting.getCloseAfterSale());
//        OrderItemOperationDTO build = OrderItemOperationDTO.builder().receiveTime(receiveTime)
//            .afterSaleStatus(OrderItemAfterSaleStatusEnum.NOT_APPLIED.name()).build();
//        List<OrderItem> orderItems = orderItemService.waitOperationOrderItem(build);
        //关闭售后订单=未售后订单+小于订单关闭售后申请时间
        orderItemService.expiredAfterSaleStatus(receiveTime);
    }
    /**
     * 关闭允许交易投诉
     *
     * @param orderSetting 订单设置
     */
    private void closeComplaint(OrderSetting orderSetting) {
        //为0则不限制
        if (orderSetting.getCloseComplaint() == null || orderSetting.getCloseComplaint() == 0) {
            return;
        }
        //订单关闭交易投诉申请时间 = 当前时间 - 自动关闭交易投诉申请天数
        DateTime receiveTime = DateUtil.offsetDay(DateUtil.date(), -orderSetting.getCloseComplaint());
        //关闭售后订单=未售后订单+小于订单关闭售后申请时间
        OrderItemOperationDTO build = OrderItemOperationDTO.builder().receiveTime(receiveTime)
            .complainStatus(OrderComplaintStatusEnum.NO_APPLY.name()).build();
        List<OrderItem> orderItems = orderItemService.waitOperationOrderItem(build);
        //判断是否有符合条件的订单,关闭允许售后申请处理
        if (!orderItems.isEmpty()) {
            //获取订单货物ID
            List<String> orderItemIdList = orderItems.stream().map(OrderItem::getId).collect(Collectors.toList());
            //修改订单投诉状态
            LambdaUpdateWrapper<OrderItem> lambdaUpdateWrapper =
                new LambdaUpdateWrapper<OrderItem>().set(OrderItem::getComplainStatus,
                    OrderItemAfterSaleStatusEnum.EXPIRED.name()).in(OrderItem::getId, orderItemIdList);
            orderItemService.update(lambdaUpdateWrapper);
        }
    }
    /**
     * 1.查询今日待结算的商家
     * 2.查询商家上次结算日期,生成本次结算单
     * 3.记录商家结算日
     */
    private void createBill() {
        //获取当前天数
        int day = DateUtil.date().dayOfMonth();
        //获取待结算商家列表
        List<StoreSettlementDay> storeList = storeDetailService.getSettlementStore(day);
        //获取当前时间
        DateTime endTime = DateUtil.date();
        //批量商家结算
        for (StoreSettlementDay storeSettlementDay : storeList) {
            //生成结算单
            billService.createBill(storeSettlementDay.getStoreId(), storeSettlementDay.getSettlementDay(), endTime);
            //修改店铺结算时间
            storeDetailService.updateSettlementDay(storeSettlementDay.getStoreId(), endTime);
        }
    }
}
lmk-job/src/main/java/cn/lili/handler/impl/order/RechargeOrderTaskExecute.java
New file
@@ -0,0 +1,61 @@
package cn.lili.handler.impl.order;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import cn.lili.handler.EveryMinuteExecute;
import cn.lili.modules.order.order.entity.enums.PayStatusEnum;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.system.entity.dto.OrderSetting;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.service.SettingService;
import cn.lili.modules.wallet.entity.dos.Recharge;
import cn.lili.modules.wallet.service.RechargeService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.stream.Collectors;
/**
 * 充值订单自动取消(每分钟执行)
 *
 * @author zhuhai
 * @since 2021/3/11
 **/
@Slf4j
@Component
public class RechargeOrderTaskExecute implements EveryMinuteExecute {
    /**
     * 充值
     */
    @Autowired
    private RechargeService rechargeService;
    /**
     * 设置
     */
    @Autowired
    private SettingService settingService;
    @Override
    public void execute() {
        Setting setting = settingService.get(SettingEnum.ORDER_SETTING.name());
        OrderSetting orderSetting = JSONUtil.toBean(setting.getSettingValue(), OrderSetting.class);
        if (orderSetting != null && orderSetting.getAutoCancel() != null) {
            //充值订单自动取消时间 = 当前时间 - 自动取消时间分钟数
            DateTime cancelTime = DateUtil.offsetMinute(DateUtil.date(), -orderSetting.getAutoCancel());
            LambdaQueryWrapper<Recharge> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Recharge::getPayStatus, PayStatusEnum.UNPAID.name());
            //充值订单创建时间 <= 订单自动取消时间
            queryWrapper.le(Recharge::getCreateTime, cancelTime);
            List<Recharge> list = rechargeService.list(queryWrapper);
            List<String> cancelSnList = list.stream().map(Recharge::getRechargeSn).collect(Collectors.toList());
            for (String sn : cancelSnList) {
                rechargeService.rechargeOrderCancel(sn);
            }
        }
    }
}
lmk-job/src/main/java/cn/lili/handler/impl/promotion/MemberCouponSignEverydayExecute.java
New file
@@ -0,0 +1,35 @@
package cn.lili.handler.impl.promotion;
import cn.lili.handler.EveryDayExecute;
import cn.lili.modules.promotion.service.MemberCouponSignService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
 * 促销活动每日定时器
 *
 * @author Chopper
 * @since 2021/3/18 3:23 下午
 */
@Slf4j
@Component
public class MemberCouponSignEverydayExecute implements EveryDayExecute {
    @Autowired
    private MemberCouponSignService memberCouponSignService;
    /**
     * 将已过期的促销活动置为结束
     */
    @Override
    public void execute() {
        try {
            memberCouponSignService.clean();
        } catch (Exception e) {
            log.error("清除领取优惠券标记异常", e);
        }
    }
}
lmk-job/src/main/java/cn/lili/handler/impl/promotion/PromotionEverydayExecute.java
New file
@@ -0,0 +1,85 @@
package cn.lili.handler.impl.promotion;
import cn.lili.common.enums.PromotionTypeEnum;
import cn.lili.handler.EveryDayExecute;
import cn.lili.modules.promotion.entity.dos.Seckill;
import cn.lili.modules.promotion.service.SeckillService;
import cn.lili.modules.promotion.tools.PromotionTools;
import cn.lili.modules.search.service.EsGoodsIndexService;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.system.entity.dto.SeckillSetting;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.service.SettingService;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
 * 促销活动每日定时器
 *
 * @author Chopper
 * @since 2021/3/18 3:23 下午
 */
@Slf4j
@Component
public class PromotionEverydayExecute implements EveryDayExecute {
    /**
     * ES商品索引
     */
    @Autowired
    private EsGoodsIndexService esGoodsIndexService;
    /**
     * 系统设置
     */
    @Autowired
    private SettingService settingService;
    /**
     * 秒杀活动
     */
    @Autowired
    private SeckillService seckillService;
    /**
     * 将已过期的促销活动置为结束
     */
    @Override
    public void execute() {
        try {
            //清除所有商品索引的无效促销活动
            this.esGoodsIndexService.cleanInvalidPromotion();
        } catch (Exception e) {
            log.error("清楚商品索引中无效促销异常", e);
        }
        try {
            //定时创建活动
            addSeckill();
        } catch (Exception e) {
            log.error("秒杀活动添加异常", e);
        }
    }
    /**
     * 添加秒杀活动
     * 从系统设置中获取秒杀活动的配置
     * 添加明天后的秒杀活动
     */
    private void addSeckill() {
        Setting setting = settingService.get(SettingEnum.SECKILL_SETTING.name());
        SeckillSetting seckillSetting = new Gson().fromJson(setting.getSettingValue(), SeckillSetting.class);
        log.info("生成秒杀活动设置:{}", seckillSetting);
        for (int i = 1; i <= SeckillService.PRE_CREATION; i++) {
            Seckill seckill = new Seckill(i, seckillSetting.getHours(), seckillSetting.getSeckillRule());
            seckill.setApplyEndTime(null);
            //如果已经存在促销,则不再次保存
            if (seckillService.list(
                    PromotionTools.checkActiveTime(seckill.getStartTime(), seckill.getEndTime(), PromotionTypeEnum.SECKILL, null, seckill.getId())).isEmpty()) {
                boolean result = seckillService.savePromotions(seckill);
                log.info("生成秒杀活动参数:{},结果:{}", seckill, result);
            }
        }
    }
}
lmk-job/src/main/java/cn/lili/handler/impl/statistics/MemberStatisticsExecute.java
New file
@@ -0,0 +1,55 @@
package cn.lili.handler.impl.statistics;
import cn.lili.handler.EveryDayExecute;
import cn.lili.modules.statistics.entity.dos.MemberStatisticsData;
import cn.lili.modules.statistics.service.MemberStatisticsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Calendar;
import java.util.Date;
/**
 * 会员数据统计
 *
 * @author Chopper
 * @since 2021-03-02 14:56
 */
@Slf4j
@Component
public class MemberStatisticsExecute implements EveryDayExecute {
    /**
     * 会员统计
     */
    @Autowired
    private MemberStatisticsService memberStatisticsService;
    @Override
    public void execute() {
        try {
            //统计的时间(开始。结束时间)
            Date startTime, endTime;
            //初始值
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.SECOND, 0);
            calendar.set(Calendar.MILLISECOND, 1);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.HOUR_OF_DAY, 0);
            endTime = calendar.getTime();
            //-1天,即为开始时间
            calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) - 1);
            startTime = calendar.getTime();
            MemberStatisticsData memberStatisticsData = new MemberStatisticsData();
            memberStatisticsData.setMemberCount(memberStatisticsService.memberCount(endTime));
            memberStatisticsData.setCreateDate(startTime);
            memberStatisticsData.setActiveQuantity(memberStatisticsService.activeQuantity(startTime));
            memberStatisticsData.setNewlyAdded(memberStatisticsService.newlyAdded(startTime, endTime));
            memberStatisticsService.save(memberStatisticsData);
        } catch (Exception e) {
            log.error("每日会员统计功能异常:", e);
        }
    }
}
lmk-job/src/main/java/cn/lili/handler/impl/statistics/OnlineMemberStatistics.java
New file
@@ -0,0 +1,114 @@
package cn.lili.handler.impl.statistics;
import cn.lili.cache.Cache;
import cn.lili.cache.CachePrefix;
import cn.lili.common.properties.StatisticsProperties;
import cn.lili.common.security.enums.UserEnums;
import cn.lili.handler.EveryHourExecute;
import cn.lili.modules.statistics.entity.vo.OnlineMemberVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
/**
 * 实时在线人数统计
 *
 * @author Chopper
 * @since 2021-02-21 09:47
 */
@Component
public class OnlineMemberStatistics implements EveryHourExecute {
    /**
     * 缓存
     */
    @Autowired
    private Cache<List<OnlineMemberVO>> cache;
    /**
     * 统计小时
     */
    @Autowired
    private StatisticsProperties statisticsProperties;
    @Override
    public void execute() {
        Calendar calendar = Calendar.getInstance();
        List<OnlineMemberVO> onlineMemberVOS = cache.get(CachePrefix.ONLINE_MEMBER.getPrefix());
        if (onlineMemberVOS == null) {
            onlineMemberVOS = new ArrayList<>();
        }
        //过滤 有效统计时间
        calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - statisticsProperties.getOnlineMember());
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        Calendar finalCalendar = calendar;
        AtomicReference<Integer> lastNum = new AtomicReference<>(0);
        onlineMemberVOS = onlineMemberVOS.stream()
                .filter(onlineMemberVO -> {
                    //如果为过滤参数,则记录为过期参数,则为统一时段上一周期的在线人数
                    if (!onlineMemberVO.getDate().after(finalCalendar.getTime())) {
                        lastNum.set(onlineMemberVO.getNum());
                    }
                    return onlineMemberVO.getDate().after(finalCalendar.getTime());
                })
                .collect(Collectors.toList());
        //计入新数据
        calendar = Calendar.getInstance();
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        onlineMemberVOS.add(new OnlineMemberVO(calendar.getTime(), cache.keys(CachePrefix.ACCESS_TOKEN.getPrefix(UserEnums.MEMBER) + "*").size(),
                lastNum.get()));
        //写入缓存
        cache.put(CachePrefix.ONLINE_MEMBER.getPrefix(), onlineMemberVOS);
    }
    /**
     * 手动设置某一时间,活跃人数
     *
     * @param time 时间
     * @param num  人数
     */
    public void execute(Date time, Integer num) {
        List<OnlineMemberVO> onlineMemberVOS = cache.get(CachePrefix.ONLINE_MEMBER.getPrefix());
        if (onlineMemberVOS == null) {
            onlineMemberVOS = new ArrayList<>();
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        //过滤 有效统计时间
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 48);
        onlineMemberVOS = onlineMemberVOS.stream()
                .filter(onlineMemberVO -> onlineMemberVO.getDate().after(calendar.getTime()))
                .collect(Collectors.toList());
        onlineMemberVOS.add(new OnlineMemberVO(time, num, num));
        //写入缓存
        cache.put(CachePrefix.ONLINE_MEMBER.getPrefix(), onlineMemberVOS);
    }
}
lmk-job/src/main/java/cn/lili/handler/impl/store/StoreExecute.java
New file
@@ -0,0 +1,49 @@
package cn.lili.handler.impl.store;
import cn.lili.handler.EveryDayExecute;
import cn.lili.modules.goods.service.GoodsSkuService;
import cn.lili.modules.store.entity.dos.Store;
import cn.lili.modules.store.entity.enums.StoreStatusEnum;
import cn.lili.modules.store.service.StoreService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
 * 店铺信息更新
 *
 * @author Chopper
 * @since 2021/3/15 5:30 下午
 */
@Component
@Slf4j
public class StoreExecute implements EveryDayExecute {
    /**
     * 店铺
     */
    @Autowired
    private StoreService storeService;
    @Autowired
    private GoodsSkuService goodsSkuService;
    @Override
    public void execute() {
        //获取所有开启的店铺
        List<Store> storeList = storeService.list(new LambdaQueryWrapper<Store>().eq(Store::getStoreDisable, StoreStatusEnum.OPEN.name()));
        for (Store store : storeList) {
            try {
                Long num = goodsSkuService.countSkuNum(store.getId());
                storeService.updateStoreGoodsNum(store.getId(), num);
            } catch (Exception e) {
                log.error("店铺id为{},更新商品数量失败", store.getId(), e);
            }
        }
    }
}
lmk-job/src/main/java/cn/lili/handler/impl/store/StoreRatingExecute.java
New file
@@ -0,0 +1,60 @@
package cn.lili.handler.impl.store;
import cn.lili.common.enums.SwitchEnum;
import cn.lili.handler.EveryDayExecute;
import cn.lili.modules.member.entity.vo.StoreRatingVO;
import cn.lili.modules.member.service.MemberEvaluationService;
import cn.lili.modules.store.entity.dos.Store;
import cn.lili.modules.store.entity.enums.StoreStatusEnum;
import cn.lili.modules.store.service.StoreService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
 * 店铺评分
 *
 * @author Chopper
 * @since 2021/3/15 5:30 下午
 */
@Component
public class StoreRatingExecute implements EveryDayExecute {
    /**
     * 店铺
     */
    @Autowired
    private StoreService storeService;
    /**
     * 会员评价
     */
    @Autowired
    private MemberEvaluationService memberEvaluationService;
    @Override
    public void execute() {
        //获取所有开启的店铺
        List<Store> storeList = storeService.list(new LambdaQueryWrapper<Store>().eq(Store::getStoreDisable, StoreStatusEnum.OPEN.name()));
        for (Store store : storeList) {
            //店铺所有开启的评价
            StoreRatingVO storeRatingVO = memberEvaluationService.getStoreRatingVO(store.getId(), SwitchEnum.OPEN.name());
            if (storeRatingVO != null) {
                //保存评分
                LambdaUpdateWrapper<Store> lambdaUpdateWrapper = Wrappers.lambdaUpdate();
                lambdaUpdateWrapper.eq(Store::getId, store.getId());
                lambdaUpdateWrapper.set(Store::getDescriptionScore, storeRatingVO.getDescriptionScore());
                lambdaUpdateWrapper.set(Store::getDeliveryScore, storeRatingVO.getDeliveryScore());
                lambdaUpdateWrapper.set(Store::getServiceScore, storeRatingVO.getServiceScore());
                storeService.update(lambdaUpdateWrapper);
            }
        }
    }
}
lmk-job/src/main/java/cn/lili/handler/impl/view/PageViewStatisticsExecute.java
New file
@@ -0,0 +1,195 @@
package cn.lili.handler.impl.view;
import cn.hutool.core.convert.Convert;
import cn.lili.cache.Cache;
import cn.lili.cache.CachePrefix;
import cn.lili.common.utils.BeanUtil;
import cn.lili.handler.EveryDayExecute;
import cn.lili.modules.statistics.entity.dos.PlatformViewData;
import cn.lili.modules.statistics.service.PlatformViewService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
/**
 * 统计 入库
 *
 * @author Chopper
 * @since 2021-01-15 18:20
 */
@Slf4j
@Component
public class PageViewStatisticsExecute implements EveryDayExecute {
    /**
     * 缓存
     */
    @Autowired
    private Cache cache;
    /**
     * 平台PV统计
     */
    @Autowired
    private PlatformViewService platformViewService;
    @Override
    public void execute() {
        //1、缓存keys 模糊匹配
        //2、过滤今日的数据,即今天只能统计今日以前的数据
        //4对key value 分别代表平台PV、平台UV、店铺PV、店铺UV
        List<String> pvKeys = filterKeys(cache.keys(CachePrefix.PV.getPrefix() + "*"));
        List<Integer> pvValues = cache.multiGet(pvKeys);
        List<String> storePVKeys = filterKeys(cache.keys(CachePrefix.STORE_PV.getPrefix() + "*"));
        List<Integer> storePvValues = cache.multiGet(storePVKeys);
        //备份UV数据,这里赋值之后,会被删除
        List<String> uvKeys = new ArrayList<>();
        List<String> storeUvKeys = new ArrayList<>();
        log.debug("开始统计平台数据,PV共计【{}】条", pvKeys.size());
        log.debug("开始统计店铺数据,PV共计【{}】条", storePvValues.size());
        //定义要统计的数据
        List<PlatformViewData> platformViewDataList = new ArrayList<>();
        //PV 统计
        if (pvKeys.size() > 0) {
            for (int i = 0; i < pvKeys.size(); i++) {
                String key = pvKeys.get(i);
                PageViewStatistics pageViewStatistics = new PageViewStatistics(key);
                PlatformViewData platformPVData = new PlatformViewData();
                BeanUtil.copyProperties(pageViewStatistics, platformPVData);
                platformPVData.setPvNum(pvValues.get(i).longValue());
                //根据pvkey 获取 uvkey
                String uvKey = getUvKey(key);
                uvKeys.add(uvKey);
                platformPVData.setUvNum(cache.counter(uvKey));
                platformPVData.setStoreId("-1");
                platformViewDataList.add(platformPVData);
            }
            batchSave(pvKeys, uvKeys, platformViewDataList);
        }
        //店铺 PV 统计
        if (storePVKeys.size() > 0) {
            platformViewDataList = new ArrayList<>();
            for (int i = 0; i < storePVKeys.size(); i++) {
                String key = storePVKeys.get(i);
                PageViewStatistics pageViewStatistics = new PageViewStatistics(key);
                PlatformViewData storePVData = new PlatformViewData();
                BeanUtil.copyProperties(pageViewStatistics, storePVData);
                storePVData.setPvNum(storePvValues.get(i).longValue());
                //根据pvkey 获取 uvkey
                String uvKey = getUvKey(key);
                uvKeys.add(uvKey);
                storePVData.setUvNum(cache.counter(uvKey));
                platformViewDataList.add(storePVData);
            }
            batchSave(storePVKeys, storeUvKeys, platformViewDataList);
        }
    }
    /**
     * 根据缓存的PVkey 获取对应的UVkey
     *
     * @param key
     * @return
     */
    private String getUvKey(String key) {
        if (StringUtils.isNotEmpty(key)) {
            key = key.replace(CachePrefix.PV.getPrefix(), CachePrefix.UV.getPrefix());
            key = key.replace(CachePrefix.STORE_PV.getPrefix(), CachePrefix.STORE_UV.getPrefix());
            return key;
        }
        return key;
    }
    /**
     * 批量保存数据&&清除保存数据的缓存
     *
     * @param pvKeys           PV key
     * @param uvKeys           UV key
     * @param platformViewData DOS
     */
    @Transactional(rollbackFor = Exception.class)
    void batchSave(List<String> pvKeys, List<String> uvKeys, List<PlatformViewData> platformViewData) {
        log.debug("批量保存流量数据,共计【{}】条", platformViewData.size());
        platformViewService.saveBatch(platformViewData);
        //批量删除缓存key
        cache.multiDel(pvKeys);
        cache.multiDel(uvKeys);
        log.debug("流量数据保存完成");
    }
    /**
     * 过滤缓存key
     *
     * @param keys 缓存key集合
     */
    private static List<String> filterKeys(List<String> keys) {
        //只统计一天前的数据
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, -24);
        List<String> result = new ArrayList<>();
        for (String key : keys) {
            PageViewStatistics temp = new PageViewStatistics(key);
            //如果需要统计,则将key写入集合
            if (temp.getDate().before(calendar.getTime())) {
                result.add(key);
            }
        }
        return result;
    }
}
/**
 * 根据缓存key 获取其中需要的参数,年月日,以及店铺信息
 */
@Data
class PageViewStatistics {
    /**
     * 年 、 月 、 日 、 店铺id
     */
    private Date date;
    private String storeId;
    public PageViewStatistics(String str) {
        //将字符串解析成需要的对象
        str = str.substring(str.indexOf("}") + 2);
        String[] dateStr = str.split("-");
        Integer year = Convert.toInt(dateStr[0]);
        Integer month = Convert.toInt(dateStr[1]);
        Integer day;
        //是否有店铺id
        if (dateStr.length > 3) {
            day = Convert.toInt(dateStr[2]);
            this.storeId = dateStr[3];
        } else {
            day = Convert.toInt(dateStr[2]);
        }
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month - 1);
        calendar.set(Calendar.DAY_OF_MONTH, day);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        this.date = calendar.getTime();
    }
}
lmk-job/src/main/java/cn/lili/job/TimedTaskJobHandler.java
New file
@@ -0,0 +1,104 @@
package cn.lili.job;
import cn.lili.handler.EveryDayExecute;
import cn.lili.handler.EveryHourExecute;
import cn.lili.handler.EveryMinuteExecute;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
 * 定时器任务
 *
 * @author Chopper
 * @version v1.0
 * 2020-12-24 11:51
 */
@Slf4j
@Component
public class TimedTaskJobHandler {
    @Autowired(required = false)
    private List<EveryMinuteExecute> everyMinuteExecutes;
    @Autowired(required = false)
    private List<EveryHourExecute> everyHourExecutes;
    @Autowired(required = false)
    private List<EveryDayExecute> everyDayExecutes;
    /**
     * 每分钟任务
     *
     * @throws Exception
     */
    @XxlJob("everyMinuteExecute")
    public ReturnT<String> everyMinuteExecute(String param)  {
        log.info("每分钟任务执行");
        if (everyMinuteExecutes == null || everyMinuteExecutes.size() == 0) {
            return ReturnT.SUCCESS;
        }
        for (int i = 0; i < everyMinuteExecutes.size(); i++) {
            try {
                everyMinuteExecutes.get(i).execute();
            } catch (Exception e) {
                log.error("每分钟任务异常", e);
            }
        }
        return ReturnT.SUCCESS;
    }
    /**
     * 每小时任务
     *
     * @throws Exception
     */
    @XxlJob("everyHourExecuteJobHandler")
    public ReturnT<String> everyHourExecuteJobHandler(String param) {
        log.info("每小时任务执行");
        if (everyHourExecutes == null || everyHourExecutes.size() == 0) {
            return ReturnT.SUCCESS;
        }
        for (int i = 0; i < everyHourExecutes.size(); i++) {
            try {
                everyHourExecutes.get(i).execute();
            } catch (Exception e) {
                log.error("每小时任务异常", e);
            }
        }
        return ReturnT.SUCCESS;
    }
    /**
     * 每日任务
     *
     * @throws Exception
     */
    @XxlJob("everyDayExecuteJobHandler")
    public ReturnT<String> everyDayExecuteJobHandler(String param) {
        log.info("每日任务执行");
        if (everyDayExecutes == null || everyDayExecutes.size() == 0) {
            return ReturnT.SUCCESS;
        }
        for (int i = 0; i < everyDayExecutes.size(); i++) {
            try {
                everyDayExecutes.get(i).execute();
            } catch (Exception e) {
                log.error("每日任务异常", e);
            }
        }
        return ReturnT.SUCCESS;
    }
}
seller-api/src/main/java/cn/lili/controller/order/OrderStoreController.java
@@ -12,7 +12,6 @@
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.member.entity.dto.MemberAddressDTO;
import cn.lili.modules.member.service.StoreLogisticsService;
import cn.lili.modules.order.order.entity.dto.OrderExportDTO;
import cn.lili.modules.order.order.entity.dto.OrderSearchParams;
import cn.lili.modules.order.order.entity.dto.PartDeliveryParamsDTO;
import cn.lili.modules.order.order.entity.vo.OrderDetailVO;