@Override
  public Response<Paging<SupplierSolutionDto>> findSignByParam(
      final Long requirementId, Integer pageNo, Integer size) {
    Response<Paging<SupplierSolutionDto>> result = new Response<Paging<SupplierSolutionDto>>();

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

    try {
      Map<String, Object> params = Maps.newHashMap();
      params.put("requirementId", requirementId);

      PageInfo pageInfo = new PageInfo(pageNo, Objects.firstNonNull(size, 10));
      params.putAll(pageInfo.toMap());

      Requirement requirement = requirementDao.findById(requirementId);

      // 获取需求下的供应商提交的方案
      Paging<RequirementSolution> solutionPaging =
          requirementSolutionDao.findSolutionsByParams(params);

      // 获取后台三级类目信息
      List<BackendJSON> categoryList =
          JSON_MAPPER.fromJson(
              requirement.getSeriesIds(),
              JSON_MAPPER.createCollectionType(List.class, BackendJSON.class));
      List<Long> categoryIds = Lists.newArrayList();
      for (BackendJSON backendJSON : categoryList) {
        categoryIds.add(backendJSON.getBcId());
      }

      List<SupplierSolutionDto> supplierSolutionDtoList = Lists.newArrayList();
      for (RequirementSolution solution : solutionPaging.getData()) {
        supplierSolutionDtoList.add(querySupplierDto(requirementId, solution, categoryIds));
      }

      result.setResult(
          new Paging<SupplierSolutionDto>(solutionPaging.getTotal(), supplierSolutionDtoList));
    } catch (Exception e) {
      log.error(
          "find requirement solution have sign secrecy failed , requirementId={} error code={}",
          requirementId,
          Throwables.getStackTraceAsString(e));
      result.setError("solution.supplier.findFailed");
    }

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

    if (requirementId == null) {
      log.error("find supplier info need requirementId");
      result.setError("solution.requirementId.null");
      return result;
    }

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

    try {
      if (Objects.equal(User.Type.from(user.getType()), User.Type.SUPPLIER)) {
        RequirementSolution solution =
            requirementSolutionDao.findByUserId(requirementId, user.getId());

        Requirement requirement = requirementDao.findById(requirementId);

        // 获取后台三级类目信息
        List<BackendJSON> categoryList =
            JSON_MAPPER.fromJson(
                requirement.getSeriesIds(),
                JSON_MAPPER.createCollectionType(List.class, BackendJSON.class));
        List<Long> categoryIds = Lists.newArrayList();
        for (BackendJSON backendJSON : categoryList) {
          categoryIds.add(backendJSON.getBcId());
        }

        result.setResult(querySupplierDto(requirementId, solution, categoryIds));
      } else {
        result.setResult(null);
      }
    } catch (Exception e) {
      log.error(
          "find supplier detail info failed, requirementId={}, error code={}",
          requirementId,
          Throwables.getStackTraceAsString(e));
      result.setError("query.supplier.fail");
    }

    return result;
  }
  @Override
  public Response<Boolean> updateBatchTechnology(String solutions) {
    Response<Boolean> result = new Response<Boolean>();
    List<RequirementSolution> solutionList =
        JSON_MAPPER.fromJson(
            solutions, JSON_MAPPER.createCollectionType(List.class, RequirementSolution.class));

    if (solutionList == null || solutionList.isEmpty()) {
      log.error("requirement solutions is empty.");
      result.setError("requirement.solution.empty");
      return result;
    }

    try {
      RequirementSolution newSolution;
      for (RequirementSolution solution : solutionList) {
        if (solution.getTechnology() == null) {
          log.error("create module solution need technology");
          result.setError("solution.technology.null");
          return result;
        }

        if (solution.getTechnology() < 0 || solution.getTechnology() > 10000) {
          log.error("requirement solution technology score is in 0~100.");
          result.setError("solution.technology.scope");
          return result;
        }

        newSolution = new RequirementSolution();
        newSolution.setId(solution.getId());
        newSolution.setTechnology(solution.getTechnology());
        // 采购商对方案的技术进行评分
        requirementSolutionDao.update(newSolution);
      }

      result.setResult(true);
    } catch (Exception e) {
      log.error(
          "update requirement solution technology is failed, error code={}.",
          Throwables.getStackTraceAsString(e));
      result.setError("solution.technology.failed");
    }

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

    Requirement requirement = requirementDao.findById(requirementId);

    // 写入供应商信用等级信息
    Response<SupplierCreditQualify> creditRes =
        supplierCreditQualifyService.findCreditQualifyByUserId(user.getId());

    if (!creditRes.isSuccess()) {
      log.error("find supplier credit qualify info failed, error code={}", creditRes.getError());
      result.setError(creditRes.getError());
      return result;
    }

    if (!creditRes.getResult().isCreditQualified()) {
      log.error("supplier credit is not allow to do.");
      result.setError("supplier.credit.failed");
      return result;
    }

    // 获取公司信息
    Response<Company> companyRes = companyService.findCompanyByUserId(user.getId());

    if (!companyRes.isSuccess()) {
      result.setError(companyRes.getError());
      return result;
    }

    // 获取后台三级类目信息
    List<BackendJSON> categoryList =
        JSON_MAPPER.fromJson(
            requirement.getSeriesIds(),
            JSON_MAPPER.createCollectionType(List.class, BackendJSON.class));
    List<Long> categoryIds = Lists.newArrayList();
    for (BackendJSON backendJSON : categoryList) {
      categoryIds.add(backendJSON.getBcId());
    }

    // 获取供应商资质验证信息
    Response<Integer> qualifyRes =
        supplierResourceMaterialService.getInfoInBcIds(companyRes.getResult().getId(), categoryIds);
    if (!qualifyRes.isSuccess()) {
      log.error(
          "find user qualify failed, userId={}, error code={}",
          user.getId(),
          qualifyRes.getError());
      result.setError(qualifyRes.getError());
      return result;
    }

    // 资质是否全部验证通过
    if (!Objects.equal(
        SupplierResourceMaterialInfo.Status.from(qualifyRes.getResult()),
        SupplierResourceMaterialInfo.Status.QUALIFIED)) {
      log.error("supplier resource is not allow to do.");
      result.setError("supplier.resource.failed");
      return result;
    }

    result.setResult(true);

    return result;
  }
  @Override
  public SupplierInfoChangedDto baseCompanyChanged(
      Long userId,
      CompanyDto updatedCompanyDto,
      Company oldCompany,
      List<CompanyMainBusiness> oldMainBusinesses,
      List<CompanySupplyPark> oldSupplyParks) {
    SupplierInfoChangedDto supplierInfoChangedDto = new SupplierInfoChangedDto();

    Company updatedCompany = updatedCompanyDto.getCompany();
    List<CompanyMainBusiness> updatedMainBusinesses = updatedCompanyDto.getCompanyMainBusinesses();
    List<CompanySupplyPark> updatedSupplyParks = updatedCompanyDto.getCompanySupplyParks();

    // 取出新的信息
    CompanyDto newCompanyDto =
        getNewBaseCompany(userId, oldCompany, oldMainBusinesses, oldSupplyParks).getSupplierInfo();
    Company newCompany = newCompanyDto.getCompany();
    List<CompanyMainBusiness> newMainBusinesses = newCompanyDto.getCompanyMainBusinesses();
    List<CompanySupplyPark> newSupplyParks = newCompanyDto.getCompanySupplyParks();

    Map<String, String> changedInfo = Maps.newHashMap();

    if (!Objects.equal(updatedCompany.getCorporation(), newCompany.getCorporation())) {
      changedInfo.put(ChangedInfoKeys.companyCorporation(), updatedCompany.getCorporation());
      updatedCompany.setCorporation(null);
    }

    if (!Objects.equal(updatedCompany.getInitAgent(), newCompany.getInitAgent())) {
      changedInfo.put(ChangedInfoKeys.companyInitAgent(), updatedCompany.getInitAgent());
      updatedCompany.setInitAgent(null);
    }

    if (!Objects.equal(updatedCompany.getDesc(), newCompany.getDesc())) {
      changedInfo.put(ChangedInfoKeys.companyDesc(), updatedCompany.getDesc());
      updatedCompany.setDesc(null);
    }

    if (!Objects.equal(updatedCompany.getRegCountry(), newCompany.getRegCountry())) {
      changedInfo.put(
          ChangedInfoKeys.companyRegCountry(), String.valueOf(updatedCompany.getRegCountry()));
      updatedCompany.setRegCountry(null);
    }

    //        if (!Objects.equal(company.getCustomers(), newCompany.getCustomers())) {
    //            changedInfo.put("", newCompany.getCustomers());
    //        }
    //
    if (!Objects.equal(updatedCompany.getProductLine(), newCompany.getProductLine())) {
      changedInfo.put(ChangedInfoKeys.companyProductLine(), updatedCompany.getProductLine());
    }

    if (mainBusinessChanged(updatedMainBusinesses, newMainBusinesses)) {
      changedInfo.put(
          ChangedInfoKeys.companyMainBusiness(),
          JsonMapper.nonEmptyMapper().toJson(updatedMainBusinesses));
    }

    if (supplyParkChanged(updatedSupplyParks, newSupplyParks)) {
      changedInfo.put(
          ChangedInfoKeys.companySupplyPark(),
          JsonMapper.nonEmptyMapper().toJson(updatedSupplyParks));
    }

    // 如果有V码,则继续检查合同信息
    if (!Strings.isNullOrEmpty(newCompany.getSupplierCode())) {

      if (!Objects.equal(updatedCompany.getGroupName(), newCompany.getGroupName())) {
        changedInfo.put(ChangedInfoKeys.companyGroupName(), updatedCompany.getGroupName());
        updatedCompany.setGroupName(null);
      }
      if (!Objects.equal(updatedCompany.getGroupAddr(), newCompany.getGroupAddr())) {
        changedInfo.put(ChangedInfoKeys.companyGroupAddr(), updatedCompany.getGroupAddr());
        updatedCompany.setGroupAddr(null);
      }
      if (!Objects.equal(updatedCompany.getRegCapital(), newCompany.getRegCapital())) {
        changedInfo.put(
            ChangedInfoKeys.companyRegCapical(), String.valueOf(updatedCompany.getRegCapital()));
        updatedCompany.setRegCapital(null);
      }
      if (!Objects.equal(updatedCompany.getRcCoinType(), newCompany.getRcCoinType())) {
        changedInfo.put(
            ChangedInfoKeys.companyRcCoinType(), String.valueOf(updatedCompany.getRcCoinType()));
        updatedCompany.setRcCoinType(null);
      }
      if (!Objects.equal(updatedCompany.getPersonScale(), newCompany.getPersonScale())) {
        changedInfo.put(ChangedInfoKeys.companyPersonScale(), updatedCompany.getPersonScale());
        updatedCompany.setPersonScale(null);
      }
      if (!Objects.equal(updatedCompany.getRegProvince(), newCompany.getRegProvince())) {
        changedInfo.put(
            ChangedInfoKeys.companyRegProvince(), String.valueOf(updatedCompany.getRegProvince()));
        updatedCompany.setRegProvince(null);
      }
      if (!Objects.equal(updatedCompany.getRegCity(), newCompany.getRegCity())) {
        changedInfo.put(
            ChangedInfoKeys.companyRegCity(), String.valueOf(updatedCompany.getRegCity()));
        updatedCompany.setRegCity(null);
      }
      if (!Objects.equal(updatedCompany.getFixedAssets(), newCompany.getFixedAssets())) {
        changedInfo.put(
            ChangedInfoKeys.companyFixedAssets(), String.valueOf(updatedCompany.getFixedAssets()));
        updatedCompany.setFixedAssets(null);
      }
      if (!Objects.equal(updatedCompany.getFaCoinType(), newCompany.getFaCoinType())) {
        changedInfo.put(
            ChangedInfoKeys.companyFaCoinType(), String.valueOf(updatedCompany.getFaCoinType()));
        updatedCompany.setFaCoinType(null);
      }

      Date updatedFoundAt = updatedCompany.getFoundAt();
      Date oldFoundAt = newCompany.getFoundAt();
      if (updatedFoundAt != null) {
        DateTime updated = new DateTime(updatedFoundAt);
        if (oldFoundAt == null) {
          changedInfo.put(ChangedInfoKeys.companyFoundAt(), updated.toString(FORMATTER));
          updatedCompany.setFoundAt(null);
        } else {
          DateTime old = new DateTime(oldFoundAt);
          if (!updated.equals(old)) {
            changedInfo.put(ChangedInfoKeys.companyFoundAt(), updated.toString(FORMATTER));
            updatedCompany.setFoundAt(null);
          }
        }
      }

      if (!Objects.equal(updatedCompany.getOfficialWebsite(), newCompany.getOfficialWebsite())) {
        changedInfo.put(
            ChangedInfoKeys.companyOfficialWebSite(), updatedCompany.getOfficialWebsite());
        updatedCompany.setOfficialWebsite(null);
      }
      if (!Objects.equal(updatedCompany.getNature(), newCompany.getNature())) {
        changedInfo.put(
            ChangedInfoKeys.companyNature(), String.valueOf(updatedCompany.getNature()));
        updatedCompany.setNature(null);
      }
      if (!Objects.equal(updatedCompany.getWorldTop(), newCompany.getWorldTop())) {
        changedInfo.put(
            ChangedInfoKeys.companyWorldTop(), String.valueOf(updatedCompany.getWorldTop()));
        updatedCompany.setWorldTop(null);
      }
      if (!Objects.equal(updatedCompany.getListedStatus(), newCompany.getListedStatus())) {
        changedInfo.put(
            ChangedInfoKeys.companyListedStatus(),
            String.valueOf(updatedCompany.getListedStatus()));
        updatedCompany.setListedStatus(null);
      }
      if (!Objects.equal(updatedCompany.getListedRegion(), newCompany.getListedRegion())) {
        changedInfo.put(ChangedInfoKeys.companyListedRegion(), updatedCompany.getListedRegion());
        updatedCompany.setListedRegion(null);
      }
      if (!Objects.equal(updatedCompany.getTicker(), newCompany.getTicker())) {
        changedInfo.put(ChangedInfoKeys.companyTicker(), updatedCompany.getTicker());
        updatedCompany.setTicker(null);
      }
    }

    if (!changedInfo.isEmpty()) {
      supplierInfoChangedDto.setChanged(true);
      supplierInfoChangedDto.setChangedInfo(changedInfo);
    }

    return supplierInfoChangedDto;
  }
  @Test
  public void testCRUD() throws Exception {
    CategoryPair cp = new CategoryPair();
    cp.setId(1L);
    cp.setPath("path");

    CategoryBinding cb =
        getCb(1L, 1L, JsonMapper.nonDefaultMapper().toJson(Lists.newArrayList(cp)));

    /*
    create
     */
    when(categoryBindingDao.create(cb)).thenReturn(1L);
    Response<Long> createRes = categoryBindingService.create(cb);
    assertTrue(createRes.isSuccess());
    assertThat(createRes.getResult(), is(1L));
    // 参数错误
    assertFalse(categoryBindingService.create(null).isSuccess());
    // dao 异常
    when(categoryBindingDao.create(any(CategoryBinding.class))).thenThrow(new RuntimeException());
    assertFalse(categoryBindingService.create(cb).isSuccess());

    /*
    update
     */
    when(categoryBindingDao.update(cb)).thenReturn(true);
    Response<Boolean> updateRes = categoryBindingService.update(cb);
    assertTrue(updateRes.isSuccess());
    assertThat(updateRes.getResult(), is(true));
    // 参数错误
    assertFalse(categoryBindingService.update(new CategoryBinding()).isSuccess());
    // dao 异常
    when(categoryBindingDao.update(any(CategoryBinding.class))).thenThrow(new RuntimeException());
    assertFalse(categoryBindingService.update(cb).isSuccess());

    /*
    delete
     */
    when(categoryBindingDao.delete(1L)).thenReturn(true);
    Response<Boolean> deleteRes = categoryBindingService.delete(1L);
    assertTrue(deleteRes.isSuccess());
    assertThat(deleteRes.getResult(), is(true));
    // 参数错误
    assertFalse(categoryBindingService.delete(null).isSuccess());
    // dao 异常
    when(categoryBindingDao.delete(1L)).thenThrow(new RuntimeException());
    assertFalse(categoryBindingService.delete(1L).isSuccess());

    /*
    findByFcId
     */
    when(categoryBindingDao.findByFcid(1L)).thenReturn(Lists.newArrayList(cp));
    Response<List<CategoryPair>> cpsRes = categoryBindingService.findByFcid(1L);
    assertTrue(cpsRes.isSuccess());
    assertThat(cpsRes.getResult().size(), is(1));
    // 查不到
    cpsRes = categoryBindingService.findByFcid(0L);
    assertTrue(cpsRes.isSuccess());
    assertThat(cpsRes.getResult().size(), is(0));
    // 参数错误
    assertFalse(categoryBindingService.findByFcid(null).isSuccess());

    /*
    findBcNamesByFcid
     */
    Response<List<CategoryPairWithBcName>> cpbcsRes = categoryBindingService.findBcNamesByFcid(1L);
    //        assertTrue(cpbcsRes.isSuccess());
    // TODO: to be completed

    /*
    findBy
     */
    when(categoryBindingDao.findBy(1L)).thenReturn(cb);
    Response<CategoryBinding> cbRes = categoryBindingService.findBy(1L);
    assertTrue(cbRes.isSuccess());
    assertThat(cbRes.getResult().getBcs(), is(cb.getBcs()));
    // 错误参数
    assertFalse(categoryBindingService.findBy(null).isSuccess());
    // dao 异常
    when(categoryBindingDao.findBy(1L)).thenThrow(new RuntimeException());
    assertFalse(categoryBindingService.findBy(1L).isSuccess());

    /*
    findById
     */
    when(categoryBindingDao.findById(1L)).thenReturn(cb);
    cbRes = categoryBindingService.findById(1L);
    assertTrue(cbRes.isSuccess());
    assertThat(cbRes.getResult().getBcs(), is(cb.getBcs()));
    // 错误参数
    assertFalse(categoryBindingService.findById(null).isSuccess());
    // dao 异常
    when(categoryBindingDao.findById(anyLong())).thenThrow(new RuntimeException());
    assertFalse(categoryBindingService.findBy(1L).isSuccess());
  }