peng
3 天以前 9f92aa108c24a67fabe80977cede0e0352318681
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;
@@ -17,16 +16,22 @@
import cn.lili.common.event.TransactionCommitSendMQEvent;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.properties.RocketmqCustomProperties;
import cn.lili.common.security.AuthUser;
import cn.lili.common.security.OperationalJudgment;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.security.enums.UserEnums;
import cn.lili.common.utils.CurrencyUtil;
import cn.lili.common.utils.SnowFlake;
import cn.lili.common.utils.StringUtils;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.goods.entity.dos.Goods;
import cn.lili.modules.goods.entity.dto.GoodsCompleteMessage;
import cn.lili.modules.goods.service.GoodsService;
import cn.lili.modules.lmk.domain.vo.OrderCountVO;
import cn.lili.modules.lmk.enums.general.AdminRoleEnum;
import cn.lili.modules.member.entity.dos.Member;
import cn.lili.modules.member.entity.dto.MemberAddressDTO;
import cn.lili.modules.member.mapper.MemberMapper;
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
import cn.lili.modules.order.cart.entity.enums.DeliveryMethodEnum;
import cn.lili.modules.order.order.aop.OrderLogPoint;
@@ -39,6 +44,9 @@
import cn.lili.modules.order.trade.entity.dos.OrderLog;
import cn.lili.modules.order.trade.service.OrderLogService;
import cn.lili.modules.payment.entity.enums.PaymentMethodEnum;
import cn.lili.modules.permission.entity.dos.AdminUser;
import cn.lili.modules.permission.service.AdminUserService;
import cn.lili.modules.permission.service.RoleService;
import cn.lili.modules.promotion.entity.dos.Pintuan;
import cn.lili.modules.promotion.service.PintuanService;
import cn.lili.modules.store.entity.dto.StoreDeliverGoodsAddressDTO;
@@ -62,6 +70,8 @@
import cn.lili.trigger.model.TimeTriggerMsg;
import cn.lili.trigger.util.DelayQueueTools;
import cn.lili.utils.COSUtil;
import cn.lili.utils.CommonUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -77,19 +87,24 @@
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import cn.lili.modules.permission.entity.dos.Role;
/**
 * 子订单业务层实现
 *
@@ -102,6 +117,8 @@
    private static final String ORDER_SN_COLUMN = "order_sn";
    @Autowired
    private MemberMapper memberMapperMapper;
    /**
     * 延时任务
     */
@@ -176,6 +193,14 @@
    private GoodsService goodsService;
    @Autowired
    private COSUtil cosUtil;
    @Autowired
    private AdminUserService adminUserService;
    @Resource
    private RedisTemplate<Object,Object> redisTemplate;
    private final static  String LOCK_ORDER_NO_MQ="lock_order_no_mq:";
    private final static  String LOCK_EDIT_ORDER_ADDRESS="lock_edit_order_address:";
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void intoDB(TradeDTO tradeDTO) {
@@ -205,6 +230,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));
                    }
@@ -224,19 +255,99 @@
    }
    @Override
    public IPage<OrderSimpleVO> queryByParams(OrderSearchParams orderSearchParams) {
    public OrderCountVO countByIdOrder(String id) {
        OrderSearchParams orderSearchParams = new OrderSearchParams();
        orderSearchParams.setOrderStatus(OrderStatusEnum.COMPLETED.name());
        orderSearchParams.setMemberId(id);
        QueryWrapper queryWrapper = orderSearchParams.queryWrapper();
        queryWrapper.groupBy("o.id");
        queryWrapper.orderByDesc("o.id");
        return this.baseMapper.queryByParams(PageUtil.initPage(orderSearchParams), queryWrapper);
    }
        List<OrderSimpleVO> list =  this.baseMapper.queryByParamsCount(queryWrapper);
        OrderCountVO orderCountVO = new OrderCountVO();
        orderCountVO.setOrderNumCount(0);
        orderCountVO.setOrderPriceCount(BigDecimal.ZERO);
        if (CollectionUtil.isEmpty(list)) {
            return orderCountVO;
        }else {
            for (OrderSimpleVO vo : list) {
                if (vo == null) {
                    System.out.println("出现空元素");
                    continue; // 跳过null元素,或根据业务处理
                }
                orderCountVO.setOrderNumCount(orderCountVO.getOrderNumCount() + 1);
                // 金额累加:用BigDecimal处理,避免精度问题
                BigDecimal flowPrice = vo.getFlowPrice() != null ?
                        BigDecimal.valueOf(vo.getFlowPrice()) : BigDecimal.ZERO;
                // 用BigDecimal的add方法累加
                BigDecimal totalPrice = orderCountVO.getOrderPriceCount().add(flowPrice);
                orderCountVO.setOrderPriceCount(totalPrice);
            }
        }
        return orderCountVO;
    }
    @Override
    public IPage<OrderSimpleXcxVO> queryByXcxParams(OrderSearchParams orderSearchParams) {
    public IPage<OrderSimpleVO> queryByParams(OrderSearchParams orderSearchParams,Boolean needHide) {
        QueryWrapper queryWrapper = orderSearchParams.queryWrapper();
        queryWrapper.groupBy("o.id");
        queryWrapper.orderByDesc("o.id");
        IPage<OrderSimpleVO> page =  this.baseMapper.queryByParams(PageUtil.initPage(orderSearchParams), queryWrapper);
        if (needHide){
            if (!adminUserService.havePermissionRole(AdminRoleEnum.ORDER_INFO_PERMISSION)){
                for (OrderSimpleVO vo : page.getRecords()){
                    vo.setConsigneeName(CommonUtil.maskName(vo.getConsigneeName()));
                    vo.setConsigneeMobile(CommonUtil.maskMobile(vo.getConsigneeMobile()));
                }
            }
        }
        return page;
    }
    @Override
    public IPage<OrderSimpleXcxVO> queryByXcxParams(OrderSearchXcxParams orderSearchParams) {
        QueryWrapper queryWrapper = orderSearchParams.queryWrapper();
        queryWrapper.groupBy("o.id");
        queryWrapper.orderByDesc("o.id");
        IPage<OrderSimpleXcxVO>  iPage = this.baseMapper.queryByXcxParams(PageUtil.initPage(orderSearchParams), queryWrapper);
        Set<String> goodsIds = new HashSet<>();
        for (OrderSimpleXcxVO orderSimpleVO : iPage.getRecords()) {
            orderSimpleVO.setOrderItems(orderSimpleVO.initOrderItems());
            String groupGoodsId = orderSimpleVO.getGroupGoodsId();
            if (StringUtils.isNotBlank(groupGoodsId)) {
                goodsIds.addAll(Arrays.asList(groupGoodsId.split(",")));
            }
        }
        if (CollectionUtil.isNotEmpty(goodsIds)) {
            List<Goods> list = goodsService.list(Wrappers.<Goods>lambdaQuery().in(Goods::getId, goodsIds));
            Map<String, String> goodsVideos = list
                    .stream().collect(Collectors.toMap(Goods::getId, g->
                            StringUtils.isNotBlank(g.getGoodsVideo())?g.getGoodsVideo():""
                    ));
            iPage.getRecords().forEach(orderSimpleVO -> {
                orderSimpleVO.getOrderItems().forEach(orderItem -> {
                    String videoUrl = goodsVideos.get(orderItem.getGoodsId());
                    if (StringUtils.isNotBlank(videoUrl)&&!videoUrl.contains("http")) {
                        orderItem.setVideo(cosUtil.getPreviewUrl(videoUrl));
                    }
                    String image = orderItem.getImage();
                    if (StringUtils.isNotBlank(image)&&!image.contains("http")) {
                        orderItem.setImage(cosUtil.getPreviewUrl(image));
                    }
                });
            });
        }
        return iPage;
    }
    @Override
    public IPage<OrderSimpleXcxVO> querySupplierOrderParams(SupplierOrderSearchParams orderSearchParams) {
        QueryWrapper queryWrapper = orderSearchParams.queryWrapper();
        queryWrapper.groupBy("o.id");
        queryWrapper.orderByDesc("o.id");
        IPage<OrderSimpleXcxVO>  iPage = this.baseMapper.querySupplierOrderParams(PageUtil.initPage(orderSearchParams), queryWrapper);
        Set<String> goodsIds = new HashSet<>();
        for (OrderSimpleXcxVO orderSimpleVO : iPage.getRecords()) {
            orderSimpleVO.setOrderItems(orderSimpleVO.initOrderItems());
@@ -335,8 +446,15 @@
    @Override
    public void queryExportOrder(HttpServletResponse response, OrderSearchParams orderSearchParams) {
        List<OrderExportDTO> orderExportDTOS = this.baseMapper.queryExportOrder(orderSearchParams.queryWrapper());
        XSSFWorkbook workbook = initOrderExportData(this.baseMapper.queryExportOrder(orderSearchParams.queryWrapper()));
        if (!adminUserService.havePermissionRole(AdminRoleEnum.ORDER_INFO_PERMISSION)){
            for (OrderExportDTO vo : orderExportDTOS){
                vo.setConsigneeName(CommonUtil.maskName(vo.getConsigneeName()));
                vo.setConsigneeMobile(CommonUtil.maskMobile(vo.getConsigneeMobile()));
            }
        }
        XSSFWorkbook workbook = initOrderExportData(orderExportDTOS);
        try {
            // 设置响应头
            String fileName = URLEncoder.encode("订单列表", "UTF-8");
@@ -371,6 +489,42 @@
        //查询订单和自订单,然后写入vo返回
        return new OrderDetailVO(order, orderItems, orderLogs, receipt);
    }
    @Override
    public OrderDetailVO queryEditAddressDetail(String orderSn) {
        Order order = this.getBySn(orderSn);
        if (order == null) {
            throw new ServiceException(ResultCode.ORDER_NOT_EXIST);
        }
        //查询订单项信息
        List<OrderItem> orderItems = orderItemService.getByOrderSn(orderSn);
        //查询订单和自订单,然后写入vo返回
        return new OrderDetailVO(order, orderItems, null, null);
    }
    @Override
    @Transactional
    public String sendMqMessage(String snNo) {
        //限制30秒只能请求一次避免出现重新提交问题
        Boolean b = redisTemplate.opsForValue().setIfAbsent(LOCK_ORDER_NO_MQ + snNo, snNo,30, TimeUnit.SECONDS);
        if ( Boolean.FALSE.equals(b)){
            throw new ServiceException("请在30秒后重试");
        }
        Order order = this.getBySn(snNo);
        if (order == null) {
            throw new ServiceException(ResultCode.ORDER_NOT_EXIST);
        }
        if (!OrderStatusEnum.PAID.name().equals(order.getOrderStatus())) {
            throw new ServiceException("订单状态不是已支付状态");
        }
        OrderMessage orderMessage = new OrderMessage();
        //发送订单已付款消息
        orderMessage.setOrderSn(order.getSn());
        orderMessage.setPaymentMethod(order.getPaymentMethod());
        orderMessage.setNewStatus(OrderStatusEnum.PAID);
        this.sendUpdateStatusMessage(orderMessage);
        return null;
    }
    @Override
    @OrderLogPoint(description = "'订单['+#orderSn+']取消,原因为:'+#reason", orderSn = "#orderSn")
@@ -403,6 +557,7 @@
            throw new ServiceException(ResultCode.ORDER_CAN_NOT_CANCEL);
        }
    }
    @Override
@@ -454,7 +609,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());
@@ -506,16 +679,52 @@
        return order;
    }
    @Override
    @SystemLogPoint(description = "修改订单", customerLog = "'订单[' + #orderSn + ']收货信息修改,修改为'+#memberAddressDTO.consigneeDetail")
    @Transactional(rollbackFor = Exception.class)
    public Order updateAddressConsignee(String orderSn, MemberAddressDTO memberAddressDTO) {
        Order order = this.getBySn(orderSn);
        if (order == null) {
            throw new ServiceException(ResultCode.ORDER_NOT_EXIST);
        }
        //限制30秒只能请求一次避免出现重新提交问题
        Boolean b = redisTemplate.opsForValue().setIfAbsent(LOCK_EDIT_ORDER_ADDRESS + orderSn, orderSn,30, TimeUnit.SECONDS);
        if ( Boolean.FALSE.equals(b)){
            throw new ServiceException("请在30秒后重试");
        }
        String modifyAddressFlag = order.getModifyAddressFlag();
        if (StringUtils.isNotBlank(modifyAddressFlag)) {
            throw new ServiceException("当前订单已经被领取");
        }
        QueryWrapper<Order> wrapper = new QueryWrapper<>();
        wrapper.eq("id", order.getId());
        // 使用 last 方法拼接 FOR UPDATE 语句
        wrapper.last("FOR UPDATE");
        baseMapper.selectOne(wrapper);
        //要记录之前的收货地址,所以需要以代码方式进行调用 不采用注解
        String message = "订单[" + orderSn + "]收货信息修改,由[" +order.getConsigneeAddressPath()+  order.getConsigneeDetail() + "]修改为[" + memberAddressDTO.getConsigneeAddressPath()+ memberAddressDTO.getConsigneeDetail() + "]";
        //记录订单操作日志
        BeanUtil.copyProperties(memberAddressDTO, order);
        order.setModifyAddressFlag(ModifyAddressEnums.USED.name());
        this.updateById(order);
        OrderLog orderLog = new OrderLog(orderSn, UserContext.getCurrentUser().getId(), UserContext.getCurrentUser().getRole().getRole(),
                UserContext.getCurrentUser().getUsername(), message);
        orderLogService.save(orderLog);
        return order;
    }
    @Override
    @OrderLogPoint(description = "'订单['+#orderSn+']发货,发货单号['+#logisticsNo+']'", orderSn = "#orderSn")
    @Transactional(rollbackFor = Exception.class)
    public Order delivery(String orderSn, String logisticsNo, String logisticsId) {
        Order order = OperationalJudgment.judgment(this.getBySn(orderSn));
        //如果订单未发货,并且订单状态值等于待发货
        log.info("获取到的订单信息为{}", JSON.toJSONString(order));
        if (order.getDeliverStatus().equals(DeliverStatusEnum.UNDELIVERED.name()) && order.getOrderStatus().equals(OrderStatusEnum.UNDELIVERED.name())) {
            //获取对应物流
            Logistics logistics = logisticsService.getById(logisticsId);
            log.info("获取到的物流信息id为{}", logisticsId);
            log.info("获取到的物流信息为{}", JSON.toJSONString(logistics));
            if (logistics == null) {
                throw new ServiceException(ResultCode.ORDER_LOGISTICS_ERROR);
            }
@@ -1182,6 +1391,12 @@
        this.update(new LambdaUpdateWrapper<Order>()
                .eq(Order::getSn, orderSn)
                .set(Order::getOrderStatus, orderStatusEnum.name()));
        //修改订单商品 todo 所有的订单需要审核后才能退款
        orderItemService.update(new LambdaUpdateWrapper<OrderItem>()
                .eq(OrderItem::getOrderSn,orderSn)
                .set(OrderItem::getAfterSaleStatus, OrderItemAfterSaleStatusEnum.NOT_APPLIED.name())
                .set(OrderItem::getCommentStatus,CommentStatusEnum.UNFINISHED.name())
                .set(OrderItem::getComplainStatus, OrderComplaintStatusEnum.NO_APPLY.name()));
        //修改订单
        OrderMessage orderMessage = new OrderMessage();
        orderMessage.setNewStatus(orderStatusEnum);
@@ -1304,7 +1519,7 @@
        // 创建表头
        Row header = sheet.createRow(0);
        String[] headers = {"主订单编号", "子订单编号", "选购商品", "商品数量", "商品ID", "商品单价", "订单应付金额",
                "运费", "优惠总金额", "平台优惠", "商家优惠", "商家改价", "支付方式", "收件人", "收件人手机号",
                "运费", "优惠总金额", "平台优惠", "商家优惠", "商家改价", "支付方式","买家名称", "收件人", "收件人手机号",
                "省", "市", "区", "街道", "详细地址", "买家留言", "订单提交时间", "支付完成时间", "来源",
                "订单状态", "订单类型", "售后状态", "取消原因", "发货时间", "完成时间", "店铺"};
@@ -1329,24 +1544,27 @@
            row.createCell(10).setCellValue(dto.getStoreMarketingCost()!=null?dto.getStoreMarketingCost():0);
            row.createCell(11).setCellValue(dto.getUpdatePrice()!=null?dto.getUpdatePrice():0);
            row.createCell(12).setCellValue(dto.getPaymentMethod());
            row.createCell(13).setCellValue(dto.getConsigneeName());
            row.createCell(14).setCellValue(dto.getConsigneeMobile());
            row.createCell(15).setCellValue(dto.getProvince());
            row.createCell(16).setCellValue(dto.getCity());
            row.createCell(17).setCellValue(dto.getDistrict());
            row.createCell(18).setCellValue(dto.getStreet());
            row.createCell(19).setCellValue(dto.getConsigneeDetail());
            row.createCell(20).setCellValue(dto.getRemark());
            row.createCell(21).setCellValue(dto.getCreateTime());
            row.createCell(22).setCellValue(dto.getPaymentTime());
            row.createCell(23).setCellValue(dto.getClientType());
            row.createCell(24).setCellValue(dto.getOrderStatus());
            row.createCell(25).setCellValue(dto.getOrderType());
            row.createCell(26).setCellValue(dto.getAfterSaleStatus());
            row.createCell(27).setCellValue(dto.getCancelReason());
            row.createCell(28).setCellValue(dto.getLogisticsTime());
            row.createCell(29).setCellValue(dto.getCompleteTime());
            row.createCell(30).setCellValue(dto.getStoreName());
            row.createCell(13).setCellValue(dto.getNickName());
            row.createCell(14).setCellValue(dto.getConsigneeName());
            row.createCell(15).setCellValue(dto.getConsigneeMobile());
            row.createCell(16).setCellValue(dto.getProvince());
            row.createCell(17).setCellValue(dto.getCity());
            row.createCell(18).setCellValue(dto.getDistrict());
            row.createCell(19).setCellValue(dto.getStreet());
            row.createCell(20).setCellValue(dto.getConsigneeDetail());
            row.createCell(21).setCellValue(dto.getRemark());
            row.createCell(22).setCellValue(dto.getCreateTime());
            row.createCell(23).setCellValue(dto.getPaymentTime());
            row.createCell(24).setCellValue(dto.getClientType());
            row.createCell(25).setCellValue(dto.getOrderStatus());
            row.createCell(26).setCellValue(dto.getOrderType());
            row.createCell(27).setCellValue(dto.getAfterSaleStatus());
            row.createCell(28).setCellValue(dto.getCancelReason());
            row.createCell(29).setCellValue(dto.getLogisticsTime());
            row.createCell(30).setCellValue(dto.getCompleteTime());
            row.createCell(31).setCellValue(dto.getStoreName());
        }
        //修改列宽