From 3fd61b2386021218909e0211b647cbd63f270f76 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期五, 27 三月 2026 15:53:48 +0800
Subject: [PATCH] feat: 销售发货单打印
---
src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java | 8 +
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java | 126 +++++++++++++++++++++++++
src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java | 6 +
src/main/java/com/ruoyi/sales/dto/SalesInvoicesDto.java | 102 ++++++++++++++++++++
4 files changed, 241 insertions(+), 1 deletions(-)
diff --git a/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java b/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
index c149b52..c961cff 100644
--- a/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
+++ b/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
@@ -380,4 +380,12 @@
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);
+ }
+
}
diff --git a/src/main/java/com/ruoyi/sales/dto/SalesInvoicesDto.java b/src/main/java/com/ruoyi/sales/dto/SalesInvoicesDto.java
new file mode 100644
index 0000000..5026f2d
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/dto/SalesInvoicesDto.java
@@ -0,0 +1,102 @@
+package com.ruoyi.sales.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * <br>
+ * 鎵撳嵃閿�鍞彂璐у崟Dto
+ * </br>
+ *
+ * @author deslrey
+ * @version 1.0
+ * @since 2026/03/27 15:30
+ */
+@Data
+public class SalesInvoicesDto {
+
+ @ApiModelProperty("瀹㈡埛鍚嶇О")
+ private String customerName;
+
+ @ApiModelProperty("鑱旂郴浜�")
+ private String contactPerson;
+
+ @ApiModelProperty("鑱旂郴鐢佃瘽")
+ private String contactPhone;
+
+ @ApiModelProperty("閫佽揣鍦板潃")
+ private String companyAddress;
+
+ @ApiModelProperty("鍙戣揣鍗曞彿")
+ private String deliveryNo;
+
+ @ApiModelProperty("瀵规柟鍗曞彿")
+ private String externalOrderNo;
+
+ @ApiModelProperty("鎬诲悎璁℃暟閲�")
+ private BigDecimal totalQuantity;
+
+ @ApiModelProperty("鎬诲悎璁¢潰绉�")
+ private BigDecimal totalArea;
+
+ @ApiModelProperty("鍒跺崟鍛�")
+ private String orderMaker;
+
+ @ApiModelProperty("鍒跺崟鏃ユ湡")
+ @JsonFormat(pattern = "yyyy/MM/dd")
+ private LocalDateTime executionDate;
+
+ @ApiModelProperty("鍙戣揣璁㈠崟鍒嗙粍")
+ private List<InvoiceOrderGroupDto> groups;
+
+ /**
+ * 璁㈠崟鍒嗙粍 DTO
+ */
+ @Data
+ public static class InvoiceOrderGroupDto {
+ @ApiModelProperty("璁㈠崟缂栧彿")
+ private String salesContractNo;
+
+ @ApiModelProperty("浜у搧鍚嶇О")
+ private String productName;
+
+ @ApiModelProperty("鏄庣粏鍒楄〃")
+ private List<InvoiceItemDto> items;
+
+ @ApiModelProperty("灏忚鏁伴噺")
+ private BigDecimal groupTotalQuantity;
+
+ @ApiModelProperty("灏忚闈㈢Н")
+ private BigDecimal groupTotalArea;
+ }
+
+ /**
+ * 鍙戣揣鍗曟槑缁� DTO
+ */
+ @Data
+ public static class InvoiceItemDto {
+ @ApiModelProperty("妤煎眰缂栧彿")
+ private String floorCode;
+
+ @ApiModelProperty("瀹�*楂�")
+ private String widthHeight;
+
+ @ApiModelProperty("鏁伴噺")
+ private BigDecimal quantity;
+
+ @ApiModelProperty("闈㈢Н")
+ private BigDecimal area;
+
+ @ApiModelProperty("澶囨敞")
+ private String remark;
+
+ @ApiModelProperty("鍔犲伐瑕佹眰")
+ private String processRequirement;
+ }
+
+}
diff --git a/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java b/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
index f96512a..23a675c 100644
--- a/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
+++ b/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
@@ -31,7 +31,8 @@
int addOrUpdateSalesLedger(SalesLedgerDto salesLedgerDto);
- List<SalesLedgerProduct> getSalesLedgerProductListByRelateId(@NotNull Long relateId,@NotNull SaleEnum type);
+ List<SalesLedgerProduct> getSalesLedgerProductListByRelateId(@NotNull Long relateId, @NotNull SaleEnum type);
+
List<SalesLedgerProduct> getSalesLedgerProductListByIds(@Nullable List<Long> relateIds, @NotNull SaleEnum type);
void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, SaleEnum type);
@@ -61,4 +62,7 @@
SalesLedgerProcessRouteDto salesProcess(Long salesLedgerId);
SalesOrdersDto salesOrders(Long salesLedgerId);
+
+ SalesInvoicesDto salesInvoices(List<Long> salesLedgerIds);
+
}
diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
index e5dd539..025fe60 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -1180,6 +1180,132 @@
return dto;
}
+ @Override
+ public SalesInvoicesDto salesInvoices(List<Long> salesLedgerIds) {
+ if (CollectionUtils.isEmpty(salesLedgerIds)) {
+ throw new ServiceException("閿�鍞彂璐у崟鎵撳嵃澶辫触,閿�鍞鍗曚笉鑳戒负绌�");
+ }
+
+ List<SalesLedger> ledgers = salesLedgerMapper.selectBatchIds(salesLedgerIds);
+ if (CollectionUtils.isEmpty(ledgers)) {
+ throw new ServiceException("閿�鍞彂璐у崟鎵撳嵃澶辫触,鏈壘鍒板搴斿彴璐﹁褰�");
+ }
+
+ Long customerId = ledgers.get(0).getCustomerId();
+ for (SalesLedger ledger : ledgers) {
+ if (!Objects.equals(customerId, ledger.getCustomerId())) {
+ throw new ServiceException("閿�鍞彂璐у崟鍚堝苟鎵撳嵃鍙兘鏄悓涓�涓鎴�");
+ }
+ }
+
+ SalesInvoicesDto dto = new SalesInvoicesDto();
+
+ Customer customer = customerMapper.selectById(customerId);
+ if (customer != null) {
+ dto.setCustomerName(customer.getCustomerName());
+ dto.setContactPerson(customer.getContactPerson());
+ dto.setContactPhone(customer.getContactPhone());
+
+ StringBuilder address = new StringBuilder();
+ if (customer.getRegionsId() != null) {
+ CustomerRegions regions = customerRegionsService.getById(customer.getRegionsId());
+ if (regions != null) {
+ address.append(regions.getRegionsName());
+ }
+ }
+ if (StringUtils.isNotEmpty(customer.getCompanyAddress())) {
+ address.append(customer.getCompanyAddress());
+ }
+ dto.setCompanyAddress(address.toString());
+ }
+
+ // 鍙戣揣鍗曞彿 (XF + 鏃ユ湡 + 搴忓垪)
+ String dateStr = LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd"));
+ String redisKey = "sales:delivery:seq:" + dateStr;
+ Long seq = redisTemplate.opsForValue().increment(redisKey);
+ if (seq != null && seq == 1) {
+ redisTemplate.expire(redisKey, 48, TimeUnit.HOURS);
+ }
+ dto.setDeliveryNo("XF" + dateStr + String.format("%03d", seq != null ? seq : 1));
+
+ // 瀵规柟鍗曞彿
+// dto.setExternalOrderNo(ledgers.get(0).getCustomerContractNo());
+
+ // 鏌ヨ鎵�鏈変骇鍝�
+ List<SalesLedgerProduct> allProducts = salesLedgerProductMapper.selectList(
+ new LambdaQueryWrapper<SalesLedgerProduct>().in(SalesLedgerProduct::getSalesLedgerId, salesLedgerIds));
+
+ if (CollectionUtils.isNotEmpty(allProducts)) {
+ Map<Long, SalesLedger> ledgerMap = ledgers.stream()
+ .collect(Collectors.toMap(SalesLedger::getId, Function.identity()));
+
+ Map<Long, List<SalesLedgerProduct>> groupedData = new LinkedHashMap<>();
+ for (SalesLedgerProduct p : allProducts) {
+ groupedData.computeIfAbsent(p.getSalesLedgerId(), k -> new ArrayList<>()).add(p);
+ }
+
+ List<SalesInvoicesDto.InvoiceOrderGroupDto> groups = new ArrayList<>();
+ BigDecimal totalQty = BigDecimal.ZERO;
+ BigDecimal totalArea = BigDecimal.ZERO;
+
+ for (Map.Entry<Long, List<SalesLedgerProduct>> ledgerEntry : groupedData.entrySet()) {
+ SalesLedger ledger = ledgerMap.get(ledgerEntry.getKey());
+ String orderNo = ledger != null ? ledger.getSalesContractNo() : "";
+ List<SalesLedgerProduct> products = ledgerEntry.getValue();
+
+ SalesInvoicesDto.InvoiceOrderGroupDto group = new SalesInvoicesDto.InvoiceOrderGroupDto();
+ group.setSalesContractNo(orderNo);
+ if (CollectionUtils.isNotEmpty(products)) {
+ group.setProductName(products.get(0).getProductCategory());
+ }
+
+ List<SalesInvoicesDto.InvoiceItemDto> itemDtos = new ArrayList<>();
+ BigDecimal groupQty = BigDecimal.ZERO;
+ BigDecimal groupArea = BigDecimal.ZERO;
+
+ for (SalesLedgerProduct p : products) {
+ SalesInvoicesDto.InvoiceItemDto item = new SalesInvoicesDto.InvoiceItemDto();
+ item.setFloorCode(p.getFloorCode());
+ item.setWidthHeight((p.getWidth() != null ? p.getWidth().stripTrailingZeros().toPlainString() : "0") +
+ " * " + (p.getHeight() != null ? p.getHeight().stripTrailingZeros().toPlainString() : "0"));
+ item.setQuantity(p.getQuantity());
+
+ // 闈㈢Н
+ BigDecimal area = p.getSettleTotalArea() != null ? p.getSettleTotalArea() : p.getActualTotalArea();
+ if (area == null && p.getWidth() != null && p.getHeight() != null && p.getQuantity() != null) {
+ area = p.getWidth().multiply(p.getHeight()).multiply(p.getQuantity()).divide(new BigDecimal(1000000), 2, RoundingMode.HALF_UP);
+ }
+ item.setArea(area);
+ item.setRemark(p.getRemark());
+ item.setProcessRequirement(p.getProcessRequirement());
+
+ itemDtos.add(item);
+ groupQty = groupQty.add(p.getQuantity() != null ? p.getQuantity() : BigDecimal.ZERO);
+ groupArea = groupArea.add(area != null ? area : BigDecimal.ZERO);
+ }
+
+ group.setItems(itemDtos);
+ group.setGroupTotalQuantity(groupQty);
+ group.setGroupTotalArea(groupArea.setScale(2, RoundingMode.HALF_UP));
+ groups.add(group);
+
+ totalQty = totalQty.add(groupQty);
+ totalArea = totalArea.add(groupArea);
+ }
+ dto.setGroups(groups);
+ dto.setTotalQuantity(totalQty);
+ dto.setTotalArea(totalArea.setScale(2, RoundingMode.HALF_UP));
+ }
+
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ if (loginUser != null && loginUser.getUser() != null) {
+ dto.setOrderMaker(loginUser.getUser().getNickName());
+ }
+ dto.setExecutionDate(LocalDateTime.now());
+
+ return dto;
+ }
+
private int findFirstMissingSequence(List<Integer> sequences) {
if (sequences.isEmpty()) {
return 1;
--
Gitblit v1.9.3