/**
   * 获取供应商的详细信息(保证金等信息)
   *
   * @param requirementId 需求编号
   * @param solution 需求方案信息
   * @param categoryIds 需求类目信息
   * @return SupplierSolutionDto 供应商详细信息
   */
  private SupplierSolutionDto querySupplierDto(
      Long requirementId, RequirementSolution solution, List<Long> categoryIds) {
    SupplierSolutionDto supplierSolutionDto = new SupplierSolutionDto();

    supplierSolutionDto.setSupplierId(solution.getSupplierId());
    supplierSolutionDto.setSupplierName(solution.getSupplierName());
    supplierSolutionDto.setUserId(solution.getUserId());
    // 是否已提交方案
    supplierSolutionDto.setDealTime(
        solution.getSolutionFile() == null ? null : solution.getUpdatedAt());

    // 写入供应商信用等级信息
    Response<SupplierCreditQualify> creditRes =
        supplierCreditQualifyService.findCreditQualifyByUserId(solution.getUserId());
    supplierSolutionDto.setCreditStatus(
        creditRes.isSuccess() ? creditRes.getResult().getStatus() : null);

    // 写入供应商资质验证信息
    Response<Integer> qualifyRes =
        supplierResourceMaterialService.getInfoInBcIds(solution.getSupplierId(), categoryIds);
    supplierSolutionDto.setQualifyStatus(qualifyRes.isSuccess() ? qualifyRes.getResult() : null);

    // 写入供应商针对需求是否提交保证金
    Response<Integer> depositRes =
        depositService.checkPaid(requirementId, solution.getSupplierId());
    supplierSolutionDto.setPaidStatus(
        depositRes.isSuccess() ? depositRes.getResult() : Deposit.Status.INIT.value());

    // 标注供应商是否可以进入配额流程
    supplierSolutionDto.setSolutionStatus(
        Objects.equal(
            RequirementSolution.Status.from(solution.getStatus()),
            RequirementSolution.Status.SEND_END));

    Response<User> userRes = accountService.findUserById(solution.getUserId());
    supplierSolutionDto.setSupplierTags(
        userRes.isSuccess() ? userRes.getResult().buildTags() : null);

    // 当阶段到达,已上传文件阶段则默认为全部承诺
    Integer interStatus =
        solution.getStatus() == 0 ? 1 : (solution.getStatus() >= 4 ? 2 : solution.getStatus());
    supplierSolutionDto.setInteractiveStatus(interStatus);

    return supplierSolutionDto;
  }
  @Override
  public Response<CheckSolEndDto> solutionEnd(Long requirementId, BaseUser user) {
    Response<CheckSolEndDto> result = new Response<CheckSolEndDto>();

    // 验证用户是否已登入
    if (user == null) {
      log.error("create requirement solution, user must login.");
      result.setError("user.not.login");
      return result;
    }

    if (requirementId == null) {
      log.error("update requirement solution need requirementId");
      result.setError("requirementId.id.null");
      return result;
    }

    try {
      // 获取用户的需求方案信息
      RequirementSolution requirementSolution =
          requirementSolutionDao.findByUserId(requirementId, user.getId());

      // 获取需求信息
      Requirement requirement = requirementDao.findById(requirementSolution.getRequirementId());

      Response<Boolean> checkSupplier = checkSupplierInfo(requirementId, user);
      if (!checkSupplier.isSuccess()) {
        log.error(
            "check supplier info for requirement failed, error code={}", checkSupplier.getError());
        result.setError(checkSupplier.getError());
        return result;
      }

      Response<Boolean> checkRes = checkReqStatusWithSol(requirement, requirementSolution);
      if (!checkRes.isSuccess()) {
        log.error("check requirement & solution info failed, error code={}", checkRes.getError());
        result.setError(checkRes.getError());
        return result;
      } else {
        CheckSolEndDto checkSolEndDto = new CheckSolEndDto();

        // 获取全部报价信息
        List<ModuleQuotation> quotations =
            moduleQuotationDao.findAllQuotations(requirementSolution.getId());

        // 获取全部的TQRDC信息
        List<ModuleSolution> solutions =
            moduleSolutionDao.findAllSolutions(requirementSolution.getId());
        Map<Long, ModuleSolution> solutionMap = Maps.newHashMap();

        for (ModuleSolution solution : solutions) {
          solutionMap.put(solution.getModuleId(), solution);
        }

        // 计算整个需求的Q&R数据用于显示
        Integer qualityValue = 0;
        Date maxReaction = null;
        Date cpmDate;

        List<Module> moduleList = moduleDao.findModules(requirementId);

        // 计算总的模块报价总权值
        int error = 0;
        Integer totalValue = 0;
        for (ModuleQuotation quotation : quotations) {
          for (Module module : moduleList) {
            // 校验报价不能低于模块的价格(统计数量)
            if (Objects.equal(quotation.getModuleId(), quotation.getModuleId())
                && quotation.getPrice() > module.getCost()) {
              log.error("module quotation cost price can't more than module default price");
              error++;
            }
          }

          // 计算总报价
          totalValue += quotation.getTotal() * quotation.getPrice();

          // 计算总Q
          qualityValue +=
              quotation.getTotal() * solutionMap.get(quotation.getModuleId()).getQuality();

          // 计算最大R
          cpmDate = solutionMap.get(quotation.getModuleId()).getReaction();
          maxReaction =
              maxReaction == null ? cpmDate : (maxReaction.after(cpmDate) ? maxReaction : cpmDate);
        }

        if (error == 0) {
          // 方案终投阶段只允许提交一次
          RequirementSolution solution = new RequirementSolution();
          solution.setId(requirementSolution.getId());
          solution.setQuality(qualityValue); // 整体的Q
          solution.setReaction(maxReaction); // 整体的R
          solution.setCost(totalValue); // 整体的C
          solution.setStatus(RequirementSolution.Status.SEND_END.value());
          requirementSolutionDao.update(solution);
        }

        // 判断采购商是否已经提交了保证金
        Response<Integer> paidRes =
            depositService.checkPaid(requirement.getId(), requirementSolution.getSupplierId());
        if (!paidRes.isSuccess()) {
          log.error(
              "check supplier send deposit fee result failed, error code={}", result.getError());
          result.setError(paidRes.getError());
          return result;
        }

        checkSolEndDto.setPaidResult(paidRes.getResult());
        checkSolEndDto.setCostResult(error == 0);

        result.setResult(checkSolEndDto);
      }
    } catch (Exception e) {
      log.error(
          "change requirement solution status failed, requirementId={}, userId={}, error code={}",
          requirementId,
          user.getId(),
          Throwables.getStackTraceAsString(e));
      result.setError("solution.update.failed");
    }

    return result;
  }