我已经构建了一个 Rails 应用程序,它记录员工时间(上类/下类)并计算总小时数,允许导出到 CSV/PDF,根据日期搜索考勤卡等。

我真正想做的是通过某种方法的范围来实现工资核算期。

工资核算期从星期日开始,并在 14 天后的星期六结束。编写这样的范围的最佳方法是什么?还可以将工资单期间的周分为两个星期吗?

我写了这些范围,但它们有缺陷:

scope :payroll_week_1, -> {
  start = Time.zone.now.beginning_of_week - 1.day
  ending = Time.zone.now.end_of_week - 1.day
  where(clock_in: start..ending)
}
scope :payroll_week_2, -> {
  start = Time.zone.now.end_of_week.beginning_of_day
  ending = Time.zone.now.end_of_week.end_of_day + 6.days
  where(clock_in: start..ending)
}

如果您目前正处于工资核算期,这些就可以工作,但是一旦您过了周末,范围就不再起作用,因为我的时间安排基于 Time.zone.now
有没有办法真正做到这一点?即使我必须设置某种静态范围或值,即 4 月 10 日 - 23 日是工资核算期 1,等等。我真的不确定如何解决这个问题以及什么可能有效。到目前为止,我所写的内容在当前的支付期内有效,但随着时间的推移,范围会发生变化。

任何帮助将不胜感激。

最佳答案

我想你想要的是创建一个范围,它可以接收一个 start_day 作为参数:

scope :payroll_week_starting, -> (start_day) {
  where(clock_in: start_day..(start_day + 1.week))
}

然后,将来您可以在支付期的第一天调用您的示波器:
ModelName.payroll_week_starting(Date.parse('31/12/2015'))

更新:

根据您的评论,您似乎正在从架构的角度寻找更多信息。在不了解您的数据库架构的情况下很难为您提供帮助,因此我将从高层次开始。

假设您有一个 Employee 模型和一个带有 Shiftclock_in 字段的 clock_out 模型。您可能还需要一个名为 PayPeriod 的模型,其中包含 start_dateend_date 字段。

每个 Employee has_many :shifts 和每个 PayPeriod has_many :shifts
您可以在 PayPeriod 上添加几个类方法,以便您可以为任何给定的日期时间查找和/或创建 PayPeriod
def self.for(time)
  find_by("start_date < ? AND end_date > ?", time, time)
end

def self.create_for(time)
  # yday is the number of days into the current year
  period_start_yday = 14 * (time.yday / 14)
  start_date = Date.new(time.year) + period_start_yday.days
  next_year = Date.new(time.year) + 1.year
  create(
    start_date: start_date,
    end_date: [start_date + 14.days, last_day_of_year].min,
  )
end

def self.find_or_create_for(time)
  for(time) || create_for(time)
end
create_for 逻辑相当复杂,但举个例子可以帮助你理解:

假设我今天打卡了 May 17th, 2016 ,今天的 yday138 ,如果你使用 integer division(ruby 的默认值)除以 14(你的支付周期的长度),你会得到 9。通过再次乘以 14,你将得到 126,这是最新的 yday 可被 14 整除。如果将这个天数加到今年年初,您将得到 PayPeriod 的开头。 PayPeriod 的结尾是 start_date 之后的 14 天,但不会滚动到下一年。

然后我要做的是向 before_save 添加 Shift 回调以查找或创建相应的 PayPeriod
before_save :associate_pay_period

def associate_pay_period
  self.pay_period_id = PayPeriod.find_or_create_for(clock_in)
end

那么每个 PayPeriod 都会有一堆 Shift ,每个 Shift 都属于一个 PayPeriod

例如,如果您想获得特定员工在特定 PayPeriod 期间的所有类次(可能总结该 PayPeriod 的工作时间),则向 Shift 添加一个范围:
scope :for, -> (user) { where(user: user) }

并调用 pay_period.shifts.for(user)
更新#2:

另一个(更简单)我认为(如果你不想创建一个实际的 PayPeriod 模型),就是向具有 clock_in 的模型添加一个方法(我将把它称为 Shift ):
def pay_period
  clock_in.to_date.mjd / 14
end

这基本上只是将任何时钟时间归结为一个代表 14 天周期的整数。然后你可以打电话
Shift.all.group_by { |shift| shift.pay_period }

如果您需要将每个 pay_period 包含在一个日历年内,您可以执行以下操作:
def pay_period
  [clock_in.year, clock_in.to_date.yday / 14]
end

关于ruby-on-rails - Rails 确定工资核算期,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37264645/

10-12 20:40