From c16a5f590db461391a4441e520f3264526c11905 Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期一, 15 六月 2026 13:13:56 +0800
Subject: [PATCH] feat(sales): 优化发货信息管理功能

---
 src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java |  337 +++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 235 insertions(+), 102 deletions(-)

diff --git a/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java b/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
index a7888e4..10cc97c 100644
--- a/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
+++ b/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
@@ -1,9 +1,8 @@
 package com.ruoyi.sales.controller;
 
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.pojo.Customer;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
@@ -11,13 +10,8 @@
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.framework.web.domain.R;
 import com.ruoyi.framework.web.page.TableDataInfo;
-import com.ruoyi.sales.dto.InvoiceLedgerDto;
-import com.ruoyi.sales.dto.SalesLedgerDto;
-import com.ruoyi.sales.dto.SalesLedgerProcessRouteDto;
-import com.ruoyi.sales.dto.SalesProcessCardDto;
+import com.ruoyi.sales.dto.*;
 import com.ruoyi.sales.mapper.InvoiceLedgerMapper;
-import com.ruoyi.sales.mapper.ReceiptPaymentMapper;
-import com.ruoyi.sales.pojo.ReceiptPayment;
 import com.ruoyi.sales.pojo.SalesLedger;
 import com.ruoyi.sales.pojo.SalesLedgerProcessRoute;
 import com.ruoyi.sales.service.ICommonFileService;
@@ -29,9 +23,11 @@
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -62,9 +58,6 @@
     @Autowired
     private InvoiceLedgerMapper invoiceLedgerMapper;
 
-    @Autowired
-    private ReceiptPaymentMapper receiptPaymentMapper;
-
     /**
      * 瀵煎叆閿�鍞彴璐�
      */
@@ -74,7 +67,8 @@
     public AjaxResult importData(@RequestParam("file")
                                  @ApiParam(value = "Excel鏂囦欢", required = true)
                                  MultipartFile file) {
-        return salesLedgerService.importData(file);
+        salesLedgerService.importData(file);
+        return AjaxResult.success();
     }
 
     @ApiOperation("瀵煎嚭閿�鍞彴璐︽ā鏉�")
@@ -119,7 +113,7 @@
      * 鏌ヨ閿�鍞彴璐﹀垪琛�
      */
     @GetMapping("/list")
-    public TableDataInfo list(Page page, SalesLedgerDto salesLedgerDto) {
+    public TableDataInfo list(Page<?> page, SalesLedgerDto salesLedgerDto) {
         startPage();
         List<SalesLedger> list = salesLedgerService.selectSalesLedgerList(salesLedgerDto);
         // 璁$畻宸插紑绁ㄩ噾棰�/鏈紑绁ㄩ噾棰�(宸插~鍐欏彂绁ㄩ噾棰濅负鍑�)
@@ -157,7 +151,7 @@
     @Log(title = "閿�鍞彴璐�", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
     public void export(HttpServletResponse response, SalesLedgerDto salesLedgerDto) {
-        Page page = new Page(-1, -1);
+        Page<?> page = new Page<>(-1, -1);
         IPage<SalesLedger> salesLedgerIPage = listPage(page, salesLedgerDto);
         ExcelUtil<SalesLedger> util = new ExcelUtil<SalesLedger>(SalesLedger.class);
         if (salesLedgerIPage == null) {
@@ -169,12 +163,36 @@
     }
 
     /**
+     * 瀵煎嚭閿�鍞彴璐﹀垪琛紙鍖呭惈浜у搧鏄庣粏锛屼袱涓猻heet椤碉級
+     */
+    @Log(title = "閿�鍞彴璐�", businessType = BusinessType.EXPORT)
+    @PostMapping("/exportWithProducts")
+    @ApiOperation("瀵煎嚭閿�鍞彴璐﹀強浜у搧鏄庣粏锛堜袱涓猻heet椤碉級")
+    public void exportWithProducts(HttpServletResponse response, SalesLedgerDto salesLedgerDto) {
+        salesLedgerService.exportWithProducts(response, salesLedgerDto);
+    }
+
+    /**
+     * 瀵煎嚭鍞悗鍙拌处宸ヨ壓璺嚎
+     */
+    @Log(title = "閿�鍞彴璐﹀伐鑹鸿矾绾�", businessType = BusinessType.EXPORT)
+    @PostMapping("/exportProcessRoute")
+    @ApiOperation("瀵煎嚭鍞悗鍙拌处宸ヨ壓璺嚎")
+    public void exportProcessRoute(HttpServletResponse response,
+                                   HttpServletRequest request,
+                                   @RequestParam(value = "completedTimeStart", required = false) String completedTimeStart,
+                                   @RequestParam(value = "completedTimeEnd", required = false) String completedTimeEnd) {
+        List<Long> salesLedgerIds = parseSalesLedgerIds(request);
+        salesLedgerService.exportProcessRoute(response, salesLedgerIds, completedTimeStart, completedTimeEnd);
+    }
+
+    /**
      * 瀵煎嚭寮�绁ㄧ櫥璁板垪琛�
      */
     @Log(title = "瀵煎嚭寮�绁ㄧ櫥璁板垪琛�", businessType = BusinessType.EXPORT)
     @PostMapping("/exportOne")
     public void exportOne(HttpServletResponse response, SalesLedgerDto salesLedgerDto) {
-        Page page = new Page();
+        Page<?> page = new Page<>();
         page.setCurrent(-1);
         page.setSize(-1);
         IPage<SalesLedger> salesLedgerIPage = listPage(page, salesLedgerDto);
@@ -196,8 +214,59 @@
      */
     @PostMapping("/saleProcessBind")
     @ApiOperation("閿�鍞鍗曠粦瀹氬伐鑹鸿矾绾�")
-    public AjaxResult saleProcessBind(@RequestBody SalesLedgerProcessRoute salesLedgerProcessRoute) {
-        salesLedgerService.saleProcessBind(salesLedgerProcessRoute);
+    public AjaxResult saleProcessBind(@RequestBody SalesLedgerProcessRouteDto salesLedgerProcessRouteDto) {
+        salesLedgerService.saleProcessBind(salesLedgerProcessRouteDto);
+        return AjaxResult.success();
+    }
+
+    /**
+     * 鍙嶅鏍告搷浣�
+     */
+    @Log(title = "閿�鍞彴璐﹀弽瀹℃牳", businessType = BusinessType.UPDATE)
+    @PostMapping("/counterReview")
+    @ApiOperation("鍙嶅鏍告搷浣滐細浣滃簾鎴栭噸鏂扮敓鎴�")
+    public AjaxResult counterReview(@RequestBody CounterReviewDto dto) {
+        List<Long> newLedgerIds = salesLedgerService.counterReview(dto);
+        AjaxResult result = AjaxResult.success("鍙嶅鏍告垚鍔�");
+        if (newLedgerIds != null && !newLedgerIds.isEmpty()) {
+            result.put("newLedgerIds", newLedgerIds);
+        }
+        return result;
+    }
+
+    /**
+     * 鏍囪璁㈠崟瀹屾垚
+     */
+    @Log(title = "閿�鍞彴璐︽爣璁板畬鎴�", businessType = BusinessType.UPDATE)
+    @PostMapping("/markOrderCompleted")
+    @ApiOperation("鏍囪璁㈠崟瀹屾垚锛堜笉鍙挙閿�锛�")
+    public AjaxResult markOrderCompleted(@RequestBody Map<String, Object> params) {
+        @SuppressWarnings("unchecked")
+        List<Long> ids = ((List<Object>) params.get("ids")).stream()
+            .map(obj -> Long.valueOf(obj.toString()))
+            .collect(Collectors.toList());
+        if (ids == null || ids.isEmpty()) {
+            return AjaxResult.error("璇烽�夋嫨瑕佹爣璁板畬鎴愮殑璁㈠崟");
+        }
+        salesLedgerService.markOrderCompleted(ids);
+        return AjaxResult.success("鏍囪瀹屾垚鎴愬姛");
+    }
+
+    /**
+     * 閫掑鎵撳嵃娆℃暟
+     */
+    @PostMapping("/incrementPrintCount")
+    @ApiOperation("閫掑鎵撳嵃娆℃暟")
+    public AjaxResult incrementPrintCount(@RequestBody Map<String, Object> params) {
+        Long id = params.get("id") != null ? Long.valueOf(params.get("id").toString()) : null;
+        String printType = (String) params.get("printType");
+        if (id == null) {
+            return AjaxResult.error("閿�鍞彴璐D涓嶈兘涓虹┖");
+        }
+        if (printType == null || (!"label".equals(printType) && !"document".equals(printType))) {
+            return AjaxResult.error("鎵撳嵃绫诲瀷蹇呴』涓� label 鎴� document");
+        }
+        salesLedgerService.incrementPrintCount(id, printType);
         return AjaxResult.success();
     }
 
@@ -270,91 +339,8 @@
      * 鏌ヨ閿�鍞彴璐﹀垪琛�
      */
     @GetMapping("/listPage")
-    public IPage<SalesLedger> listPage(Page page, SalesLedgerDto salesLedgerDto) {
-        IPage<SalesLedger> iPage = salesLedgerService.selectSalesLedgerListPage(page, salesLedgerDto);
-
-        //  鏌ヨ缁撴灉涓虹┖,鐩存帴杩斿洖
-        if (CollectionUtils.isEmpty(iPage.getRecords())) {
-            return iPage;
-        }
-
-        //  鑾峰彇褰撳墠椤垫墍鏈夊彴璐﹁褰曠殑 ID 闆嗗悎
-        List<Long> salesLedgerIds = iPage.getRecords().stream().map(SalesLedger::getId).collect(Collectors.toList());
-
-        //  鏌ヨ鍙戠エ淇℃伅鐨勫凡寮�绁ㄩ噾棰�
-        List<InvoiceLedgerDto> invoiceLedgerDtoList = invoiceLedgerMapper.invoicedTotal(salesLedgerIds);
-        if (CollectionUtils.isEmpty(invoiceLedgerDtoList)) {
-            invoiceLedgerDtoList = Collections.emptyList();
-        }
-
-        //  杞崲鍙戠エ鏁版嵁, key 涓哄彴璐D, value 涓鸿鍙拌处鐨勬�诲紑绁ㄩ噾棰�
-        Map<Long, BigDecimal> invoiceTotals = invoiceLedgerDtoList.stream()
-                .filter(dto -> dto.getSalesLedgerId() != null && dto.getInvoiceTotal() != null)
-                .collect(Collectors.toMap(
-                        dto -> dto.getSalesLedgerId().longValue(),
-                        InvoiceLedgerDto::getInvoiceTotal,
-                        BigDecimal::add // 瀛樺湪閲嶅ID鎵ц绱姞
-                ));
-
-        //  鏌ヨ鍥炴/浠樻璁板綍
-        List<ReceiptPayment> receiptPayments = Collections.emptyList();
-        if (!CollectionUtils.isEmpty(salesLedgerIds)) {
-            receiptPayments = receiptPaymentMapper.selectList(new LambdaQueryWrapper<ReceiptPayment>()
-                    .in(ReceiptPayment::getSalesLedgerId, salesLedgerIds));
-        }
-
-        //  杞崲鍥炴鏁版嵁, key 涓哄彴璐D, value 涓鸿鍙拌处鐨勬�诲洖娆鹃噾棰�
-        Map<Long, BigDecimal> receiptTotals = new HashMap<>();
-        if (!CollectionUtils.isEmpty(receiptPayments)) {
-            for (ReceiptPayment receiptPayment : receiptPayments) {
-                if (receiptPayment.getSalesLedgerId() != null && receiptPayment.getReceiptPaymentAmount() != null) {
-                    //  濡傛灉 key 瀛樺湪鍒欑浉鍔�,涓嶅瓨鍦ㄥ垯鏀惧叆
-                    receiptTotals.merge(receiptPayment.getSalesLedgerId(), receiptPayment.getReceiptPaymentAmount(), BigDecimal::add);
-                }
-            }
-        }
-
-        for (SalesLedger salesLedger : iPage.getRecords()) {
-            Long ledgerId = salesLedger.getId();
-            // 鍚堝悓鎬婚噾棰�
-            BigDecimal contractAmount = salesLedger.getContractAmount() == null ? BigDecimal.ZERO : salesLedger.getContractAmount();
-            // 寮�绁ㄦ�婚鍜屽洖娆炬�婚
-            BigDecimal invoiceTotal = invoiceTotals.getOrDefault(ledgerId, BigDecimal.ZERO);
-            BigDecimal receiptPaymentAmountTotal = receiptTotals.getOrDefault(ledgerId, BigDecimal.ZERO);
-
-            //  鏈紑绁ㄩ噾棰� = 鍚堝悓閲戦 - 宸插紑绁ㄩ噾棰�
-            BigDecimal noInvoiceAmountTotal = contractAmount.subtract(invoiceTotal);
-            if (noInvoiceAmountTotal.compareTo(BigDecimal.ZERO) < 0) {
-                noInvoiceAmountTotal = BigDecimal.ZERO;
-            }
-
-            //  寰呭洖娆鹃噾棰� = 宸插紑绁ㄩ噾棰� - 宸插洖娆鹃噾棰�
-            BigDecimal noReceiptPaymentAmountTotal = invoiceTotal.subtract(receiptPaymentAmountTotal);
-            if (noReceiptPaymentAmountTotal.compareTo(BigDecimal.ZERO) < 0) {
-                noReceiptPaymentAmountTotal = BigDecimal.ZERO;
-            }
-
-            salesLedger.setNoInvoiceAmountTotal(noInvoiceAmountTotal);
-            salesLedger.setInvoiceTotal(invoiceTotal);
-            salesLedger.setReceiptPaymentAmountTotal(receiptPaymentAmountTotal);
-            salesLedger.setNoReceiptAmount(noReceiptPaymentAmountTotal);
-
-            //  濡傛灉宸茬粡鏈夎繃寮�绁ㄦ垨鍥炴鎿嶄綔,鍒欎笉鍏佽缂栬緫
-            boolean hasInvoiceOperation = invoiceTotal.compareTo(BigDecimal.ZERO) > 0;
-            boolean hasReceiptOperation = receiptPaymentAmountTotal.compareTo(BigDecimal.ZERO) > 0;
-            salesLedger.setIsEdit(!(hasInvoiceOperation || hasReceiptOperation));
-        }
-
-        if (ObjectUtils.isNotEmpty(salesLedgerDto.getStatus())) {
-            if (salesLedgerDto.getStatus()) {
-                // 娓呴櫎鎵�鏈夆�滄湭寮�绁ㄩ噾棰濃�濅负 0 鐨勮褰�
-                iPage.getRecords().removeIf(salesLedger ->
-                        Objects.equals(salesLedger.getNoInvoiceAmountTotal(), new BigDecimal("0.00")));
-                iPage.setTotal(iPage.getRecords().size());
-            }
-        }
-
-        return iPage;
+    public IPage<SalesLedger> listPage(Page<?> page, SalesLedgerDto salesLedgerDto) {
+        return salesLedgerService.selectSalesLedgerListPage(page, salesLedgerDto);
     }
 
     @ApiOperation("鏌ヨ閿�鍞彴璐︽秷鑰楃墿鏂欎俊鎭�")
@@ -377,4 +363,151 @@
         return AjaxResult.success(dto);
     }
 
+    @GetMapping("/salesOrders/{salesLedgerId}")
+    @ApiOperation("鎵撳嵃閿�鍞鍗�")
+    public AjaxResult salesOrders(@PathVariable Long salesLedgerId) {
+        SalesOrdersDto salesOrdersDto = salesLedgerService.salesOrders(salesLedgerId);
+        return AjaxResult.success(salesOrdersDto);
+    }
+
+    @PostMapping("/salesInvoices")
+    @ApiOperation("鎵撳嵃閿�鍞彂璐у崟")
+    public AjaxResult salesInvoices(@RequestBody List<Long> salesLedgerIds) {
+        SalesInvoicesDto dto = salesLedgerService.salesInvoices(salesLedgerIds);
+        return AjaxResult.success(dto);
+    }
+
+    @GetMapping("/salesLabel/{salesLedgerId}")
+    @ApiOperation("鎵撳嵃璁㈠崟鏍囩")
+    public AjaxResult salesLabel(@PathVariable Long salesLedgerId) {
+        List<SalesLabelDto> list = salesLedgerService.salesLabel(salesLedgerId);
+        return AjaxResult.success(list);
+    }
+
+    @PostMapping("/salesStock")
+    @ApiOperation("閿�鍞彴璐︿骇鍝佸叆搴�")
+    public AjaxResult salesStock(@RequestBody SalesProductStockDto dto) {
+        salesLedgerService.salesStock(dto);
+        return AjaxResult.success();
+    }
+
+    @GetMapping("/shippedCustomers")
+    @ApiOperation("宸插彂璐у鎴峰悕鍗�")
+    public AjaxResult shippedCustomers() {
+        List<Customer> list = salesLedgerService.shippedCustomers();
+        return AjaxResult.success(list);
+    }
+
+    @PostMapping("/scanInbound")
+    @ApiOperation("閿�鍞鍗曟壂鐮�-鍚堟牸鍏ュ簱")
+    public AjaxResult scanInbound(@RequestBody SalesScanInboundDto dto) {
+        salesLedgerService.scanInbound(dto);
+        return AjaxResult.success();
+    }
+
+    @PostMapping("/scanInboundUnqualified")
+    @ApiOperation("閿�鍞鍗曟壂鐮�-涓嶅悎鏍煎叆搴�")
+    public AjaxResult scanInboundUnqualified(@RequestBody SalesScanInboundDto dto) {
+        salesLedgerService.scanInboundUnqualified(dto);
+        return AjaxResult.success();
+    }
+
+    @PostMapping("/scanOutbound")
+    @ApiOperation("閿�鍞鍗曟壂鐮�-鍚堟牸鍑哄簱")
+    public AjaxResult scanOutbound(@RequestBody SalesScanInboundDto dto) {
+        salesLedgerService.scanOutbound(dto);
+        return AjaxResult.success();
+    }
+
+    @PostMapping("/scanShipApply")
+    @ApiOperation("閿�鍞鍗曟壂鐮�-鍙戣捣鍙戣揣瀹℃壒锛堝~鍐欒溅鐗�/蹇�掋�佸鎵逛汉銆侀檮浠讹紱閫氳繃鍚庤嚜鍔ㄦ墸搴撳瓨骞舵爣璁板凡鍙戣揣锛�")
+    public AjaxResult scanShipApply(@RequestBody SalesScanShipDto dto) {
+        salesLedgerService.scanShipApply(dto);
+        return AjaxResult.success("鍙戣揣瀹℃壒宸插彂璧�");
+    }
+
+    @PostMapping("/scanOutboundUnqualified")
+    @ApiOperation("閿�鍞鍗曟壂鐮�-涓嶅悎鏍煎嚭搴�")
+    public AjaxResult scanOutboundUnqualified(@RequestBody SalesScanInboundDto dto) {
+        salesLedgerService.scanOutboundUnqualified(dto);
+        return AjaxResult.success();
+    }
+
+    @PostMapping("/salesHistory/shippingImport")
+    @ApiOperation("閿�鍞彂璐у巻鍙叉暟鎹鍏�-宸插彂璐�")
+    public AjaxResult shippingImport(MultipartFile file) {
+        salesLedgerService.shippingImport(file);
+        return AjaxResult.success();
+    }
+
+    @PostMapping("/salesHistory/notShippingImport")
+    @ApiOperation("閿�鍞彂璐у巻鍙叉暟鎹鍏�-鏈彂璐�")
+    public AjaxResult notShippingImport(MultipartFile file) {
+        salesLedgerService.notShippingImport(file);
+        return AjaxResult.success();
+    }
+
+    @PostMapping("/salesHistory/shippingImportTemplate")
+    @ApiOperation("閿�鍞彂璐у巻鍙叉暟鎹鍏�-宸插彂璐у鍏ユā鏉夸笅杞�")
+    public void shippingImportTemplate(HttpServletResponse response) {
+        ExcelUtil<SalesShippingImportDto> excelUtil = new ExcelUtil<>(SalesShippingImportDto.class);
+        excelUtil.importTemplateExcel(response, "宸插嚭搴撳鍏ユā鏉夸笅杞�");
+    }
+
+    @PostMapping("/salesHistory/notShippingImportTemplate")
+    @ApiOperation("閿�鍞彂璐у巻鍙叉暟鎹鍏�-鏈彂璐у鍏ユā鏉夸笅杞�")
+    public void notShippingImportTemplate(HttpServletResponse response) {
+        ExcelUtil<SalesNotShippingImportDto> excelUtil = new ExcelUtil<>(SalesNotShippingImportDto.class);
+        excelUtil.importTemplateExcel(response, "鏈嚭搴撳鍏ユā鏉夸笅杞�");
+    }
+
+    private List<Long> parseSalesLedgerIds(HttpServletRequest request) {
+        if (request == null) {
+            return Collections.emptyList();
+        }
+
+        List<Long> ids = new ArrayList<>();
+        Map<String, String[]> parameterMap = request.getParameterMap();
+        if (parameterMap == null || parameterMap.isEmpty()) {
+            return ids;
+        }
+
+        String directValue = request.getParameter("salesLedgerIds");
+        if (StringUtils.hasText(directValue)) {
+            for (String value : directValue.split(",")) {
+                addParsedLong(ids, value);
+            }
+        }
+
+        for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
+            String key = entry.getKey();
+            if (!StringUtils.hasText(key)) {
+                continue;
+            }
+            if (!"salesLedgerIds".equals(key) && !key.startsWith("salesLedgerIds[")) {
+                continue;
+            }
+            String[] values = entry.getValue();
+            if (values == null) {
+                continue;
+            }
+            for (String value : values) {
+                addParsedLong(ids, value);
+            }
+        }
+
+        return ids.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList());
+    }
+
+    private void addParsedLong(List<Long> target, String value) {
+        if (target == null || !StringUtils.hasText(value)) {
+            return;
+        }
+        try {
+            target.add(Long.valueOf(value.trim()));
+        } catch (Exception ignored) {
+            // ignore invalid id values
+        }
+    }
+
 }

--
Gitblit v1.9.3