liujie
2026-05-06 a3972e331b703c703ba29e6070432997428bb00f
发票功能
5个文件已添加
3个文件已修改
590 ■■■■■ 已修改文件
xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/order/UpdateInvoiceStatusDto.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/order/XpOrder.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/query/order/InvoiceOrdersQuery.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/query/order/XpOrderInvoiceQuery.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/order/XpInvoiceVo.java 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpInvoiceController.java 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/IXpOrderService.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/order/UpdateInvoiceStatusDto.java
New file
@@ -0,0 +1,38 @@
package com.xiaopeng.api.dto.order;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
@Data
@ApiModel(value = "更新发票状态参数")
public class UpdateInvoiceStatusDto {
    @ApiModelProperty(value = "请求ID(开票id)")
    @NotBlank(message = "请求ID不能为空")
    private String requestId;
    @ApiModelProperty(value = "订单列表")
    @Valid
    @NotEmpty(message = "订单列表不能为空")
    private List<Order> orderList;
    @Data
    @ApiModel(value = "UpdateInvoiceStatusOrder对象", description = "订单发票状态")
    public static class Order {
        @ApiModelProperty(value = "订单号")
        @NotBlank(message = "订单号不能为空")
        private String orderNo;
        @ApiModelProperty(value = "发票状态(-1: 无需开票;0: 未开票;1: 开票中;2: 已开票)")
        @NotNull(message = "发票状态不能为空")
        private Integer invoiceStatus;
    }
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/order/XpOrder.java
@@ -263,4 +263,14 @@
    @ApiModelProperty(value = "XPU送驾行程任务id")
    @TableField("xpu_end_task_id")
    private String xpuEndTaskId;
    @ApiModelProperty(value = "-1:无需开票;0:未开票;1:开票中;2:已开票")
    @TableField("invoice_status")
    private Integer invoiceStatus;
    @ApiModelProperty(value = "发票id")
    @TableField("invoice_id")
    private String invoiceId;
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/query/order/InvoiceOrdersQuery.java
New file
@@ -0,0 +1,22 @@
package com.xiaopeng.api.query.order;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import java.util.List;
@Data
@ApiModel(value = "开票订单查询参数")
public class InvoiceOrdersQuery {
    @ApiModelProperty(value = "用户ID")
    @NotBlank(message = "用户ID不能为空")
    private String uid;
    @ApiModelProperty(value = "订单号列表")
    @NotEmpty(message = "订单号列表不能为空")
    private List<String> orderNoList;
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/query/order/XpOrderInvoiceQuery.java
New file
@@ -0,0 +1,34 @@
package com.xiaopeng.api.query.order;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
@ApiModel(value = "订单开票查询参数")
public class XpOrderInvoiceQuery {
    @ApiModelProperty(value = "用户ID")
    @NotBlank(message = "用户ID不能为空")
    private String uid;
    @ApiModelProperty(value = "业务类型;9-Robotaxi")
    @NotBlank(message = "业务类型不能为空")
    private String busType;
    @ApiModelProperty(value = "查询月份起始时间(格式:yyyyMM)")
    @NotBlank(message = "查询月份起始时间不能为空")
    private String startTime;
    @ApiModelProperty(value = "查询截止时间(格式:yyyyMM)")
    @NotBlank(message = "查询截止时间不能为空")
    private String endTime;
    @ApiModelProperty(value = "页码")
    private Integer pageNo;
    @ApiModelProperty(value = "每页数量10")
    private Integer pageSize = 10;
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/order/XpInvoiceVo.java
New file
@@ -0,0 +1,157 @@
package com.xiaopeng.api.vo.order;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
@Data
@ApiModel(value = "XpInvoiceVo对象", description = "电子发票参数")
public class XpInvoiceVo {
    @ApiModelProperty(value = "用户uid")
    private String uid;
    @ApiModelProperty(value = "业务订单号")
    private String orderNo;
    @ApiModelProperty(value = "订单描述")
    private String orderDesc;
    @ApiModelProperty(value = "商品明细(JSON格式)")
    private String goodsDetail;
    @ApiModelProperty(value = "订单总金额")
    private BigDecimal orderTotalAmount;
    @ApiModelProperty(value = "业务金额")
    private BigDecimal orderBusAmount;
    @ApiModelProperty(value = "服务费金额")
    private BigDecimal orderServiceAmount;
    @ApiModelProperty(value = "占位费金额")
    private BigDecimal orderLocationAmount;
    @ApiModelProperty(value = "充电险金额")
    private BigDecimal insuranceAmount;
    @ApiModelProperty(value = "折扣费金额")
    private BigDecimal orderDiscountAmount;
    @ApiModelProperty(value = "订单完成时间")
    private String orderFinishTime;
    @ApiModelProperty(value = "扩展字段(JSON格式)")
    private String extData;
    @ApiModelProperty(value = "发票总金额(实际支付费用)")
    private BigDecimal invoiceTotalAmount;
    @ApiModelProperty(value = "商户ID")
    private String businessId;
    @ApiModelProperty(value = "业务分类ID")
    private String categoryId;
    @ApiModelProperty(value = "子订单号")
    private String subOrderNo;
    @ApiModelProperty(value = "业务类型")
    private Integer busType;
    @ApiModelProperty(value = "是否小鹏开票")
    private Boolean xpInvoiceFlag;
    @ApiModelProperty(value = "开票状态(-1: 无需开票;0: 未开票;1: 开票中;2: 已开票)")
    private Integer invoiceStatus;
    @ApiModelProperty(value = "行程单")
    private Object itinerary;
    @Data
    @ApiModel(value = "GoodsDetail对象", description = "商品明细参数")
    public static class GoodsDetail {
        @ApiModelProperty(value = "商品名词")
        private String productName;
        @ApiModelProperty(value = "产品编码")
        private String productCode;
        @ApiModelProperty(value = "产品规格编码(物料编码)")
        private String productSpecCode;
        @ApiModelProperty(value = "产品规格型号")
        private String productSpec;
        @ApiModelProperty(value = "产品单位")
        private String productUnit;
        @ApiModelProperty(value = "数量")
        private Integer quantity;
        @ApiModelProperty(value = "单价")
        private BigDecimal unitPrice;
        @ApiModelProperty(value = "含税金额")
        private BigDecimal inTaxAmount;
        @ApiModelProperty(value = "税率")
        private BigDecimal taxRate;
        @ApiModelProperty(value = "税额")
        private BigDecimal taxAmount;
        @ApiModelProperty(value = "不含税金额")
        private BigDecimal exTaxAmount;
        @ApiModelProperty(value = "商品ItemId")
        private String itemId;
        @ApiModelProperty(value = "优惠(优惠额度+积分)")
        private BigDecimal couponAmount;
        @ApiModelProperty(value = "公司编码")
        private String companyCode;
    }
    @Data
    @ApiModel(value = "Itinerary对象", description = "行程单参数")
    public static class Itinerary {
        @ApiModelProperty(value = "行程起始日期,格式:yyyy-MM-dd")
        private String tripStartDate;
        @ApiModelProperty(value = "行程结束日期,格式:yyyy-MM-dd")
        private String tripEndDate;
        @ApiModelProperty(value = "行程人手机号")
        private String phone;
        @ApiModelProperty(value = "车型")
        private String carType;
        @ApiModelProperty(value = "上车时间")
        private String pickupTime;
        @ApiModelProperty(value = "城市")
        private String city;
        @ApiModelProperty(value = "起点")
        private String startPoint;
        @ApiModelProperty(value = "终点")
        private String endPoint;
        @ApiModelProperty(value = "里程(公里)")
        private String mileage;
        @ApiModelProperty(value = "金额(元)")
        private BigDecimal amount;
        @ApiModelProperty(value = "备注")
        private String remark;
    }
}
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpInvoiceController.java
New file
@@ -0,0 +1,144 @@
package com.xiaopeng.order.controller;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xiaopeng.api.dto.QueryOrderRouteDTO;
import com.xiaopeng.api.dto.operation.LonLatDto;
import com.xiaopeng.api.dto.order.GetOrderNumDto;
import com.xiaopeng.api.dto.order.PopOrderDto;
import com.xiaopeng.api.dto.order.UpdateInvoiceStatusDto;
import com.xiaopeng.api.dto.statistics.OrderStatisticsDTO;
import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO;
import com.xiaopeng.api.dto.vehicleConvoy.BaseVehicleUserDto;
import com.xiaopeng.api.feignClient.account.SysGroupMenuClient;
import com.xiaopeng.api.feignClient.operation.XpWhiteListClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.VehicleMacClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient;
import com.xiaopeng.api.model.operation.XpOfficialPartner;
import com.xiaopeng.api.model.operation.XpWhitelist;
import com.xiaopeng.api.model.order.XpOrder;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.query.order.InvoiceOrdersQuery;
import com.xiaopeng.api.query.order.XpOrderInvoiceQuery;
import com.xiaopeng.api.vo.operation.NavigationVo;
import com.xiaopeng.api.vo.operation.NearestNextVo;
import com.xiaopeng.api.vo.operation.RouteVo;
import com.xiaopeng.api.vo.order.*;
import com.xiaopeng.api.vo.vehicleConvoy.GetBleInfoVo;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.exception.ServiceException;
import com.xiaopeng.common.core.utils.StringUtils;
import com.xiaopeng.common.core.utils.WebUtils;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.common.redis.service.RedisService;
import com.xiaopeng.common.security.service.TokenService;
import com.xiaopeng.order.dto.OrderNavigationDto;
import com.xiaopeng.order.mangodb.model.OrderTrajectory;
import com.xiaopeng.order.model.dto.XpOrderCommentDto;
import com.xiaopeng.order.model.dto.XpOrderOperateDTO;
import com.xiaopeng.order.model.dto.XpOrderPayDto;
import com.xiaopeng.order.model.dto.XpOrderReassignDTO;
import com.xiaopeng.order.model.exportExcel.XpOrderExportExcel;
import com.xiaopeng.order.model.query.XpHistoryOrderListQuery;
import com.xiaopeng.order.model.query.XpOrderExcelQuery;
import com.xiaopeng.order.model.query.XpOrderPageQuery;
import com.xiaopeng.order.model.vo.XpOrderDetailVO;
import com.xiaopeng.order.model.vo.XpOrderHistoryVO;
import com.xiaopeng.order.model.vo.XpOrderPageVO;
import com.xiaopeng.order.service.IXpOrderService;
import com.xiaopeng.order.vo.BluetoothTokenVo;
import com.xiaopeng.order.vo.OrderDetailVo;
import com.xiaopeng.order.vo.UpdateOrderStatusVo;
import com.xiaopeng.order.vo.XpOrderInfoVo;
import com.xiaopeng.unifiedverification.interceptor.XpClientCheck;
import io.swagger.annotations.*;
import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;
/**
 * <p>
 * 订单 前端控制器
 * </p>
 *
 * @author mitao
 * @since 2026-02-03
 */
@RestController
@Api(tags = "订单发票")
@RequiredArgsConstructor(onConstructor_ = @Lazy)
public class XpInvoiceController {
    private final IXpOrderService xpOrderService;
    @Resource
    private TokenService tokenService;
    /**
     * 开票列表数据查询
     *
     * @param query 查询参数
     * @return 开票列表数据查询
     */
    @ApiOperation(value = "开票列表数据查询", tags = {"三方对接"})
    @PostMapping("/logan/order/invoice/invoiceList")
    public R<List<XpInvoiceVo>> invoiceList(@RequestBody @Valid XpOrderInvoiceQuery query) {
        return R.ok(xpOrderService.invoiceList(query));
    }
    /**
     * 查询开票数据(批量)
     * @param query
     * @return
     */
    @ApiOperation(value = "查询开票数据(批量)", tags = {"三方对接"})
    @PostMapping("/logan/order/invoice/queryInvoiceOrders")
    public R<List<XpInvoiceVo>> queryInvoiceOrders(@RequestBody @Valid InvoiceOrdersQuery query) {
        return R.ok(xpOrderService.queryInvoiceOrders(query));
    }
    /**
     * 订单状态推送
     */
    @ApiOperation(value = "订单状态推送", tags = {"三方对接"})
    @PostMapping("/logan/order/invoice/updateInvoiceStatus")
    public R<?> updateInvoiceStatus(@RequestBody @Valid UpdateInvoiceStatusDto dto) {
        xpOrderService.updateInvoiceStatus(dto);
        return R.ok();
    }
}
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/IXpOrderService.java
@@ -4,15 +4,15 @@
import com.baomidou.mybatisplus.extension.service.IService;
import com.xiaopeng.api.dto.order.GetOrderNumDto;
import com.xiaopeng.api.dto.order.PopOrderDto;
import com.xiaopeng.api.dto.order.UpdateInvoiceStatusDto;
import com.xiaopeng.api.dto.statistics.OrderStatisticsDTO;
import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO;
import com.xiaopeng.api.model.order.XpOrder;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.query.order.InvoiceOrdersQuery;
import com.xiaopeng.api.query.order.XpOrderInvoiceQuery;
import com.xiaopeng.api.vo.operation.NearestNextVo;
import com.xiaopeng.api.vo.order.FareBreakdownVo;
import com.xiaopeng.api.vo.order.XpHistoryEndPointsVo;
import com.xiaopeng.api.vo.order.XpHistoryStartPointsVo;
import com.xiaopeng.api.vo.order.XpPointInfoVo;
import com.xiaopeng.api.vo.order.*;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.order.dto.UserOrderListDto;
@@ -32,6 +32,7 @@
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.List;
@@ -273,4 +274,28 @@
     * @param vo
     */
    R<?> officialPartnerUpdateOrderStatus(UpdateOrderStatusVo vo, Integer officialPartnerId);
    /**
     * 开票列表数据查询
     * @param query
     * @return
     */
    List<XpInvoiceVo> invoiceList(XpOrderInvoiceQuery query);
    /**
     * 查询开票数据(批量)
     * @param query
     * @return
     */
    List<XpInvoiceVo> queryInvoiceOrders(InvoiceOrdersQuery query);
    /**
     * 订单状态推送
     * @param dto
     */
    void updateInvoiceStatus(@Valid UpdateInvoiceStatusDto dto);
}
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
@@ -20,10 +20,7 @@
import com.xiaopeng.api.dto.map.OrderRouteAndFareDto;
import com.xiaopeng.api.dto.map.RouteAndFareDto;
import com.xiaopeng.api.dto.operation.LonLatDto;
import com.xiaopeng.api.dto.order.GetOrderNumDto;
import com.xiaopeng.api.dto.order.HistoryEndPointsDto;
import com.xiaopeng.api.dto.order.HistoryStartPointsDto;
import com.xiaopeng.api.dto.order.PopOrderDto;
import com.xiaopeng.api.dto.order.*;
import com.xiaopeng.api.dto.pushMessage.SendMessageDTO;
import com.xiaopeng.api.dto.statistics.DailyCountDTO;
import com.xiaopeng.api.dto.statistics.OrderStatisticsDTO;
@@ -46,6 +43,8 @@
import com.xiaopeng.api.model.order.*;
import com.xiaopeng.api.model.vehicleConvoy.XpFleet;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.query.order.InvoiceOrdersQuery;
import com.xiaopeng.api.query.order.XpOrderInvoiceQuery;
import com.xiaopeng.api.vo.OrderType;
import com.xiaopeng.api.vo.account.CalculateDiscountAmountVo;
import com.xiaopeng.api.vo.account.UserCouponVo;
@@ -4483,4 +4482,149 @@
        return R.ok();
    }
    /**
     * 发票列表
     * @param query
     * @return
     */
    @Override
    public List<XpInvoiceVo> invoiceList(XpOrderInvoiceQuery query) {
        // 格式:yyyyMM 转yyyy-MM
        query.setStartTime(query.getStartTime().substring(0, 4) + "-" + query.getStartTime().substring(4, 6));
        query.setEndTime(query.getEndTime().substring(0, 4) + "-" + query.getEndTime().substring(4, 6));
        List<XpOrder> list =null;
        // 通过uid 和时间查出来数据  先判断是否传入了分页
        if (query.getPageNo()!=null && query.getPageSize()!=null) {
            Page<XpOrder> page = new Page<>(query.getPageNo(), query.getPageSize());
            Page<XpOrder> orderPage = this.baseMapper.selectPage(page, new LambdaQueryWrapper<XpOrder>().eq(XpOrder::getAppUserId, Long.valueOf(query.getUid())).ge(XpOrder::getStatus, 9).between(BaseModel::getCreateTime, query.getStartTime(), query.getEndTime()));
            list = orderPage.getRecords();
        }else {
            list = this.baseMapper.selectList(new LambdaQueryWrapper<XpOrder>().eq(XpOrder::getAppUserId, Long.valueOf(query.getUid())).ge(XpOrder::getStatus, 9).between(BaseModel::getCreateTime, query.getStartTime(), query.getEndTime()));
        }
        if(list.isEmpty()){
            return new ArrayList<>();
        }
        ArrayList<XpInvoiceVo> xpInvoiceVoList = new ArrayList<>(list.size());
        R<List<XpVehicle>> r = xpVehicleClient.listByIds(list.stream().map(XpOrder::getVehicleId).collect(Collectors.toList()));
        List<XpVehicle> vehicleList = r.getData();
        // 数据组装
        for (XpOrder xpOrder : list) {
            XpInvoiceVo xpInvoiceVo = new XpInvoiceVo();
            xpInvoiceVo.setUid(xpOrder.getAppUserId().toString());
            xpInvoiceVo.setOrderNo(xpOrder.getOrderNumber());
            xpInvoiceVo.setOrderTotalAmount(xpOrder.getOrderMoney());
            xpInvoiceVo.setOrderDiscountAmount(xpOrder.getCouponMoney());
            xpInvoiceVo.setOrderFinishTime(String.valueOf(xpOrder.getTripEnd()));
            xpInvoiceVo.setXpInvoiceFlag(true);
            xpInvoiceVo.setInvoiceStatus(xpOrder.getInvoiceStatus());
            XpInvoiceVo.Itinerary itinerary = new XpInvoiceVo.Itinerary();
            // yyyy-MM-dd格式
            itinerary.setTripStartDate(xpOrder.getAcceptanceTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            itinerary.setTripEndDate(xpOrder.getTripEnd().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            XpVehicle xpVehicle = vehicleList.stream().filter(vehicle -> vehicle.getId().equals(xpOrder.getVehicleId())).findFirst().get();
            itinerary.setCarType(xpVehicle.getVehicleModel());
            itinerary.setTripStartDate(xpOrder.getBoardingTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            itinerary.setCity(xpOrder.getCityName());
            itinerary.setStartPoint(xpOrder.getStartAddress());
            itinerary.setEndPoint(xpOrder.getEndAddress());
            itinerary.setMileage(xpOrder.getMileageKilometers().toString());
            itinerary.setAmount(xpOrder.getOrderMoney());
            xpInvoiceVo.setItinerary(itinerary);
            xpInvoiceVoList.add(xpInvoiceVo);
        }
        return xpInvoiceVoList;
    }
    /**
     * 查询发票订单
     * @param query
     * @return
     */
    @Override
    public List<XpInvoiceVo> queryInvoiceOrders(InvoiceOrdersQuery query) {
        if(query.getOrderNoList().isEmpty()){
            return Collections.emptyList();
        }
        List<XpOrder> list = this.baseMapper.selectList(new LambdaQueryWrapper<XpOrder>().eq(XpOrder::getAppUserId, Long.valueOf(query.getUid())).ge(XpOrder::getStatus, 9).in(XpOrder::getOrderNumber, query.getOrderNoList()));
        if(list.isEmpty()){
            return Collections.emptyList();
        }
        ArrayList<XpInvoiceVo> xpInvoiceVoList = new ArrayList<>(list.size());
        R<List<XpVehicle>> r = xpVehicleClient.listByIds(list.stream().map(XpOrder::getVehicleId).collect(Collectors.toList()));
        List<XpVehicle> vehicleList = r.getData();
        // 数据组装
        for (XpOrder xpOrder : list) {
            XpInvoiceVo xpInvoiceVo = new XpInvoiceVo();
            xpInvoiceVo.setUid(xpOrder.getAppUserId().toString());
            xpInvoiceVo.setOrderNo(xpOrder.getOrderNumber());
            xpInvoiceVo.setOrderTotalAmount(xpOrder.getOrderMoney());
            xpInvoiceVo.setOrderDiscountAmount(xpOrder.getCouponMoney());
            xpInvoiceVo.setOrderFinishTime(String.valueOf(xpOrder.getTripEnd()));
            xpInvoiceVo.setXpInvoiceFlag(true);
            xpInvoiceVo.setInvoiceStatus(xpOrder.getInvoiceStatus());
            XpInvoiceVo.Itinerary itinerary = new XpInvoiceVo.Itinerary();
            // yyyy-MM-dd格式
            itinerary.setTripStartDate(xpOrder.getAcceptanceTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            itinerary.setTripEndDate(xpOrder.getTripEnd().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            XpVehicle xpVehicle = vehicleList.stream().filter(vehicle -> vehicle.getId().equals(xpOrder.getVehicleId())).findFirst().get();
            itinerary.setCarType(xpVehicle.getVehicleModel());
            itinerary.setTripStartDate(xpOrder.getBoardingTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            itinerary.setCity(xpOrder.getCityName());
            itinerary.setStartPoint(xpOrder.getStartAddress());
            itinerary.setEndPoint(xpOrder.getEndAddress());
            itinerary.setMileage(xpOrder.getMileageKilometers().toString());
            itinerary.setAmount(xpOrder.getOrderMoney());
            xpInvoiceVo.setItinerary(itinerary);
            xpInvoiceVoList.add(xpInvoiceVo);
        }
        return xpInvoiceVoList;
    }
    /**
     * 修改发票状态
     * @param dto
     */
    @Override
    public void updateInvoiceStatus(UpdateInvoiceStatusDto dto) {
        List<UpdateInvoiceStatusDto.Order> orderList = dto.getOrderList();
        if(!orderList.isEmpty()){
            List<String> orderNos = orderList.stream().map(UpdateInvoiceStatusDto.Order::getOrderNo).collect(Collectors.toList());
            List<XpOrder> xpOrders = this.baseMapper.selectList(new LambdaQueryWrapper<XpOrder>().in(XpOrder::getOrderNumber, orderNos));
            for (XpOrder xpOrder : xpOrders) {
                UpdateInvoiceStatusDto.Order order = orderList.stream().filter(e -> e.getOrderNo().equals(xpOrder.getOrderNumber())).findFirst().orElse(null);
                if(order!=null){
                    xpOrder.setInvoiceStatus(order.getInvoiceStatus());
                    xpOrder.setInvoiceId(dto.getRequestId());
                    xpOrder.setAppUserId(null);
                    this.updateById(xpOrder);
                }
            }
        }
    }
}