111
k94314517
2025-03-20 3d3ed4872b5038a8cc72abc72f95fc2c134e7bc4
server/services/src/main/java/com/doumee/service/business/impl/GoodsorderServiceImpl.java
@@ -6,6 +6,7 @@
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.doumee.core.annotation.excel.ExcelExporter;
import com.doumee.core.constants.Constants;
import com.doumee.biz.system.SystemDictDataBiz;
import com.doumee.core.constants.Constants;
@@ -28,6 +29,8 @@
import com.doumee.dao.business.model.Goodsorder;
import com.doumee.dao.business.model.Member;
import com.doumee.dao.business.model.MemberRides;
import com.doumee.dao.business.vo.BikeIncomeDetailReportVO;
import com.doumee.dao.business.vo.BikeIncomeReportVO;
import com.doumee.dao.business.vo.GoodsorderExportVO;
import com.doumee.dao.business.vo.GoodsorderTotalDataVO;
import com.doumee.dao.business.web.request.*;
@@ -58,10 +61,14 @@
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.sql.Ref;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
@@ -199,7 +206,9 @@
            MPJLambdaWrapper<Goodsorder> queryWrapper = new MPJLambdaWrapper<>();
            queryWrapper.selectAll(Goodsorder.class);
            queryWrapper.selectAs(Member::getOpenid, Goodsorder::getOpenid);
            queryWrapper.selectAs(BaseParam::getType, Goodsorder::getBikeType);
            queryWrapper.leftJoin(Member.class, Member::getId  ,Goodsorder::getMemberId);
            queryWrapper.leftJoin(BaseParam.class, BaseParam::getId  ,Goodsorder::getParamId);
            queryWrapper.select("(select max(r.done_date) from refund r where r.obj_id=t.id  and r.status=2 ) as refund_date");
            queryWrapper.select("(select sum(r.money) from refund r where r.obj_id=t.id and r.status=2) as refund_money");
            //时间段筛选
@@ -213,6 +222,9 @@
            queryWrapper.eq(Goodsorder::getPayStatus,Constants.ONE);
            queryWrapper.orderByAsc(Goodsorder::getPayDate);
            goodsorderExportVOIPage = goodsorderJoinMapper.selectJoinPage(page, GoodsorderExportVO.class, queryWrapper);
        }else{
            MPJLambdaWrapper<Refund> queryWrapper = new MPJLambdaWrapper<>();
            queryWrapper.selectAs(Refund::getMoney,GoodsorderExportVO::getRefundMoney);
@@ -240,6 +252,7 @@
        if (!CollectionUtils.isEmpty(goodsorderExportVOIPage.getRecords())){
            goodsorderExportVOIPage.getRecords().forEach(s->{
                s.setBikeType(s.getType()==Constants.ZERO?s.getBikeType():Constants.ONE);
                s.setMoney(Constants.translateMoney(s.getMoney()));
                s.setRefundMoney(Constants.translateMoney(s.getRefundMoney()));
                s.setCloseMoney(Constants.translateMoney(s.getCloseMoney()).compareTo(s.getMoney()) > 0 ? s.getMoney() : Constants.translateMoney(s.getCloseMoney()));
@@ -283,6 +296,7 @@
        }
        if (!CollectionUtils.isEmpty(goodsorderList)){
            goodsorderList.forEach(s->{
                s.setBikeType(s.getType()==Constants.ZERO?s.getBikeType():Constants.ONE);
                s.setMoney(Constants.translateMoney(s.getMoney()));
                s.setCloseMoney(Constants.translateMoney(s.getCloseMoney()).compareTo(s.getMoney()) > 0 ? s.getMoney() : Constants.translateMoney(s.getCloseMoney()));
                s.setRefundMoney(Constants.translateMoney(s.getRefundMoney()));
@@ -296,11 +310,13 @@
        queryWrapper.selectAll(Goodsorder.class);
        queryWrapper.selectAs(Member::getOpenid, Goodsorder::getOpenid);
        queryWrapper.selectAs(DiscountMember::getName, Goodsorder::getDiscountName);
        queryWrapper.selectAs(BaseParam::getType, Goodsorder::getBikeType);
        queryWrapper.leftJoin(Member.class, Member::getId  ,Goodsorder::getMemberId);
        queryWrapper.leftJoin(DiscountMember.class, DiscountMember::getGoodsorderId  ,Goodsorder::getId);
//        queryWrapper.select("(select r.name from discount_member r where r.isdeleted=0  and r.goodsorder_id=t.id limit 1) as discountName");
        queryWrapper.leftJoin(BaseParam.class, BaseParam::getId  ,Goodsorder::getParamId);
        queryWrapper.select("(select max(r.done_date) from refund r where r.obj_id=t.id  and  r.status in(0,2)) as refund_date");
        queryWrapper.select("(select sum(r.money) from refund r where r.obj_id=t.id and r.status in(0,2)) as refund_money");
        queryWrapper.select("(select  sum(d.ride_price)  from discount_log d where d.goodsorder_id=t.id and d.type = 0) as discountMoney");
        //时间段筛选
        if (Objects.nonNull(model.getStartDate())){
            queryWrapper.ge(Goodsorder::getPayDate, Utils.Date.getStart(model.getStartDate()));
@@ -308,6 +324,7 @@
        if (Objects.nonNull(model.getEndDate())){
            queryWrapper.le( Goodsorder::getPayDate, Utils.Date.getEnd(model.getEndDate()));
        }
        queryWrapper.eq(Objects.nonNull(model.getBikeType()),BaseParam::getType,model.getBikeType());
        queryWrapper.eq(Constants.equalsInteger(model.getType(),Constants.ONE)&&model.getPayStatus() !=null,Goodsorder::getPayStatus,model.getPayStatus());
        queryWrapper.like(model.getCode() !=null,Goodsorder::getCode,model.getCode());
        queryWrapper.like(model.getId() !=null,Goodsorder::getId,model.getId());
@@ -333,6 +350,8 @@
        queryWrapper.select("(select  sum(er.discount_price) from member_rides  er  where er.ordre_id=t.id and er.isdeleted=0) as discountMoney," +
                "(select  er.status from member_rides  er  where er.ordre_id=t.id order by er.create_date desc limit 1) as memberRidesStatus");
        queryWrapper.select("( select s.realname from refund r left join system_user s on r.creator = s.id where r.obj_id = t.id order by r.id desc  limit 1  ) ",Goodsorder::getRefundUserName);
        if(Objects.nonNull(pageWrap.getModel().getCloseStatus()) && pageWrap.getModel().getCloseStatus().equals(Constants.ZERO)){
            queryWrapper.ne(Goodsorder::getStatus,Constants.GOODSORDER_STATUS.CLOSE.getKey());
@@ -627,6 +646,7 @@
                freeTime = Integer.parseInt(systemDictDataBiz.queryByCode(Constants.MINI_PROGRAMME, Constants.FREE_RENT_TIME).getCode());
            }catch (Exception e){
            }
            closeMoney = getCloseMoneyByRides(memberRides,freeTime,true,goodsorder.getMoney(),goodsorder.getMemberId(),true).getAmount();
            //实际结算价格,记录在最高车型记录上
//            memberRides.get(0).setActualPrice(closeMoney);
@@ -674,6 +694,15 @@
                memberRidesJoinMapper.updateById(up);
            }
        }
        int durationSum = 0;
        int freeTime = 0;
        try {
            freeTime = Integer.parseInt(systemDictDataBiz.queryByCode(Constants.MINI_PROGRAMME, Constants.FREE_RENT_TIME).getCode());
        }catch (Exception e){
        }
        //最高价格车型的骑行记录
        MemberRides topRides = this.getMaxRides(memberRides,durationSum,freeTime,true);
//        BigDecimal closeMoney =( Constants.formatDecimalNum(goodsorder.getMoney()).subtract(refund.getMoney()));
        //退款乐行
//       int type =Constants.formatIntegerNum(refund.getType());
@@ -681,6 +710,7 @@
        update.setId(goodsorder.getId());
        update.setStatus(Constants.GOODSORDER_STATUS.CLOSE.getKey());
        update.setCloseMoney(closeMoney);
        update.setParamId(Objects.nonNull(topRides)?topRides.getParamId():null);
        update.setCloseStatus(Constants.ONE);
        update.setCloseDate(new Date());
        update.setCloseInfo(Constants.REFUND_TYPE.get(type).getInfo());
@@ -717,6 +747,23 @@
        transactionsMapper.insert(transactions);
        //修改订单信息
        goodsorderMapper.updateById(update);
    }
    public MemberRides getMaxRides(List<MemberRides> memberRides,Integer durationSum,Integer freeTime,boolean isClose){
        MemberRides topRides =null;
        for(MemberRides rides : memberRides){
            if ( isClose && Constants.MEMBER_RIDES_STATUS.BACK_CYCLING.getKey()!=(Constants.formatIntegerNum(rides.getStatus()))){
                throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"当前订单有未完成的骑行,无法强制结算");
            }
            durationSum += Constants.formatIntegerNum(rides.getDuration());//累计骑行(计费)时长
            if(durationSum-freeTime > 0 ){//只算超出免费时长的数据
                if(topRides == null ||( Constants.formatIntegerNum(topRides.getSortnum())<Constants.formatIntegerNum(rides.getSortnum())
                        && Constants.formatIntegerNum(rides.getDuration())>0)){
                    topRides = rides;
                }
            }
        }
        return topRides;
    }
    /**
     * 退款成功回调
@@ -797,21 +844,8 @@
        ridesDetailResponse.setHaveDisCount(Constants.ZERO);
        BigDecimal closeMoney = new BigDecimal(0.00);
        int durationSum = 0;
        MemberRides topRides =null;
        //取最高车型计算方案结算订单
        for(MemberRides rides : memberRides){
            if ( isClose && Constants.MEMBER_RIDES_STATUS.BACK_CYCLING.getKey()!=(Constants.formatIntegerNum(rides.getStatus()))){
                throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"当前订单有未完成的骑行,无法强制结算");
            }
            durationSum += Constants.formatIntegerNum(rides.getDuration());//累计骑行(计费)时长
            if(durationSum-freeTime > 0 ){//只算超出免费时长的数据
                if(topRides == null ||( Constants.formatIntegerNum(topRides.getSortnum())<Constants.formatIntegerNum(rides.getSortnum())
                        && Constants.formatIntegerNum(rides.getDuration())>0)){
                    topRides = rides;
                }
            }
        }
        //最高价格车型的骑行记录
        MemberRides topRides = this.getMaxRides(memberRides,durationSum,freeTime,isClose);
        //计算应付金额
        if( topRides != null){
@@ -827,6 +861,8 @@
                }
            }
            topRides.setActualPrice(closeMoney);
            //2025年3月18日11:28:38 返回骑行价格最高的车型
            ridesDetailResponse.setParamId(topRides.getParamId());
        } 
        //查询是否存在套餐信息
        DiscountMember discountMember = this.getUseDiscount(memberId,durationSum,Objects.nonNull(topRides)?topRides.getType():null);
@@ -1016,6 +1052,7 @@
            model.setPayMoney(new BigDecimal(0.00));
            model.setRefundMoney(new BigDecimal(0.00));
            model.setClosedMoney(new BigDecimal(0.00));
            model.setDiscountMoney(new BigDecimal(0.00));
            model.setUnClosedMoney(new BigDecimal(0.00));
            model.setClosedNum(0);
            model.setUnClosedNum(0);
@@ -1030,28 +1067,36 @@
            }
            queryWrapper.lambda().eq(Goodsorder::getPayStatus, Constants.ONE);//已支付
            queryWrapper.lambda().eq(Goodsorder::getIsdeleted, Constants.ZERO);
            queryWrapper.lambda().groupBy(Goodsorder::getStatus);
            queryWrapper.select( "status ","count(id) as count_num"
            queryWrapper.lambda().groupBy(Goodsorder::getStatus,Goodsorder::getType);
            queryWrapper.select( "type","status ","count(id) as count_num"
                    ,"sum(money) as money","sum(close_money) as close_money" );
            //按订单状态分组统计
            List<Goodsorder> detailList = goodsorderMapper.selectList(queryWrapper);
            for(Goodsorder goodsorder : detailList){
                if(Constants.formatIntegerNum(goodsorder.getStatus()) == Constants.GOODSORDER_STATUS.CLOSE.getKey()){
                    //已结算
                    model.setClosedNum(model.getClosedNum()+goodsorder.getCountNum());
                    //修改bug 结算收入 = 支付金额-退款-未结算
                if(Constants.equalsInteger(goodsorder.getType(),Constants.ZERO)){
                    //如果是骑行订单押金,计算骑行收入
                    if(Constants.formatIntegerNum(goodsorder.getStatus()) == Constants.GOODSORDER_STATUS.CLOSE.getKey()){
                        //已结算
                        model.setClosedNum(model.getClosedNum()+goodsorder.getCountNum());
                        //修改bug 结算收入 = 支付金额-退款-未结算
//                    model.setClosedMoney(model.getClosedMoney().add(Constants.translateMoney(goodsorder.getCloseMoney())));
                    model.setPayNum(model.getPayNum()+goodsorder.getCountNum());
                    model.setPayMoney(model.getPayMoney().add(Constants.translateMoney(goodsorder.getMoney())));
                }else  if(Constants.formatIntegerNum(goodsorder.getStatus()) == Constants.GOODSORDER_STATUS.HAVING_PAY.getKey()){
                    //已支付未结算
                    model.setUnClosedNum(model.getUnClosedNum()+goodsorder.getCountNum());
                    model.setUnClosedMoney(model.getUnClosedMoney().add(Constants.translateMoney(goodsorder.getMoney())));
                        model.setPayNum(model.getPayNum()+goodsorder.getCountNum());
                        model.setPayMoney(model.getPayMoney().add(Constants.translateMoney(goodsorder.getMoney())));
                    }else  if(Constants.formatIntegerNum(goodsorder.getStatus()) == Constants.GOODSORDER_STATUS.HAVING_PAY.getKey()){
                        //已支付未结算
                        model.setUnClosedNum(model.getUnClosedNum()+goodsorder.getCountNum());
                        model.setUnClosedMoney(model.getUnClosedMoney().add(Constants.translateMoney(goodsorder.getMoney())));
                    model.setPayNum(model.getPayNum()+goodsorder.getCountNum());
                    model.setPayMoney(model.getPayMoney().add(Constants.translateMoney(goodsorder.getMoney())));
                        model.setPayNum(model.getPayNum()+goodsorder.getCountNum());
                        model.setPayMoney(model.getPayMoney().add(Constants.translateMoney(goodsorder.getMoney())));
                    }
                }else{
                    //套餐卡收入累计 (交易笔数和交易金额)
                    model.setDiscountNum(model.getDiscountNum()+goodsorder.getCountNum());
                    model.setDiscountMoney(model.getDiscountMoney().add(Constants.translateMoney(goodsorder.getMoney())));
                }
            }
        QueryWrapper<Refund> queryWrapper2 = new QueryWrapper<>();
        if(Objects.nonNull(param.getStartDate())) {
@@ -1376,6 +1421,7 @@
    public void autoCloseOrder( ) {
        Goodsorder goodsorder = new Goodsorder();
        goodsorder.setIsdeleted(Constants.ZERO);
        goodsorder.setType(Constants.ZERO);
        goodsorder.setStatus(Constants.goodsorderStatus.pay);
        List<Goodsorder> list = findList(goodsorder);
        if (!CollectionUtils.isEmpty(list)){
@@ -1392,8 +1438,8 @@
                }
            });
        }
    }
    @Override
    public void goodsOrderSettlement(String memberId) {
        Goodsorder goodsorder = this.goodsorderMapper.selectOne(new QueryWrapper<Goodsorder>()
@@ -1632,4 +1678,85 @@
        );
    }
    @Override
    public List<List<String>> getBikeIncomeReportVOList(Date startDate ,Date endDate){
        if( (Objects.isNull(startDate)||Objects.isNull(endDate))
        || startDate.getTime()>endDate.getTime()
        || DateUtil.daysBetweenDates(endDate,startDate) > 30
        )
        {
            throw new BusinessException(ResponseStatus.BAD_REQUEST);
        }
        System.out.println( DateUtil.daysBetweenDates(endDate,startDate));
        //获取所有车型信息
        List<BaseParam> baseParamList = baseParamMapper.selectList(new QueryWrapper<BaseParam>().lambda().eq(BaseParam::getIsdeleted,Constants.ZERO)
                .in(BaseParam::getType,Constants.THREE,Constants.FOUR)
                .orderByAsc(BaseParam::getType,BaseParam::getSortnum)
        );
        //获取2个日期下所有天数
        List<Date> dateList = DateUtil.getDateList(startDate,endDate);
        //查询日期内的所有数据
        List<Goodsorder> goodsorderList = goodsorderMapper.selectList(new QueryWrapper<Goodsorder>().lambda().eq(Goodsorder::getType,Constants.ZERO)
                .eq(Goodsorder::getIsdeleted,Constants.ZERO)
                .eq(Goodsorder::getStatus,Constants.FOUR)
                .isNotNull(Goodsorder::getParamId)
                .ge(Goodsorder::getPayDate, Utils.Date.getStart(startDate))
                .le( Goodsorder::getPayDate, Utils.Date.getEnd(endDate))
        );
        List<List<String>> parentList = new ArrayList<>();
        for (BaseParam baseParam:baseParamList) {
            List<String> dataChildList = new ArrayList<>();
            dataChildList.add(baseParam.getName()+"(元)");
            BigDecimal totalAmount = BigDecimal.ZERO;
            for (Date date:dateList) {
                BigDecimal amount = goodsorderList.stream()
                        .filter(i->StringUtils.isNotBlank(i.getParamId())&&DateUtil.getShortDateStr(date).equals(DateUtil.getShortDateStr(i.getCreateDate()))&&baseParam.getId().equals(i.getParamId()))
                        .map(i->i.getCloseMoney()).reduce(BigDecimal.ZERO,BigDecimal::add);
                dataChildList.add(amount.divide(new BigDecimal("100"),2,BigDecimal.ROUND_HALF_UP).toString());
                totalAmount  = amount.add(totalAmount);
            }
            BikeIncomeDetailReportVO detail = new BikeIncomeDetailReportVO();
            dataChildList.add("¥"+totalAmount);
            parentList.add(dataChildList);
        }
        List<String> dataStrList = new ArrayList<>();
        dataStrList.add("日期");
        for (Date date:dateList) {
            dataStrList.add(DateUtil.getShortDateStr(date));
        }
        dataStrList.add("总计");
        parentList.add(0,dataStrList);
        return parentList;
    }
    @Override
    public void excel(Date startDate , Date endDate, HttpServletResponse response){
        List<List<String>> data = this.getBikeIncomeReportVOList(startDate,endDate);
        try {
            String fileName = "车型收入分析_"+System.currentTimeMillis();
            String encodeFileName = URLEncoder.encode(fileName, Charset.forName("UTF-8").toString()) + ".xlsx";
            response.setHeader("Content-Disposition","attachment;filename=" + encodeFileName);
            response.setContentType("application/octet-stream");
            response.setHeader("eva-opera-type", "download");
            response.setHeader("eva-download-filename", encodeFileName);
            ExcelExporter.exportList(data, fileName, response.getOutputStream());
        } catch (IOException e) {
            throw new BusinessException(ResponseStatus.EXPORT_EXCEL_ERROR, e);
        }
    }
}