Пример #1
0
  /**
   * Returns a specific employee's free days on a specific week.
   *
   * <p>Saturday and Sunday cannot be day off.
   *
   * <p>Work day is overwritten by the day off, sick days are also, <b>unless it's weekend, then it
   * will not count as neither work day/sick day nor day off</b>
   *
   * @param id the employee's id
   * @param date the date that provides the week (can be any day on that week) we want to analyze
   * @return the number of free days
   */
  public static int getDayOffsOnAWeekByEmployeeId(int id, Date date) {
    LocalDate startDate = new LocalDate(date);
    int dayOfWeek = startDate.getDayOfWeek();
    startDate = startDate.minusDays(dayOfWeek - 1);
    LocalDate endDate = startDate.plusDays(6);
    List<WorkSession> sickDaysTemp = new ArrayList<>();
    List<WorkSession> dayOffsTemp = new ArrayList<>();
    try (PreparedStatement pstmt =
        ConnectionHelper.getConnection()
            .prepareStatement(
                "select session_date, type, sum(duration) duration from worksessions"
                    + " where employee_id = ? and session_date between ? and ? group by session_date, type")) {
      pstmt.setInt(1, id);
      pstmt.setDate(2, new Date(startDate.toDate().getTime()));
      pstmt.setDate(3, new Date(endDate.toDate().getTime()));
      try (ResultSet rset = pstmt.executeQuery()) {
        int temp_id = 1;
        while (rset.next()) {
          WorkSession ws =
              new WorkSession(
                  temp_id++,
                  id,
                  rset.getDate("session_date"),
                  (short) rset.getInt("duration"),
                  rset.getString("type"));
          switch (ws.getType()) {
            case WORK:
              break;
            case SICKNESS:
              sickDaysTemp.add(ws);
              break;
            case DAY_OFF:
              dayOffsTemp.add(ws);
              break;
            default:
              break;
          }
        }
      }
    } catch (SQLException | IOException e) {
      logger.error("Error while getting dayoffs on a week by employeeid", e);
      throw new PersistentLayerException(e);
    }

    List<WorkSession> dayOffs = new ArrayList<>();

    for (WorkSession dayOff : dayOffsTemp) {
      LocalDate ldate = new LocalDate(dayOff.getDate());
      if (ldate.getDayOfWeek() < 6) {
        dayOffs.add(dayOff);
      }
    }
    return dayOffs.size();
  }
Пример #2
0
  /**
   * Returns the number of specific employee's worked days in the current year.
   *
   * <p>Work days are overwritten by sick days.
   *
   * <p>Sick days are overwritten by days taken off.
   *
   * @param id the employee's id
   * @return the number of worked days
   */
  public static int getAllWorkedDayCurrentYearByEmployeeId(int id) {
    List<WorkSession> workDaysTemp = new ArrayList<>();
    List<WorkSession> sickDaysTemp = new ArrayList<>();
    List<WorkSession> dayOffsTemp = new ArrayList<>();
    try (PreparedStatement pstmt =
        ConnectionHelper.getConnection()
            .prepareStatement(
                "select session_date, type from worksessions"
                    + " where employee_id = ? and to_char(session_date, 'YYYY') = to_char(sysdate, 'YYYY') group by session_date, type")) {
      pstmt.setInt(1, id);
      try (ResultSet rset = pstmt.executeQuery()) {
        int temp_id = 1;
        while (rset.next()) {
          WorkSession ws =
              new WorkSession(
                  temp_id++, id, rset.getDate("session_date"), (short) 8, rset.getString("type"));
          switch (ws.getType()) {
            case WORK:
              workDaysTemp.add(ws);
              break;
            case SICKNESS:
              sickDaysTemp.add(ws);
              break;
            case DAY_OFF:
              dayOffsTemp.add(ws);
              break;
            default:
              break;
          }
        }
      }
    } catch (SQLException | IOException e) {
      logger.error("error while retrieving worked days in current year", e);
      throw new PersistentLayerException(e);
    }
    List<WorkSession> workDays = new ArrayList<>();

    for (WorkSession workDay : workDaysTemp) {
      boolean contains = false;
      for (WorkSession sickDay : sickDaysTemp) {
        if (workDay.getDate().equals(sickDay.getDate())) {
          contains = true;
        }
      }
      for (WorkSession dayOff : dayOffsTemp) {
        if (workDay.getDate().equals(dayOff.getDate())) {
          contains = true;
        }
      }
      if (!contains) {
        workDays.add(workDay);
      }
    }
    return workDays.size();
  }
Пример #3
0
  /**
   * Returns the number of a specific employee's free days in a specific month.
   *
   * <p>Work days are overwritten by sick days unless it's weekend, then it's not counted for
   * anywhere.
   *
   * <p>Sick days are overwritten by free days unless it's weekend, then it's not counted for
   * anywhere.
   *
   * @param id the employee's id
   * @param date the month (can be any of the month's day) we want to analyze
   * @return the number of the employee's days taken off (only weekdays)
   */
  public static int getDayOffsInAMonthByEmployeeId(int id, Date date) {
    List<WorkSession> dayOffsTemp = new ArrayList<>();
    try (PreparedStatement pstmt =
        ConnectionHelper.getConnection()
            .prepareStatement(
                "select session_date, type from worksessions"
                    + " where employee_id = ? and to_char(session_date, 'YYYY.MM') = to_char(?, 'YYYY.MM') group by session_date, type")) {
      pstmt.setInt(1, id);
      pstmt.setDate(2, date);
      try (ResultSet rset = pstmt.executeQuery()) {
        int temp_id = 1;
        while (rset.next()) {
          WorkSession ws =
              new WorkSession(
                  temp_id++, id, rset.getDate("session_date"), (short) 8, rset.getString("type"));
          switch (ws.getType()) {
            case DAY_OFF:
              dayOffsTemp.add(ws);
              break;
            default:
              break;
          }
        }
      }
    } catch (SQLException | IOException e) {
      logger.error("Error while retrieving dayoffs in a month by employeeid", e);
      throw new PersistentLayerException(e);
    }

    List<WorkSession> dayOffs = new ArrayList<>();

    for (WorkSession dayOff : dayOffsTemp) {
      LocalDate ldate = new LocalDate(dayOff.getDate());
      if (ldate.getDayOfWeek() < 6) {
        dayOffs.add(dayOff);
      }
    }
    return dayOffs.size();
  }
Пример #4
0
  /**
   * Returns the salary earned by a specific {@code Employee}'s id in a specific month.
   *
   * <p>Work days are overwritten by sick days.
   *
   * <p>Sick days are overwritten by free days.
   *
   * <p>If a sick day is on weekend then it does not get into the final salary.
   *
   * <p>If a day off is on weekend then it does not get into the final salary.
   *
   * <p>Salary is retrieved from the database. That's the base salary.
   *
   * <p>Base salary is for 20 worked days, with 8 hours per day.
   *
   * <p>Sick days, and days taken off have the same hourly rate as worked days.
   *
   * <p>Sick days, and days taken off are counted with 8 hours per day.
   *
   * <p>If a person does overtime (over 8 hours per day), then the plus hours' rate has a 1.5x
   * multiplier.
   *
   * <p>If a person works on Saturday, then the hour rate has 1.5x multiplier. Overtime is not
   * counted on these days.
   *
   * <p>If a person works on Sunday, then the hour rate has 2x multiplier. Overtime is not counted
   * on these days.
   *
   * <p>If a person starts working on a weekend day, and then he gets sick or decides to go
   * home(take a day off), then the day is not counted as work day, neither sick day nor free day.
   *
   * <p><b>Rules</b>
   *
   * <ul>
   *   <li>A person should work more than 4 hours per every work day on weekdays. After 10 work day
   *       with less equals than 4 hours per work day, the program throws an exception which
   *       indicates this.
   *   <li>A person should work more than 40 hours per week. If he doesn't apply to this
   *       expectations an exception is thrown, which indicates this.
   *   <li>A person should work more than 160 hours per month. If he doesn't apply to this
   *       expectations an exception is thrown, which indicates this.
   * </ul>
   *
   * <p>{@code SalaryException} collects these rule breaks. If any of these rules are broken, the
   * exception will be thrown. This exception will contain the salary, and the error messages.
   *
   * @see SalaryException
   * @param id the employee's id
   * @param date the date of the month (can be given any of the month's days) we want to analyze
   * @return the employee's salary in the specific month
   * @throws SalaryException if the rules above are broken
   */
  public static BigDecimal getSalaryInAMonthByEmployeeId(int id, Date date) throws SalaryException {
    List<WorkSession> workDaysTemp = new ArrayList<>();
    List<WorkSession> sickDaysTemp = new ArrayList<>();
    List<WorkSession> dayOffsTemp = new ArrayList<>();
    try (PreparedStatement pstmt =
        ConnectionHelper.getConnection()
            .prepareStatement(findWorkSessionsInAMonthWithATypeByEmployeeId)) {
      pstmt.setInt(1, id);
      pstmt.setDate(2, date);
      try (ResultSet rset = pstmt.executeQuery()) {
        int temp_id = 1;
        while (rset.next()) {
          WorkSession ws =
              new WorkSession(
                  temp_id++,
                  id,
                  rset.getDate("session_date"),
                  (short) rset.getInt("duration"),
                  rset.getString("type"));
          switch (ws.getType()) {
            case WORK:
              workDaysTemp.add(ws);
              break;
            case SICKNESS:
              sickDaysTemp.add(ws);
              break;
            case DAY_OFF:
              dayOffsTemp.add(ws);
              break;
            default:
              break;
          }
        }
      }
    } catch (SQLException | IOException e) {
      logger.error("Error while getting worksessions for calculating salary", e);
      throw new PersistentLayerException(e);
    }
    List<WorkSession> workDays = new ArrayList<>();
    List<WorkSession> sickDays = new ArrayList<>();
    List<WorkSession> dayOffs = new ArrayList<>();

    for (WorkSession workDay : workDaysTemp) {
      boolean contains = false;
      for (WorkSession sickDay : sickDaysTemp) {
        if (workDay.getDate().equals(sickDay.getDate())) {
          contains = true;
        }
      }
      for (WorkSession dayOff : dayOffsTemp) {
        if (workDay.getDate().equals(dayOff.getDate())) {
          contains = true;
        }
      }
      if (!contains) {
        workDays.add(workDay);
      }
    }
    for (WorkSession sickDay : sickDaysTemp) {
      boolean contains = false;
      for (WorkSession dayOff : dayOffsTemp) {
        if (sickDay.getDate().equals(dayOff.getDate())) {
          contains = true;
        }
      }
      LocalDate ldate = new LocalDate(sickDay.getDate());
      if (!contains && ldate.getDayOfWeek() < 6) {
        sickDays.add(sickDay);
      }
    }
    for (WorkSession dayOff : dayOffsTemp) {
      LocalDate ldate = new LocalDate(dayOff.getDate());
      if (ldate.getDayOfWeek() < 6) {
        dayOffs.add(dayOff);
      }
    }
    StringBuilder sb = new StringBuilder();
    int lessThanFourHourWorkDayCount = 0;
    for (WorkSession workDay : workDays) {
      LocalDate ldate = new LocalDate(workDay.getDate());
      if (workDay.getDuration() <= 4
          && ldate.getDayOfWeek() < 6) { // worked less than 4 hour on a weekday
        lessThanFourHourWorkDayCount++;
      }
    }
    if (lessThanFourHourWorkDayCount > 10) {
      sb = sb.append("Day expectation (4h/Day) BROKEN\n");
    }

    Map<Integer, Integer> map = new HashMap<>();

    LocalDate startOfMonth = new LocalDate(date.getTime());
    startOfMonth = startOfMonth.minusDays(startOfMonth.getDayOfMonth() - 1);
    LocalDate endOfMonth = startOfMonth.plusMonths(1);
    endOfMonth = endOfMonth.minusDays(1);
    int startWeek = startOfMonth.getWeekOfWeekyear();
    int endWeek = endOfMonth.getWeekOfWeekyear();
    while (startWeek <= endWeek) {
      map.put(startWeek, 0);
      startWeek++;
    }

    for (WorkSession workDay : workDays) {
      LocalDate ldate = new LocalDate(workDay.getDate());
      int weekWorkHours =
          getWorkedHoursOnAWeekByEmployeeId(workDay.getEmployee_id(), workDay.getDate());
      map.put(ldate.getWeekOfWeekyear(), weekWorkHours);
    }
    boolean XWorkHourPerWeekWarn = false;
    int count = 0;
    for (Entry<Integer, Integer> entry : map.entrySet()) {
      if (entry.getValue() < 40) {
        XWorkHourPerWeekWarn = true;
        count++;
      }
    }
    if (XWorkHourPerWeekWarn) {
      sb = sb.append("Week expectation (40h/Week) BROKEN\n");
    }

    int sumWorkedHours = 0;
    for (WorkSession workDay : workDays) {
      sumWorkedHours += workDay.getDuration();
    }
    if (sumWorkedHours < 160) {
      sb = sb.append("Month expectation (160h/Month) BROKEN\n");
    }

    BigDecimal baseSalary = new BigDecimal(0);
    try (PreparedStatement pstmt =
        ConnectionHelper.getConnection()
            .prepareStatement("select salary from employees where employee_id = ?")) {
      pstmt.setInt(1, id);
      try (ResultSet rset = pstmt.executeQuery()) {
        if (rset.next()) {
          baseSalary = rset.getBigDecimal("salary");
        }
      }
    } catch (SQLException | IOException e) {
      logger.error("error while retrieving baseSalary in calculating salary", e);
      throw new PersistentLayerException(e);
    }

    baseSalary = baseSalary.divide(new BigDecimal(20)).divide(new BigDecimal(8));
    // sickday's count * 8 hour
    BigDecimal salary =
        baseSalary.multiply(new BigDecimal(8)).multiply(new BigDecimal(sickDays.size()));
    // dayoff's count * 8 hour
    salary =
        salary.add(baseSalary.multiply(new BigDecimal(8)).multiply(new BigDecimal(dayOffs.size())));
    for (WorkSession workSession : workDays) {
      LocalDate ldate = new LocalDate(workSession.getDate());
      if (ldate.getDayOfWeek() < 6) { // weekdays
        if (workSession.getDuration() <= 8) { // no plus hours
          salary = salary.add(baseSalary.multiply(new BigDecimal(workSession.getDuration())));
        } else { // plus hours
          short plusHours = (short) (workSession.getDuration() - 8);
          salary = salary.add(baseSalary.multiply(new BigDecimal(8))); // normal hours
          salary =
              salary.add(
                  baseSalary
                      .multiply(new BigDecimal(1.5))
                      .multiply(new BigDecimal(plusHours))); // plus hours
        }
      } else { // saturday & sunday
        if (ldate.getDayOfWeek() == 6) { // saturday 1.5x multiplier
          salary =
              salary.add(
                  baseSalary
                      .multiply(new BigDecimal(1.5))
                      .multiply(new BigDecimal(workSession.getDuration())));
        } else if (ldate.getDayOfWeek() == 7) { // sunday 2x multiplier
          salary =
              salary.add(
                  baseSalary
                      .multiply(new BigDecimal(2))
                      .multiply(new BigDecimal(workSession.getDuration())));
        }
      }
    }
    try {
      return salary;
    } finally {
      if (sb.length() > 0) {
        logger.info("id=" + id + ", employee has problems with expectations: \n" + sb.toString());
        throw new SalaryException(salary, sb.toString());
      }
    }
  }
Пример #5
0
  /**
   * Returns the number of a specific employee's worked hours in a specific month.
   *
   * @param id the employee's id
   * @param date the date that provides the month (can be any day in that month) we want to analyze
   * @return the number of hours worked in that month
   */
  public static int getWorkedHoursInAMonthByEmployeeId(int id, Date date) {
    LocalDate startOfMonth = new LocalDate(date);
    startOfMonth = startOfMonth.minusDays(startOfMonth.getDayOfMonth() - 1);
    LocalDate endOfMonth = startOfMonth.plusMonths(1).minusDays(1);
    List<WorkSession> workDaysTemp = new ArrayList<>();
    List<WorkSession> sickDaysTemp = new ArrayList<>();
    List<WorkSession> dayOffsTemp = new ArrayList<>();
    try (PreparedStatement pstmt =
        ConnectionHelper.getConnection()
            .prepareStatement(
                "select session_date, type, sum(duration) duration from worksessions"
                    + " where employee_id = ? and session_date between ? and ? group by session_date, type")) {
      pstmt.setInt(1, id);
      pstmt.setDate(2, new Date(startOfMonth.toDate().getTime()));
      pstmt.setDate(3, new Date(endOfMonth.toDate().getTime()));
      try (ResultSet rset = pstmt.executeQuery()) {
        int temp_id = 1;
        while (rset.next()) {
          WorkSession ws =
              new WorkSession(
                  temp_id++,
                  id,
                  rset.getDate("session_date"),
                  (short) rset.getInt("duration"),
                  rset.getString("type"));
          switch (ws.getType()) {
            case WORK:
              workDaysTemp.add(ws);
              break;
            case SICKNESS:
              sickDaysTemp.add(ws);
              break;
            case DAY_OFF:
              dayOffsTemp.add(ws);
              break;
            default:
              break;
          }
        }
      }
    } catch (SQLException | IOException e1) {
      logger.error("Error while retrieving worked hours in a month by employeeid", e1);
      throw new PersistentLayerException(e1);
    }
    List<WorkSession> workDays = new ArrayList<>();

    for (WorkSession workDay : workDaysTemp) {
      boolean contains = false;
      for (WorkSession sickDay : sickDaysTemp) {
        if (workDay.getDate().equals(sickDay.getDate())) {
          contains = true;
        }
      }
      for (WorkSession dayOff : dayOffsTemp) {
        if (workDay.getDate().equals(dayOff.getDate())) {
          contains = true;
        }
      }
      if (!contains) {
        workDays.add(workDay);
      }
    }
    int sum = 0;
    for (WorkSession workSession : workDays) {
      sum += workSession.getDuration();
    }
    return sum;
  }