src/main/java/com/ruoyi/basic/pojo/ProductModel.java
@@ -26,4 +26,9 @@ * 规格型号 */ private String model; /** * 单位 */ private String unit; } src/main/java/com/ruoyi/purchase/controller/TicketRegistrationController.java
@@ -1,24 +1,21 @@ package com.ruoyi.purchase.controller; import javax.servlet.http.HttpServletResponse; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.purchase.dto.TicketRegistrationDto; import com.ruoyi.purchase.pojo.TicketRegistration; import com.ruoyi.purchase.service.ITicketRegistrationService; import lombok.AllArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.ruoyi.framework.aspectj.lang.annotation.Log; import com.ruoyi.framework.aspectj.lang.enums.BusinessType; import com.ruoyi.framework.web.controller.BaseController; import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.framework.web.page.TableDataInfo; import com.ruoyi.purchase.dto.TicketRegistrationDto; import com.ruoyi.purchase.pojo.TicketRegistration; import com.ruoyi.purchase.service.ITicketRegistrationService; import com.ruoyi.sales.service.ICommonFileService; import lombok.AllArgsConstructor; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; /** @@ -33,6 +30,8 @@ public class TicketRegistrationController extends BaseController { private ITicketRegistrationService ticketRegistrationService; private ICommonFileService commonFileService; /** * 查询来票登记列表 @@ -70,8 +69,7 @@ */ @Log(title = "来票登记", businessType = BusinessType.INSERT) @PostMapping ("/addOrUpdateRegistration") public AjaxResult addOrUpdateRegistration(@RequestBody TicketRegistrationDto ticketRegistrationDto) { public AjaxResult addOrUpdateRegistration(@RequestBody TicketRegistrationDto ticketRegistrationDto) throws IOException { return toAjax(ticketRegistrationService.addOrUpdateRegistration(ticketRegistrationDto)); } @@ -85,4 +83,13 @@ return toAjax(ticketRegistrationService.delRegistration(ids)); } @PostMapping("/upload") public AjaxResult uploadFile(MultipartFile file, Long id, String type) { try { return AjaxResult.success(commonFileService.uploadFile(file, id, type)); } catch (Exception e) { return AjaxResult.error(e.getMessage()); } } } src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java
@@ -107,4 +107,13 @@ */ private Long businessPersonId; /** * 产品id */ private Long productId; /** * 产品规格id */ private Long productModelId; } src/main/java/com/ruoyi/purchase/dto/TicketRegistrationDto.java
@@ -1,5 +1,6 @@ package com.ruoyi.purchase.dto; import com.ruoyi.sales.pojo.CommonFile; import com.ruoyi.sales.pojo.SalesLedgerProduct; import lombok.Data; @@ -52,4 +53,9 @@ private Long salesContractNoId; private String supplierName; private List<String> tempFileIds; private List<CommonFile> CommonFiles; private String fileName; } src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java
@@ -110,17 +110,17 @@ * 合同金额(产品含税总价) */ private BigDecimal contractAmount; /** * 业务员 */ @Excel(name = "业务员") private String businessPerson; /** * 业务员id */ private Long businessPersonId; // // /** // * 业务员 // */ // @Excel(name = "业务员") // private String businessPerson; // // /** // * 业务员id // */ // private Long businessPersonId; /** * 业务员手机号 src/main/java/com/ruoyi/purchase/pojo/TicketRegistration.java
@@ -1,12 +1,13 @@ package com.ruoyi.purchase.pojo; import java.math.BigDecimal; import java.util.Date; import com.baomidou.mybatisplus.annotation.*; import com.fasterxml.jackson.annotation.JsonFormat; import com.ruoyi.framework.aspectj.lang.annotation.Excel; import lombok.Data; import java.math.BigDecimal; import java.time.LocalDate; import java.util.Date; /** * 来票登记对象 ticket_registration @@ -53,16 +54,41 @@ */ private String customerName; /** * 业务员 */ @Excel(name = "业务员") private String businessPerson; // /** // * 业务员 // */ // @Excel(name = "业务员") // private String businessPerson; // // /** // * 业务员id // */ // private Long businessPersonId; /** * 业务员id * 发票号 */ private Long businessPersonId; @Excel(name = "发票号") private String invoiceNumber; /** * 发票金额(元) */ @Excel(name = "发票金额(元)") private BigDecimal invoiceAmount; /** * 开票人 */ @Excel(name = "开票人") private String issUer; /** * 开票日期 */ @JsonFormat(pattern = "yyyy-MM-dd" ,timezone = "GMT+8") @Excel(name = "开票日期", width = 30, dateFormat = "yyyy-MM-dd") private LocalDate issueDate; /** * 项目名称 src/main/java/com/ruoyi/purchase/service/ITicketRegistrationService.java
@@ -4,6 +4,7 @@ import com.ruoyi.purchase.dto.TicketRegistrationDto; import com.ruoyi.purchase.pojo.TicketRegistration; import java.io.IOException; import java.util.List; /** @@ -16,7 +17,7 @@ List<TicketRegistration> selectTicketRegistrationList(TicketRegistration ticketRegistration); int addOrUpdateRegistration(TicketRegistrationDto ticketRegistrationDto); int addOrUpdateRegistration(TicketRegistrationDto ticketRegistrationDto) throws IOException; int delRegistration(Long[] ids); src/main/java/com/ruoyi/purchase/service/impl/InvoicePurchaseServiceImpl.java
@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.other.mapper.TempFileMapper; import com.ruoyi.other.pojo.TempFile; import com.ruoyi.project.system.domain.SysUser; import com.ruoyi.project.system.mapper.SysUserMapper; import com.ruoyi.purchase.dto.InvoicePurchaseDto; @@ -19,19 +18,11 @@ import com.ruoyi.sales.pojo.CommonFile; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FilenameUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; @@ -141,79 +132,11 @@ } // 迁移临时文件到正式目录 if (invoicePurchaseDto.getTempFileIds() != null && !invoicePurchaseDto.getTempFileIds().isEmpty()) { migrateTempFilesToFormal(invoicePurchase.getId(), invoicePurchaseDto.getTempFileIds()); } // if (invoicePurchaseDto.getTempFileIds() != null && !invoicePurchaseDto.getTempFileIds().isEmpty()) { // migrateTempFilesToFormal(invoicePurchase.getId(), invoicePurchaseDto.getTempFileIds()); // } return i; } /** * 将临时文件迁移到正式目录 * * @param businessId 业务ID(销售台账ID) * @param tempFileIds 临时文件ID列表 * @throws IOException 文件操作异常 */ private void migrateTempFilesToFormal(Long businessId, List<String> tempFileIds) throws IOException { if (CollectionUtils.isEmpty(tempFileIds)) { return; } // 构建正式目录路径(按业务类型和日期分组) String formalDir = uploadDir + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE); Path formalDirPath = Paths.get(formalDir); // 确保正式目录存在(递归创建) if (!Files.exists(formalDirPath)) { Files.createDirectories(formalDirPath); } for (String tempFileId : tempFileIds) { // 查询临时文件记录 TempFile tempFile = tempFileMapper.selectById(tempFileId); if (tempFile == null) { log.warn("临时文件不存在,跳过处理: {}", tempFileId); continue; } // 构建正式文件名(包含业务ID和时间戳,避免冲突) String originalFilename = tempFile.getOriginalName(); String fileExtension = FilenameUtils.getExtension(originalFilename); String formalFilename = businessId + "_" + System.currentTimeMillis() + "_" + UUID.randomUUID().toString().substring(0, 8) + (com.ruoyi.common.utils.StringUtils.hasText(fileExtension) ? "." + fileExtension : ""); Path formalFilePath = formalDirPath.resolve(formalFilename); try { // 执行文件迁移(使用原子操作确保安全性) Files.move( Paths.get(tempFile.getTempPath()), formalFilePath, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE ); log.info("文件迁移成功: {} -> {}", tempFile.getTempPath(), formalFilePath); // 更新文件记录(关联到业务ID) CommonFile fileRecord = new CommonFile(); fileRecord.setCommonId(businessId); fileRecord.setName(originalFilename); fileRecord.setUrl(formalFilePath.toString()); fileRecord.setCreateTime(LocalDateTime.now()); fileRecord.setType(tempFile.getType()); commonFileMapper.insert(fileRecord); log.info("文件迁移成功: {} -> {}", tempFile.getTempPath(), formalFilePath); } catch (IOException e) { log.error("文件迁移失败: {}", tempFile.getTempPath(), e); // 可选择回滚事务或记录失败文件 throw new IOException("文件迁移异常", e); } } } @Override src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
@@ -4,7 +4,11 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.basic.mapper.ProductMapper; import com.ruoyi.basic.mapper.ProductModelMapper; import com.ruoyi.basic.mapper.SupplierManageMapper; import com.ruoyi.basic.pojo.Product; import com.ruoyi.basic.pojo.ProductModel; import com.ruoyi.basic.pojo.SupplierManage; import com.ruoyi.common.exception.base.BaseException; import com.ruoyi.common.utils.StringUtils; @@ -65,6 +69,10 @@ private final SupplierManageMapper supplierManageMapper; private final ProductMapper productMapper; private final ProductModelMapper productModelMapper; @Value("${file.upload-dir}") private String uploadDir; @@ -72,7 +80,7 @@ public List<PurchaseLedger> selectPurchaseLedgerList(PurchaseLedger purchaseLedger) { LambdaQueryWrapper<PurchaseLedger> queryWrapper = new LambdaQueryWrapper<>(); if (StringUtils.isNotBlank(purchaseLedger.getPurchaseContractNumber())) { queryWrapper.like(PurchaseLedger::getPurchaseContractNumber,purchaseLedger.getPurchaseContractNumber()); queryWrapper.like(PurchaseLedger::getPurchaseContractNumber, purchaseLedger.getPurchaseContractNumber()); } return purchaseLedgerMapper.selectList(queryWrapper); } @@ -81,9 +89,6 @@ public int addOrEditPurchase(PurchaseLedgerDto purchaseLedgerDto) throws IOException { SalesLedger salesLedger = salesLedgerMapper.selectById(purchaseLedgerDto.getSalesLedgerId()); //业务员 SysUser businessPerson = userMapper.selectUserById(purchaseLedgerDto.getBusinessPersonId()); if (salesLedger == null) { throw new BaseException("销售台账不存在"); @@ -101,8 +106,6 @@ purchaseLedger.setSupplierName(supplierManage.getSupplierName()); purchaseLedger.setRecorderId(purchaseLedgerDto.getRecorderId()); purchaseLedger.setRecorderName(sysUser.getNickName()); purchaseLedger.setBusinessPersonId(purchaseLedgerDto.getBusinessPersonId()); purchaseLedger.setBusinessPerson(businessPerson.getNickName()); purchaseLedger.setPhoneNumber(sysUser.getPhonenumber()); // 3. 新增或更新主表 @@ -115,7 +118,7 @@ // 4. 处理子表数据 List<SalesLedgerProduct> productList = purchaseLedgerDto.getProductData(); if (productList != null && !productList.isEmpty()) { handleSalesLedgerProducts(purchaseLedger.getId(), productList, purchaseLedgerDto.getType()); handleSalesLedgerProducts(purchaseLedger.getId(), purchaseLedgerDto.getProductId(), purchaseLedgerDto.getProductModelId(), productList, purchaseLedgerDto.getType()); } // 5. 迁移临时文件到正式目录 @@ -126,10 +129,19 @@ return 1; } private void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, Integer type) { private void handleSalesLedgerProducts(Long salesLedgerId, Long productId, Long productModelId, List<SalesLedgerProduct> products, Integer type) { Product pro = productMapper.selectById(productId); ProductModel productModel = productModelMapper.selectById(productModelId); // 按ID分组,区分新增和更新的记录 Map<Boolean, List<SalesLedgerProduct>> partitionedProducts = products.stream() .peek(p -> p.setSalesLedgerId(salesLedgerId)) .peek(p -> { p.setSalesLedgerId(salesLedgerId); p.setProductId(productId); p.setProductCategory(pro.getProductName()); p.setProductModelId(productModelId); p.setSpecificationModel(productModel.getModel()); }) .collect(Collectors.partitioningBy(p -> p.getId() != null)); List<SalesLedgerProduct> updateList = partitionedProducts.get(true); @@ -297,7 +309,6 @@ resultDto.setSalesContractNo(purchaseLedger.getSalesContractNo()); resultDto.setSupplierName(purchaseLedger.getSupplierName()); resultDto.setProjectName(purchaseLedger.getProjectName()); resultDto.setBusinessPersonId(purchaseLedger.getBusinessPersonId()); // 查询并设置关联产品 LambdaQueryWrapper<SalesLedgerProduct> queryWrapper = new LambdaQueryWrapper<>(); @@ -312,7 +323,7 @@ @Override public List getPurchasesNo() { LambdaQueryWrapper<PurchaseLedger> queryWrapper = Wrappers.lambdaQuery(); queryWrapper.select(PurchaseLedger::getId, PurchaseLedger::getPurchaseContractNumber,PurchaseLedger::getSupplierId); queryWrapper.select(PurchaseLedger::getId, PurchaseLedger::getPurchaseContractNumber, PurchaseLedger::getSupplierId); // 获取原始查询结果 List<Map<String, Object>> result = purchaseLedgerMapper.selectMaps(queryWrapper); src/main/java/com/ruoyi/purchase/service/impl/TicketRegistrationServiceImpl.java
@@ -1,25 +1,41 @@ package com.ruoyi.purchase.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.exception.base.BaseException; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.project.system.domain.SysUser; import com.ruoyi.project.system.mapper.SysUserMapper; import com.ruoyi.other.mapper.TempFileMapper; import com.ruoyi.other.pojo.TempFile; import com.ruoyi.purchase.dto.TicketRegistrationDto; import com.ruoyi.purchase.mapper.PurchaseLedgerMapper; import com.ruoyi.purchase.mapper.TicketRegistrationMapper; import com.ruoyi.purchase.pojo.PurchaseLedger; import com.ruoyi.purchase.pojo.TicketRegistration; import com.ruoyi.purchase.service.ITicketRegistrationService; import com.ruoyi.sales.mapper.CommonFileMapper; import com.ruoyi.sales.mapper.SalesLedgerProductMapper; import com.ruoyi.sales.pojo.CommonFile; import com.ruoyi.sales.pojo.SalesLedgerProduct; import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FilenameUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.io.IOException; import java.math.BigDecimal; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.List; import java.util.UUID; import java.util.stream.Collectors; /** @@ -29,51 +45,131 @@ * @date 2025-05-13 */ @Service @AllArgsConstructor @RequiredArgsConstructor @Slf4j public class TicketRegistrationServiceImpl extends ServiceImpl<TicketRegistrationMapper, TicketRegistration> implements ITicketRegistrationService { private TicketRegistrationMapper ticketRegistrationMapper; private final TicketRegistrationMapper ticketRegistrationMapper; private PurchaseLedgerMapper purchaseLedgerMapper; private final PurchaseLedgerMapper purchaseLedgerMapper; private SalesLedgerProductMapper salesLedgerProductMapper; private final SalesLedgerProductMapper salesLedgerProductMapper; private SysUserMapper userMapper; private final CommonFileMapper commonFileMapper; private final TempFileMapper tempFileMapper; @Value("${file.upload-dir}") private String uploadDir; @Override public List<TicketRegistration> selectTicketRegistrationList(TicketRegistration ticketRegistration) { LambdaQueryWrapper<TicketRegistration> queryWrapper = new LambdaQueryWrapper<>(); if (StringUtils.isNotBlank(ticketRegistration.getPurchaseContractNumber())) { queryWrapper.like(TicketRegistration::getPurchaseContractNumber,ticketRegistration.getPurchaseContractNumber()); queryWrapper.like(TicketRegistration::getPurchaseContractNumber, ticketRegistration.getPurchaseContractNumber()); } return ticketRegistrationMapper.selectList(queryWrapper); } @Override public int addOrUpdateRegistration(TicketRegistrationDto ticketRegistrationDto) { public int addOrUpdateRegistration(TicketRegistrationDto ticketRegistrationDto) throws IOException { PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(ticketRegistrationDto.getPurchaseLedgerId()); SysUser sysUser = userMapper.selectUserById(ticketRegistrationDto.getBusinessPersonId()); TicketRegistration ticketRegistration = new TicketRegistration(); BeanUtils.copyProperties(ticketRegistrationDto, ticketRegistration); ticketRegistration.setPurchaseContractNumber(purchaseLedger.getPurchaseContractNumber()); ticketRegistration.setBusinessPerson(sysUser.getNickName()); ticketRegistration.setTenantId(purchaseLedger.getTenantId()); ticketRegistration.setContractAmount(purchaseLedger.getContractAmount()); // 处理子表数据 List<SalesLedgerProduct> productData = ticketRegistrationDto.getProductData(); List<SalesLedgerProduct> productData = ticketRegistrationDto.getProductData(); if (productData != null && !productData.isEmpty()) { handleSalesLedgerProducts(purchaseLedger.getId(), productData, 2); } // 执行插入或更新操作 int i; if (ticketRegistrationDto.getId() == null) { return ticketRegistrationMapper.insert(ticketRegistration); i = ticketRegistrationMapper.insert(ticketRegistration); } else { return ticketRegistrationMapper.updateById(ticketRegistration); i = ticketRegistrationMapper.updateById(ticketRegistration); } // 迁移临时文件到正式目录 if (ticketRegistrationDto.getTempFileIds() != null && !ticketRegistrationDto.getTempFileIds().isEmpty()) { migrateTempFilesToFormal(ticketRegistration.getId(), ticketRegistrationDto.getTempFileIds()); } return i; } /** * 将临时文件迁移到正式目录 * * @param businessId 业务ID(销售台账ID) * @param tempFileIds 临时文件ID列表 * @throws IOException 文件操作异常 */ private void migrateTempFilesToFormal(Long businessId, List<String> tempFileIds) throws IOException { if (CollectionUtils.isEmpty(tempFileIds)) { return; } // 构建正式目录路径(按业务类型和日期分组) String formalDir = uploadDir + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE); Path formalDirPath = Paths.get(formalDir); // 确保正式目录存在(递归创建) if (!Files.exists(formalDirPath)) { Files.createDirectories(formalDirPath); } for (String tempFileId : tempFileIds) { // 查询临时文件记录 TempFile tempFile = tempFileMapper.selectById(tempFileId); if (tempFile == null) { log.warn("临时文件不存在,跳过处理: {}", tempFileId); continue; } // 构建正式文件名(包含业务ID和时间戳,避免冲突) String originalFilename = tempFile.getOriginalName(); String fileExtension = FilenameUtils.getExtension(originalFilename); String formalFilename = businessId + "_" + System.currentTimeMillis() + "_" + UUID.randomUUID().toString().substring(0, 8) + (com.ruoyi.common.utils.StringUtils.hasText(fileExtension) ? "." + fileExtension : ""); Path formalFilePath = formalDirPath.resolve(formalFilename); try { // 执行文件迁移(使用原子操作确保安全性) Files.move( Paths.get(tempFile.getTempPath()), formalFilePath, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE ); log.info("文件迁移成功: {} -> {}", tempFile.getTempPath(), formalFilePath); // 更新文件记录(关联到业务ID) CommonFile fileRecord = new CommonFile(); fileRecord.setCommonId(businessId); fileRecord.setName(originalFilename); fileRecord.setUrl(formalFilePath.toString()); fileRecord.setCreateTime(LocalDateTime.now()); fileRecord.setType(tempFile.getType()); commonFileMapper.insert(fileRecord); log.info("文件迁移成功: {} -> {}", tempFile.getTempPath(), formalFilePath); } catch (IOException e) { log.error("文件迁移失败: {}", tempFile.getTempPath(), e); // 可选择回滚事务或记录失败文件 throw new IOException("文件迁移异常", e); } } } @Override public int delRegistration(Long[] ids) { @@ -84,14 +180,14 @@ public TicketRegistrationDto getRegistrationById(TicketRegistrationDto ticketRegistrationDto) { TicketRegistration ticketRegistration = ticketRegistrationMapper.selectById(ticketRegistrationDto.getId()); LambdaQueryWrapper<PurchaseLedger> purchaseQueryWrapper = new LambdaQueryWrapper<>(); purchaseQueryWrapper.eq(PurchaseLedger::getId,ticketRegistration.getPurchaseLedgerId()); purchaseQueryWrapper.eq(PurchaseLedger::getId, ticketRegistration.getPurchaseLedgerId()); PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectOne(purchaseQueryWrapper); if (ticketRegistration == null) { throw new BaseException("采购台账不存在"); } // 创建并填充DTO TicketRegistrationDto resultDto = new TicketRegistrationDto(); BeanUtils.copyProperties(ticketRegistration,resultDto); BeanUtils.copyProperties(ticketRegistration, resultDto); // 查询并设置关联产品 LambdaQueryWrapper<SalesLedgerProduct> queryWrapper = new LambdaQueryWrapper<>(); @@ -115,11 +211,13 @@ p.setSalesLedgerId(salesLedgerId); p.setType(type); }) .collect(Collectors.toList()); // Java 8 兼容写法 .collect(Collectors.toList()); // 批量更新(需要 MyBatis 提供批量更新方法) if (!updateList.isEmpty()) { updateList.forEach(product -> { product.setFutureTickets(product.getQuantity().subtract(new BigDecimal(product.getTicketsNum())).longValue()); product.setFutureTicketsAmount(product.getTaxExclusiveTotalPrice().subtract(product.getTicketsAmount())); product.setType(type); salesLedgerProductMapper.updateById(product); }); src/main/java/com/ruoyi/sales/controller/CommonFileController.java
@@ -11,6 +11,9 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.io.IOException; import java.util.List; @RestController @RequestMapping("/commonFile") @AllArgsConstructor @@ -29,4 +32,10 @@ } return toAjax(commonFileService.delCommonFileByIds(ids)); } public void migrateTempFilesToFormal(Long businessId, List<String> tempFileIds) throws IOException{ } } src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
@@ -1,7 +1,5 @@ package com.ruoyi.sales.pojo; import java.math.BigDecimal; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -9,6 +7,8 @@ import com.ruoyi.framework.aspectj.lang.annotation.Excel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.math.BigDecimal; /** * 产品信息对象 sales_ledger_product @@ -103,12 +103,12 @@ private BigDecimal ticketsAmount; /** * 未来开票数 * 未来票数 */ private Long futureTickets; /** * 未来开票金额(元) * 未来票金额(元) */ private BigDecimal futureTicketsAmount; @@ -131,4 +131,14 @@ @TableField(exist = false) @ApiModelProperty(value = "本次开票金额") private BigDecimal currentInvoiceAmount; /** * 产品id */ private Long productId; /** * 产品规格id */ private Long productModelId; } src/main/java/com/ruoyi/sales/service/impl/CommonFileServiceImpl.java
@@ -1,26 +1,40 @@ package com.ruoyi.sales.service.impl; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.other.mapper.TempFileMapper; import com.ruoyi.other.pojo.TempFile; import com.ruoyi.sales.mapper.CommonFileMapper; import com.ruoyi.sales.pojo.CommonFile; import com.ruoyi.sales.service.ICommonFileService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FilenameUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.List; import java.util.UUID; @Service @RequiredArgsConstructor @Slf4j public class CommonFileServiceImpl extends ServiceImpl<CommonFileMapper, CommonFile> implements ICommonFileService { private final CommonFileMapper commonFileMapper; private final TempFileMapper tempFileMapper; @Value("${file.upload-dir}") private String uploadDir; @@ -60,4 +74,73 @@ public int delCommonFileByIds(Long[] ids) { return commonFileMapper.deleteBatchIds(Arrays.asList(ids)); } /** * 将临时文件迁移到正式目录 * * @param businessId 业务ID(销售台账ID) * @param tempFileIds 临时文件ID列表 * @throws IOException 文件操作异常 */ @Transactional(rollbackFor = Exception.class) public void migrateTempFilesToFormal(Long businessId, List<String> tempFileIds) throws IOException { if (CollectionUtils.isEmpty(tempFileIds)) { return; } // 构建正式目录路径(按业务类型和日期分组) String formalDir = uploadDir + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE); Path formalDirPath = Paths.get(formalDir); // 确保正式目录存在(递归创建) if (!Files.exists(formalDirPath)) { Files.createDirectories(formalDirPath); } for (String tempFileId : tempFileIds) { // 查询临时文件记录 TempFile tempFile = tempFileMapper.selectById(tempFileId); if (tempFile == null) { log.warn("临时文件不存在,跳过处理: {}", tempFileId); continue; } // 构建正式文件名(包含业务ID和时间戳,避免冲突) String originalFilename = tempFile.getOriginalName(); String fileExtension = FilenameUtils.getExtension(originalFilename); String formalFilename = businessId + "_" + System.currentTimeMillis() + "_" + UUID.randomUUID().toString().substring(0, 8) + (com.ruoyi.common.utils.StringUtils.hasText(fileExtension) ? "." + fileExtension : ""); Path formalFilePath = formalDirPath.resolve(formalFilename); try { // 执行文件迁移(使用原子操作确保安全性) Files.move( Paths.get(tempFile.getTempPath()), formalFilePath, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE ); log.info("文件迁移成功: {} -> {}", tempFile.getTempPath(), formalFilePath); // 更新文件记录(关联到业务ID) CommonFile fileRecord = new CommonFile(); fileRecord.setCommonId(businessId); fileRecord.setName(originalFilename); fileRecord.setUrl(formalFilePath.toString()); fileRecord.setCreateTime(LocalDateTime.now()); fileRecord.setType(tempFile.getType()); commonFileMapper.insert(fileRecord); log.info("文件迁移成功: {} -> {}", tempFile.getTempPath(), formalFilePath); } catch (IOException e) { log.error("文件迁移失败: {}", tempFile.getTempPath(), e); // 可选择回滚事务或记录失败文件 throw new IOException("文件迁移异常", e); } } } }