/**
   * Method to call when we want to apply (grant or deny) an agreement visa
   *
   * @param employee
   * @param visaStatus
   * @param comment
   * @return
   */
  public Request applyAgreementVisa(
      Employee employee, RequestAgreementVisaStatus visaStatus, String comment) {
    if (!waitsForAnAgreementVisa()) {
      throw REQUEST_DOES_NOT_EXPECT_ANY_AGREEMENT_VISA.exception();
    }

    if (userHasAlreadyAppliedAVisa(employee.getId())) {
      throw EMPLOYEE_HAS_ALREADY_APPLIED_A_VISA.exception(employee.getFullName());
    }

    AgreementRuleVisaAud nextExpectedVisa =
        getNextExpectedAgreementVisa()
            .orElseThrow(() -> COULD_NOT_FIND_NEXT_EXPECTED_AGREEMENT_VISA.exception());

    Department department = employee.getDepartment();
    Seniority seniority = employee.getSeniority();

    if (!nextExpectedVisa.canBeAppliedBy(department, seniority)) {
      throw VISA_TO_APPLY_DOESNT_MATCH_NEXT_EXPECTED_ONE.exception(
          department.getName(), seniority.getValue(),
          nextExpectedVisa.getDepartment().getName(), nextExpectedVisa.getSeniority().getValue());
    }

    LocalDateTime now = LocalDateTime.now();

    RequestAgreementVisa appliedVisa =
        RequestAgreementVisa.build(
            this,
            null,
            employee,
            visaStatus,
            nextAgreementVisaRank,
            comment,
            department,
            seniority,
            now);

    addAgreementVisa(appliedVisa);

    updateUser = employee.getUid();
    updateDate = now;

    return this;
  }
 @Override
 public String toString() {
   return "Employee [id=" + id + ", name=" + name + ", department=" + department.getName() + "]";
 }