feat(erp): 采购来票登记过滤已开完票订单
- ErpPurchaseOrderPageReqVO 新增 remainPriceEnable 参数:仅返回剩余可开票金额>0 的订单
- 分页查询按 totalPrice > 已来票金额合计 过滤已开完票订单(关联 erp_purchase_invoice 动态计算)
- ErpPurchaseOrderRespVO 新增 remainInvoicePrice 字段(订单总金额 - 已来票金额)
- 新增按订单批量统计来票金额的服务方法
Co-Authored-By: Claude <noreply@anthropic.com>
| | |
| | | import cn.iocoder.yudao.module.erp.enums.ErpPurchaseOrderSourceTypeEnum; |
| | | import cn.iocoder.yudao.module.srm.api.supplier.SrmSupplierApi; |
| | | import cn.iocoder.yudao.module.srm.api.supplier.dto.SrmSupplierRespDTO; |
| | | import cn.iocoder.yudao.module.erp.service.purchase.ErpPurchaseInvoiceService; |
| | | import cn.iocoder.yudao.module.erp.service.purchase.ErpPurchaseOrderService; |
| | | import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi; |
| | | import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO; |
| | |
| | | |
| | | @Resource |
| | | private ErpPurchaseOrderService purchaseOrderService; |
| | | @Resource |
| | | private ErpPurchaseInvoiceService purchaseInvoiceService; |
| | | @Resource |
| | | private SrmSupplierApi srmSupplierApi; |
| | | |
| | |
| | | // 1.5 单位信息 |
| | | Map<Long, MdmUnitMeasureRespDTO> unitMeasureMap = mdmUnitMeasureApi.getUnitMeasureMap( |
| | | convertSet(purchaseOrderItemList, ErpPurchaseOrderItemDO::getProductUnitId)); |
| | | // 1.6 已来票金额:按采购订单统计,用于计算剩余可开票金额 |
| | | Map<Long, BigDecimal> invoicePriceSumMap = purchaseInvoiceService |
| | | .getPurchaseInvoicePriceSumMapByOrderIds(convertSet(pageResult.getList(), ErpPurchaseOrderDO::getId)); |
| | | // 2. 开始拼接 |
| | | return BeanUtils.toBean(pageResult, ErpPurchaseOrderRespVO.class, purchaseOrder -> { |
| | | purchaseOrder.setItems(BeanUtils.toBean(purchaseOrderItemMap.get(purchaseOrder.getId()), ErpPurchaseOrderRespVO.Item.class, |
| | |
| | | MapUtils.findAndThen(userMap, Long.parseLong(purchaseOrder.getCreator()), user -> purchaseOrder.setCreatorName(user.getNickname())); |
| | | purchaseOrder.setSourceTypeName(ErpPurchaseOrderSourceTypeEnum.WORK_ORDER.getType() |
| | | .equals(purchaseOrder.getSourceType()) ? "生产工单" : null); |
| | | // 剩余可开票金额 = 订单总金额 - 已来票金额 |
| | | purchaseOrder.setRemainInvoicePrice(purchaseOrder.getTotalPrice().subtract( |
| | | invoicePriceSumMap.getOrDefault(purchaseOrder.getId(), BigDecimal.ZERO))); |
| | | }); |
| | | } |
| | | |
| | |
| | | @Schema(description = "是否可退货", example = "true") |
| | | private Boolean returnEnable; |
| | | |
| | | /** |
| | | * 仅返回剩余可开票金额大于 0 的订单 |
| | | * |
| | | * 用于"采购来票"登记时选择采购订单:金额已开完(剩余可开票金额 <= 0)的订单不展示。 |
| | | * 剩余可开票金额 = totalPrice - SUM(erp_purchase_invoice.price) |
| | | */ |
| | | @Schema(description = "是否仅返回剩余可开票金额大于 0 的订单(采购来票登记使用)", example = "true") |
| | | private Boolean remainPriceEnable; |
| | | |
| | | } |
| | |
| | | @Schema(description = "合计税额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") |
| | | private BigDecimal totalTaxPrice; |
| | | |
| | | @Schema(description = "剩余可开票金额(订单总金额 - 已来票金额),单位:元", example = "100.00") |
| | | private BigDecimal remainInvoicePrice; |
| | | |
| | | @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") |
| | | private BigDecimal discountPercent; |
| | | |
| | |
| | | import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInvoiceDO; |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | .eq(ErpPurchaseInvoiceDO::getSupplierId, supplierId)); |
| | | } |
| | | |
| | | default List<ErpPurchaseInvoiceDO> selectListByOrderIds(Collection<Long> orderIds) { |
| | | return selectList(new LambdaQueryWrapperX<ErpPurchaseInvoiceDO>() |
| | | .in(ErpPurchaseInvoiceDO::getPurchaseOrderId, orderIds)); |
| | | } |
| | | |
| | | } |
| | |
| | | query.eq(ErpPurchaseOrderDO::getStatus, ErpAuditStatus.APPROVE.getStatus()) |
| | | .apply("t.return_count < t.in_count"); |
| | | } |
| | | // 可来票登记(剩余可开票金额 > 0):金额已开完的订单不展示 |
| | | if (Boolean.TRUE.equals(reqVO.getRemainPriceEnable())) { |
| | | query.apply("t.total_price > (SELECT IFNULL(SUM(i.price), 0) FROM erp_purchase_invoice i " |
| | | + "WHERE i.purchase_order_id = t.id AND i.deleted = 0)"); |
| | | } |
| | | if (reqVO.getProductId() != null) { |
| | | query.leftJoin(ErpPurchaseOrderItemDO.class, ErpPurchaseOrderItemDO::getOrderId, ErpPurchaseOrderDO::getId) |
| | | .eq(reqVO.getProductId() != null, ErpPurchaseOrderItemDO::getProductId, reqVO.getProductId()) |
| | |
| | | import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInvoiceDO; |
| | | import jakarta.validation.Valid; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | |
| | | */ |
| | | List<ErpPurchaseInvoiceDO> getPurchaseInvoiceListBySupplierId(Long supplierId); |
| | | |
| | | /** |
| | | * 根据采购订单编号列表,统计每个订单的来票金额合计(用于计算剩余可开票金额) |
| | | * |
| | | * @param orderIds 采购订单编号列表 |
| | | * @return Map<采购订单编号, 来票金额合计> |
| | | */ |
| | | Map<Long, BigDecimal> getPurchaseInvoicePriceSumMapByOrderIds(Collection<Long> orderIds); |
| | | |
| | | } |
| | |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.Collection; |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.stream.Collectors; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; |
| | |
| | | return invoiceMapper.selectListBySupplierId(supplierId); |
| | | } |
| | | |
| | | @Override |
| | | public Map<Long, BigDecimal> getPurchaseInvoicePriceSumMapByOrderIds(Collection<Long> orderIds) { |
| | | if (CollUtil.isEmpty(orderIds)) { |
| | | return Collections.emptyMap(); |
| | | } |
| | | List<ErpPurchaseInvoiceDO> invoices = invoiceMapper.selectListByOrderIds(orderIds); |
| | | return invoices.stream().collect(Collectors.groupingBy(ErpPurchaseInvoiceDO::getPurchaseOrderId, |
| | | Collectors.mapping(ErpPurchaseInvoiceDO::getPrice, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add)))); |
| | | } |
| | | |
| | | } |