| | |
| | | import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.account.pojo.AccountExpense; |
| | | import com.ruoyi.account.pojo.AccountIncome; |
| | | import com.ruoyi.account.service.AccountExpenseService; |
| | | import com.ruoyi.account.service.AccountIncomeService; |
| | | import com.ruoyi.approve.bean.dto.ApprovalInstanceDto; |
| | | import com.ruoyi.approve.mapper.ApprovalTemplateMapper; |
| | | import com.ruoyi.approve.pojo.ApprovalInstance; |
| | | import com.ruoyi.approve.pojo.ApprovalTemplate; |
| | | import com.ruoyi.approve.pojo.ApproveProcess; |
| | | import com.ruoyi.approve.service.ApprovalInstanceService; |
| | | import com.ruoyi.approve.service.impl.ApproveProcessServiceImpl; |
| | | import com.ruoyi.basic.enums.ApplicationTypeEnum; |
| | | import com.ruoyi.basic.enums.RecordTypeEnum; |
| | | 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.enums.FileNameType; |
| | | import com.ruoyi.basic.utils.FileUtil; |
| | | import com.ruoyi.common.exception.base.BaseException; |
| | | import com.ruoyi.common.enums.ApprovalStatusEnum; |
| | | import com.ruoyi.common.enums.ReviewStatusEnum; |
| | | import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum; |
| | | import com.ruoyi.common.utils.DateUtils; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.framework.security.LoginUser; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import com.ruoyi.framework.web.domain.R; |
| | | import com.ruoyi.other.mapper.TempFileMapper; |
| | | import com.ruoyi.other.pojo.TempFile; |
| | | import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper; |
| | | import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage; |
| | | import com.ruoyi.procurementrecord.utils.StockUtils; |
| | | import com.ruoyi.project.system.domain.SysUser; |
| | | import com.ruoyi.project.system.mapper.SysUserMapper; |
| | | import com.ruoyi.purchase.dto.PurchaseLedgerDto; |
| | | import com.ruoyi.purchase.mapper.PaymentRegistrationMapper; |
| | | import com.ruoyi.purchase.mapper.ProductRecordMapper; |
| | | import com.ruoyi.purchase.dto.PurchaseLedgerImportDto; |
| | | import com.ruoyi.purchase.dto.PurchaseLedgerProductImportDto; |
| | | import com.ruoyi.purchase.mapper.PurchaseLedgerMapper; |
| | | import com.ruoyi.purchase.mapper.TicketRegistrationMapper; |
| | | import com.ruoyi.purchase.pojo.PaymentRegistration; |
| | | import com.ruoyi.purchase.pojo.ProductRecord; |
| | | import com.ruoyi.purchase.pojo.PurchaseLedger; |
| | | import com.ruoyi.purchase.pojo.TicketRegistration; |
| | | import com.ruoyi.purchase.service.IPurchaseLedgerService; |
| | | import com.ruoyi.quality.mapper.QualityInspectMapper; |
| | | import com.ruoyi.quality.mapper.QualityInspectParamMapper; |
| | |
| | | import com.ruoyi.quality.pojo.QualityInspectParam; |
| | | import com.ruoyi.quality.pojo.QualityTestStandard; |
| | | import com.ruoyi.quality.pojo.QualityTestStandardParam; |
| | | import com.ruoyi.sales.mapper.*; |
| | | import com.ruoyi.sales.pojo.CommonFile; |
| | | import com.ruoyi.sales.pojo.InvoiceRegistrationProduct; |
| | | import com.ruoyi.quality.service.IQualityInspectService; |
| | | import com.ruoyi.sales.mapper.CommonFileMapper; |
| | | import com.ruoyi.sales.mapper.SalesLedgerMapper; |
| | | import com.ruoyi.sales.mapper.SalesLedgerProductMapper; |
| | | import com.ruoyi.sales.pojo.SalesLedger; |
| | | import com.ruoyi.sales.pojo.SalesLedgerProduct; |
| | | import com.ruoyi.sales.service.impl.CommonFileServiceImpl; |
| | | import com.ruoyi.stock.pojo.StockInRecord; |
| | | import com.ruoyi.stock.service.StockInRecordService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.io.FilenameUtils; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.data.redis.core.StringRedisTemplate; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | 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.math.RoundingMode; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.ZoneId; |
| | |
| | | * @date 2025-05-09 |
| | | */ |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | @Slf4j |
| | | @RequiredArgsConstructor |
| | | public class PurchaseLedgerServiceImpl extends ServiceImpl<PurchaseLedgerMapper, PurchaseLedger> implements IPurchaseLedgerService { |
| | | private final AccountExpenseService accountExpenseService; |
| | | private final PurchaseLedgerMapper purchaseLedgerMapper; |
| | | |
| | | private final PurchaseLedgerMapper purchaseLedgerMapper; |
| | | private final SalesLedgerMapper salesLedgerMapper; |
| | | private final SalesLedgerProductMapper salesLedgerProductMapper; |
| | | |
| | | private final SysUserMapper userMapper; |
| | | |
| | | private final TempFileMapper tempFileMapper; |
| | | |
| | | private final CommonFileMapper commonFileMapper; |
| | | |
| | | private final SupplierManageMapper supplierManageMapper; |
| | | |
| | | private final ProductMapper productMapper; |
| | | |
| | | private final ProductModelMapper productModelMapper; |
| | | |
| | | private final TicketRegistrationMapper ticketRegistrationMapper; |
| | | |
| | | private final ProductRecordMapper productRecordMapper; |
| | | |
| | | private final PaymentRegistrationMapper paymentRegistrationMapper; |
| | | |
| | | private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper; |
| | | |
| | | private final SysUserMapper sysUserMapper; |
| | | private final StringRedisTemplate redisTemplate; |
| | | private final QualityInspectMapper qualityInspectMapper; |
| | | private final QualityTestStandardMapper qualityTestStandardMapper; |
| | | private final CommonFileServiceImpl commonFileService; |
| | | private final QualityTestStandardParamMapper qualityTestStandardParamMapper; |
| | | private final QualityTestStandardMapper qualityTestStandardMapper; |
| | | private final QualityInspectParamMapper qualityInspectParamMapper; |
| | | |
| | | @Value("${file.upload-dir}") |
| | | private String uploadDir; |
| | | private final ApproveProcessServiceImpl approveProcessService; |
| | | private final ProcurementRecordMapper procurementRecordStorageMapper; |
| | | private final FileUtil fileUtil; |
| | | private final ApprovalInstanceService approvalInstanceService; |
| | | private final IQualityInspectService qualityInspectService; |
| | | private final StockInRecordService stockInRecordService; |
| | | private final StockUtils stockUtils; |
| | | private final ApprovalTemplateMapper approvalTemplateMapper; |
| | | |
| | | @Override |
| | | public List<PurchaseLedger> selectPurchaseLedgerList(PurchaseLedger purchaseLedger) { |
| | |
| | | if (StringUtils.isNotBlank(purchaseLedger.getPurchaseContractNumber())) { |
| | | queryWrapper.like(PurchaseLedger::getPurchaseContractNumber, purchaseLedger.getPurchaseContractNumber()); |
| | | } |
| | | if(purchaseLedger.getSupplierId()!=null){ |
| | | queryWrapper.eq(PurchaseLedger::getSupplierId, purchaseLedger.getSupplierId()); |
| | | } |
| | | if (purchaseLedger.getApprovalStatus() != null) { |
| | | queryWrapper.eq(PurchaseLedger::getApprovalStatus, purchaseLedger.getApprovalStatus()); |
| | | } |
| | | return purchaseLedgerMapper.selectList(queryWrapper); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int addPurchaseTemplate(PurchaseLedgerDto purchaseLedgerDto)throws IOException { |
| | | //录入人 |
| | | SysUser sysUser = userMapper.selectUserById(purchaseLedgerDto.getRecorderId()); |
| | | |
| | | SupplierManage supplierManage = supplierManageMapper.selectById(purchaseLedgerDto.getSupplierId()); |
| | | public int addOrEditPurchase(PurchaseLedgerDto purchaseLedgerDto) throws Exception { |
| | | PurchaseLedger purchaseLedger = new PurchaseLedger(); |
| | | // BeanUtils.copyProperties(purchaseLedger,purchaseLedgerDto); |
| | | LoginUser loginUser = SecurityUtils.getLoginUser(); |
| | | if(ObjectUtils.isNotEmpty(loginUser) && null != loginUser.getTenantId()) { |
| | | purchaseLedger.setTenantId(loginUser.getTenantId()); |
| | | } |
| | | purchaseLedger.setPaymentMethod(purchaseLedgerDto.getPaymentMethod()); |
| | | purchaseLedger.setRecorderId(purchaseLedgerDto.getRecorderId()); |
| | | purchaseLedger.setSupplierId(purchaseLedgerDto.getSupplierId()); |
| | | purchaseLedger.setTemplateName(purchaseLedgerDto.getTemplateName()); |
| | | // purchaseLedger.setSalesLedgerPId(purchaseLedgerDto.getSalesLedgerId()); |
| | | purchaseLedger.setApprovalStatus(3); |
| | | purchaseLedger.setSupplierName(supplierManage.getSupplierName()); |
| | | purchaseLedger.setRecorderName(sysUser.getNickName()); |
| | | purchaseLedger.setPhoneNumber(sysUser.getPhonenumber()); |
| | | purchaseLedger.setPurchaseContractNumber(UUID.randomUUID().toString().replaceAll("-", "")); |
| | | purchaseLedger.setEntryDate(Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant())); |
| | | int insert = purchaseLedgerMapper.insert(purchaseLedger); |
| | | |
| | | LambdaQueryWrapper<PurchaseLedger> queryWrapper = new LambdaQueryWrapper<>(); |
| | | queryWrapper.eq(PurchaseLedger::getSupplierName, purchaseLedger.getSupplierName()) |
| | | .eq(PurchaseLedger::getPurchaseContractNumber, purchaseLedger.getPurchaseContractNumber()) |
| | | .eq(PurchaseLedger::getApprovalStatus,3); |
| | | PurchaseLedger purchaseLedger1 = purchaseLedgerMapper.selectOne(queryWrapper); |
| | | |
| | | if(ObjectUtils.isNotEmpty(purchaseLedgerDto.getProductData())) { |
| | | // 4. 处理子表数据 |
| | | List<SalesLedgerProduct> salesLedgerProductList = purchaseLedgerDto.getProductData(); |
| | | salesLedgerProductList.forEach(salesLedgerProduct -> { |
| | | salesLedgerProduct.setSalesLedgerId(purchaseLedger1.getId()); |
| | | salesLedgerProduct.setType(2); |
| | | }); |
| | | salesLedgerProductList.forEach(salesLedgerProductMapper::insert); |
| | | } |
| | | return insert; |
| | | } |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int addOrEditPurchase(PurchaseLedgerDto purchaseLedgerDto) throws IOException { |
| | | |
| | | // DTO转Entity |
| | | BeanUtils.copyProperties(purchaseLedgerDto, purchaseLedger); |
| | | SalesLedger salesLedger = salesLedgerMapper.selectById(purchaseLedgerDto.getSalesLedgerId()); |
| | | //录入人 |
| | | SysUser sysUser = userMapper.selectUserById(purchaseLedgerDto.getRecorderId()); |
| | | if (ObjectUtils.isNotEmpty(sysUser)) { |
| | | purchaseLedger.setRecorderName(sysUser.getNickName()); |
| | | purchaseLedger.setPhoneNumber(sysUser.getPhonenumber()); |
| | | }else { |
| | | purchaseLedger.setRecorderName(SecurityUtils.getLoginUser().getNickName()); |
| | | SysUser sysUser1 = userMapper.selectUserById(SecurityUtils.getUserId()); |
| | | purchaseLedger.setPhoneNumber(sysUser1.getPhonenumber()); |
| | | } |
| | | |
| | | SupplierManage supplierManage = supplierManageMapper.selectById(purchaseLedgerDto.getSupplierId()); |
| | | |
| | | // DTO转Entity |
| | | PurchaseLedger purchaseLedger = new PurchaseLedger(); |
| | | BeanUtils.copyProperties(purchaseLedgerDto, purchaseLedger); |
| | | LoginUser loginUser = SecurityUtils.getLoginUser(); |
| | | if (ObjectUtils.isNotEmpty(loginUser) && null != loginUser.getTenantId()) { |
| | | purchaseLedger.setTenantId(loginUser.getTenantId()); |
| | |
| | | purchaseLedger.setSalesLedgerId(ObjectUtils.isNotEmpty(salesLedger) ? salesLedger.getId() : -1); |
| | | purchaseLedger.setSupplierName(supplierManage.getSupplierName()); |
| | | purchaseLedger.setRecorderId(purchaseLedgerDto.getRecorderId()); |
| | | purchaseLedger.setRecorderName(sysUser.getNickName()); |
| | | purchaseLedger.setPhoneNumber(sysUser.getPhonenumber()); |
| | | // 2. 处理账户收入 |
| | | AccountExpense accountExpense = new AccountExpense(); |
| | | accountExpense.setExpenseDate(purchaseLedger.getEntryDate()); |
| | | accountExpense.setExpenseType("0"); |
| | | accountExpense.setSupplierName(purchaseLedger.getSupplierName()); |
| | | accountExpense.setExpenseMoney(purchaseLedger.getContractAmount()); |
| | | accountExpense.setExpenseDescribed("采购合同:" + purchaseLedger.getPurchaseContractNumber()); |
| | | accountExpense.setExpenseMethod("0"); |
| | | accountExpense.setInvoiceNumber(purchaseLedger.getPurchaseContractNumber()); |
| | | accountExpense.setInputTime(new Date()); |
| | | accountExpense.setInputUser(loginUser.getNickName()); |
| | | |
| | | |
| | | purchaseLedger.setApprovalStatus(1); |
| | | // 3. 新增或更新主表 |
| | | if (purchaseLedger.getId() == null) { |
| | | purchaseLedgerMapper.insert(purchaseLedger); |
| | | // accountIncomeService.save(accountIncome); |
| | | accountExpenseService.save(accountExpense); |
| | | } else { |
| | | purchaseLedgerMapper.updateById(purchaseLedger); |
| | | PurchaseLedger purchaseLedgerDB = purchaseLedgerMapper.selectById(purchaseLedger.getId()); |
| | | List<AccountExpense> accountExpenseDBs = accountExpenseService.getByInvoiceNumberList(purchaseLedger.getPurchaseContractNumber()); |
| | | if (!CollectionUtils.isEmpty(accountExpenseDBs)) { |
| | | accountExpenseDBs.forEach(accountExpenseDB ->{ |
| | | accountExpenseDB.setExpenseDate(purchaseLedgerDB.getEntryDate()); |
| | | accountExpenseDB.setExpenseType("0"); |
| | | accountExpenseDB.setSupplierName(purchaseLedgerDB.getSupplierName()); |
| | | accountExpenseDB.setExpenseMoney(purchaseLedgerDB.getContractAmount()); |
| | | accountExpenseDB.setExpenseDescribed("采购合同:" + purchaseLedgerDB.getPurchaseContractNumber()); |
| | | accountExpenseDB.setExpenseMethod("0"); |
| | | accountExpenseDB.setInvoiceNumber(purchaseLedgerDB.getPurchaseContractNumber()); |
| | | accountExpenseService.updateById(accountExpenseDB); |
| | | }); |
| | | // 删除采购审核,重新提交 |
| | | ApproveProcess one = approveProcessService.getOne(new LambdaQueryWrapper<ApproveProcess>() |
| | | .eq(ApproveProcess::getApproveType, 5) |
| | | .eq(ApproveProcess::getApproveReason, purchaseLedger.getPurchaseContractNumber()) |
| | | .eq(ApproveProcess::getApproveDelete, 0) |
| | | .last("limit 1")); |
| | | if (one != null) { |
| | | approveProcessService.delByIds(Collections.singletonList(one.getId())); |
| | | } |
| | | |
| | | purchaseLedgerMapper.updateById(purchaseLedger); |
| | | } |
| | | |
| | | // 4. 处理子表数据 |
| | |
| | | if (productList != null && !productList.isEmpty()) { |
| | | handleSalesLedgerProducts(purchaseLedger.getId(), productList, purchaseLedgerDto.getType()); |
| | | } |
| | | //新增原材料检验 |
| | | for (SalesLedgerProduct saleProduct : productList) { |
| | | QualityInspect qualityInspect = new QualityInspect(); |
| | | qualityInspect.setInspectType(0); |
| | | qualityInspect.setSupplier(purchaseLedger.getSupplierName()); |
| | | qualityInspect.setPurchaseLedgerId(purchaseLedger.getId()); |
| | | qualityInspect.setProductId(saleProduct.getId()); |
| | | qualityInspect.setProductName(saleProduct.getProductCategory()); |
| | | qualityInspect.setModel(saleProduct.getSpecificationModel()); |
| | | qualityInspect.setUnit(saleProduct.getUnit()); |
| | | qualityInspect.setQuantity(saleProduct.getQuantity()); |
| | | qualityInspectMapper.insert(qualityInspect); |
| | | // 6.采购审核新增;审批管理未配置采购审批人时,审批服务会自动置为审批通过。 |
| | | addApproveByPurchase(loginUser, purchaseLedger); |
| | | // 5. 迁移临时文件到正式目录 |
| | | fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.PURCHASE_LEDGER, purchaseLedger.getId(), purchaseLedgerDto.getStorageBlobDTOS()); |
| | | return 1; |
| | | } |
| | | |
| | | List<QualityTestStandardParam> qualityTestStandardParams = qualityTestStandardParamMapper.selectListByProductId(saleProduct.getProductId()); |
| | | if (qualityTestStandardParams.size()>0) { |
| | | qualityTestStandardParams.forEach(standard -> { |
| | | QualityInspectParam param = new QualityInspectParam(); |
| | | com.ruoyi.common.utils.bean.BeanUtils.copyProperties(standard, param); |
| | | param.setId(null); |
| | | param.setInspectId(qualityInspect.getId()); |
| | | qualityInspectParamMapper.insert(param); |
| | | }); |
| | | @Override |
| | | public R batchInsertPurchaseSteps(List<Long> ids) { |
| | | if (CollectionUtils.isEmpty(ids)) { |
| | | return R.fail("请选择采购台账"); |
| | | } |
| | | |
| | | List<Long> distinctIds = ids.stream() |
| | | .filter(Objects::nonNull) |
| | | .distinct() |
| | | .collect(Collectors.toList()); |
| | | if (CollectionUtils.isEmpty(distinctIds)) { |
| | | return R.fail("请选择采购台账"); |
| | | } |
| | | |
| | | PurchaseLedgerDto queryDto = new PurchaseLedgerDto(); |
| | | queryDto.setIds(distinctIds); |
| | | IPage<PurchaseLedgerDto> pageResult = this.selectPurchaseLedgerListPage( |
| | | new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(1, distinctIds.size()), |
| | | queryDto |
| | | ); |
| | | List<PurchaseLedgerDto> ledgerDtos = pageResult == null || pageResult.getRecords() == null |
| | | ? Collections.emptyList() |
| | | : pageResult.getRecords(); |
| | | |
| | | Map<Long, PurchaseLedgerDto> ledgerDtoMap = ledgerDtos.stream() |
| | | .filter(item -> item.getId() != null) |
| | | .collect(Collectors.toMap(PurchaseLedgerDto::getId, item -> item, (left, right) -> left, LinkedHashMap::new)); |
| | | |
| | | List<Map<String, Object>> details = new ArrayList<>(); |
| | | int successCount = 0; |
| | | int skipCount = 0; |
| | | int failCount = 0; |
| | | int autoApprovedCount = 0; |
| | | |
| | | for (Long id : distinctIds) { |
| | | Map<String, Object> detail = new LinkedHashMap<>(); |
| | | detail.put("purchaseLedgerId", id); |
| | | PurchaseLedgerDto purchaseLedgerDto = ledgerDtoMap.get(id); |
| | | if (purchaseLedgerDto == null) { |
| | | failCount++; |
| | | detail.put("status", "FAIL"); |
| | | detail.put("message", "采购台账不存在或未查询到"); |
| | | details.add(detail); |
| | | continue; |
| | | } |
| | | |
| | | detail.put("purchaseContractNumber", purchaseLedgerDto.getPurchaseContractNumber()); |
| | | detail.put("approvalStatus", purchaseLedgerDto.getApprovalStatus()); |
| | | detail.put("stockInStatus", purchaseLedgerDto.getStockInStatus()); |
| | | |
| | | if (ApprovalStatusEnum.REJECTED.getCode().equals(purchaseLedgerDto.getApprovalStatus())) { |
| | | skipCount++; |
| | | detail.put("status", "SKIP"); |
| | | detail.put("message", "采购单已驳回"); |
| | | details.add(detail); |
| | | continue; |
| | | } |
| | | |
| | | if ("完全入库".equals(purchaseLedgerDto.getStockInStatus())) { |
| | | skipCount++; |
| | | detail.put("status", "SKIP"); |
| | | detail.put("message", "采购单已完全入库"); |
| | | details.add(detail); |
| | | continue; |
| | | } |
| | | |
| | | try { |
| | | PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(id); |
| | | if (purchaseLedger == null) { |
| | | failCount++; |
| | | detail.put("status", "FAIL"); |
| | | detail.put("message", "采购台账不存在"); |
| | | details.add(detail); |
| | | continue; |
| | | } |
| | | |
| | | if (!ApprovalStatusEnum.APPROVED.getCode().equals(purchaseLedger.getApprovalStatus())) { |
| | | ApprovalInstance approvalInstance = approvalInstanceService.getOne( |
| | | Wrappers.<ApprovalInstance>lambdaQuery() |
| | | .eq(ApprovalInstance::getBusinessId, purchaseLedger.getId()) |
| | | .eq(ApprovalInstance::getBusinessType, 5L) |
| | | .eq(ApprovalInstance::getDeleted, 0) |
| | | .orderByDesc(ApprovalInstance::getId) |
| | | .last("limit 1") |
| | | ); |
| | | if (approvalInstance == null) { |
| | | failCount++; |
| | | detail.put("status", "FAIL"); |
| | | detail.put("message", "未找到对应的采购审批实例"); |
| | | details.add(detail); |
| | | continue; |
| | | } |
| | | |
| | | if ("APPROVED".equals(approvalInstance.getStatus()) |
| | | && !ApprovalStatusEnum.APPROVED.getCode().equals(purchaseLedger.getApprovalStatus())) { |
| | | purchaseLedger.setApprovalStatus(ApprovalStatusEnum.APPROVED.getCode()); |
| | | purchaseLedgerMapper.updateById(purchaseLedger); |
| | | } else if (!"APPROVED".equals(approvalInstance.getStatus())) { |
| | | R autoApproveResult = approvalInstanceService.autoApprove(approvalInstance.getId()); |
| | | if (autoApproveResult == null || !R.isSuccess(autoApproveResult)) { |
| | | failCount++; |
| | | detail.put("status", "FAIL"); |
| | | detail.put("message", autoApproveResult == null ? "采购审批自动通过失败" : autoApproveResult.getMsg()); |
| | | details.add(detail); |
| | | continue; |
| | | } |
| | | autoApprovedCount++; |
| | | } |
| | | |
| | | purchaseLedger = purchaseLedgerMapper.selectById(id); |
| | | if (purchaseLedger == null || !ApprovalStatusEnum.APPROVED.getCode().equals(purchaseLedger.getApprovalStatus())) { |
| | | failCount++; |
| | | detail.put("status", "FAIL"); |
| | | detail.put("message", "采购单审批状态未更新为已通过"); |
| | | details.add(detail); |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList( |
| | | Wrappers.<SalesLedgerProduct>lambdaQuery() |
| | | .eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedger.getId()) |
| | | .eq(SalesLedgerProduct::getType, 2) |
| | | .orderByAsc(SalesLedgerProduct::getId) |
| | | ); |
| | | if (CollectionUtils.isEmpty(products)) { |
| | | skipCount++; |
| | | detail.put("status", "SKIP"); |
| | | detail.put("message", "采购单没有产品明细"); |
| | | details.add(detail); |
| | | continue; |
| | | } |
| | | |
| | | int processedProductCount = 0; |
| | | int skippedProductCount = 0; |
| | | int failedProductCount = 0; |
| | | for (SalesLedgerProduct product : products) { |
| | | try { |
| | | boolean processed; |
| | | if (Boolean.TRUE.equals(product.getIsChecked())) { |
| | | processed = processPurchaseQualityProduct(purchaseLedger, product); |
| | | } else { |
| | | processed = processPurchaseDirectProduct(purchaseLedger, product); |
| | | } |
| | | if (processed) { |
| | | processedProductCount++; |
| | | } else { |
| | | skippedProductCount++; |
| | | } |
| | | } catch (Exception ex) { |
| | | failedProductCount++; |
| | | log.error("批量推进采购台账失败, purchaseLedgerId={}, productId={}, productModelId={}", |
| | | purchaseLedger.getId(), product.getId(), product.getProductModelId(), ex); |
| | | } |
| | | } |
| | | |
| | | successCount++; |
| | | detail.put("status", failedProductCount > 0 ? "PARTIAL" : "SUCCESS"); |
| | | detail.put("processedProductCount", processedProductCount); |
| | | detail.put("skippedProductCount", skippedProductCount); |
| | | detail.put("failedProductCount", failedProductCount); |
| | | detail.put("message", failedProductCount > 0 ? "部分产品处理失败" : "处理完成"); |
| | | details.add(detail); |
| | | } catch (Exception ex) { |
| | | failCount++; |
| | | detail.put("status", "FAIL"); |
| | | detail.put("message", ex.getMessage()); |
| | | details.add(detail); |
| | | log.error("批量推进采购台账失败, purchaseLedgerId={}", id, ex); |
| | | } |
| | | } |
| | | |
| | | // 5. 迁移临时文件到正式目录 |
| | | if (purchaseLedgerDto.getTempFileIds() != null && !purchaseLedgerDto.getTempFileIds().isEmpty()) { |
| | | migrateTempFilesToFormal(purchaseLedger.getId(), purchaseLedgerDto.getTempFileIds()); |
| | | Map<String, Object> summary = new LinkedHashMap<>(); |
| | | summary.put("totalCount", distinctIds.size()); |
| | | summary.put("successCount", successCount); |
| | | summary.put("skipCount", skipCount); |
| | | summary.put("failCount", failCount); |
| | | summary.put("autoApprovedCount", autoApprovedCount); |
| | | summary.put("details", details); |
| | | return R.ok(summary, "批量推进采购步骤完成"); |
| | | } |
| | | |
| | | |
| | | public void addQualityInspect(PurchaseLedger purchaseLedger, SalesLedgerProduct saleProduct) { |
| | | QualityInspect qualityInspect = new QualityInspect(); |
| | | qualityInspect.setInspectType(0); |
| | | qualityInspect.setSupplier(purchaseLedger.getSupplierName()); |
| | | qualityInspect.setPurchaseLedgerId(purchaseLedger.getId()); |
| | | qualityInspect.setProductId(saleProduct.getProductId()); |
| | | qualityInspect.setProductName(saleProduct.getProductCategory()); |
| | | qualityInspect.setModel(saleProduct.getSpecificationModel()); |
| | | qualityInspect.setProductModelId(saleProduct.getProductModelId()); |
| | | qualityInspect.setUnit(saleProduct.getUnit()); |
| | | qualityInspect.setQuantity(saleProduct.getQuantity()); |
| | | qualityInspectMapper.insert(qualityInspect); |
| | | List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(saleProduct.getProductId(), 0,null); |
| | | if (qualityTestStandard.size()>0){ |
| | | qualityInspect.setTestStandardId(qualityTestStandard.get(0).getId()); |
| | | qualityInspectMapper.updateById(qualityInspect); |
| | | qualityTestStandardParamMapper.selectList(Wrappers.<QualityTestStandardParam>lambdaQuery() |
| | | .eq(QualityTestStandardParam::getTestStandardId,qualityTestStandard.get(0).getId())) |
| | | .forEach(qualityTestStandardParam -> { |
| | | QualityInspectParam param = new QualityInspectParam(); |
| | | com.ruoyi.common.utils.bean.BeanUtils.copyProperties(qualityTestStandardParam, param); |
| | | param.setId(null); |
| | | param.setInspectId(qualityInspect.getId()); |
| | | qualityInspectParamMapper.insert(param); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | private boolean processPurchaseQualityProduct(PurchaseLedger purchaseLedger, SalesLedgerProduct product) { |
| | | if (purchaseLedger == null || product == null || product.getProductModelId() == null) { |
| | | return false; |
| | | } |
| | | |
| | | return 1; |
| | | QualityInspect qualityInspect = findLatestPurchaseQualityInspect(purchaseLedger.getId(), product.getProductModelId()); |
| | | if (qualityInspect == null) { |
| | | addQualityInspect(purchaseLedger, product); |
| | | qualityInspect = findLatestPurchaseQualityInspect(purchaseLedger.getId(), product.getProductModelId()); |
| | | } |
| | | if (qualityInspect == null) { |
| | | return false; |
| | | } |
| | | |
| | | LocalDateTime purchaseInspectTime = toStartOfDayPlusDays(purchaseLedger.getEntryDate(), 1); |
| | | if (purchaseInspectTime != null && (qualityInspect.getCheckTime() == null |
| | | || !DateUtils.toLocalDate(qualityInspect.getCheckTime()).equals(purchaseInspectTime.toLocalDate()))) { |
| | | qualityInspect.setCheckTime(DateUtils.toDate(purchaseInspectTime.toLocalDate())); |
| | | qualityInspectMapper.updateById(qualityInspect); |
| | | } |
| | | |
| | | List<StockInRecord> stockRecords = findQualityStockRecords(qualityInspect.getId(), product.getProductModelId()); |
| | | if (hasApprovedStockRecord(stockRecords)) { |
| | | return true; |
| | | } |
| | | |
| | | if (!Integer.valueOf(1).equals(qualityInspect.getInspectState())) { |
| | | R autoSubmitResult = qualityInspectService.autoSubmit(qualityInspect.getId()); |
| | | if (autoSubmitResult == null || !R.isSuccess(autoSubmitResult)) { |
| | | return false; |
| | | } |
| | | qualityInspect = qualityInspectMapper.selectById(qualityInspect.getId()); |
| | | } |
| | | |
| | | stockRecords = findQualityStockRecords(qualityInspect.getId(), product.getProductModelId()); |
| | | if (CollectionUtils.isEmpty(stockRecords) |
| | | && qualityInspect.getQualifiedQuantity() != null |
| | | && qualityInspect.getQualifiedQuantity().compareTo(BigDecimal.ZERO) > 0) { |
| | | stockUtils.addStockWithBatchNo( |
| | | product.getProductModelId(), |
| | | qualityInspect.getQualifiedQuantity(), |
| | | StockInQualifiedRecordTypeEnum.CUSTOMIZATION_UNSTOCK_OUT.getCode(), |
| | | qualityInspect.getId(), |
| | | null, |
| | | purchaseInspectTime == null ? null : purchaseInspectTime.plusDays(1) |
| | | ); |
| | | stockRecords = findQualityStockRecords(qualityInspect.getId(), product.getProductModelId()); |
| | | } |
| | | |
| | | StockInRecord targetStockRecord = findLatestUnapprovedStockRecord(stockRecords); |
| | | if (targetStockRecord == null) { |
| | | return false; |
| | | } |
| | | |
| | | LocalDateTime qualityStockCreateTime = resolveQualityStockCreateTime(qualityInspect); |
| | | if (qualityStockCreateTime != null && (targetStockRecord.getCreateTime() == null |
| | | || !qualityStockCreateTime.equals(targetStockRecord.getCreateTime()))) { |
| | | targetStockRecord.setCreateTime(qualityStockCreateTime); |
| | | stockInRecordService.updateById(targetStockRecord); |
| | | } |
| | | |
| | | approveStockRecords(Collections.singletonList(targetStockRecord)); |
| | | stockRecords = findQualityStockRecords(qualityInspect.getId(), product.getProductModelId()); |
| | | return hasApprovedStockRecord(stockRecords); |
| | | } |
| | | |
| | | private boolean processPurchaseDirectProduct(PurchaseLedger purchaseLedger, SalesLedgerProduct product) { |
| | | if (purchaseLedger == null || product == null || product.getProductModelId() == null) { |
| | | return false; |
| | | } |
| | | if (product.getQuantity() == null) { |
| | | return false; |
| | | } |
| | | if (!StringUtils.hasText(purchaseLedger.getPurchaseContractNumber())) { |
| | | return false; |
| | | } |
| | | |
| | | LocalDateTime stockCreateTime = toStartOfDayPlusDays(purchaseLedger.getEntryDate(), 1); |
| | | |
| | | List<StockInRecord> stockRecords = findDirectStockRecords(purchaseLedger.getId(), purchaseLedger.getPurchaseContractNumber(), product.getProductModelId(), product.getId()); |
| | | if (hasApprovedStockRecord(stockRecords)) { |
| | | return true; |
| | | } |
| | | |
| | | if (CollectionUtils.isEmpty(stockRecords)) { |
| | | stockUtils.addStockWithBatchNo( |
| | | product.getProductModelId(), |
| | | product.getQuantity(), |
| | | StockInQualifiedRecordTypeEnum.PURCHASE_STOCK_IN.getCode(), |
| | | purchaseLedger.getId(), |
| | | purchaseLedger.getPurchaseContractNumber() + "-" + product.getId(), |
| | | stockCreateTime |
| | | ); |
| | | stockRecords = findDirectStockRecords(purchaseLedger.getId(), purchaseLedger.getPurchaseContractNumber(), product.getProductModelId(), product.getId()); |
| | | } |
| | | |
| | | if (CollectionUtils.isEmpty(stockRecords)) { |
| | | return false; |
| | | } |
| | | |
| | | StockInRecord targetStockRecord = findLatestUnapprovedStockRecord(stockRecords); |
| | | if (targetStockRecord == null) { |
| | | return false; |
| | | } |
| | | |
| | | if (stockCreateTime != null && (targetStockRecord.getCreateTime() == null |
| | | || !stockCreateTime.equals(targetStockRecord.getCreateTime()))) { |
| | | targetStockRecord.setCreateTime(stockCreateTime); |
| | | stockInRecordService.updateById(targetStockRecord); |
| | | } |
| | | |
| | | approveStockRecords(Collections.singletonList(targetStockRecord)); |
| | | stockRecords = findDirectStockRecords(purchaseLedger.getId(), purchaseLedger.getPurchaseContractNumber(), product.getProductModelId(), product.getId()); |
| | | return hasApprovedStockRecord(stockRecords); |
| | | } |
| | | |
| | | private LocalDateTime toStartOfDayPlusDays(Date date, int days) { |
| | | if (date == null) { |
| | | return null; |
| | | } |
| | | return DateUtils.toLocalDate(date).plusDays(days).atStartOfDay(); |
| | | } |
| | | |
| | | private LocalDateTime resolveQualityStockCreateTime(QualityInspect qualityInspect) { |
| | | if (qualityInspect == null || qualityInspect.getCheckTime() == null) { |
| | | return null; |
| | | } |
| | | return DateUtils.toLocalDate(qualityInspect.getCheckTime()).plusDays(1).atStartOfDay(); |
| | | } |
| | | |
| | | private QualityInspect findLatestPurchaseQualityInspect(Long purchaseLedgerId, Long productModelId) { |
| | | if (purchaseLedgerId == null || productModelId == null) { |
| | | return null; |
| | | } |
| | | return qualityInspectMapper.selectOne( |
| | | Wrappers.<QualityInspect>lambdaQuery() |
| | | .eq(QualityInspect::getInspectType, 0) |
| | | .eq(QualityInspect::getPurchaseLedgerId, purchaseLedgerId) |
| | | .eq(QualityInspect::getProductModelId, productModelId) |
| | | .orderByDesc(QualityInspect::getId) |
| | | .last("limit 1") |
| | | ); |
| | | } |
| | | |
| | | private List<StockInRecord> findQualityStockRecords(Long qualityInspectId, Long productModelId) { |
| | | if (qualityInspectId == null || productModelId == null) { |
| | | return Collections.emptyList(); |
| | | } |
| | | return stockInRecordService.list( |
| | | Wrappers.<StockInRecord>lambdaQuery() |
| | | .eq(StockInRecord::getRecordType, StockInQualifiedRecordTypeEnum.CUSTOMIZATION_UNSTOCK_OUT.getCode()) |
| | | .eq(StockInRecord::getRecordId, qualityInspectId) |
| | | .eq(StockInRecord::getProductModelId, productModelId) |
| | | .orderByDesc(StockInRecord::getId) |
| | | ); |
| | | } |
| | | |
| | | private List<StockInRecord> findDirectStockRecords(Long purchaseLedgerId, String purchaseContractNumber, Long productModelId, Long purchaseProductId) { |
| | | if (purchaseLedgerId == null || productModelId == null || purchaseProductId == null || !StringUtils.hasText(purchaseContractNumber)) { |
| | | return Collections.emptyList(); |
| | | } |
| | | String batchNo = purchaseContractNumber + "-" + purchaseProductId; |
| | | return stockInRecordService.list( |
| | | Wrappers.<StockInRecord>lambdaQuery() |
| | | .eq(StockInRecord::getRecordType, StockInQualifiedRecordTypeEnum.PURCHASE_STOCK_IN.getCode()) |
| | | .eq(StockInRecord::getRecordId, purchaseLedgerId) |
| | | .eq(StockInRecord::getProductModelId, productModelId) |
| | | .eq(StockInRecord::getBatchNo, batchNo) |
| | | .orderByDesc(StockInRecord::getId) |
| | | ); |
| | | } |
| | | |
| | | private boolean hasApprovedStockRecord(List<StockInRecord> stockRecords) { |
| | | return stockRecords != null && stockRecords.stream() |
| | | .anyMatch(item -> ReviewStatusEnum.APPROVED.getCode().equals(item.getApprovalStatus())); |
| | | } |
| | | |
| | | private StockInRecord findLatestUnapprovedStockRecord(List<StockInRecord> stockRecords) { |
| | | if (CollectionUtils.isEmpty(stockRecords)) { |
| | | return null; |
| | | } |
| | | return stockRecords.stream() |
| | | .filter(item -> !ReviewStatusEnum.APPROVED.getCode().equals(item.getApprovalStatus())) |
| | | .findFirst() |
| | | .orElse(null); |
| | | } |
| | | |
| | | private void approveStockRecords(List<StockInRecord> stockRecords) { |
| | | if (CollectionUtils.isEmpty(stockRecords)) { |
| | | return; |
| | | } |
| | | List<Long> rejectedIds = stockRecords.stream() |
| | | .filter(item -> ReviewStatusEnum.REJECTED.getCode().equals(item.getApprovalStatus())) |
| | | .map(StockInRecord::getId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toList()); |
| | | if (!rejectedIds.isEmpty()) { |
| | | stockInRecordService.batchReAudit(rejectedIds); |
| | | } |
| | | |
| | | List<Long> pendingIds = stockRecords.stream() |
| | | .filter(item -> item.getApprovalStatus() == null |
| | | || ReviewStatusEnum.PENDING_REVIEW.getCode().equals(item.getApprovalStatus()) |
| | | || ReviewStatusEnum.REJECTED.getCode().equals(item.getApprovalStatus())) |
| | | .map(StockInRecord::getId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toList()); |
| | | if (!pendingIds.isEmpty()) { |
| | | stockInRecordService.batchApprove(pendingIds, ReviewStatusEnum.APPROVED.getCode()); |
| | | } |
| | | } |
| | | |
| | | private void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, Integer type) { |
| | | if (products == null || products.isEmpty()) { |
| | | throw new BaseException("产品信息不存在"); |
| | | } |
| | | Integer ledgerType = type == null ? 2 : type; |
| | | |
| | | // 提前收集所有需要查询的ID |
| | | Set<Long> productIds = products.stream() |
| | |
| | | // 执行更新操作 |
| | | if (!updateList.isEmpty()) { |
| | | for (SalesLedgerProduct product : updateList) { |
| | | product.setType(type); |
| | | product.setType(ledgerType); |
| | | salesLedgerProductMapper.updateById(product); |
| | | } |
| | | } |
| | | // 执行插入操作 |
| | | if (!insertList.isEmpty()) { |
| | | for (SalesLedgerProduct salesLedgerProduct : insertList) { |
| | | salesLedgerProduct.setType(type); |
| | | salesLedgerProduct.setType(ledgerType); |
| | | Date entryDate = purchaseLedger.getEntryDate(); |
| | | |
| | | LocalDateTime localDateTime = entryDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); |
| | | salesLedgerProduct.setRegisterDate(localDateTime); |
| | | salesLedgerProduct.setInvoiceTotal(salesLedgerProduct.getTaxInclusiveTotalPrice()); |
| | | salesLedgerProductMapper.insert(salesLedgerProduct); |
| | | } |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 将临时文件迁移到正式目录 |
| | | * |
| | | * @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) + |
| | | (StringUtils.hasText(fileExtension) ? "." + fileExtension : ""); |
| | | |
| | | Path formalFilePath = formalDirPath.resolve(formalFilename); |
| | | |
| | | try { |
| | | // 执行文件迁移(使用原子操作确保安全性) |
| | | // Files.move( |
| | | // Paths.get(tempFile.getTempPath()), |
| | | // formalFilePath, |
| | | // StandardCopyOption.REPLACE_EXISTING, |
| | | // StandardCopyOption.ATOMIC_MOVE |
| | | // ); |
| | | // 原子移动失败,使用复制+删除 |
| | | Files.copy(Paths.get(tempFile.getTempPath()), formalFilePath, StandardCopyOption.REPLACE_EXISTING); |
| | | Files.deleteIfExists(Paths.get(tempFile.getTempPath())); |
| | | 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(FileNameType.PURCHASE.getValue()); |
| | | commonFileMapper.insert(fileRecord); |
| | | |
| | | // 删除临时文件记录 |
| | | tempFileMapper.deleteById(tempFile); |
| | | |
| | | log.info("文件迁移成功: {} -> {}", tempFile.getTempPath(), formalFilePath); |
| | | } catch (IOException e) { |
| | | log.error("文件迁移失败: {}", tempFile.getTempPath(), e); |
| | | // 可选择回滚事务或记录失败文件 |
| | | throw new IOException("文件迁移异常", e); |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public int deletePurchaseLedgerByIds(Long[] ids) { |
| | | if (ids == null || ids.length == 0) { |
| | | throw new BaseException("请选中至少一条数据"); |
| | | } |
| | | for (Long id : ids) { |
| | | PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(id); |
| | | if (purchaseLedger.getApprovalStatus().equals(3)) { |
| | | throw new BaseException(purchaseLedger.getPurchaseContractNumber()+"已经审批通过,不允许删除"); |
| | | } |
| | | } |
| | | // 批量删除关联的采购入库记录 |
| | | LambdaQueryWrapper<SalesLedgerProduct> salesLedgerProductQueryWrapper = new LambdaQueryWrapper<>(); |
| | | salesLedgerProductQueryWrapper.in(SalesLedgerProduct::getSalesLedgerId, ids) |
| | | .eq(SalesLedgerProduct::getType, 2); |
| | | List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(salesLedgerProductQueryWrapper); |
| | | if (CollectionUtils.isNotEmpty(salesLedgerProducts)) { |
| | | salesLedgerProducts.stream().forEach(salesLedgerProduct -> { |
| | | // 批量删除关联的采购台账产品 |
| | | LambdaQueryWrapper<ProcurementRecordStorage> queryWrapper = new LambdaQueryWrapper<>(); |
| | | queryWrapper.eq(ProcurementRecordStorage::getSalesLedgerProductId, salesLedgerProduct.getId()); |
| | | procurementRecordStorageMapper.delete(queryWrapper); |
| | | }); |
| | | } |
| | | // 批量删除关联的采购台账产品 |
| | | LambdaQueryWrapper<SalesLedgerProduct> queryWrapper = new LambdaQueryWrapper<>(); |
| | | queryWrapper.in(SalesLedgerProduct::getSalesLedgerId, ids) |
| | | .eq(SalesLedgerProduct::getType, 2); |
| | | salesLedgerProductMapper.delete(queryWrapper); |
| | | // 批量删除关联的采购台账的来票登记 |
| | | LambdaQueryWrapper<TicketRegistration> ticketRegistrationLambdaQueryWrapper = new LambdaQueryWrapper<>(); |
| | | ticketRegistrationLambdaQueryWrapper.in(TicketRegistration::getSalesLedgerId,ids); |
| | | ticketRegistrationMapper.delete(ticketRegistrationLambdaQueryWrapper); |
| | | // 批量删除关联的采购台账的来票登记记录 |
| | | LambdaQueryWrapper<ProductRecord> productRecordLambdaQueryWrapper = new LambdaQueryWrapper<>(); |
| | | productRecordLambdaQueryWrapper.in(ProductRecord::getPurchaseLedgerId,ids); |
| | | productRecordMapper.delete(productRecordLambdaQueryWrapper); |
| | | // 批量删除付款登记 |
| | | LambdaQueryWrapper<PaymentRegistration> paymentRegistrationLambdaQueryWrapper = new LambdaQueryWrapper<>(); |
| | | paymentRegistrationLambdaQueryWrapper.in(PaymentRegistration::getPurchaseLedgerId, ids); |
| | | paymentRegistrationMapper.delete(paymentRegistrationLambdaQueryWrapper); |
| | | //批量删除检验标准 |
| | | LambdaQueryWrapper<QualityInspect> materialInspectLambdaQueryWrapper = new LambdaQueryWrapper<>(); |
| | | materialInspectLambdaQueryWrapper.in(QualityInspect::getPurchaseLedgerId, ids); |
| | | |
| | | List<QualityInspect> qualityInspects = qualityInspectMapper.selectList(materialInspectLambdaQueryWrapper); |
| | | qualityInspects.stream().forEach(qualityInspect -> { |
| | | if (ObjectUtils.isNotEmpty(qualityInspect.getInspectState())&&qualityInspect.getInspectState().equals(1)) { |
| | | throw new BaseException("已提交的检验单不能删除"); |
| | | } |
| | | }); |
| | | List<Long> inspectIds = qualityInspects.stream() |
| | | .map(QualityInspect::getId) |
| | | .collect(Collectors.toList()); |
| | |
| | | qualityStandardLambdaQueryWrapper.in(QualityInspectParam::getInspectId, inspectIds); |
| | | qualityInspectParamMapper.delete(qualityStandardLambdaQueryWrapper); |
| | | } |
| | | |
| | | // 删除采购审批记录 |
| | | for (Long id : ids) { |
| | | PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(id); |
| | | if(purchaseLedger != null){ |
| | | ApproveProcess one = approveProcessService.getOne(new LambdaQueryWrapper<ApproveProcess>() |
| | | .eq(ApproveProcess::getApproveType, 5) |
| | | .eq(ApproveProcess::getApproveDelete, 0) |
| | | .eq(ApproveProcess::getApproveReason, purchaseLedger.getPurchaseContractNumber()) |
| | | .last("limit 1")); |
| | | if (one != null) { |
| | | approveProcessService.delByIds(Collections.singletonList(one.getId())); |
| | | } |
| | | } |
| | | } |
| | | //批量删除原材料检验数据 |
| | | qualityInspectMapper.delete(materialInspectLambdaQueryWrapper); |
| | | //删除附件 |
| | | commonFileService.deleteByBusinessIds(Arrays.asList(ids), 2); |
| | | // 批量删除采购台账 |
| | | return purchaseLedgerMapper.deleteBatchIds(Arrays.asList(ids)); |
| | | } |
| | |
| | | .eq(SalesLedgerProduct::getType, purchaseLedgerDto.getType()); |
| | | List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(productWrapper); |
| | | |
| | | // 3.查询上传文件 |
| | | LambdaQueryWrapper<CommonFile> salesLedgerFileWrapper = new LambdaQueryWrapper<>(); |
| | | salesLedgerFileWrapper.eq(CommonFile::getCommonId, purchaseLedger.getId()) |
| | | .eq(CommonFile::getType,FileNameType.PURCHASE.getValue()); |
| | | List<CommonFile> salesLedgerFiles = commonFileMapper.selectList(salesLedgerFileWrapper); |
| | | |
| | | // 4. 转换 DTO |
| | | PurchaseLedgerDto resultDto = new PurchaseLedgerDto(); |
| | |
| | | if (!products.isEmpty()) { |
| | | resultDto.setHasChildren(true); |
| | | resultDto.setProductData(products); |
| | | resultDto.setSalesLedgerFiles(salesLedgerFiles); |
| | | resultDto.setStorageBlobVOS(fileUtil.getStorageBlobVOsByApplicationAndRecordTypeAndRecordId(ApplicationTypeEnum.FILE, RecordTypeEnum.PURCHASE_LEDGER, purchaseLedger.getId())); |
| | | } |
| | | return resultDto; |
| | | } |
| | |
| | | queryWrapper.eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedger.getId()) |
| | | .eq(SalesLedgerProduct::getType, 2); |
| | | List<SalesLedgerProduct> productList = salesLedgerProductMapper.selectList(queryWrapper); |
| | | productList.forEach(product -> { |
| | | product.setFutureTickets(product.getFutureTickets() != null ? product.getFutureTickets() : product.getQuantity()); |
| | | product.setFutureTicketsAmount(product.getFutureTicketsAmount() != null ? product.getFutureTicketsAmount() : product.getTaxInclusiveTotalPrice()); |
| | | product.setTicketsNum(null); |
| | | product.setTicketsAmount(null); |
| | | product.setTempFutureTickets(product.getFutureTickets()); |
| | | product.setTempFutureTicketsAmount(product.getFutureTicketsAmount()); |
| | | }); |
| | | resultDto.setProductData(productList); |
| | | return resultDto; |
| | | } |
| | |
| | | PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(id); |
| | | |
| | | BeanUtils.copyProperties(purchaseLedger, purchaseLedgerDto); |
| | | // TicketRegistration ticketRegistration = ticketRegistrationMapper.selectOne(new LambdaQueryWrapper<TicketRegistration>().eq(TicketRegistration::getPurchaseLedgerId, id)); |
| | | // if (ticketRegistration != null) { |
| | | // purchaseLedgerDto.setInvoiceNumber(ticketRegistration.getInvoiceNumber()); |
| | | // purchaseLedgerDto.setInvoiceAmount(ticketRegistration.getInvoiceAmount()); |
| | | // purchaseLedgerDto.setTicketRegistrationId(ticketRegistration.getId()); |
| | | // } |
| | | return purchaseLedgerDto; |
| | | } |
| | | |
| | | @Override |
| | | public IPage<PurchaseLedgerDto> selectPurchaseLedgerListPage(IPage ipage, PurchaseLedgerDto purchaseLedger) { |
| | | IPage<PurchaseLedgerDto> purchaseLedgerDtoIPage = purchaseLedgerMapper.selectPurchaseLedgerListPage(ipage, purchaseLedger); |
| | | purchaseLedgerDtoIPage.getRecords().forEach(purchaseLedgerDto -> { |
| | | List<CommonFile> commonFiles = commonFileMapper.selectList(new LambdaQueryWrapper<CommonFile>().eq(CommonFile::getCommonId, purchaseLedgerDto.getId()).eq(CommonFile::getType, FileNameType.PURCHASE.getValue())); |
| | | purchaseLedgerDto.setSalesLedgerFiles(commonFiles); |
| | | }); |
| | | return purchaseLedgerDtoIPage; |
| | | return purchaseLedgerMapper.selectPurchaseLedgerListPage(ipage, purchaseLedger); |
| | | } |
| | | |
| | | @Override |
| | | public List<InvoiceRegistrationProduct> getProductBySalesNo(Long id) { |
| | | List<InvoiceRegistrationProduct> invoiceRegistrationProducts = invoiceRegistrationProductMapper.selectList(new LambdaQueryWrapper<InvoiceRegistrationProduct>() |
| | | .select(InvoiceRegistrationProduct::getId, InvoiceRegistrationProduct::getProductCategory, InvoiceRegistrationProduct::getSpecificationModel, |
| | | InvoiceRegistrationProduct::getUnit, InvoiceRegistrationProduct::getQuantity) |
| | | .eq(InvoiceRegistrationProduct::getSalesLedgerId, id)); |
| | | if (invoiceRegistrationProducts.isEmpty()) { |
| | | return new ArrayList<>(); |
| | | } |
| | | return invoiceRegistrationProducts; |
| | | } |
| | | |
| | | @Override |
| | | public String getPurchaseNo() { |
| | | public String getPurchaseNo(Date entryDate) { |
| | | LocalDate localDate = entryDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); |
| | | // 生成日期前缀(例如:CG20250405) |
| | | String purchaseNo = "CG" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")); |
| | | String purchaseNo = "CG" + localDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")); |
| | | |
| | | // 构建 Redis Key(按天分隔) |
| | | String redisKey = "purchase_no:" + LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE); |
| | | String redisKey = "purchase_no:" + localDate.format(DateTimeFormatter.ISO_LOCAL_DATE); |
| | | |
| | | // 获取当前序号并递增(原子操作) |
| | | Long sequence = redisTemplate.opsForValue().increment(redisKey); |
| | |
| | | return purchaseNo + String.format("%03d", sequence); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public AjaxResult importData(MultipartFile file) { |
| | | LoginUser loginUser = SecurityUtils.getLoginUser(); |
| | | try { |
| | | InputStream inputStream = file.getInputStream(); |
| | | ExcelUtil<PurchaseLedgerImportDto> salesLedgerImportDtoExcelUtil = new ExcelUtil<>(PurchaseLedgerImportDto.class); |
| | | Map<String, List<PurchaseLedgerImportDto>> stringListMap = salesLedgerImportDtoExcelUtil.importExcelMultiSheet(Arrays.asList("采购台账数据", "采购产品数据"), inputStream, 0); |
| | | if (CollectionUtils.isEmpty(stringListMap)) return AjaxResult.error("采购表格为空!"); |
| | | // 业务层合并 |
| | | List<PurchaseLedgerImportDto> salesLedgerImportDtoList = stringListMap.get("采购台账数据"); |
| | | if (CollectionUtils.isEmpty(salesLedgerImportDtoList)) return AjaxResult.error("采购台账数据为空!"); |
| | | List<PurchaseLedgerImportDto> salesLedgerProductImportDtoList = stringListMap.get("采购产品数据"); |
| | | if (CollectionUtils.isEmpty(salesLedgerProductImportDtoList)) return AjaxResult.error("采购产品数据为空!"); |
| | | // 供应商数据 |
| | | List<SupplierManage> customers = supplierManageMapper.selectList(new LambdaQueryWrapper<SupplierManage>().in(SupplierManage::getSupplierName, |
| | | salesLedgerImportDtoList.stream().map(PurchaseLedgerImportDto::getSupplierName).collect(Collectors.toList()))); |
| | | List<Map<String,Object>> list = productModelMapper.getProductAndModelList(); |
| | | // 录入人数据 |
| | | List<SysUser> sysUsers = sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>().in(SysUser::getNickName, |
| | | salesLedgerImportDtoList.stream().map(PurchaseLedgerImportDto::getRecorderName).collect(Collectors.toList()))); |
| | | for (PurchaseLedgerImportDto salesLedgerImportDto : salesLedgerImportDtoList) { |
| | | PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectOne(new LambdaQueryWrapper<PurchaseLedger>() |
| | | .eq(PurchaseLedger::getPurchaseContractNumber, salesLedgerImportDto.getPurchaseContractNumber()) |
| | | .last("limit 1")); |
| | | if(purchaseLedger != null){ |
| | | continue; |
| | | } |
| | | PurchaseLedger salesLedger = new PurchaseLedger(); |
| | | BeanUtils.copyProperties(salesLedgerImportDto, salesLedger); |
| | | // 通过供应商名称查询ID |
| | | salesLedger.setSupplierId(customers.stream() |
| | | .filter(customer -> customer.getSupplierName().equals(salesLedger.getSupplierName())) |
| | | .findFirst() |
| | | .map(SupplierManage::getId) |
| | | .orElse(null)); |
| | | Long aLong = sysUsers.stream() |
| | | .filter(sysUser -> sysUser.getNickName().equals(salesLedger.getRecorderName())) |
| | | .findFirst() |
| | | .map(SysUser::getUserId) |
| | | .orElse(null); |
| | | if (aLong == null) |
| | | throw new RuntimeException("录入人:" + salesLedger.getRecorderName() + ",无对应用户!"); |
| | | salesLedger.setRecorderId(aLong); |
| | | // 采购产品数据绑定,通过采购单号获取对应采购产品数据 |
| | | List<PurchaseLedgerProductImportDto> salesLedgerProductImportDtos = salesLedgerProductImportDtoList.stream() |
| | | .filter(salesLedgerProductImportDto -> salesLedgerProductImportDto.getPurchaseContractNumber().equals(salesLedger.getPurchaseContractNumber())) |
| | | .collect(Collectors.toList()); |
| | | if (CollectionUtils.isEmpty(salesLedgerProductImportDtos)) |
| | | throw new RuntimeException("采购单号:" + salesLedgerImportDto.getPurchaseContractNumber() + ",无对应产品数据!"); |
| | | salesLedger.setContractAmount(salesLedgerProductImportDtos.stream() |
| | | .map(PurchaseLedgerProductImportDto::getTaxInclusiveTotalPrice) |
| | | .reduce(BigDecimal.ZERO,BigDecimal::add)); |
| | | // 通过销售单号绑定销售 |
| | | SalesLedger salesLedger1 = salesLedgerMapper.selectOne(new LambdaQueryWrapper<SalesLedger>() |
| | | .eq(SalesLedger::getSalesContractNo, salesLedger.getSalesContractNo()) |
| | | .last("LIMIT 1")); |
| | | if(salesLedger1 != null){ |
| | | salesLedger.setSalesLedgerId(salesLedger1.getId()); |
| | | } |
| | | if (StringUtils.hasText(salesLedger.getApproveUserIds())) { |
| | | // 采购审核:历史导入模板传审批人姓名时,继续兼容转换为用户ID。 |
| | | String[] split = salesLedger.getApproveUserIds().split(","); |
| | | List<Long> ids = new ArrayList<>(); |
| | | for (int i = 0; i < split.length; i++) { |
| | | SysUser sysUser = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getNickName, split[i]) |
| | | .last("LIMIT 1")); |
| | | if (sysUser != null) { |
| | | ids.add(sysUser.getUserId()); |
| | | } |
| | | } |
| | | // 将集合转为字符串,隔开 |
| | | String collect = ids.stream().map(Object::toString).collect(Collectors.joining(",")); |
| | | salesLedger.setApproveUserIds(collect); |
| | | } |
| | | purchaseLedgerMapper.insert(salesLedger); |
| | | |
| | | for (PurchaseLedgerProductImportDto salesLedgerProductImportDto : salesLedgerProductImportDtos) { |
| | | SalesLedgerProduct salesLedgerProduct = new SalesLedgerProduct(); |
| | | BeanUtils.copyProperties(salesLedgerProductImportDto, salesLedgerProduct); |
| | | salesLedgerProduct.setSalesLedgerId(salesLedger.getId()); |
| | | salesLedgerProduct.setType(2); |
| | | // 计算不含税总价 |
| | | salesLedgerProduct.setTaxExclusiveTotalPrice(salesLedgerProduct.getTaxInclusiveTotalPrice().divide(new BigDecimal(1).add(salesLedgerProduct.getTaxRate().divide(new BigDecimal(100))), 2, RoundingMode.HALF_UP)); |
| | | list.stream() |
| | | .filter(map -> map.get("productName").equals(salesLedgerProduct.getProductCategory()) && map.get("model").equals(salesLedgerProduct.getSpecificationModel())) |
| | | .findFirst() |
| | | .ifPresent(map -> { |
| | | salesLedgerProduct.setProductModelId(Long.parseLong(map.get("modelId").toString())); |
| | | salesLedgerProduct.setProductId(Long.parseLong(map.get("id").toString())); |
| | | }); |
| | | salesLedgerProduct.setRegister(loginUser.getNickName()); |
| | | salesLedgerProduct.setRegisterDate(LocalDateTime.now()); |
| | | salesLedgerProduct.setApproveStatus(0); |
| | | // 是否质检判断 |
| | | salesLedgerProduct.setIsChecked(salesLedgerProductImportDto.getIsChecked() == 1); |
| | | if(salesLedgerProductImportDto.getIsChecked() == 1){ |
| | | addQualityInspect(salesLedger, salesLedgerProduct); |
| | | } |
| | | salesLedgerProductMapper.insert(salesLedgerProduct); |
| | | } |
| | | // 采购审核 |
| | | addApproveByPurchase(loginUser,salesLedger); |
| | | } |
| | | |
| | | return AjaxResult.success("导入成功"); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return AjaxResult.success("导入失败"); |
| | | } |
| | | |
| | | @Override |
| | | public PurchaseLedgerDto getPurchaseByCode(PurchaseLedgerDto purchaseLedgerDto) { |
| | | // 1. 查询主表 |
| | | PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectOne(new LambdaQueryWrapper<PurchaseLedger>() |
| | | .eq(PurchaseLedger::getPurchaseContractNumber, purchaseLedgerDto.getPurchaseContractNumber()) |
| | | .last("LIMIT 1")); |
| | | if (purchaseLedger == null) { |
| | | throw new BaseException("采购台账不存在"); |
| | | } |
| | | |
| | | // 2. 查询子表 |
| | | LambdaQueryWrapper<SalesLedgerProduct> productWrapper = new LambdaQueryWrapper<>(); |
| | | productWrapper.eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedger.getId()) |
| | | .eq(SalesLedgerProduct::getType, 2); |
| | | List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(productWrapper); |
| | | |
| | | // 4. 转换 DTO |
| | | PurchaseLedgerDto resultDto = new PurchaseLedgerDto(); |
| | | BeanUtils.copyProperties(purchaseLedger, resultDto); |
| | | if (!products.isEmpty()) { |
| | | resultDto.setHasChildren(true); |
| | | resultDto.setProductData(products); |
| | | } |
| | | return resultDto; |
| | | } |
| | | |
| | | public void addApproveByPurchase(LoginUser loginUser,PurchaseLedger purchaseLedger) throws Exception { |
| | | if (loginUser == null) { |
| | | return; |
| | | } |
| | | ApprovalTemplate approvalTemplate = approvalTemplateMapper.selectOne( |
| | | new LambdaQueryWrapper<ApprovalTemplate>() |
| | | .eq(ApprovalTemplate::getBusinessType, 5L) |
| | | .orderByDesc(ApprovalTemplate::getId) |
| | | .last("LIMIT 1") |
| | | ); |
| | | if (approvalTemplate == null) { |
| | | throw new BaseException("请先配置采购审批模板"); |
| | | } |
| | | |
| | | ApprovalInstanceDto approvalInstance = new ApprovalInstanceDto(); |
| | | approvalInstance.setTemplateId(approvalTemplate.getId()); |
| | | approvalInstance.setTemplateName(approvalTemplate.getTemplateName()); |
| | | approvalInstance.setBusinessId(purchaseLedger.getId()); |
| | | approvalInstance.setBusinessType(5L); |
| | | approvalInstance.setCurrentLevel(1); |
| | | approvalInstance.setApplicantId(loginUser.getUserId()); |
| | | approvalInstance.setTitle(purchaseLedger.getPurchaseContractNumber()+"审批"); |
| | | approvalInstance.setApplicantName(loginUser.getNickName()); |
| | | approvalInstance.setApplyTime(LocalDateTime.now()); |
| | | approvalInstanceService.add(approvalInstance); |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 下划线命名转驼峰命名 |
| | | */ |