hr_lite 0.52.0 → 0.54.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 +4 -4
- data/CHANGELOG.md +17 -0
- data/README.md +5 -2
- data/app/assets/javascripts/hr_lite/emoji_pick.js +4 -4
- data/app/assets/javascripts/hr_lite/vendor/turbo.min.js +28 -0
- data/app/assets/stylesheets/hr_lite/hr_lite.css +7 -6
- data/app/controllers/hr_lite/admin/attendances_controller.rb +2 -0
- data/app/controllers/hr_lite/admin/comp_off_requests_controller.rb +1 -1
- data/app/controllers/hr_lite/admin/documents_controller.rb +1 -1
- data/app/controllers/hr_lite/admin/expenses_controller.rb +13 -1
- data/app/controllers/hr_lite/admin/leave_requests_controller.rb +1 -1
- data/app/controllers/hr_lite/admin/regularization_requests_controller.rb +1 -1
- data/app/controllers/hr_lite/admin/statutory_rate_cards_controller.rb +2 -1
- data/app/controllers/hr_lite/admin/tax_declarations_controller.rb +2 -1
- data/app/controllers/hr_lite/admin/work_locations_controller.rb +1 -1
- data/app/controllers/hr_lite/home_controller.rb +0 -9
- data/app/controllers/hr_lite/loans_controller.rb +1 -1
- data/app/helpers/hr_lite/application_helper.rb +21 -2
- data/app/models/hr_lite/attendance_record.rb +7 -4
- data/app/models/hr_lite/salary_slip.rb +2 -1
- data/app/models/hr_lite/statutory_rate_card_record.rb +6 -0
- data/app/views/hr_lite/admin/attendances/index.html.erb +4 -4
- data/app/views/hr_lite/admin/attendances/show.html.erb +1 -1
- data/app/views/hr_lite/admin/benefits/index.html.erb +10 -4
- data/app/views/hr_lite/admin/comp_off_requests/show.html.erb +1 -1
- data/app/views/hr_lite/admin/documents/index.html.erb +2 -2
- data/app/views/hr_lite/admin/employees/show.html.erb +2 -1
- data/app/views/hr_lite/admin/expense_categories/index.html.erb +1 -1
- data/app/views/hr_lite/admin/expenses/index.html.erb +4 -2
- data/app/views/hr_lite/admin/holidays/index.html.erb +2 -1
- data/app/views/hr_lite/admin/hr_requests/index.html.erb +2 -2
- data/app/views/hr_lite/admin/hr_requests/show.html.erb +1 -1
- data/app/views/hr_lite/admin/leave_requests/show.html.erb +1 -1
- data/app/views/hr_lite/admin/leave_types/index.html.erb +2 -2
- data/app/views/hr_lite/admin/loans/new.html.erb +1 -1
- data/app/views/hr_lite/admin/office_locations/index.html.erb +1 -1
- data/app/views/hr_lite/admin/overview/index.html.erb +10 -31
- data/app/views/hr_lite/admin/payroll_line_items/new.html.erb +2 -1
- data/app/views/hr_lite/admin/payroll_runs/index.html.erb +1 -1
- data/app/views/hr_lite/admin/payroll_runs/show.html.erb +6 -4
- data/app/views/hr_lite/admin/performance_plans/_form.html.erb +2 -1
- data/app/views/hr_lite/admin/policies/index.html.erb +1 -1
- data/app/views/hr_lite/admin/policies/new.html.erb +2 -1
- data/app/views/hr_lite/admin/regularization_requests/show.html.erb +1 -1
- data/app/views/hr_lite/admin/roles/_form.html.erb +2 -1
- data/app/views/hr_lite/admin/roles/edit.html.erb +4 -2
- data/app/views/hr_lite/admin/roles/index.html.erb +1 -1
- data/app/views/hr_lite/admin/statutory_rate_cards/_form.html.erb +11 -7
- data/app/views/hr_lite/admin/tax_declarations/show.html.erb +6 -4
- data/app/views/hr_lite/admin/wfh_requests/show.html.erb +1 -1
- data/app/views/hr_lite/approvals/index.html.erb +4 -3
- data/app/views/hr_lite/attendance/_custom_status.html.erb +7 -9
- data/app/views/hr_lite/attendance/_punch_card.html.erb +8 -0
- data/app/views/hr_lite/attendance/show.html.erb +5 -3
- data/app/views/hr_lite/home/index.html.erb +4 -3
- data/app/views/hr_lite/leave_requests/_balance_chips.html.erb +2 -1
- data/app/views/hr_lite/loans/index.html.erb +1 -1
- data/app/views/hr_lite/resignations/show.html.erb +2 -1
- data/app/views/hr_lite/salary_slips/_slip_detail.html.erb +5 -5
- data/app/views/hr_lite/salary_slips/pdf.html.erb +1 -0
- data/app/views/hr_lite/work_time/_bars.html.erb +4 -3
- data/app/views/layouts/hr_lite/application.html.erb +7 -0
- data/app/views/layouts/hr_lite/mailer.html.erb +10 -2
- data/app/views/layouts/hr_lite/mailer.text.erb +4 -1
- data/config/routes.rb +1 -1
- data/lib/hr_lite/amount_in_words.rb +7 -5
- data/lib/hr_lite/configuration.rb +4 -0
- data/lib/hr_lite/statutory_seeds.rb +1 -1
- data/lib/hr_lite/version.rb +1 -1
- metadata +2 -1
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
<section class="hrl-card">
|
|
34
34
|
<h2 class="hrl-card__title">Reject</h2>
|
|
35
35
|
<%= form_with url: hr_lite.reject_admin_wfh_request_path(@request), method: :post, local: true do |f| %>
|
|
36
|
-
<div class="hrl-field"><%= f.label :decision_note, "Remark (required)", for: "reject_note" %><%= f.text_area :decision_note, id: "reject_note" %></div>
|
|
36
|
+
<div class="hrl-field"><%= f.label :decision_note, "Remark (required)", for: "reject_note" %><%= f.text_area :decision_note, id: "reject_note", required: true %></div>
|
|
37
37
|
<div class="hrl-form-actions"><%= f.button "Reject", type: :submit, class: "hrl-btn hrl-btn--danger" %></div>
|
|
38
38
|
<% end %>
|
|
39
39
|
</section>
|
|
@@ -45,13 +45,14 @@
|
|
|
45
45
|
</td>
|
|
46
46
|
</tr>
|
|
47
47
|
<% end %>
|
|
48
|
-
<%# The HR queues this viewer decides; Open lands on
|
|
48
|
+
<%# The HR queues this viewer decides; Open lands on the request itself where it has a page. %>
|
|
49
49
|
<% rows.each do |tab, record| %>
|
|
50
|
+
<% what, href = hrl_inbox_item(tab, record) %>
|
|
50
51
|
<tr>
|
|
51
|
-
<td data-label="Request"><strong><%=
|
|
52
|
+
<td data-label="Request"><strong><%= what %></strong></td>
|
|
52
53
|
<td data-label="From"><%= hr_display_name(record.user) %></td>
|
|
53
54
|
<td data-label="Waiting"><%= time_ago_in_words(record.created_at) %></td>
|
|
54
|
-
<td data-label=""><a class="hrl-btn" href="<%=
|
|
55
|
+
<td data-label=""><a class="hrl-btn" href="<%= href %>">Open</a></td>
|
|
55
56
|
</tr>
|
|
56
57
|
<% end %>
|
|
57
58
|
</tbody>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
<%# The person's own status
|
|
1
|
+
<%# The person's own status, Slack-style. Independent of check-in. Quick picks are words: no emoji in the UI. %>
|
|
2
2
|
<% custom = status.custom
|
|
3
|
-
picks =
|
|
3
|
+
picks = [ "In a meeting", "On a call", "Focus time", "At lunch", "Commuting", "Travelling", "At a client", "Out sick" ] %>
|
|
4
4
|
<% if custom %>
|
|
5
5
|
<div class="hrl-row hrl-row--mb hrl-small">
|
|
6
6
|
<span class="hrl-custom-status"><% if custom.emoji %><span aria-hidden="true"><%= custom.emoji %></span> <% end %><%= custom.title || "Status" %></span>
|
|
@@ -10,15 +10,13 @@
|
|
|
10
10
|
<% end %>
|
|
11
11
|
<details>
|
|
12
12
|
<summary class="hrl-btn hrl-btn--block"><%= custom ? "Change my status" : "Set a status" %></summary>
|
|
13
|
-
<%= form_with url: hr_lite.status_work_mode_path, method: :post, local: true
|
|
14
|
-
<div class="hrl-field"><label for="st-
|
|
15
|
-
<input class="hrl-input" id="st-
|
|
16
|
-
<div class="hrl-
|
|
17
|
-
<% picks.each do |
|
|
13
|
+
<%= form_with url: hr_lite.status_work_mode_path, method: :post, local: true do %>
|
|
14
|
+
<div class="hrl-field"><label for="st-text">What's your status?</label>
|
|
15
|
+
<input class="hrl-input" id="st-text" name="text" maxlength="100" value="<%= custom&.title %>" placeholder="e.g. Visiting the Ladakh camp">
|
|
16
|
+
<div class="hrl-row hrl-mt" role="group" aria-label="Quick picks">
|
|
17
|
+
<% picks.each do |text| %><button type="button" class="hrl-btn" data-hrl-pick="<%= text %>"><%= text %></button><% end %>
|
|
18
18
|
</div>
|
|
19
19
|
</div>
|
|
20
|
-
<div class="hrl-field"><label for="st-text">What's your status?</label>
|
|
21
|
-
<input class="hrl-input" id="st-text" name="text" maxlength="100" value="<%= custom&.title %>" placeholder="e.g. Visiting the Ladakh camp"></div>
|
|
22
20
|
<div class="hrl-field"><label for="st-clear">Clear after</label>
|
|
23
21
|
<%= select_tag :clear_after, options_for_select([ [ "30 minutes", "30" ], [ "1 hour", "60" ], [ "4 hours", "240" ], [ "Today", "today" ], [ "Don't clear", "never" ] ], "today"), id: "st-clear" %></div>
|
|
24
22
|
<button type="submit" class="hrl-btn hrl-btn--primary">Save status</button>
|
|
@@ -93,6 +93,14 @@
|
|
|
93
93
|
</fieldset></div>
|
|
94
94
|
<% end %>
|
|
95
95
|
<button type="submit" class="hrl-btn hrl-btn--primary hrl-btn--big hrl-btn--block"><%= record&.check_out_at ? "Check in again" : "Check in" %></button>
|
|
96
|
+
<% if HrLite.config.attendance_slots && !record&.check_out_at %>
|
|
97
|
+
<%# The late rules AttendancePuncher#apply_slot_rules applies, shifted by the person's buffer like there. %>
|
|
98
|
+
<% shift = HrLite::EmployeeProfile.where(user_id: hr_current_user.id).pick(:buffer_minutes).to_i
|
|
99
|
+
by = HrLite::AttendanceSlot.start_minute_for(hr_current_user.id, Date.current) + HrLite::AttendanceSlot::GRACE_MINUTES + shift
|
|
100
|
+
at = ->(minute) { HrLite::AttendanceSlot.label(minute + shift) } %>
|
|
101
|
+
<p class="hrl-small hrl-mt">Check in by <strong><%= HrLite::AttendanceSlot.label(by) %></strong>. Later adds 30 min to your day for every half hour;
|
|
102
|
+
after <%= at.(HrLite::AttendanceSlot::CARRY_AFTER_MINUTE) %> also 1 hour on each of the next 2 working days; after <%= at.(HrLite::AttendanceSlot::HALF_DAY_AFTER_MINUTE) %> the day is a half day.</p>
|
|
103
|
+
<% end %>
|
|
96
104
|
<p class="hrl-small hrl-muted" data-hrl-geo-status role="status" aria-live="polite"></p>
|
|
97
105
|
<% end %>
|
|
98
106
|
<% elsif record.check_out_at.nil? %>
|
|
@@ -20,9 +20,11 @@
|
|
|
20
20
|
</div>
|
|
21
21
|
<%= render "hr_lite/attendance/month_grid", month: @month, day_status: @day_status, pending_dates: @pending_dates,
|
|
22
22
|
link_builder: ->(d) { hr_lite.attendance_path(month: @month.strftime("%Y-%m"), day: d.iso8601, anchor: "day") if d <= Date.current } %>
|
|
23
|
-
<p class="hrl-small hrl-muted hrl-mt">Forgot to check in or out on some day
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
<p class="hrl-small hrl-muted hrl-mt">Forgot to check in or out on some day?</p>
|
|
24
|
+
<div class="hrl-row">
|
|
25
|
+
<a class="hrl-btn" href="<%= hr_lite.new_regularization_request_path %>">Raise a regularization ticket</a>
|
|
26
|
+
<a class="hrl-btn" href="<%= hr_lite.regularization_requests_path %>">My tickets</a>
|
|
27
|
+
</div>
|
|
26
28
|
</section>
|
|
27
29
|
|
|
28
30
|
<% if HrLite.config.attendance_slots %>
|
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
<h1 class="hrl-page__title">Hello, <%= hr_display_name(hr_current_user) %></h1>
|
|
3
3
|
</div>
|
|
4
4
|
|
|
5
|
-
<%
|
|
5
|
+
<% waiting = @waiting + hrl_inbox_count %>
|
|
6
|
+
<% if waiting.positive? %>
|
|
6
7
|
<section class="hrl-card">
|
|
7
|
-
<h2 class="hrl-card__title"><%= pluralize(
|
|
8
|
-
<a class="hrl-btn hrl-btn--primary hrl-mt" href="<%=
|
|
8
|
+
<h2 class="hrl-card__title"><%= pluralize(waiting, "request") %> waiting on you</h2>
|
|
9
|
+
<a class="hrl-btn hrl-btn--primary hrl-mt" href="<%= hr_lite.approvals_path %>">Review requests</a>
|
|
9
10
|
</section>
|
|
10
11
|
<% end %>
|
|
11
12
|
|
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
<div class="hrl-row">
|
|
8
8
|
<% types.each do |type| %>
|
|
9
9
|
<% balance = HrLite::LeaveBalance.for(user, type, HrLite::LeaveYear.current_key) %>
|
|
10
|
+
<% pending = HrLite::LeaveRequest.pending.where(user_id: user.id, leave_type_id: type.id, start_date: HrLite::LeaveYear.range(HrLite::LeaveYear.current_key)).sum(&:days_count) %>
|
|
10
11
|
<span class="hrl-badge hrl-badge--type" style="--hrl-type: <%= type.color %>">
|
|
11
|
-
<%= type.name %> · <%= hrl_days(balance.available) %> of <%= hrl_days(balance.entitled) %> left<% if (held = balance.penalty_days).positive? %> · <%= hrl_days(held) %> held for penalties<% end %>
|
|
12
|
+
<%= type.name %> · <%= hrl_days(balance.available) %> of <%= hrl_days(balance.entitled) %> left<% if pending.positive? %> · <%= hrl_days(pending) %> pending<% end %><% if (held = balance.penalty_days).positive? %> · <%= hrl_days(held) %> held for penalties<% end %>
|
|
12
13
|
</span>
|
|
13
14
|
<% end %>
|
|
14
15
|
</div>
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
<dl class="hrl-deflist">
|
|
22
22
|
<dt>Monthly instalment</dt><dd><%= hrl_money(loan.monthly_instalment) %></dd>
|
|
23
23
|
<dt>Repaid so far</dt><dd><%= hrl_money(loan.repaid) %></dd>
|
|
24
|
-
<dt>Outstanding</dt><dd><strong><%= hrl_money(loan.outstanding) %></strong></dd>
|
|
24
|
+
<dt>Outstanding</dt><dd><strong><%= loan.active? ? hrl_money(loan.outstanding) : "—" %></strong></dd>
|
|
25
25
|
<dt>Next deduction</dt>
|
|
26
26
|
<dd>
|
|
27
27
|
<% amount = loan.instalment_for(@next_month) %>
|
|
@@ -35,7 +35,8 @@
|
|
|
35
35
|
<%= f.text_area :reason %>
|
|
36
36
|
</div>
|
|
37
37
|
<div class="hrl-form-actions">
|
|
38
|
-
<%= f.submit "Submit resignation", class: "hrl-btn hrl-btn--primary"
|
|
38
|
+
<%= f.submit "Submit resignation", class: "hrl-btn hrl-btn--primary",
|
|
39
|
+
data: { turbo_confirm: "Submit your resignation? Leadership is told straight away." } %>
|
|
39
40
|
</div>
|
|
40
41
|
<% end %>
|
|
41
42
|
</section>
|
|
@@ -9,17 +9,17 @@
|
|
|
9
9
|
<section class="hrl-card">
|
|
10
10
|
<h2 class="hrl-card__title">Earnings</h2>
|
|
11
11
|
<div class="hrl-table-wrap">
|
|
12
|
-
<table class="hrl-table">
|
|
12
|
+
<table class="hrl-table hrl-table--stack">
|
|
13
13
|
<thead><tr><th>Component</th><th class="hrl-num">Full</th><th class="hrl-num">Earned</th></tr></thead>
|
|
14
14
|
<tbody>
|
|
15
15
|
<% slip.earnings_rows.each do |row| %>
|
|
16
16
|
<tr>
|
|
17
|
-
<td><%= row["label"] %></td>
|
|
18
|
-
<td class="hrl-num"><%= hrl_money(row["full_amount"]) %></td>
|
|
19
|
-
<td class="hrl-num"><%= hrl_money(row["amount"]) %></td>
|
|
17
|
+
<td data-label="Component"><%= row["label"] %></td>
|
|
18
|
+
<td data-label="Full" class="hrl-num"><%= hrl_money(row["full_amount"]) %></td>
|
|
19
|
+
<td data-label="Earned" class="hrl-num"><%= hrl_money(row["amount"]) %></td>
|
|
20
20
|
</tr>
|
|
21
21
|
<% end %>
|
|
22
|
-
<tr><td><strong>Gross</strong></td><td></td><td class="hrl-num"><strong><%= hrl_money(slip.gross_earnings) %></strong></td></tr>
|
|
22
|
+
<tr><td data-label="Component"><strong>Gross</strong></td><td class="hrl-cell--void"></td><td data-label="Earned" class="hrl-num"><strong><%= hrl_money(slip.gross_earnings) %></strong></td></tr>
|
|
23
23
|
</tbody>
|
|
24
24
|
</table>
|
|
25
25
|
</div>
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
<% end %>
|
|
8
8
|
<div class="pdf-company"><%= company[:name] %></div>
|
|
9
9
|
<% if company[:address].present? %><div class="pdf-muted"><%= company[:address] %></div><% end %>
|
|
10
|
+
<% if (contact = company.values_at(:phone, :email, :website).compact_blank).any? %><div class="pdf-muted"><%= contact.join(" · ") %></div><% end %>
|
|
10
11
|
</div>
|
|
11
12
|
<div style="text-align:right;">
|
|
12
13
|
<h1>Salary slip</h1>
|
|
@@ -7,11 +7,12 @@
|
|
|
7
7
|
<section class="hrl-card">
|
|
8
8
|
<h2 class="hrl-card__title">By <%= period.bucket %></h2>
|
|
9
9
|
<div class="hrl-chart-scroll">
|
|
10
|
-
<svg class="hrl-bars" viewBox="0 0 <%= buckets.size * (w + gap) %> <%= h + 14 %>" role="img"
|
|
10
|
+
<svg class="hrl-bars" style="--hrl-bars-n: <%= buckets.size %>" viewBox="0 0 <%= buckets.size * (w + gap) %> <%= h + 14 %>" role="img"
|
|
11
11
|
aria-label="Time per <%= period.bucket %> stacked by work mode; tallest bar <%= hrl_duration(max) %>; details in the table">
|
|
12
12
|
<% buckets.each_with_index do |(key, modes), i| %>
|
|
13
13
|
<% x = i * (w + gap); y = h %>
|
|
14
|
-
<a href="<%= path.(period: period.bucket == :day ? "day" : (period.bucket == :week ? "week" : "month"), date: key) %>"
|
|
14
|
+
<a href="<%= path.(period: period.bucket == :day ? "day" : (period.bucket == :week ? "week" : "month"), date: key) %>"
|
|
15
|
+
aria-label="<%= key.strftime(period.bucket == :day ? "%a %-d %b" : fmt) %>: <%= hrl_duration(totals[key]) %>">
|
|
15
16
|
<% modes.except("offline").sort.each do |mode, secs| %>
|
|
16
17
|
<% next unless secs.positive? %>
|
|
17
18
|
<% bh = secs / max * h; y -= bh %>
|
|
@@ -28,7 +29,7 @@
|
|
|
28
29
|
</svg>
|
|
29
30
|
</div>
|
|
30
31
|
<details class="hrl-small">
|
|
31
|
-
<summary>Show as a table</summary>
|
|
32
|
+
<summary class="hrl-card__link">Show as a table</summary>
|
|
32
33
|
<table class="hrl-table">
|
|
33
34
|
<thead><tr><th><%= period.bucket.to_s.capitalize %></th><th class="hrl-num">Working (breaks incl.)</th><th class="hrl-num">Of which breaks</th><th class="hrl-num">Total</th></tr></thead>
|
|
34
35
|
<tbody>
|
|
@@ -7,6 +7,13 @@
|
|
|
7
7
|
<%= csrf_meta_tags %>
|
|
8
8
|
<%= csp_meta_tag %>
|
|
9
9
|
<%= yield :head %>
|
|
10
|
+
<% if HrLite.config.native_app.call(request) %>
|
|
11
|
+
<%# The host's iOS/Android shells drive pages through Turbo. "reload" makes
|
|
12
|
+
every visit a full page load, so the plain scripts below run exactly
|
|
13
|
+
as they do in a browser. Browsers never load Turbo here. %>
|
|
14
|
+
<meta name="turbo-visit-control" content="reload">
|
|
15
|
+
<%= javascript_include_tag "hr_lite/vendor/turbo.min", type: "module" %>
|
|
16
|
+
<% end %>
|
|
10
17
|
<%= stylesheet_link_tag "hr_lite/hr_lite", media: "all" %>
|
|
11
18
|
<% HrLite.config.extra_stylesheets.each do |sheet| %>
|
|
12
19
|
<%= stylesheet_link_tag sheet, media: "all" %>
|
|
@@ -21,9 +21,17 @@
|
|
|
21
21
|
<body>
|
|
22
22
|
<div class="wrap">
|
|
23
23
|
<div class="card">
|
|
24
|
-
|
|
24
|
+
<% company = HrLite.config.company.call %>
|
|
25
|
+
<%# Mail clients strip data: URIs, so this is the host's absolute https logo, not logo_url. %>
|
|
26
|
+
<% if company[:email_logo_url].present? %>
|
|
27
|
+
<img src="<%= company[:email_logo_url] %>" alt="<%= company[:name] %>" height="40" style="display:block; height:40px; width:auto; border:0; margin-bottom:12px;">
|
|
28
|
+
<% end %>
|
|
29
|
+
<div class="brand"><%= company[:name].presence || "HR" %></div>
|
|
25
30
|
<%= yield %>
|
|
26
|
-
<p class="foot">
|
|
31
|
+
<p class="foot">
|
|
32
|
+
Sent by the HR system of <%= company[:name].presence || "your company" %>. Do not reply to this email.
|
|
33
|
+
<% if (contact = company.values_at(:phone, :email, :website).compact_blank).any? %><br>Questions: <%= contact.join(" · ") %><% end %>
|
|
34
|
+
</p>
|
|
27
35
|
</div>
|
|
28
36
|
</div>
|
|
29
37
|
</body>
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
<% company = HrLite.config.company.call %>
|
|
2
|
+
<%= company[:name].presence || "HR" %>
|
|
2
3
|
|
|
3
4
|
<%= yield %>
|
|
4
5
|
|
|
5
6
|
--
|
|
6
7
|
Sent by the HR system. Do not reply to this email.
|
|
8
|
+
<% if (contact = company.values_at(:phone, :email, :website).compact_blank).any? %>Questions: <%= contact.join(" · ") %>
|
|
9
|
+
<% end %>
|
data/config/routes.rb
CHANGED
|
@@ -115,7 +115,7 @@ HrLite::Engine.routes.draw do
|
|
|
115
115
|
end
|
|
116
116
|
resources :reports, only: %i[index show]
|
|
117
117
|
resources :expenses, only: :index do
|
|
118
|
-
member { post :approve; post :reject; post :reimburse }
|
|
118
|
+
member { post :approve; post :reject; post :reimburse; get :receipt }
|
|
119
119
|
end
|
|
120
120
|
resources :hr_requests, only: %i[index show] do
|
|
121
121
|
member { post :assign; post :resolve }
|
|
@@ -10,15 +10,17 @@ module HrLite
|
|
|
10
10
|
|
|
11
11
|
module_function
|
|
12
12
|
|
|
13
|
+
# Paise are spelled too: a slip showing ₹99,612.91 must not say "six hundred thirteen".
|
|
13
14
|
def words(amount)
|
|
14
|
-
|
|
15
|
-
return "Zero rupees" if
|
|
15
|
+
paise = (Money.d(amount) * 100).round(0, BigDecimal::ROUND_HALF_UP).to_i
|
|
16
|
+
return "Zero rupees" if paise.zero?
|
|
16
17
|
|
|
18
|
+
rupees, cents = paise.abs.divmod(100)
|
|
17
19
|
# A negative amount rendered as bare " rupees": no group was >= its
|
|
18
20
|
# divisor, so nothing was ever appended.
|
|
19
|
-
sentence = groups(rupees
|
|
20
|
-
sentence = "minus #{sentence}" if
|
|
21
|
-
"#{sentence.capitalize} rupees"
|
|
21
|
+
sentence = rupees.zero? ? "zero" : groups(rupees).join(" ")
|
|
22
|
+
sentence = "minus #{sentence}" if paise.negative?
|
|
23
|
+
"#{sentence.capitalize} rupees#{" and #{two_digit(cents)} paise" if cents.positive?}"
|
|
22
24
|
end
|
|
23
25
|
|
|
24
26
|
def groups(rupees)
|
|
@@ -13,6 +13,9 @@ module HrLite
|
|
|
13
13
|
# ->(user) { { url:, unread: } } — shows a notifications link in
|
|
14
14
|
# the HR shell; nil (default) shows nothing.
|
|
15
15
|
:notifications,
|
|
16
|
+
# ->(request) { bool } — is this request from the host's native app?
|
|
17
|
+
# Native pages load Turbo (see the layout); browsers never do.
|
|
18
|
+
:native_app,
|
|
16
19
|
# e.g. 6 — default probation for new hires (admin edits per employee)
|
|
17
20
|
:probation_months,
|
|
18
21
|
# true = a punch without GPS is refused (default: recorded and flagged)
|
|
@@ -114,6 +117,7 @@ module HrLite
|
|
|
114
117
|
@public_url_base = nil # e.g. "https://hr.example.com" — enables email links + HrLite.public_url
|
|
115
118
|
@notification_matrix = nil # resolved lazily to Notifications::DEFAULT_MATRIX
|
|
116
119
|
@back_link = nil # optional {label:, url:} for the shell nav
|
|
120
|
+
@native_app = ->(request) { request.user_agent.to_s.match?(/Hotwire Native|Turbo Native/) }
|
|
117
121
|
@leave_year_start_month = 1 # 1 = calendar year; 7 = July–June leave year
|
|
118
122
|
@slip_release_day = nil # e.g. 10 = slips open on the 10th of the next month
|
|
119
123
|
@self_regularization = nil # e.g. { within_days: 2, per_week: 2 } — employees fix their own missed punch
|
|
@@ -22,7 +22,7 @@ module HrLite
|
|
|
22
22
|
income_tax: card[:income_tax].transform_values { |regime| stringify_regime(regime) },
|
|
23
23
|
notes: StatutoryRateCard::SOURCES[effective_from] ||
|
|
24
24
|
"Shipped with hr_lite #{HrLite::VERSION}. Confirm with your accountant, then record who verified it.",
|
|
25
|
-
verified_by: (StatutoryRateCard::SOURCES.key?(effective_from)
|
|
25
|
+
verified_by: (StatutoryRateCardRecord::SHIPPED_SIGN_OFF if StatutoryRateCard::SOURCES.key?(effective_from)),
|
|
26
26
|
verified_on: (Date.current if StatutoryRateCard::SOURCES.key?(effective_from))
|
|
27
27
|
)
|
|
28
28
|
"rate card FY #{FinancialYear.label(effective_from)}"
|
data/lib/hr_lite/version.rb
CHANGED
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.
|
|
4
|
+
version: 0.54.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- kshitiz sinha
|
|
@@ -79,6 +79,7 @@ files:
|
|
|
79
79
|
- app/assets/javascripts/hr_lite/share.js
|
|
80
80
|
- app/assets/javascripts/hr_lite/tax_preview.js
|
|
81
81
|
- app/assets/javascripts/hr_lite/vendor/html_to_image.js
|
|
82
|
+
- app/assets/javascripts/hr_lite/vendor/turbo.min.js
|
|
82
83
|
- app/assets/stylesheets/hr_lite/application.css
|
|
83
84
|
- app/assets/stylesheets/hr_lite/hr_lite.css
|
|
84
85
|
- app/controllers/hr_lite/admin/appraisals_controller.rb
|