Вычислять остатки из joining_date на ежегодной основе

#ruby-on-rails

#ruby-on-rails

Вопрос:

Например, сотруднику разрешено 15 отпусков в год. Моя функция вычисляет общее количество листьев allover. Но я хочу рассчитать дату присоединения с момента завершения года, а по завершении года с даты присоединения разрешенные отпуска обновляются до 15.он метод, который вычисляет общее количество отпусков сотрудника.

 class Employee < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  acts_as_paranoid
  devise :database_authenticatable,
         :recoverable, :rememberable, :validatable

  validates :email, presence: true,
            format: { with: /A[w -.] @[a-zd-] (.[a-zd-] )*.[a-z] z/i,
                      message: "is not valid"
                    }
  validates :first_name, :last_name, :address, :city, :country, presence: true, format: { with: /[a-z] /i ,
    message: "only allows letters" }
  validates :joining_date, :bank_name, :bank_title, presence: true
  validates :current_salary, :allowed_leaves, numericality: true, presence: true
  validates :bank_account_id, uniqueness:true, numericality: true, presence: true, length: { minimum: 16, maximum: 16}
  has_many :increments, dependent: :destroy
  has_many :salaries, dependent: :destroy
  has_many :leaves, dependent: :destroy
  has_many :designations, dependent: :destroy
  has_many :employee_projects, dependent: :destroy
  has_many :projects, through: :employee_projects
  has_many :timelogs, dependent: :destroy
  has_many :medical_applications, dependent: :destroy
  before_update :update_leaves, :if => :allowed_leaves_changed?
  
  def display_name
    [first_name, last_name].join(' ')
  end

  def self.send_and_create_salary_slips
    send_salary_slips
  end

  def update_leaves
    taken_leaves = self.leaves.where(status: "Approved").count
    allowed_leaves = self.allowed_leaves
    total_leaves = (allowed_leaves-taken_leaves)
    self.update_column(:availed_leaves, total_leaves) 
  end

  def create_salary_slip
    salary = self.salaries.new
    salary.gross_salary = self.current_salary
    salary.basic_salary = self.current_salary
    salary.month = Date.today.month
    salary.year = Date.today.year
    salary.status = "pending"
    salary.save!
  end

  def self.send_salary_slips
    self.all.each do |employee|
      salary_slip = employee.salaries.last
      EmployeeMailer.send_salary_slip(salary_slip, employee).deliver if salary_slip.present?

      employee.create_salary_slip
    end
  end
end
  

Модель leave — это hear

 class Leave < ApplicationRecord
  PENDING = "Pending"
  Approved = "Approved"
  REJECTED = "Rejected"

  belongs_to :employee
  before_save :save_status
  after_update :calculate_availed_leave
  validates :leave_date, :leave_description, presence: true

  def allowed?
    self.employee.availed_leaves > 0
  end

  def display_status
    {
      PENDING => "Pending",
      Approved => "Approved",
      REJECTED => "Rejected",
    }[status.to_s]
  end

  def Approved?
    status == Approved
  end

  def REJECTED?
    status == REJECTED
  end

  private

  def save_status
    self.status ||= "Pending" # note self.status = 'P' if self.status.nil? might be safer (per @frontendbeauty)
  end

  def calculate_availed_leave
    date = self.employee.joining_date   1.year
    apply_date = self.leave_date
    if apply_date < date
      taken_leaves = self.employee.leaves.where(status: "Approved").count
      availed_leaves = self.employee.allowed_leaves - taken_leaves
      self.employee.update(availed_leaves: availed_leaves)
    elsif apply_date < new_date
      allowed_leaves = self.employee.allowed_leaves
      self.employee.update(availed_leaves: allowed_leaves)
   end
 end
end
  

Комментарии:

1. Пропорционально ли количество разрешенных листьев? То есть, в его 4-месячную годовщину ему разрешено занимать 5 дней? Или ему разрешено взять отпуск только на 15 дней после годовщины? На дату его присоединения 1.год 1.день у него будет 30 дней или только 15?

2. Сотруднику разрешается брать отпуск только на 15 дней после его юбилейной даты

3. @SteveTurczyn Я рассчитываю отпуск с даты присоединения до завершения года. по завершении года увольнения сотрудников начинаются снова с 15. Если сотрудник подал заявку на 15 отпусков в год, то ему не разрешается подавать заявку на отпуска

4. Может ли он перенести? То есть, если в прошлом году он взял только 12, на его годовщину ему нужно взять 15 или 18?

5. @SteveTurczyn Нет, каждый год ему нужно брать 15

Ответ №1:

Спасибо за публикацию дополнительной информации. Теперь я вижу, что этот метод заключается в after_update обновлении общего и доступного отпуска в employees таблице.

Неясно, как долго вы будете хранить записи об отпусках в системе, но если у вас нет конкретных планов по очистке записей, вам нужно убедиться, что вы не обновляете доступные даты сотрудника при повторном сохранении записи об отпуске, скажем, трехлетней давности.

Я также отмечаю, что вы сохраняете оставшийся доступный отпуск в записи о сотруднике, а это значит, что есть вероятность, что он может стать неправильным. Я думаю, что лучше вычислять по мере необходимости.

Итак, я бы добавил следующие методы в запись о сотруднике.

 class Employee < ActiveRecord

  def allocated_leave_days(date=nil)
    date ||= Date.today
    date > joining_date   1.year ? 15 : 0
  end

  def year_to_examine(date=nil)
    date ||= Date.today
    end_date = joining_date
    end_date = end_date   1.year while end_date < date
    start_date = [joining_date, end_date - 1.year].max
    (start_date..end_date)
  end

  def taken_leave_days(date=nil)
    date ||= Date.today
    leaves.where(status: 'Approved', leave_date: year_to_examine(date)).count
  end

  def remaining_leave_days(date=nil)
    date ||= Date.today
    [allocated_leave_days(date) - taken_leave_days(date), 0].max
  end

end
  

Итак, теперь, если вы хотите узнать права сотрудника сегодня, вы должны сделать my_employee.allocated_leave_days или (для некоторой даты в будущем или прошлом) my_employee.allocated_leave_days(my_test_date)

Если вы хотите узнать, сколько дней у него осталось, вы бы сделали my_employee.remaining_leave_days или (для некоторой даты в будущем году) my_employee.remaining_leave_days(my_test_date)

Комментарии:

1. сэр, отпуск сотрудника за текущий год завершен в этом году, когда я выбираю дату после года из joining_date, он все еще не подает заявку на отпуск

2. Какой из методов не работает? Я не совсем понимаю, о чем вы говорите.

3. @ SteveTurczyn по завершении года увольнения сотрудников начинаются снова с 15. Но вышеупомянутый метод снова не начинается с 15. когда увольнение сотрудника завершено, разрешенный отпуск начинается снова с 15

4. Вам нужно указать, что вы подразумеваете под «вышеуказанным методом»… Я дал вам четыре метода. Если интересующая вас дата больше, чем join_date 1.year, то allocated_leave_days всегда возвращается 15. taken_leve_days Всегда возвращает фактические утвержденные отпуска за текущий год сотрудника. remaining_leave_days дает вам разницу между ними. Вы должны быть более четкими в своих вопросах. `