hr_lite 0.18.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c73e1512e67fbae1abb7b12f6134564974819e2055c937e3fabcb294a196bea9
4
- data.tar.gz: 93bd305c7aa148e6e2f034f9355cc15078ddf8252cf0af92f938da136b945ac1
3
+ metadata.gz: d99d3408ecc4296bfb60310343f56df91495a48a6bc277881f6ebbd79a57de80
4
+ data.tar.gz: 9286e4b08358dbbe9f360967a57b134aa0ee6d74841daf80310ad79b372ae7b2
5
5
  SHA512:
6
- metadata.gz: f4c2331de1a65bbfb074277c9a309b1276c213a55747fd8f8446c5d54c72a41edfb3087a950bfd19aff5fc00ed2b96130e20d200583e9e8970dc0edd10750806
7
- data.tar.gz: 25103c4830b09f09e13996557e926dfb4bde694fb0cb60a8f10d8adb355ba4f25d553b226ec38f039df395a339a832c4822ecd2a4aaa5ebbf5b6f111a957e88c
6
+ metadata.gz: a96b511a5031812bf57b8b10314c1316eb29857f25f0e5dd4e454caea586bf88c3feff01180e3d5bdd8da693421c52524c9da93038740266c8bf9c079dca24ed
7
+ data.tar.gz: dc3d6659e50a6421935556bb13db5a0749198e119b6bc01fa5a84415a913d26e4a38397c71f2e529c379fdc14663eb9afb8825c1f402e9723e7c1fb2ba933ba8
data/CHANGELOG.md CHANGED
@@ -7,6 +7,60 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.19.0] - 2026-09-30
11
+
12
+ Each night closes the day. A missed check-out becomes a half day, and
13
+ employees can fix a recent missed punch themselves. No migration.
14
+
15
+ ### Added
16
+
17
+ - **`HrLite::AttendanceCloseJob`**, scheduled by the host each night (a run
18
+ before noon closes the previous day, so retries are safe). On a working
19
+ day it checks out every punch still open at the day's end (23:59), marks the
20
+ day `half_day` (payroll pays
21
+ half and counts half as loss of pay), and emails the employee. Anyone who
22
+ never checked in is emailed that the day is absent; no record is written.
23
+ Weekends, holidays and approved leave (full or half day) are skipped. Run it
24
+ once a day: a re-run emails the no-shows again.
25
+ - **Self-fix.** With `config.self_regularization = { within_days:, per_week: }`,
26
+ a ticket that fills a missed punch on a working day, today or up to
27
+ `within_days` back, is approved as soon as the employee submits it, for up to
28
+ `per_week` days in a Monday–Sunday week. The punch is written the way an HR
29
+ approval writes it, with the usual audit row, and nobody is notified. Older
30
+ days, off days, fixes past the weekly limit, a change to a real punch, and a
31
+ day HR already regularized or rejected go to HR as ordinary tickets; the
32
+ flash says which happened. A check-out-only ticket for a day with no check-in
33
+ stays pending for HR.
34
+ `nil` (default) keeps HR as the only one who fixes punches. The ticket form
35
+ states the rule when it is on.
36
+ - The Leaves page links "Record leave for someone" for anyone who can approve
37
+ leave.
38
+ - The record-leave form says why somebody may be missing from the employee
39
+ list (no HR profile yet). Leadership gets a link to set one up.
40
+
41
+ ### Changed
42
+
43
+ - Approving a regularization ticket on a day the close job marked half day
44
+ sets it back to present. A half day HR set on purpose stays.
45
+ - Approving a ticket for a month whose payroll run is in review adds a warning
46
+ to that run, so the slip is recomputed before it is finalized.
47
+ - The admin overview and daily digest still count a day the close job checked
48
+ out as a missing checkout.
49
+
50
+ ### Fixed
51
+
52
+ - The sidebar, and the phone's More sheet, open scrolled to the current screen
53
+ instead of the top. A Manage item such as Approvals is no longer below the
54
+ fold.
55
+ - Page action buttons wrap on a narrow phone instead of running off the screen.
56
+
57
+ ### Upgrading
58
+
59
+ Schedule `HrLite::AttendanceCloseJob` daily at `55 23 * * * Asia/Kolkata` in
60
+ your job scheduler (a run before noon closes the previous day). To let employees fix their own recent misses, set
61
+ `c.self_regularization = { within_days: 2, per_week: 2 }` in the initializer.
62
+ No migration.
63
+
10
64
  ## [0.18.0] - 2026-09-29
11
65
 
12
66
  Salary follows leave. One migration (`paid_days` on leave requests, nullable;
data/README.md CHANGED
@@ -142,6 +142,9 @@ HrLite.configure do |c|
142
142
  PdfRenderer.render(template: template, assigns: assigns, cache_key: cache_key)
143
143
  }
144
144
  c.slip_release_day = 10 # employees see a slip from the 10th of the next month; nil (default) = on publish
145
+ # Self-fix: employees correct their own missed punch within 2 days, at most
146
+ # 2 a week. nil (default) = only HR fixes it, via a regularization ticket.
147
+ c.self_regularization = { within_days: 2, per_week: 2 }
145
148
 
146
149
  # Mirror promotions into your own user model (optional).
147
150
  c.on_designation_change = ->(user, designation) { user.update!(designation: designation) }
@@ -267,6 +270,13 @@ approved; regularization tickets (`/regularization_requests`) let someone who
267
270
  forgot to punch propose the real times for admin approval, which writes them
268
271
  onto the attendance record with a full audit trail.
269
272
 
273
+ With `config.self_regularization = { within_days: 2, per_week: 2 }`, a ticket that
274
+ fills a missed punch on a working day, today or up to 2 days back, is approved on
275
+ submit, by the employee, at most twice per Mon–Sun week. No approver is notified;
276
+ the audit row is the trail. Older days, off days, the third fix of a week, a change
277
+ to a real punch, a day HR already regularized or rejected, or a fix that cannot
278
+ apply (no check-in that day) stay ordinary tickets for HR.
279
+
270
280
  ### Holidays and calendar
271
281
 
272
282
  `bin/rails hr_lite:seed` inserts the three fixed-date national holidays
@@ -353,6 +363,7 @@ whatever you run). Each is idempotent and sends nothing on a quiet day.
353
363
  | `HrLite::DailyDigestJob` | each morning | Leadership digest: who is out today, pending approvals, flagged punches, missing checkouts |
354
364
  | `HrLite::PayrollAutoDraftJob` | monthly, on the 1st | Draft and compute the previous month's payroll from attendance, then notify leadership for review (publishing stays a human action) |
355
365
  | `HrLite::LeaveYearRolloverJob` | leave year's first day (Jan 1, or Jul 1 for a July–June year) | Materialize carry-forward into the new year's balances |
366
+ | `HrLite::AttendanceCloseJob` | each night, `55 23 * * * Asia/Kolkata` | Close the day: an open punch is checked out at 23:59 and marked half day; a run before noon (a retry, or a morning schedule that lets night shifts check out first) closes the previous day instead; nobody checked in stays absent. Each is emailed how to fix it. Skips weekends, holidays and approved leave. Run it once a day — a re-run tells the no-shows again. |
356
367
 
357
368
  ## Rake tasks
358
369
 
@@ -0,0 +1,21 @@
1
+ // Keeps the current screen in view. The rail and the phone's More sheet both
2
+ // scroll, and a Manage item sits below the fold. scrollIntoView is avoided on
3
+ // purpose: it would scroll the page as well as the menu.
4
+ (function () {
5
+ function centre(panel) {
6
+ var link = panel && panel.querySelector(".hrl-nav__link--active");
7
+ if (!link) return;
8
+ var box = panel.getBoundingClientRect();
9
+ var item = link.getBoundingClientRect();
10
+ panel.scrollTop += item.top - box.top - (box.height - item.height) / 2;
11
+ }
12
+
13
+ centre(document.querySelector(".hrl-side"));
14
+
15
+ var more = document.querySelector(".hrl-tabbar__more");
16
+ if (more) {
17
+ more.addEventListener("toggle", function () {
18
+ if (more.open) centre(more.querySelector(".hrl-sheet"));
19
+ });
20
+ }
21
+ })();
@@ -143,7 +143,7 @@
143
143
  .hrl-page__head { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem; margin: .25rem 0 .9rem; }
144
144
  .hrl-page__title { font-size: 1.25rem; font-weight: 700; margin: 0; }
145
145
  .hrl-page__sub { color: var(--hrl-muted); font-size: .86rem; margin: .15rem 0 0; width: 100%; }
146
- .hrl-page__actions { margin-left: auto; display: flex; gap: .5rem; }
146
+ .hrl-page__actions { margin-left: auto; display: flex; flex-wrap: wrap; gap: .5rem; }
147
147
 
148
148
  /* Cards */
149
149
  .hrl-card {
@@ -13,7 +13,7 @@ module HrLite
13
13
  def create
14
14
  @request = RegularizationRequest.new(request_params.merge(user_id: hr_current_user.id))
15
15
  if @request.save
16
- redirect_to regularization_requests_path, notice: "Ticket raised — an admin will review it."
16
+ redirect_to regularization_requests_path, notice: create_notice
17
17
  else
18
18
  render :new, status: :unprocessable_entity
19
19
  end
@@ -29,6 +29,15 @@ module HrLite
29
29
 
30
30
  private
31
31
 
32
+ def create_notice
33
+ rule = HrLite.config.self_regularization
34
+ return "Ticket raised — an admin will review it." unless rule
35
+ return "Fixed. #{helpers.pluralize(@request.self_fixes_left, 'self-fix')} left this week." if @request.approved?
36
+
37
+ "Sent to HR as a ticket — you can fix only a missed punch on a working day in the last #{rule[:within_days]} days yourself, " \
38
+ "#{rule[:per_week]} times a week."
39
+ end
40
+
32
41
  def request_params
33
42
  params.require(:regularization_request).permit(:date, :check_in_at, :check_out_at, :reason)
34
43
  end
@@ -0,0 +1,42 @@
1
+ module HrLite
2
+ # Closes the working day that ended last: a run at 23:55 closes today, and a
3
+ # retry or late run after midnight (or a morning schedule) closes yesterday.
4
+ # A punch left open is checked out at the day's end and paid as a half day.
5
+ # Nobody punched in already reads as absent (DayStatus), so they are only
6
+ # told. Leave days are left alone.
7
+ class AttendanceCloseJob < ApplicationJob
8
+ def perform(date: (Time.current - 12.hours).to_date)
9
+ return unless WorkingCalendar.new(date..date).working_day?(date)
10
+
11
+ on_leave = LeaveRequest.active_on(date).pluck(:user_id)
12
+ records = AttendanceRecord.for_date(date).index_by(&:user_id)
13
+ day = date.strftime("%d %b")
14
+ HrLite.active_employees(on: date).each do |user|
15
+ next if on_leave.include?(user.id)
16
+
17
+ record = records[user.id]
18
+ if record.nil? || record.check_in_at.nil?
19
+ tell(user, date, "attendance.missed_check_in", "You didn't check in on #{day} — marked absent")
20
+ elsif record.check_out_at.nil?
21
+ record.update!(check_out_at: date.end_of_day, status: "half_day",
22
+ regularization_note: AttendanceRecord::AUTO_CHECKOUT_NOTE)
23
+ tell(user, date, "attendance.missed_check_out", "You didn't check out on #{day} — marked half day")
24
+ end
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def tell(user, date, event, title)
31
+ rule = HrLite.config.self_regularization
32
+ body = if rule
33
+ "Fix it yourself by #{(date + rule[:within_days]).strftime('%d %b')} (up to #{rule[:per_week]} a week), " \
34
+ "or raise a ticket for HR."
35
+ else
36
+ "Raise a regularization ticket to get it fixed."
37
+ end
38
+ Notifications.publish(event, title: title, body: body, path: "/regularization_requests/new?date=#{date.iso8601}",
39
+ bell_to: [ user ], email_to: [ user ])
40
+ end
41
+ end
42
+ end
@@ -1,6 +1,7 @@
1
1
  module HrLite
2
2
  class AttendanceRecord < ApplicationRecord
3
3
  STATUSES = %w[present half_day].freeze
4
+ AUTO_CHECKOUT_NOTE = "Auto check-out: no check-out punched".freeze
4
5
 
5
6
  belongs_to :user, class_name: HrLite.config.user_class
6
7
  belongs_to :regularized_by, class_name: HrLite.config.user_class, optional: true
@@ -21,7 +21,7 @@ module HrLite
21
21
  validate :no_approved_leave_conflict
22
22
  end
23
23
 
24
- after_create :notify_requested
24
+ after_create :self_fix_or_notify
25
25
 
26
26
  scope :pending, -> { where(status: "pending") }
27
27
  scope :recent_first, -> { order(date: :desc, id: :desc) }
@@ -39,6 +39,27 @@ module HrLite
39
39
  AttendanceRecord.find_by(user_id: user_id, date: date)
40
40
  end
41
41
 
42
+ # config.self_regularization: a missed punch on a recent working day, under
43
+ # the weekly cap, is fixed by the employee without HR. A real punch, or a
44
+ # day HR already decided or rejected, stays HR's call.
45
+ def self_fixable?
46
+ rule = HrLite.config.self_regularization
47
+ return false unless rule && date >= Date.current - rule[:within_days] && WorkingCalendar.new(date..date).working_day?(date)
48
+
49
+ day = punch
50
+ fills_gap = (check_in_at.nil? || !day&.check_in_at) &&
51
+ (check_out_at.nil? || !day&.check_out_at || day.regularization_note == AttendanceRecord::AUTO_CHECKOUT_NOTE)
52
+ fills_gap && !day&.regularized? && !self.class.exists?(user_id: user_id, date: date, status: "rejected") &&
53
+ self_fixes_left.positive?
54
+ end
55
+
56
+ # Self-fixes the user still has in this ticket's Mon–Sun week.
57
+ def self_fixes_left
58
+ week = date.beginning_of_week(:monday)..date.end_of_week(:monday)
59
+ used = self.class.where(user_id: user_id, decided_by_id: user_id, status: "approved", date: week).count
60
+ HrLite.config.self_regularization[:per_week] - used
61
+ end
62
+
42
63
  # --- transitions -------------------------------------------------------
43
64
 
44
65
  # Applies the proposed times to the day's record (creating it if the
@@ -47,7 +68,7 @@ module HrLite
47
68
  # A merge that would produce a nonsense record (checkout before the
48
69
  # existing check-in, or a checkout with no check-in at all) raises
49
70
  # InvalidMerge with the real story so the admin knows what to fix.
50
- def approve!(actor:, note: nil)
71
+ def approve!(actor:, note: nil, notify: true)
51
72
  transition!("approved", actor, note) do
52
73
  # Re-checked at approval, not only at create: leave can be approved for
53
74
  # that day while the ticket waits in the queue, and DayStatus ranks
@@ -64,7 +85,8 @@ module HrLite
64
85
  raise InvalidMerge, "the day has no check-in — the ticket needs a check-in time too"
65
86
  end
66
87
 
67
- record.status = "present" if record.status.blank?
88
+ # Lifts only the close job's half day; one HR set on purpose stays.
89
+ record.status = "present" if record.status.blank? || record.regularization_note == AttendanceRecord::AUTO_CHECKOUT_NOTE
68
90
  record.regularized_by_id = actor.id
69
91
  record.regularized_at = Time.current
70
92
  record.regularization_note = "Ticket ##{id}: #{reason}"
@@ -75,7 +97,12 @@ module HrLite
75
97
  action: "regularize", subject: record, actor: actor,
76
98
  changes: { "date" => record.date.to_s, "ticket" => id, "note" => reason }
77
99
  )
100
+ # A slip computed before this fix still counts the old day; a recompute clears the note.
101
+ run = PayrollRun.find_by(period_month: date.beginning_of_month, status: "review")
102
+ run&.update!(warnings: run.warnings + [ "#{HrLite.display_name(user)}'s attendance on #{date.strftime('%d %b')} " \
103
+ "was fixed after compute — recompute" ])
78
104
  end
105
+ return true unless notify # self-fix: the flash and the audit row are the trail
79
106
 
80
107
  Notifications.publish(
81
108
  "regularization.approved",
@@ -174,6 +201,16 @@ module HrLite
174
201
  errors.add(:date, "is covered by your approved leave — cancel the leave first") if leave.exists?
175
202
  end
176
203
 
204
+ # A self-fix approve! can't merge (e.g. no check-in yet) -> an ordinary ticket.
205
+ def self_fix_or_notify
206
+ user.lock! if HrLite.config.self_regularization # one user's tickets at once can't both spend the last fix
207
+ return approve!(actor: user, note: "Self-fixed", notify: false) if self_fixable?
208
+
209
+ notify_requested
210
+ rescue InvalidMerge
211
+ notify_requested
212
+ end
213
+
177
214
  def notify_requested
178
215
  Notifications.publish(
179
216
  "regularization.requested",
@@ -30,8 +30,11 @@ module HrLite
30
30
  AttendanceRecord.for_date(@date).flagged.includes(:user)
31
31
  end
32
32
 
33
+ # AttendanceCloseJob fills check_out_at, so the days it closed count too.
33
34
  def missing_checkout_yesterday
34
- AttendanceRecord.for_date(@date - 1).missing_checkout.includes(:user)
35
+ yesterday = AttendanceRecord.for_date(@date - 1)
36
+ yesterday.missing_checkout.or(yesterday.where(regularization_note: AttendanceRecord::AUTO_CHECKOUT_NOTE))
37
+ .includes(:user)
35
38
  end
36
39
 
37
40
  def kpis
@@ -9,12 +9,19 @@
9
9
  <%= render "hr_lite/shared/form_errors", record: @request %>
10
10
  <div class="hrl-field">
11
11
  <%= label_tag :employee_code, "Employee (type a name or code)" %>
12
- <%= text_field_tag :employee_code, params[:employee_code], list: "hrl-employees", required: true, autocomplete: "off" %>
12
+ <%= text_field_tag :employee_code, params[:employee_code], list: "hrl-employees", required: true, autocomplete: "off", placeholder: "Start typing a name or code…" %>
13
13
  <datalist id="hrl-employees">
14
14
  <% @people.each do |p| %>
15
15
  <option value="<%= p.employee_code %>"><%= hr_display_name(p.user) %></option>
16
16
  <% end %>
17
17
  </datalist>
18
+ <p class="hrl-small hrl-muted">Someone missing? Only people with an HR profile are listed.
19
+ <% if hr_leadership? %>
20
+ <a href="<%= hr_lite.admin_employees_path %>">Set up their profile</a>
21
+ <% else %>
22
+ Ask leadership to set up their HR profile.
23
+ <% end %>
24
+ </p>
18
25
  </div>
19
26
  <div class="hrl-field">
20
27
  <%= f.label :leave_type_id, "Type" %>
@@ -4,6 +4,9 @@
4
4
  <div class="hrl-page__actions">
5
5
  <a class="hrl-btn" href="<%= hr_lite.leave_balances_path %>">Balances</a>
6
6
  <a class="hrl-btn" href="<%= hr_lite.comp_off_requests_path %>">Comp-off</a>
7
+ <% if hr_can?("leave.approve", scope: :team) %>
8
+ <a class="hrl-btn" href="<%= hr_lite.new_admin_leave_request_path %>">Record leave for someone</a>
9
+ <% end %>
7
10
  <a class="hrl-btn hrl-btn--primary" href="<%= hr_lite.new_leave_request_path %>">Apply</a>
8
11
  </div>
9
12
  </div>
@@ -6,6 +6,9 @@
6
6
  <section class="hrl-card">
7
7
  <%= form_with model: @request, url: hr_lite.regularization_requests_path, scope: :regularization_request, local: true do |f| %>
8
8
  <%= render "hr_lite/shared/form_errors", record: @request %>
9
+ <% if (rule = HrLite.config.self_regularization) %>
10
+ <p class="hrl-small hrl-muted">A missed punch on a working day from today back to <%= rule[:within_days] %> days ago is fixed as soon as you submit, up to <%= rule[:per_week] %> times a week. Anything else goes to HR as a ticket.</p>
11
+ <% end %>
9
12
  <div class="hrl-field">
10
13
  <%= f.label :date, "Which day needs fixing?" %>
11
14
  <%= f.date_field :date, value: @request.date&.strftime("%Y-%m-%d"), max: Date.current %>
@@ -125,6 +125,7 @@
125
125
 
126
126
  <%= javascript_include_tag "hr_lite/confirm", defer: true %>
127
127
  <%= javascript_include_tag "hr_lite/mention", defer: true %>
128
+ <%= javascript_include_tag "hr_lite/nav", defer: true %>
128
129
  <%= yield :scripts %>
129
130
  </body>
130
131
  </html>
@@ -14,7 +14,7 @@ module HrLite
14
14
  # the HR shell; nil (default) shows nothing.
15
15
  :notifications
16
16
 
17
- attr_reader :leave_year_start_month, :slip_release_day
17
+ attr_reader :leave_year_start_month, :slip_release_day, :self_regularization
18
18
 
19
19
  # Misconfiguration must fail at boot, not as production 500s on every
20
20
  # balance screen. Accepts "7" (ENV-friendly) and validates 1..12.
@@ -36,6 +36,15 @@ module HrLite
36
36
  @slip_release_day = day
37
37
  end
38
38
 
39
+ # nil = only HR fixes a missed punch. { within_days: 2, per_week: 2 } = an
40
+ # employee may fix their own day for 2 days after it, at most 2 a week.
41
+ def self_regularization=(value)
42
+ ok = value.nil? || (value.is_a?(Hash) && %i[within_days per_week].all? { |k| value[k].is_a?(Integer) && value[k].positive? })
43
+ raise ArgumentError, "self_regularization must be nil or { within_days:, per_week: } (positive integers), got #{value.inspect}" unless ok
44
+
45
+ @self_regularization = value
46
+ end
47
+
39
48
  # 0.1.0 pre-release name for public_url_base; kept as an alias so early
40
49
  # adopters' initializers don't break.
41
50
  alias_method :mail_link_base, :public_url_base
@@ -77,6 +86,7 @@ module HrLite
77
86
  @back_link = nil # optional {label:, url:} for the shell nav
78
87
  @leave_year_start_month = 1 # 1 = calendar year; 7 = July–June leave year
79
88
  @slip_release_day = nil # e.g. 10 = slips open on the 10th of the next month
89
+ @self_regularization = nil # e.g. { within_days: 2, per_week: 2 } — employees fix their own missed punch
80
90
 
81
91
  # Leadership onboarding/offboarding. onboard_user must return a saved
82
92
  # user record (default: create on user_class with whatever of
@@ -18,6 +18,8 @@ module HrLite
18
18
  "leave.cancelled" => { bell: true, email: false, leadership_email: true, leadership_bell: false },
19
19
  "attendance.flagged" => { bell: true, email: false, leadership_email: false, leadership_bell: false },
20
20
  "attendance.regularized" => { bell: true, email: true, leadership_email: true, leadership_bell: false },
21
+ "attendance.missed_check_in" => { bell: true, email: true, leadership_email: false, leadership_bell: false },
22
+ "attendance.missed_check_out" => { bell: true, email: true, leadership_email: false, leadership_bell: false },
21
23
  "payroll.finalized" => { bell: false, email: false, leadership_email: true, leadership_bell: true },
22
24
  "payroll.published" => { bell: true, email: true, leadership_email: true, leadership_bell: false },
23
25
  "kudos.mentioned" => { bell: true, email: true, leadership_email: false, leadership_bell: false },
@@ -1,3 +1,3 @@
1
1
  module HrLite
2
- VERSION = "0.18.0"
2
+ VERSION = "0.19.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hr_lite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.0
4
+ version: 0.19.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - kshitiz sinha
@@ -67,6 +67,7 @@ files:
67
67
  - app/assets/javascripts/hr_lite/confirm.js
68
68
  - app/assets/javascripts/hr_lite/geo_punch.js
69
69
  - app/assets/javascripts/hr_lite/mention.js
70
+ - app/assets/javascripts/hr_lite/nav.js
70
71
  - app/assets/javascripts/hr_lite/print.js
71
72
  - app/assets/stylesheets/hr_lite/application.css
72
73
  - app/assets/stylesheets/hr_lite/hr_lite.css
@@ -136,6 +137,7 @@ files:
136
137
  - app/helpers/hr_lite/application_helper.rb
137
138
  - app/jobs/hr_lite/application_job.rb
138
139
  - app/jobs/hr_lite/approval_escalation_job.rb
140
+ - app/jobs/hr_lite/attendance_close_job.rb
139
141
  - app/jobs/hr_lite/daily_digest_job.rb
140
142
  - app/jobs/hr_lite/document_expiry_job.rb
141
143
  - app/jobs/hr_lite/leave_year_rollover_job.rb