| | |
| | | import com.ruoyi.basic.pojo.ProductModel; |
| | | import com.ruoyi.basic.pojo.SupplierManage; |
| | | 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.exception.base.BaseException; |
| | | import com.ruoyi.common.utils.DateUtils; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | |
| | | if (purchaseLedger.getApprovalStatus() != null) { |
| | | queryWrapper.eq(PurchaseLedger::getApprovalStatus, purchaseLedger.getApprovalStatus()); |
| | | } |
| | | queryWrapper.orderByDesc(PurchaseLedger::getEntryDate); |
| | | return purchaseLedgerMapper.selectList(queryWrapper); |
| | | } |
| | | |
| | |
| | | purchaseLedger.setApprovalStatus(1); |
| | | // 3. 新增或更新主表 |
| | | if (purchaseLedger.getId() == null) { |
| | | if (!StringUtils.hasText(purchaseLedger.getPurchaseContractNumber())) { |
| | | purchaseLedger.setPurchaseContractNumber(generatePurchaseContractNo(purchaseLedger.getEntryDate())); |
| | | } |
| | | purchaseLedgerMapper.insert(purchaseLedger); |
| | | } else { |
| | | // 删除采购审核,重新提交 |
| | |
| | | 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>() |
| | | PurchaseLedger existPurchaseLedger = purchaseLedgerMapper.selectOne(new LambdaQueryWrapper<PurchaseLedger>() |
| | | .eq(PurchaseLedger::getPurchaseContractNumber, salesLedgerImportDto.getPurchaseContractNumber()) |
| | | .last("limit 1")); |
| | | if(purchaseLedger != null){ |
| | | // 已审核通过的采购单跳过,不再重复导入 |
| | | if (existPurchaseLedger != null && ApprovalStatusEnum.APPROVED.getCode().equals(existPurchaseLedger.getApprovalStatus())) { |
| | | 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)); |
| | | // 待审核状态的采购单:删除该单下的产品详情和审批实例,重新录入详情 |
| | | if (existPurchaseLedger != null) { |
| | | salesLedgerProductMapper.delete(new LambdaQueryWrapper<SalesLedgerProduct>() |
| | | .eq(SalesLedgerProduct::getSalesLedgerId, existPurchaseLedger.getId()) |
| | | .eq(SalesLedgerProduct::getType, 2)); |
| | | // 清理该单下的质检记录及质检参数 |
| | | deleteQualityInspectByPurchaseLedger(existPurchaseLedger.getId()); |
| | | ApprovalInstance existApprovalInstance = approvalInstanceService.getOne( |
| | | Wrappers.<ApprovalInstance>lambdaQuery() |
| | | .eq(ApprovalInstance::getBusinessId, existPurchaseLedger.getId()) |
| | | .eq(ApprovalInstance::getBusinessType, 5L) |
| | | .eq(ApprovalInstance::getDeleted, 0) |
| | | .orderByDesc(ApprovalInstance::getId) |
| | | .last("limit 1")); |
| | | if (existApprovalInstance != null) { |
| | | approvalInstanceService.delete(Collections.singletonList(existApprovalInstance.getId())); |
| | | } |
| | | salesLedger.setId(existPurchaseLedger.getId()); |
| | | salesLedger.setApprovalStatus(ApprovalStatusEnum.PENDING.getCode()); |
| | | } |
| | | // 通过供应商名称查询ID,不存在则自动新增 |
| | | salesLedger.setSupplierId(findOrCreateSupplier(salesLedger.getSupplierName(), customers)); |
| | | Long aLong = sysUsers.stream() |
| | | .filter(sysUser -> sysUser.getNickName().equals(salesLedger.getRecorderName())) |
| | | .findFirst() |
| | |
| | | String collect = ids.stream().map(Object::toString).collect(Collectors.joining(",")); |
| | | salesLedger.setApproveUserIds(collect); |
| | | } |
| | | purchaseLedgerMapper.insert(salesLedger); |
| | | if (salesLedger.getId() == null) { |
| | | purchaseLedgerMapper.insert(salesLedger); |
| | | } else { |
| | | // 待审核状态重新录入时,更新主表 |
| | | purchaseLedgerMapper.updateById(salesLedger); |
| | | } |
| | | |
| | | for (PurchaseLedgerProductImportDto salesLedgerProductImportDto : salesLedgerProductImportDtos) { |
| | | SalesLedgerProduct salesLedgerProduct = new 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.setTaxExclusiveTotalPrice(salesLedgerProduct.getTaxInclusiveTotalPrice().divide(new BigDecimal(1).add(salesLedgerProduct.getTaxRate().divide(new BigDecimal(100))), 6, RoundingMode.HALF_UP)); |
| | | // 产品大类/规格型号不存在时自动创建 |
| | | String productName = salesLedgerProduct.getProductCategory(); |
| | | if (StringUtils.isNotBlank(productName)) { |
| | | // 规格型号为空时用产品大类作为规格型号 |
| | | String model = StringUtils.isNotBlank(salesLedgerProduct.getSpecificationModel()) |
| | | ? salesLedgerProduct.getSpecificationModel() |
| | | : productName; |
| | | salesLedgerProduct.setSpecificationModel(model); |
| | | Long productId = findOrCreateProduct(productName, list); |
| | | Long modelId = findOrCreateProductModel(productId, productName, model, |
| | | salesLedgerProduct.getUnit(), list); |
| | | salesLedgerProduct.setProductId(productId); |
| | | salesLedgerProduct.setProductModelId(modelId); |
| | | } |
| | | 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); |
| | | } |
| | | // 采购审核 |
| | |
| | | e.printStackTrace(); |
| | | } |
| | | return AjaxResult.success("导入失败"); |
| | | } |
| | | |
| | | /** |
| | | * 查找或新增供应商:supplier_manage 表按 supplier_name 匹配,不存在则新增,缺失信息默认写"/" |
| | | */ |
| | | private Long findOrCreateSupplier(String supplierName, List<SupplierManage> supplierList) { |
| | | if (StringUtils.isBlank(supplierName)) { |
| | | return null; |
| | | } |
| | | // 内存列表中查找(本次导入已新增的也包含在内) |
| | | for (SupplierManage supplier : supplierList) { |
| | | if (supplierName.equals(supplier.getSupplierName())) { |
| | | return supplier.getId(); |
| | | } |
| | | } |
| | | // 数据库查找 |
| | | SupplierManage existSupplier = supplierManageMapper.selectOne(new LambdaQueryWrapper<SupplierManage>() |
| | | .eq(SupplierManage::getSupplierName, supplierName) |
| | | .last("limit 1")); |
| | | if (existSupplier != null) { |
| | | supplierList.add(existSupplier); |
| | | return existSupplier.getId(); |
| | | } |
| | | // 新增供应商,缺失信息(税号、地址、电话等)默认写"/" |
| | | SupplierManage newSupplier = new SupplierManage(); |
| | | newSupplier.setSupplierName(supplierName); |
| | | newSupplier.setTaxpayerIdentificationNum("/"); |
| | | newSupplier.setCompanyAddress("/"); |
| | | newSupplier.setSupplierType("/"); |
| | | newSupplier.setCompanyPhone("/"); |
| | | newSupplier.setBankAccountName("/"); |
| | | newSupplier.setBankAccountNum("/"); |
| | | newSupplier.setContactUserName("/"); |
| | | newSupplier.setContactUserPhone("/"); |
| | | supplierManageMapper.insert(newSupplier); |
| | | supplierList.add(newSupplier); |
| | | return newSupplier.getId(); |
| | | } |
| | | |
| | | /** |
| | | * 查找或新增产品大类:product 表按 product_name 匹配,不存在则新增,默认父ID为278 |
| | | */ |
| | | private Long findOrCreateProduct(String productName, List<Map<String, Object>> productAndModelList) { |
| | | // 内存列表中查找(本次导入已新增的也包含在内) |
| | | for (Map<String, Object> map : productAndModelList) { |
| | | if (map.get("productName") != null && productName.equals(map.get("productName"))) { |
| | | return Long.valueOf(map.get("id").toString()); |
| | | } |
| | | } |
| | | // 数据库查找(已存在但暂无规格型号的产品不在内存列表中) |
| | | Product existProduct = productMapper.selectOne(new LambdaQueryWrapper<Product>() |
| | | .eq(Product::getProductName, productName) |
| | | .last("limit 1")); |
| | | if (existProduct != null) { |
| | | return existProduct.getId(); |
| | | } |
| | | // 新增产品大类,默认父ID为278 |
| | | Product product = new Product(); |
| | | product.setProductName(productName); |
| | | product.setParentId(278L); |
| | | productMapper.insert(product); |
| | | return product.getId(); |
| | | } |
| | | |
| | | /** |
| | | * 查找或新增产品规格型号:product_model 按 产品ID+规格型号 匹配,不存在则新增。 |
| | | * 产品编码 = 规格型号 + "_" + 三位流水号;规格型号为空时用产品大类作为规格型号。 |
| | | */ |
| | | private Long findOrCreateProductModel(Long productId, String productName, String model, String unit, |
| | | List<Map<String, Object>> productAndModelList) { |
| | | // 内存列表中查找 |
| | | for (Map<String, Object> map : productAndModelList) { |
| | | if (map.get("id") != null && Long.valueOf(map.get("id").toString()).equals(productId) |
| | | && model.equals(map.get("model"))) { |
| | | return Long.valueOf(map.get("modelId").toString()); |
| | | } |
| | | } |
| | | // 数据库查找 |
| | | ProductModel existProductModel = productModelMapper.selectOne(new LambdaQueryWrapper<ProductModel>() |
| | | .eq(ProductModel::getProductId, productId) |
| | | .eq(ProductModel::getModel, model) |
| | | .last("limit 1")); |
| | | if (existProductModel != null) { |
| | | return existProductModel.getId(); |
| | | } |
| | | // 新增规格型号,产品编码 = 规格型号 + "_" + 三位流水号(同产品下自增) |
| | | long count = productModelMapper.selectCount(new LambdaQueryWrapper<ProductModel>() |
| | | .eq(ProductModel::getProductId, productId)); |
| | | ProductModel productModel = new ProductModel(); |
| | | productModel.setProductId(productId); |
| | | productModel.setModel(model); |
| | | productModel.setUnit(unit); |
| | | productModel.setProductCode(model + "_" + String.format("%03d", count + 1)); |
| | | productModelMapper.insert(productModel); |
| | | // 记录到内存列表,避免本次导入内重复创建 |
| | | Map<String, Object> newMap = new HashMap<>(); |
| | | newMap.put("id", productId); |
| | | newMap.put("modelId", productModel.getId()); |
| | | newMap.put("productName", productName); |
| | | newMap.put("model", model); |
| | | productAndModelList.add(newMap); |
| | | return productModel.getId(); |
| | | } |
| | | |
| | | /** |
| | | * 删除采购单下的质检记录及质检参数(已提交的检验单不允许删除) |
| | | */ |
| | | private void deleteQualityInspectByPurchaseLedger(Long purchaseLedgerId) { |
| | | LambdaQueryWrapper<QualityInspect> inspectWrapper = new LambdaQueryWrapper<>(); |
| | | inspectWrapper.eq(QualityInspect::getPurchaseLedgerId, purchaseLedgerId); |
| | | List<QualityInspect> qualityInspects = qualityInspectMapper.selectList(inspectWrapper); |
| | | for (QualityInspect qualityInspect : qualityInspects) { |
| | | if (ObjectUtils.isNotEmpty(qualityInspect.getInspectState()) && qualityInspect.getInspectState().equals(1)) { |
| | | throw new BaseException("已提交的检验单不能删除"); |
| | | } |
| | | } |
| | | List<Long> inspectIds = qualityInspects.stream() |
| | | .map(QualityInspect::getId) |
| | | .collect(Collectors.toList()); |
| | | if (!inspectIds.isEmpty()) { |
| | | qualityInspectParamMapper.delete(new LambdaQueryWrapper<QualityInspectParam>() |
| | | .in(QualityInspectParam::getInspectId, inspectIds)); |
| | | } |
| | | qualityInspectMapper.delete(inspectWrapper); |
| | | } |
| | | |
| | | @Override |
| | |
| | | } |
| | | return sb.toString(); |
| | | } |
| | | |
| | | private static final String PURCHASE_LOCK_PREFIX = "purchase_contract_no:"; |
| | | private static final long PURCHASE_LOCK_WAIT_TIMEOUT = 10; |
| | | private static final long PURCHASE_LOCK_EXPIRE_TIME = 30; |
| | | |
| | | private String generatePurchaseContractNo(Date entryDate) { |
| | | LocalDate currentDate = entryDate != null ? DateUtils.toLocalDate(entryDate) : LocalDate.now(); |
| | | String datePart = currentDate.format(DateTimeFormatter.BASIC_ISO_DATE); |
| | | String lockKey = PURCHASE_LOCK_PREFIX + datePart; |
| | | String lockValue = Thread.currentThread().getId() + "-" + System.nanoTime(); |
| | | |
| | | try { |
| | | long startWaitTime = System.currentTimeMillis(); |
| | | while (System.currentTimeMillis() - startWaitTime < PURCHASE_LOCK_WAIT_TIMEOUT * 1000) { |
| | | Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, PURCHASE_LOCK_EXPIRE_TIME, TimeUnit.SECONDS); |
| | | if (Boolean.TRUE.equals(locked)) { |
| | | break; |
| | | } |
| | | try { |
| | | Thread.sleep(100); |
| | | } catch (InterruptedException e) { |
| | | Thread.currentThread().interrupt(); |
| | | throw new RuntimeException("获取锁时被中断", e); |
| | | } |
| | | } |
| | | |
| | | if (Boolean.FALSE.equals(redisTemplate.hasKey(lockKey))) { |
| | | throw new RuntimeException("获取采购合同编号生成锁失败:超时"); |
| | | } |
| | | |
| | | String prefix = "CG-" + datePart + "-"; |
| | | List<PurchaseLedger> existingList = purchaseLedgerMapper.selectList( |
| | | new LambdaQueryWrapper<PurchaseLedger>() |
| | | .likeRight(PurchaseLedger::getPurchaseContractNumber, prefix) |
| | | .select(PurchaseLedger::getPurchaseContractNumber)); |
| | | List<Integer> existingSequences = existingList.stream() |
| | | .map(PurchaseLedger::getPurchaseContractNumber) |
| | | .filter(Objects::nonNull) |
| | | .map(no -> { |
| | | int lastDash = no.lastIndexOf('-'); |
| | | if (lastDash >= 0) { |
| | | try { |
| | | return Integer.parseInt(no.substring(lastDash + 1)); |
| | | } catch (NumberFormatException e) { |
| | | return 0; |
| | | } |
| | | } |
| | | return 0; |
| | | }) |
| | | .collect(Collectors.toList()); |
| | | int nextSequence = findFirstMissingSequence(existingSequences); |
| | | |
| | | return prefix + String.format("%03d", nextSequence); |
| | | } finally { |
| | | String luaScript = "if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('DEL', KEYS[1]) else return 0 end"; |
| | | redisTemplate.execute( |
| | | new org.springframework.data.redis.core.script.DefaultRedisScript<>(luaScript, Long.class), |
| | | Collections.singletonList(lockKey), |
| | | lockValue |
| | | ); |
| | | } |
| | | } |
| | | |
| | | private int findFirstMissingSequence(List<Integer> sequences) { |
| | | if (sequences.isEmpty()) { |
| | | return 1; |
| | | } |
| | | sequences.sort(Integer::compareTo); |
| | | int next = 1; |
| | | for (int seq : sequences) { |
| | | if (seq == next) { |
| | | next++; |
| | | } else if (seq > next) { |
| | | break; |
| | | } |
| | | } |
| | | return next; |
| | | } |
| | | } |