From c1bbff15e4f64767d471de763613a54c9cb8d4b4 Mon Sep 17 00:00:00 2001
From: liyong <18434998025@163.com>
Date: 星期五, 24 四月 2026 14:28:15 +0800
Subject: [PATCH] feat(sales): 添加销售台账批量导入功能
---
src/main/resources/mapper/basic/ProductModelMapper.xml | 3
src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java | 9 +
src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java | 14 +-
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java | 140 +++++++++++++++++++++++++++
src/main/resources/mapper/basic/CustomerPrivatePoolMapper.xml | 35 ++++++
src/main/java/com/ruoyi/basic/mapper/CustomerPrivatePoolMapper.java | 1
src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java | 7 +
src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java | 3
src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java | 2
src/main/java/com/ruoyi/sales/dto/SalesLedgerSimpleImportDto.java | 37 +++++++
src/main/resources/static/销售台账导入模板.xlsx | 0
11 files changed, 235 insertions(+), 16 deletions(-)
diff --git a/src/main/java/com/ruoyi/basic/mapper/CustomerPrivatePoolMapper.java b/src/main/java/com/ruoyi/basic/mapper/CustomerPrivatePoolMapper.java
index 4c6f325..334ab07 100644
--- a/src/main/java/com/ruoyi/basic/mapper/CustomerPrivatePoolMapper.java
+++ b/src/main/java/com/ruoyi/basic/mapper/CustomerPrivatePoolMapper.java
@@ -26,4 +26,5 @@
List<CustomerPrivatePoolDto> selectInfos();
+ List<CustomerPrivatePoolDto> selectByCusterNames(@Param("collect") List<String> collect);
}
diff --git a/src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java b/src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java
index d93307c..55bfdce 100644
--- a/src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java
+++ b/src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java
@@ -184,6 +184,13 @@
}else {
//鎵惧埌鐖惰妭鐐�
Product productParent = productMapper.selectOne(new QueryWrapper<Product>().lambda().eq(Product::getProductName, "鎴愬搧").last("limit 1"));
+ if (ObjectUtils.isEmpty(productParent)) {
+ Product product = new Product();
+ product.setProductName("鎴愬搧");
+ product.setDeptId(SecurityUtils.getDeptId()[0]);
+ productMapper.insert(product);
+ productParent.setId(product.getId());
+ }
//鏂板浜у搧澶х被
Product product = new Product();
product.setProductName(productModelDto.getProductName());
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
index 798baa0..442ad9d 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -2,7 +2,6 @@
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
-import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -16,7 +15,6 @@
import com.ruoyi.basic.pojo.ProductModel;
import com.ruoyi.common.enums.AuditEnum;
import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
-import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
@@ -35,18 +33,18 @@
import com.ruoyi.quality.service.IQualityInspectService;
import lombok.AllArgsConstructor;
import org.springframework.aop.framework.AopContext;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
-import com.ruoyi.production.mapper.ProductionProductMainMapper;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
import java.util.stream.Collectors;
@Service
@@ -183,7 +181,7 @@
productionProductInput.setQuantity(productStructureDto.getUnitQuantity().multiply(dto.getQuantity()));
productionProductInput.setProductMainId(productionProductMain.getId());
productionProductInputMapper.insert(productionProductInput);
- stockUtils.substractStock(productStructureDto.getProductModelId(), productionProductInput.getQuantity(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(), productionProductMain.getId());
+// stockUtils.substractStock(productStructureDto.getProductModelId(), productionProductInput.getQuantity(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(), productionProductMain.getId());
}
/*鏂板鎶ュ伐浜у嚭琛�*/
@@ -465,7 +463,7 @@
//鍒犻櫎涓嶉渶瑕佽川妫�鐨勫悎鏍煎叆搴�
stockUtils.deleteStockInRecord(productionProductMain.getId(), StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode());
//鍒犻櫎鎶曞叆瀵瑰簲鐨勫嚭搴撹褰�
- stockUtils.deleteStockOutRecord(productionProductMain.getId(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode());
+// stockUtils.deleteStockOutRecord(productionProductMain.getId(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode());
// 鍒犻櫎涓昏〃
productionProductMainMapper.deleteById(productionProductMain.getId());
return true;
diff --git a/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java b/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
index 79771c5..cb37002 100644
--- a/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
+++ b/src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
@@ -185,7 +185,14 @@
salesLedgerService.exportProcessContract(id);
}
- /**
+ @GetMapping("/importSalsesLedger")
+ @ApiOperation("闃冲厜瀵煎叆閿�鍞彴璐︽柊")
+ public AjaxResult importSalsesLedger( MultipartFile file) {
+ return salesLedgerService.importSalsesLedger(file);
+ }
+
+
+ /**w
* 鏂板淇敼閿�鍞彴璐�
*/
@Log(title = "閿�鍞彴璐�", businessType = BusinessType.INSERT)
diff --git a/src/main/java/com/ruoyi/sales/dto/SalesLedgerSimpleImportDto.java b/src/main/java/com/ruoyi/sales/dto/SalesLedgerSimpleImportDto.java
new file mode 100644
index 0000000..6cea320
--- /dev/null
+++ b/src/main/java/com/ruoyi/sales/dto/SalesLedgerSimpleImportDto.java
@@ -0,0 +1,37 @@
+package com.ruoyi.sales.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+@Data
+public class SalesLedgerSimpleImportDto {
+
+
+ @Excel(name = "璁㈣揣鏃ユ湡")
+ @DateTimeFormat(pattern = "yy.MM.dd")
+ @JsonFormat(pattern = "yy.MM.dd", timezone = "GMT+8")
+ private Date orderDate;
+
+ @Excel(name = "瀹㈡埛鍚嶇О")
+ private String customerName;
+
+ @Excel(name = "浜у搧鍚嶇О")
+ private String productName;
+
+ @Excel(name = "鏁伴噺")
+ private BigDecimal quantity;
+
+ @Excel(name = "鍗曚环")
+ private BigDecimal unitPrice;
+
+ @Excel(name = "閲戦")
+ private BigDecimal amount;
+
+ @Excel(name = "璁㈠崟缂栧彿")
+ private String orderNo;
+}
diff --git a/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java b/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
index aa2abf2..2323340 100644
--- a/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
+++ b/src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
@@ -3,7 +3,6 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.aftersalesservice.pojo.AfterSalesService;
import com.ruoyi.common.enums.SaleEnum;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.sales.dto.LossProductModelDto;
@@ -58,4 +57,6 @@
* @param id
*/
void exportProcessContract(@NotNull Long id);
+
+ AjaxResult importSalsesLedger(MultipartFile file);
}
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 5f4ec02..c9ba799 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -531,6 +531,141 @@
exportProcessContractToWord(exportProcessContract);
}
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public AjaxResult importSalsesLedger(MultipartFile file) {
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ int successCount = 0;
+ Date lastDate = null;
+ BigDecimal lastUnitPrice = null;
+ int skipCount = 0;
+ List<String> errorMessages = new ArrayList<>();
+ CustomerPrivatePoolDto lastCustomer = null;
+
+ try {
+ InputStream inputStream = file.getInputStream();
+ ExcelUtil<SalesLedgerSimpleImportDto> excelUtil = new ExcelUtil<>(SalesLedgerSimpleImportDto.class);
+ List<SalesLedgerSimpleImportDto> importDataList = excelUtil.importExcel(inputStream);
+
+ if (CollectionUtils.isEmpty(importDataList)) {
+ return AjaxResult.error("瀵煎叆鏁版嵁涓虹┖锛�");
+ }
+
+ List<String> customerNames = importDataList.stream()
+ .map(SalesLedgerSimpleImportDto::getCustomerName)
+ .filter(StrUtil::isNotBlank)
+ .distinct()
+ .collect(Collectors.toList());
+
+ List<CustomerPrivatePoolDto> customers = customerPrivatePoolMapper.selectByCusterNames(customerNames);
+
+ for (int i = 0; i < importDataList.size(); i++) {
+ SalesLedgerSimpleImportDto importDto = importDataList.get(i);
+ int rowNum = i + 2;
+
+ if (StrUtil.isBlank(importDto.getOrderNo())) {
+ errorMessages.add(String.format("绗�%d琛岋細璁㈠崟缂栧彿涓虹┖", rowNum));
+ skipCount++;
+ continue;
+ }
+
+ if (importDto.getQuantity() == null ) {
+ errorMessages.add(String.format("绗�%d琛岋細鏁伴噺涓嶈兘涓虹┖", rowNum));
+ skipCount++;
+ continue;
+ }
+
+ long count = salesLedgerMapper.selectCount(new LambdaQueryWrapper<SalesLedger>()
+ .eq(SalesLedger::getSalesContractNo, importDto.getOrderNo()));
+ if (count > 0) {
+ errorMessages.add(String.format("绗�%d琛岋細璁㈠崟缂栧彿[%s]宸插瓨鍦�", rowNum, importDto.getOrderNo()));
+ skipCount++;
+ continue;
+ }
+
+ CustomerPrivatePoolDto matchedCustomer = customers.stream()
+ .filter(c -> c.getCustomerName().equals(importDto.getCustomerName()))
+ .findFirst()
+ .orElse(lastCustomer);
+
+ if (matchedCustomer == null) {
+ errorMessages.add(String.format("绗�%d琛岋細瀹㈡埛[%s]涓嶅瓨鍦ㄤ笖鏃犲巻鍙插鎴�", rowNum, importDto.getCustomerName()));
+ skipCount++;
+ continue;
+ }
+
+ lastCustomer = matchedCustomer;
+
+ try {
+ SalesLedger salesLedger = new SalesLedger();
+ salesLedger.setSalesContractNo(importDto.getOrderNo());
+ salesLedger.setCustomerName(matchedCustomer.getCustomerName());
+ salesLedger.setCustomerId(matchedCustomer.getCustomerId());
+ salesLedger.setCustomerContractNo(matchedCustomer.getTaxpayerIdentificationNumber());
+ Date date = importDto.getOrderDate();
+ if (ObjectUtils.isEmpty(date)){
+ date = lastDate;
+ }
+ lastDate = date;
+ salesLedger.setEntryDate(date);
+ salesLedger.setContractAmount(importDto.getAmount());
+ salesLedger.setEntryPerson(loginUser.getUserId().toString());
+ salesLedger.setTenantId(matchedCustomer.getTenantId());
+ salesLedgerMapper.insert(salesLedger);
+
+ SalesLedgerProduct product = new SalesLedgerProduct();
+ product.setSalesLedgerId(salesLedger.getId());
+ product.setType(1);
+ product.setQuantity(importDto.getQuantity());
+ BigDecimal unitPrice = importDto.getUnitPrice();
+ if (ObjectUtils.isEmpty(unitPrice)) {
+ unitPrice = lastUnitPrice;
+ }
+ lastUnitPrice = unitPrice;
+ product.setTaxInclusiveUnitPrice(unitPrice);
+ product.setTaxInclusiveTotalPrice(unitPrice.multiply(importDto.getQuantity()));
+ product.setTaxExclusiveTotalPrice(unitPrice.multiply(importDto.getQuantity()));
+ product.setNoInvoiceNum(importDto.getQuantity());
+ product.setNoInvoiceAmount(importDto.getAmount());
+ product.setPendingInvoiceTotal(importDto.getAmount());
+ product.setUnit("/");
+ product.setProductCategory(importDto.getProductName());
+ product.setSpecificationModel(importDto.getProductName());
+ product.setRegister(loginUser.getNickName());
+ product.setRegisterDate(LocalDateTime.now());
+ product.setApproveStatus(0);
+
+ if (ObjectUtils.isEmpty(product.getProductModelId())) {
+ ProductModelAnticlockwiseDto productModelAnticlockwiseDto = new ProductModelAnticlockwiseDto();
+ productModelAnticlockwiseDto.setModel(product.getSpecificationModel());
+ productModelAnticlockwiseDto.setProductName(product.getProductCategory());
+ productModelAnticlockwiseDto.setUnit("/");
+ productModelAnticlockwiseDto.setSubUnit("/");
+ Long productModelId = productModelService.productModelAnticlockwise(productModelAnticlockwiseDto);
+ product.setProductModelId(productModelId);
+ }
+
+ salesLedgerProductMapper.insert(product);
+ salesLedgerProductServiceImpl.addProductionData(product);
+ successCount++;
+
+ } catch (Exception e) {
+ log.error("绗瑊}琛岃鍗昜{}]瀵煎叆澶辫触锛歿}", rowNum, importDto.getOrderNo(), e.getMessage(), e);
+ errorMessages.add(String.format("绗�%d琛岃鍗昜%s]锛氬鍏ュけ璐�-%s", rowNum, importDto.getOrderNo(), e.getMessage()));
+ skipCount++;
+ }
+ }
+
+ String message = String.format("瀵煎叆瀹屾垚锛佹垚鍔�%d鏉★紝璺宠繃%d鏉�", successCount, skipCount);
+ if (!errorMessages.isEmpty()) {
+ message += "銆傞敊璇鎯咃細" + String.join("锛�", errorMessages);
+ }
+ return AjaxResult.success(message);
+ } catch (Exception e) {
+ log.error("瀵煎叆閿�鍞彴璐﹀け璐�", e);
+ throw new RuntimeException("瀵煎叆澶辫触锛�" + e.getMessage(), e);
+ }
+ }
@SneakyThrows
private void exportProcessContractToWord(@NotNull ExportProcessContractVo exportProcessContract) {
@@ -611,11 +746,12 @@
List<Long> productIds = products.stream()
.map(SalesLedgerProduct::getId)
.collect(Collectors.toList());
- //鍒犻櫎鐢熶骇鏁版嵁
- salesLedgerProductServiceImpl.deleteProductionData(productIds);
+
// 鎵归噺鍒犻櫎浜у搧瀛愯〃
if (!productIds.isEmpty()) {
+ //鍒犻櫎鐢熶骇鏁版嵁
+ salesLedgerProductServiceImpl.deleteProductionData(productIds);
salesLedgerProductMapper.deleteBatchIds(productIds);
}
diff --git a/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java b/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
index e1668ef..dbccebc 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
+++ b/src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
@@ -6,12 +6,10 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
-import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.sales.dto.SimpleProductDto;
import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
-import com.ruoyi.sales.pojo.SalesLedgerProduct;
import com.ruoyi.stock.dto.StockInRecordDto;
import com.ruoyi.stock.dto.StockInventoryDto;
import com.ruoyi.stock.dto.StockOutRecordDto;
diff --git a/src/main/resources/mapper/basic/CustomerPrivatePoolMapper.xml b/src/main/resources/mapper/basic/CustomerPrivatePoolMapper.xml
index 2e69ab0..99bfd98 100644
--- a/src/main/resources/mapper/basic/CustomerPrivatePoolMapper.xml
+++ b/src/main/resources/mapper/basic/CustomerPrivatePoolMapper.xml
@@ -99,7 +99,7 @@
coalesce(c.tenant_id, cp.tenant_id) as tenant_id,
coalesce(c.basic_bank_account, cp.basic_bank_account) as basic_bank_account,
coalesce(c.bank_account, cp.bank_account) as bank_account,
- coalesce(c.bank_code, cp.bank_code) as bank_code
+ coalesce(c.bank_code, cp.bank_code) as bank_code,
coalesce(c.corporation, cp.corporation) as corporation,
coalesce(c.fax, cp.fax) as fax,
coalesce(c.agent, cp.agent) as agent,
@@ -108,5 +108,38 @@
left join customer c on c.id = cpp.customer_id and cpp.type = 1
left join customer_private cp on cp.id = cpp.customer_id and cpp.type = 0
</select>
+ <select id="selectByCusterNames" resultType="com.ruoyi.basic.dto.CustomerPrivatePoolDto">
+ select cpp.id,
+ cpp.bound_id,
+ cpp.type,
+ coalesce(c.id, cp.id) as customer_id,
+ coalesce(c.customer_name, cp.customer_name) as customer_name,
+ coalesce(c.customer_type, cp.customer_type) as customer_type,
+ coalesce(c.taxpayer_identification_number, cp.taxpayer_identification_number) as taxpayer_identification_number,
+ coalesce(c.company_address, cp.company_address) as company_address,
+ coalesce(c.company_phone, cp.company_phone) as company_phone,
+ coalesce(c.contact_person, cp.contact_person) as contact_person,
+ coalesce(c.contact_phone, cp.contact_phone) as contact_phone,
+ coalesce(c.maintainer, cp.maintainer) as maintainer,
+ coalesce(c.maintenance_time, cp.maintenance_time) as maintenance_time,
+ coalesce(c.tenant_id, cp.tenant_id) as tenant_id,
+ coalesce(c.basic_bank_account, cp.basic_bank_account) as basic_bank_account,
+ coalesce(c.bank_account, cp.bank_account) as bank_account,
+ coalesce(c.bank_code, cp.bank_code) as bank_code,
+ coalesce(c.corporation, cp.corporation) as corporation,
+ coalesce(c.fax, cp.fax) as fax,
+ coalesce(c.agent, cp.agent) as agent,
+ coalesce(c.bank_name, cp.bank_name) as bank_name
+ from customer_private_pool cpp
+ left join customer c on c.id = cpp.customer_id and cpp.type = 1
+ left join customer_private cp on cp.id = cpp.customer_id and cpp.type = 0
+ where c.customer_name in
+ <foreach item="item" collection="collect" separator="," open="(" close=")">
+ #{item}
+ </foreach> or cp.customer_name in
+ <foreach item="item" collection="collect" separator="," open="(" close=")">
+ #{item}
+ </foreach>
+ </select>
</mapper>
diff --git a/src/main/resources/mapper/basic/ProductModelMapper.xml b/src/main/resources/mapper/basic/ProductModelMapper.xml
index 500e4f9..b0d8750 100644
--- a/src/main/resources/mapper/basic/ProductModelMapper.xml
+++ b/src/main/resources/mapper/basic/ProductModelMapper.xml
@@ -126,7 +126,8 @@
INNER JOIN tree t ON t2.id = t.id;
</select>
<select id="selectOldProductModel" resultType="com.ruoyi.basic.pojo.ProductModel">
- select * from product_model left join
+ select product_model.*,product.product_name
+ from product_model left join
product on product_model.product_id = product.id
where product_model.model = #{model}
and product.product_name = #{productName}
diff --git "a/src/main/resources/static/\351\224\200\345\224\256\345\217\260\350\264\246\345\257\274\345\205\245\346\250\241\346\235\277.xlsx" "b/src/main/resources/static/\351\224\200\345\224\256\345\217\260\350\264\246\345\257\274\345\205\245\346\250\241\346\235\277.xlsx"
index 9558711..1d13d65 100644
--- "a/src/main/resources/static/\351\224\200\345\224\256\345\217\260\350\264\246\345\257\274\345\205\245\346\250\241\346\235\277.xlsx"
+++ "b/src/main/resources/static/\351\224\200\345\224\256\345\217\260\350\264\246\345\257\274\345\205\245\346\250\241\346\235\277.xlsx"
Binary files differ
--
Gitblit v1.9.3