gaoluyang
6 天以前 3688f07fd292812994dbf3c84bde18a440d8275c
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseInvoiceController.java
@@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.erp.controller.admin.purchase;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
@@ -9,13 +10,14 @@
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.invoice.ErpPurchaseInvoiceOrderRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.invoice.ErpPurchaseInvoicePageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.invoice.ErpPurchaseInvoiceRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.invoice.ErpPurchaseInvoiceSaveReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderRespVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInvoiceDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInvoiceOrderDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO;
import cn.iocoder.yudao.module.erp.enums.ErpPurchaseInvoiceAuditStatusEnum;
import cn.iocoder.yudao.module.erp.service.finance.ErpFinancePaymentService;
import cn.iocoder.yudao.module.erp.service.purchase.ErpPurchaseInvoiceService;
import cn.iocoder.yudao.module.erp.service.purchase.ErpPurchaseInvoiceServiceImpl;
@@ -39,17 +41,19 @@
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - ERP 采购来票")
@RestController
@@ -140,10 +144,33 @@
        Map<Long, SrmSupplierRespDTO> supplierMap = srmSupplierApi.getSupplierList(
                convertSet(invoiceList, ErpPurchaseInvoiceDO::getSupplierId)).getCheckedData().stream()
                .collect(java.util.stream.Collectors.toMap(SrmSupplierRespDTO::getId, v -> v, (a, b) -> a));
        // 1.2 获取采购订单列表
        // 1.2 获取采购订单分摊明细(一张来票可关联多张订单)
        Map<Long, List<ErpPurchaseInvoiceOrderDO>> allocationMap = convertMultiMap(
                invoiceService.getPurchaseInvoiceOrderListByInvoiceIds(
                        convertSet(invoiceList, ErpPurchaseInvoiceDO::getId)),
                ErpPurchaseInvoiceOrderDO::getInvoiceId);
        // 1.2.1 兼容历史数据:没有分摊明细的来票,按主订单 + 来票金额视为一条分摊
        for (ErpPurchaseInvoiceDO invoice : invoiceList) {
            if (!allocationMap.containsKey(invoice.getId()) && invoice.getPurchaseOrderId() != null) {
                allocationMap.put(invoice.getId(), Collections.singletonList(
                        ErpPurchaseInvoiceOrderDO.builder().invoiceId(invoice.getId())
                                .purchaseOrderId(invoice.getPurchaseOrderId()).price(invoice.getPrice()).sort(0).build()));
            }
        }
        // 1.2.2 这些订单的全部分摊明细,用于计算每张订单「其他来票已占用金额」
        Set<Long> orderIds = convertSet(allocationMap.values().stream().flatMap(List::stream).toList(),
                ErpPurchaseInvoiceOrderDO::getPurchaseOrderId);
        List<ErpPurchaseInvoiceOrderDO> orderAllocations = invoiceService.getPurchaseInvoiceOrderListByPurchaseOrderIds(orderIds);
        // 1.2.3 获取采购订单列表(含主订单,兼容历史数据)
        Set<Long> orderIdsAll = new HashSet<>(orderIds);
        invoiceList.stream().map(ErpPurchaseInvoiceDO::getPurchaseOrderId)
                .filter(java.util.Objects::nonNull).forEach(orderIdsAll::add);
        Map<Long, ErpPurchaseOrderDO> orderMap = convertMap(
                purchaseOrderService.getPurchaseOrderList(convertList(invoiceList, ErpPurchaseInvoiceDO::getPurchaseOrderId)),
                ErpPurchaseOrderDO::getId);
                purchaseOrderService.getPurchaseOrderList(new ArrayList<>(orderIdsAll)), ErpPurchaseOrderDO::getId);
        // 1.2.4 获取分摊订单的供应商列表(一张来票可能涉及多个供应商)
        Map<Long, SrmSupplierRespDTO> orderSupplierMap = srmSupplierApi.getSupplierList(
                        convertSet(orderMap.values(), ErpPurchaseOrderDO::getSupplierId)).getCheckedData().stream()
                .collect(java.util.stream.Collectors.toMap(SrmSupplierRespDTO::getId, v -> v, (a, b) -> a));
        // 1.3 获取创建人列表
        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
                convertSet(invoiceList, invoice -> NumberUtils.parseLong(invoice.getCreator())));
@@ -154,9 +181,37 @@
        return BeanUtils.toBean(invoiceList, ErpPurchaseInvoiceRespVO.class, (invoiceVO) -> {
            // 2.1 拼接供应商名称
            findAndThen(supplierMap, invoiceVO.getSupplierId(), supplier -> invoiceVO.setSupplierName(supplier.getName()));
            // 2.2 拼接采购订单信息
            // 2.2 拼接采购订单信息(主订单)
            findAndThen(orderMap, invoiceVO.getPurchaseOrderId(), order ->
                    invoiceVO.setOrder(BeanUtils.toBean(order, ErpPurchaseOrderRespVO.class)));
            // 2.2.1 拼接采购订单分摊明细
            List<ErpPurchaseInvoiceOrderDO> rows = allocationMap.getOrDefault(invoiceVO.getId(), Collections.emptyList());
            List<ErpPurchaseInvoiceOrderRespVO> allocationVOs = new ArrayList<>(rows.size());
            for (ErpPurchaseInvoiceOrderDO row : rows) {
                ErpPurchaseInvoiceOrderRespVO allocationVO = new ErpPurchaseInvoiceOrderRespVO()
                        .setPurchaseOrderId(row.getPurchaseOrderId()).setPrice(row.getPrice());
                ErpPurchaseOrderDO order = orderMap.get(row.getPurchaseOrderId());
                if (order != null) {
                    allocationVO.setOrderNo(order.getNo()).setSupplierId(order.getSupplierId())
                            .setOrderTotalPrice(order.getTotalPrice());
                    findAndThen(orderSupplierMap, order.getSupplierId(),
                            supplier -> allocationVO.setSupplierName(supplier.getName()));
                }
                // 该订单其他来票已占用金额 = 全部分摊 - 本张来票的分摊
                BigDecimal otherInvoicedPrice = orderAllocations.stream()
                        .filter(other -> ObjectUtil.equal(other.getPurchaseOrderId(), row.getPurchaseOrderId())
                                && !ObjectUtil.equal(other.getInvoiceId(), invoiceVO.getId()))
                        .map(ErpPurchaseInvoiceOrderDO::getPrice)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                allocationVO.setInvoicedPrice(otherInvoicedPrice);
                if (order != null) {
                    allocationVO.setRemainPrice(order.getTotalPrice().subtract(otherInvoicedPrice));
                }
                allocationVOs.add(allocationVO);
            }
            invoiceVO.setOrderAllocations(allocationVOs);
            invoiceVO.setOrderCount(allocationVOs.size());
            invoiceVO.setOrderNos(CollUtil.join(allocationVOs, "、", ErpPurchaseInvoiceOrderRespVO::getOrderNo));
            // 2.3 拼接创建人名称
            MapUtils.findAndThen(userMap, NumberUtils.parseLong(invoiceVO.getCreator()),
                    user -> invoiceVO.setCreatorName(user.getNickname()));
@@ -170,23 +225,8 @@
        });
    }
    @PutMapping("/submit")
    @Operation(summary = "提交来票审批")
    @PreAuthorize("@ss.hasPermission('erp:purchase-invoice:update')")
    public CommonResult<Boolean> submitPurchaseInvoice(@RequestParam("id") Long id) {
        invoiceService.submitPurchaseInvoice(id, getLoginUserId());
        return success(true);
    }
    @GetMapping("/audit-count")
    @Operation(summary = "获得待审核来票数量")
    @PreAuthorize("@ss.hasPermission('erp:purchase-invoice:query')")
    public CommonResult<Long> getAuditInvoiceCount() {
        return success(invoiceService.getAuditInvoiceCount());
    }
    @GetMapping("/simple-list")
    @Operation(summary = "获得来票精简列表", description = "只包含审核通过且已上传发票附件的来票,主要用于付款创建时选择关联来票")
    @Operation(summary = "获得来票精简列表", description = "只包含已上传发票附件的来票,主要用于付款创建时选择关联来票")
    @Parameter(name = "supplierId", description = "供应商编号", required = true)
    @Parameter(name = "purchaseOrderId", description = "采购订单编号(可选,用于按订单过滤)")
    @PreAuthorize("@ss.hasPermission('erp:purchase-invoice:query')")
@@ -195,11 +235,9 @@
            @RequestParam(value = "purchaseOrderId", required = false) Long purchaseOrderId) {
        List<ErpPurchaseInvoiceDO> invoices;
        if (purchaseOrderId != null) {
            invoices = invoiceService.getPurchaseInvoiceListByOrderIdAndStatus(purchaseOrderId,
                    List.of(ErpPurchaseInvoiceAuditStatusEnum.APPROVE.getStatus()));
            invoices = invoiceService.getPurchaseInvoiceListByOrderId(purchaseOrderId);
        } else {
            invoices = invoiceService.getPurchaseInvoiceListBySupplierIdAndStatus(supplierId,
                    List.of(ErpPurchaseInvoiceAuditStatusEnum.APPROVE.getStatus()));
            invoices = invoiceService.getPurchaseInvoiceListBySupplierId(supplierId);
        }
        if (CollUtil.isEmpty(invoices)) {
            return success(Collections.emptyList());
@@ -225,7 +263,7 @@
                    .setId(invoice.getId()).setNo(invoice.getNo()).setInvoiceNo(invoice.getInvoiceNo())
                    .setInvoiceTitle(invoice.getInvoiceTitle()).setPrice(invoice.getPrice())
                    .setSupplierId(invoice.getSupplierId()).setPurchaseOrderId(invoice.getPurchaseOrderId())
                    .setAuditStatus(invoice.getAuditStatus()).setHasAttachment(true)
                    .setHasAttachment(true)
                    .setRemainingInvoicePrice(remainingPrice));
        }
        return success(result);