hr_lite 0.54.0 → 0.56.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 +71 -0
- data/app/assets/javascripts/hr_lite/confirm.js +9 -5
- data/app/assets/javascripts/hr_lite/countdown.js +9 -2
- data/app/assets/javascripts/hr_lite/search.js +1 -1
- data/app/assets/stylesheets/hr_lite/hr_lite.css +18 -9
- data/app/controllers/hr_lite/admin/attendances_controller.rb +10 -3
- data/app/controllers/hr_lite/admin/audit_logs_controller.rb +1 -0
- data/app/controllers/hr_lite/admin/employees_controller.rb +11 -4
- data/app/controllers/hr_lite/admin/expenses_controller.rb +6 -2
- data/app/controllers/hr_lite/admin/hr_requests_controller.rb +4 -0
- data/app/controllers/hr_lite/admin/leave_requests_controller.rb +4 -1
- data/app/controllers/hr_lite/admin/payroll_runs_controller.rb +9 -5
- data/app/controllers/hr_lite/admin/reports_controller.rb +3 -2
- data/app/controllers/hr_lite/admin/salary_structures_controller.rb +2 -0
- data/app/controllers/hr_lite/admin/tax_declarations_controller.rb +13 -3
- data/app/controllers/hr_lite/approvals_controller.rb +1 -0
- data/app/controllers/hr_lite/home_controller.rb +2 -2
- data/app/controllers/hr_lite/regularization_requests_controller.rb +4 -4
- data/app/controllers/hr_lite/tax_declarations_controller.rb +9 -5
- data/app/helpers/hr_lite/application_helper.rb +20 -14
- data/app/jobs/hr_lite/attendance_close_job.rb +1 -1
- data/app/jobs/hr_lite/payroll_compute_job.rb +12 -0
- data/app/models/concerns/hr_lite/audited.rb +3 -1
- data/app/models/concerns/hr_lite/encrypted_money.rb +8 -5
- data/app/models/hr_lite/attendance_record.rb +14 -0
- data/app/models/hr_lite/benefit_enrolment.rb +3 -1
- data/app/models/hr_lite/comp_off_request.rb +2 -0
- data/app/models/hr_lite/document.rb +1 -1
- data/app/models/hr_lite/expense.rb +13 -5
- data/app/models/hr_lite/hr_request.rb +2 -0
- data/app/models/hr_lite/kudo.rb +2 -2
- data/app/models/hr_lite/leave_request.rb +25 -6
- data/app/models/hr_lite/payroll_line_item.rb +8 -0
- data/app/models/hr_lite/payroll_run.rb +18 -6
- data/app/models/hr_lite/regularization_request.rb +2 -2
- data/app/models/hr_lite/resignation.rb +5 -1
- data/app/models/hr_lite/role.rb +5 -0
- data/app/models/hr_lite/salary_slip.rb +1 -1
- data/app/models/hr_lite/tax_declaration.rb +5 -0
- data/app/services/hr_lite/attendance_puncher.rb +4 -0
- data/app/services/hr_lite/overview_query.rb +0 -12
- data/app/services/hr_lite/payroll_run_processor.rb +3 -0
- data/app/services/hr_lite/slip_builder.rb +17 -9
- data/app/services/hr_lite/work_status.rb +5 -2
- data/app/views/hr_lite/admin/assets/index.html.erb +9 -2
- data/app/views/hr_lite/admin/attendances/show.html.erb +3 -1
- data/app/views/hr_lite/admin/attendances/summary.html.erb +5 -2
- data/app/views/hr_lite/admin/audit_logs/index.html.erb +6 -4
- data/app/views/hr_lite/admin/ca_reviews/index.html.erb +3 -3
- data/app/views/hr_lite/admin/checklists/index.html.erb +3 -3
- data/app/views/hr_lite/admin/comp_off_requests/index.html.erb +1 -2
- data/app/views/hr_lite/admin/comp_off_requests/show.html.erb +5 -5
- data/app/views/hr_lite/admin/designation_changes/new.html.erb +4 -3
- data/app/views/hr_lite/admin/documents/index.html.erb +8 -3
- data/app/views/hr_lite/admin/documents/show.html.erb +2 -1
- data/app/views/hr_lite/admin/employees/_form.html.erb +12 -5
- data/app/views/hr_lite/admin/employees/show.html.erb +38 -32
- data/app/views/hr_lite/admin/expenses/index.html.erb +4 -3
- data/app/views/hr_lite/admin/holidays/index.html.erb +5 -4
- data/app/views/hr_lite/admin/hr_requests/index.html.erb +1 -1
- data/app/views/hr_lite/admin/hr_requests/show.html.erb +4 -3
- data/app/views/hr_lite/admin/leave_balances/index.html.erb +6 -4
- data/app/views/hr_lite/admin/leave_requests/index.html.erb +1 -2
- data/app/views/hr_lite/admin/leave_requests/show.html.erb +5 -3
- data/app/views/hr_lite/admin/leave_types/edit.html.erb +4 -4
- data/app/views/hr_lite/admin/leave_types/index.html.erb +3 -3
- data/app/views/hr_lite/admin/loans/index.html.erb +2 -2
- data/app/views/hr_lite/admin/loans/show.html.erb +8 -12
- data/app/views/hr_lite/admin/office_locations/edit.html.erb +4 -4
- data/app/views/hr_lite/admin/payroll_runs/index.html.erb +2 -2
- data/app/views/hr_lite/admin/payroll_runs/show.html.erb +10 -7
- data/app/views/hr_lite/admin/policies/index.html.erb +1 -1
- data/app/views/hr_lite/admin/policies/new.html.erb +2 -2
- data/app/views/hr_lite/admin/regularization_requests/index.html.erb +3 -4
- data/app/views/hr_lite/admin/regularization_requests/show.html.erb +4 -5
- data/app/views/hr_lite/admin/reports/index.html.erb +3 -6
- data/app/views/hr_lite/admin/reports/show.html.erb +16 -2
- data/app/views/hr_lite/admin/roles/_form.html.erb +6 -5
- data/app/views/hr_lite/admin/salary_slips/show.html.erb +3 -2
- data/app/views/hr_lite/admin/salary_structures/_form.html.erb +1 -0
- data/app/views/hr_lite/admin/settings/edit.html.erb +5 -1
- data/app/views/hr_lite/admin/statutory_rate_cards/_form.html.erb +3 -3
- data/app/views/hr_lite/admin/statutory_rate_cards/index.html.erb +3 -1
- data/app/views/hr_lite/admin/tax_declarations/index.html.erb +1 -1
- data/app/views/hr_lite/admin/tax_declarations/show.html.erb +2 -0
- data/app/views/hr_lite/admin/wfh_requests/index.html.erb +17 -16
- data/app/views/hr_lite/admin/wfh_requests/show.html.erb +2 -4
- data/app/views/hr_lite/admin/work_locations/index.html.erb +1 -1
- data/app/views/hr_lite/admin/work_modes/index.html.erb +1 -1
- data/app/views/hr_lite/approvals/index.html.erb +1 -1
- data/app/views/hr_lite/attendance/_month_grid.html.erb +9 -9
- data/app/views/hr_lite/attendance/_penalties.html.erb +2 -2
- data/app/views/hr_lite/attendance/_punch_card.html.erb +2 -4
- data/app/views/hr_lite/attendance/_slot.html.erb +9 -6
- data/app/views/hr_lite/attendance/_trail.html.erb +1 -1
- data/app/views/hr_lite/attendance/_work_mode.html.erb +1 -1
- data/app/views/hr_lite/attendance/show.html.erb +4 -4
- data/app/views/hr_lite/calendar/show.html.erb +2 -2
- data/app/views/hr_lite/comp_off_requests/index.html.erb +1 -1
- data/app/views/hr_lite/comp_off_requests/new.html.erb +1 -1
- data/app/views/hr_lite/documents/_upload_form.html.erb +1 -1
- data/app/views/hr_lite/employee_profiles/show.html.erb +4 -2
- data/app/views/hr_lite/home/index.html.erb +2 -2
- data/app/views/hr_lite/id_cards/show.html.erb +5 -1
- data/app/views/hr_lite/leave_requests/_balance_chips.html.erb +2 -2
- data/app/views/hr_lite/leave_requests/new.html.erb +17 -8
- data/app/views/hr_lite/leave_requests/show.html.erb +2 -0
- data/app/views/hr_lite/org/show.html.erb +1 -1
- data/app/views/hr_lite/regularization_requests/index.html.erb +7 -7
- data/app/views/hr_lite/regularization_requests/new.html.erb +7 -5
- data/app/views/hr_lite/salary_slips/_slip_detail.html.erb +2 -2
- data/app/views/hr_lite/salary_slips/pdf.html.erb +1 -1
- data/app/views/hr_lite/tax/_computation.html.erb +1 -1
- data/app/views/hr_lite/tax_declarations/show.html.erb +4 -4
- data/app/views/hr_lite/team/show.html.erb +8 -7
- data/app/views/hr_lite/timelines/show.html.erb +1 -0
- data/app/views/hr_lite/wfh_requests/index.html.erb +3 -3
- data/app/views/hr_lite/work_time/_bars.html.erb +1 -1
- data/app/views/hr_lite/work_time/_donut.html.erb +1 -1
- data/app/views/hr_lite/work_time/_report.html.erb +14 -8
- data/app/views/layouts/hr_lite/application.html.erb +1 -0
- data/db/migrate/20261017161441_make_hr_lite_benefit_enrolments_unique_while_open.rb +8 -0
- data/db/migrate/20261017161443_add_attendance_record_id_index_to_hr_lite_work_mode_events.rb +5 -0
- data/lib/hr_lite/notifications.rb +5 -2
- data/lib/hr_lite/version.rb +1 -1
- metadata +4 -1
|
@@ -71,10 +71,8 @@ module HrLite
|
|
|
71
71
|
deductions << { code: "pt", label: "Professional tax", amount: pt } if pt.positive?
|
|
72
72
|
|
|
73
73
|
deductions.concat(extra_deductions)
|
|
74
|
-
loan = loan_instalment
|
|
75
|
-
deductions << loan if loan
|
|
76
74
|
|
|
77
|
-
fy =
|
|
75
|
+
fy =SalarySlip.fy_to_date(@user, @run.period_month)
|
|
78
76
|
tds = Calculators::Tds.call(
|
|
79
77
|
regime: tax_regime,
|
|
80
78
|
structure_monthly_gross: @structure.monthly_gross,
|
|
@@ -90,9 +88,16 @@ module HrLite
|
|
|
90
88
|
rates: @rates[:income_tax],
|
|
91
89
|
override: @tds_override
|
|
92
90
|
)
|
|
91
|
+
loan = loan_instalment(gross_earned - deductions.sum(BigDecimal(0)) { |row| row[:amount] } - tds.monthly)
|
|
92
|
+
deductions << loan if loan
|
|
93
93
|
deductions << { code: "tds", label: "Income tax (TDS)", amount: tds.monthly } if tds.monthly.positive?
|
|
94
94
|
|
|
95
95
|
total_deductions = deductions.sum(BigDecimal(0)) { |row| row[:amount] }
|
|
96
|
+
# Claims booked onto this month: paid back with the salary but not
|
|
97
|
+
# salary, so outside gross and every PF, ESI, PT and TDS base.
|
|
98
|
+
claims = Expense.awaiting_reimbursement.where(user_id: @user.id, reimbursed_in: @run.period_month).includes(:category).map do |claim|
|
|
99
|
+
{ code: "reimbursement", label: "#{claim.category.name} claim (reimbursement, outside gross)", amount: claim.amount }
|
|
100
|
+
end
|
|
96
101
|
|
|
97
102
|
{
|
|
98
103
|
period_month: @run.period_month,
|
|
@@ -104,7 +109,7 @@ module HrLite
|
|
|
104
109
|
lop_days: Money.d(summary[:lop_days]),
|
|
105
110
|
lop_override: @lop_override,
|
|
106
111
|
tds_override: @tds_override,
|
|
107
|
-
earnings: serialize_rows(earnings),
|
|
112
|
+
earnings: serialize_rows(earnings + claims),
|
|
108
113
|
deductions: serialize_rows(deductions),
|
|
109
114
|
employer_costs: employer_costs.transform_values { |v| v.to_s("F") }.to_json,
|
|
110
115
|
tax_details: tds.details.to_json,
|
|
@@ -113,7 +118,7 @@ module HrLite
|
|
|
113
118
|
# A heavy-LOP month can leave TDS (projected from the full structure)
|
|
114
119
|
# larger than what was actually earned. Nobody is paid a negative
|
|
115
120
|
# salary; PayrollRunProcessor warns when this floor bites.
|
|
116
|
-
net_pay: [ gross_earned - total_deductions, BigDecimal(0) ].max,
|
|
121
|
+
net_pay: [ gross_earned + claims.sum(BigDecimal(0)) { |row| row[:amount] } - total_deductions, BigDecimal(0) ].max,
|
|
117
122
|
computed_at: Time.current
|
|
118
123
|
}
|
|
119
124
|
end
|
|
@@ -172,13 +177,16 @@ module HrLite
|
|
|
172
177
|
# The month's loan instalment, as one deduction line. Computed here and
|
|
173
178
|
# BOOKED only when the run is finalized — a draft is recomputed freely,
|
|
174
179
|
# and booking at compute would take a repayment on every pass.
|
|
175
|
-
|
|
176
|
-
|
|
180
|
+
# Never more than `room` (pay left after every other deduction); the rest stays owed.
|
|
181
|
+
def loan_instalment(room)
|
|
182
|
+
due = Loan.active.where(user_id: @user.id).sum(BigDecimal(0)) do |loan|
|
|
177
183
|
loan.instalment_for(@run.period_month)
|
|
178
184
|
end
|
|
179
|
-
return nil unless
|
|
185
|
+
return nil unless due.positive?
|
|
180
186
|
|
|
181
|
-
|
|
187
|
+
amount = room.clamp(BigDecimal(0), due)
|
|
188
|
+
row = { code: "loan_repayment", label: "Loan repayment", amount: amount }
|
|
189
|
+
amount < due ? row.merge(meta: { carried_forward: (due - amount).to_s("F") }) : row
|
|
182
190
|
end
|
|
183
191
|
|
|
184
192
|
# Months left in the Indian FY (Apr–Mar) including the run month itself:
|
|
@@ -16,8 +16,11 @@ module HrLite
|
|
|
16
16
|
def self.for(user_id, at: Time.current) = for_users([ user_id ], at: at)[user_id]
|
|
17
17
|
|
|
18
18
|
# When an open Busy or Meeting ends, or nil when the person is reachable.
|
|
19
|
-
def self.do_not_disturb_until(user_id, at: Time.current)
|
|
20
|
-
|
|
19
|
+
def self.do_not_disturb_until(user_id, at: Time.current) = do_not_disturb_for([ user_id ], at: at)[user_id]
|
|
20
|
+
|
|
21
|
+
# The same for many people in one query: { user_id => ends_at }, reachable people absent.
|
|
22
|
+
def self.do_not_disturb_for(user_ids, at: Time.current)
|
|
23
|
+
WorkModeEvent.open.overlay.where(user_id: user_ids, mode: %w[busy meeting]).where("ends_at > ?", at).group(:user_id).maximum(:ends_at)
|
|
21
24
|
end
|
|
22
25
|
|
|
23
26
|
def self.for_users(user_ids, at: Time.current)
|
|
@@ -22,6 +22,9 @@
|
|
|
22
22
|
<% end %>
|
|
23
23
|
|
|
24
24
|
<section class="hrl-card">
|
|
25
|
+
<% if @assets.empty? %>
|
|
26
|
+
<p class="hrl-muted">No assets recorded yet. Add the first one above.</p>
|
|
27
|
+
<% else %>
|
|
25
28
|
<div class="hrl-table-wrap">
|
|
26
29
|
<table class="hrl-table hrl-table--stack">
|
|
27
30
|
<thead><tr><th>Asset</th><th>Status</th><th>With</th><th></th></tr></thead>
|
|
@@ -39,13 +42,16 @@
|
|
|
39
42
|
<td data-label="">
|
|
40
43
|
<% if asset.assigned? %>
|
|
41
44
|
<%= form_with url: hr_lite.take_back_admin_asset_path(asset), method: :post do %>
|
|
42
|
-
<%=
|
|
45
|
+
<%= label_tag "asset-condition-#{asset.id}", "Condition on return", class: "hrl-sr-only" %>
|
|
46
|
+
<%= text_field_tag :condition_note, nil, id: "asset-condition-#{asset.id}", placeholder: "Condition on return", class: "hrl-input" %>
|
|
43
47
|
<%= submit_tag "Take back", class: "hrl-btn" %>
|
|
44
48
|
<% end %>
|
|
45
49
|
<% elsif asset.available? %>
|
|
46
50
|
<%= form_with url: hr_lite.assign_admin_asset_path(asset), method: :post do %>
|
|
51
|
+
<%= label_tag "asset-holder-#{asset.id}", "Hand over to", class: "hrl-sr-only" %>
|
|
47
52
|
<%= select_tag :user_id,
|
|
48
|
-
options_for_select(HrLite.employees.map { |u| [ hr_display_name(u), u.id ] }),
|
|
53
|
+
options_for_select(HrLite.employees.map { |u| [ hr_display_name(u), u.id ] }), id: "asset-holder-#{asset.id}",
|
|
54
|
+
include_blank: "Choose…", required: true, class: "hrl-input",
|
|
49
55
|
data: { hrl_filter: "Type a name to filter" } %>
|
|
50
56
|
<%= submit_tag "Hand over", class: "hrl-btn" %>
|
|
51
57
|
<% end %>
|
|
@@ -56,5 +62,6 @@
|
|
|
56
62
|
</tbody>
|
|
57
63
|
</table>
|
|
58
64
|
</div>
|
|
65
|
+
<% end %>
|
|
59
66
|
<%= hrl_pagination %>
|
|
60
67
|
</section>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<% content_for(:page_title) { "Attendance — #{hr_display_name(@employee)}" } %>
|
|
2
2
|
<% content_for(:tabrow) { render "hr_lite/shared/person_tabs", user: @employee } %>
|
|
3
|
+
<% content_for(:back, "Team") %>
|
|
3
4
|
<div class="hrl-page__head">
|
|
4
5
|
<h1 class="hrl-page__title"><%= hr_display_name(@employee) %></h1>
|
|
5
6
|
<div class="hrl-page__actions">
|
|
@@ -33,6 +34,7 @@
|
|
|
33
34
|
<% if @punches.any? %>
|
|
34
35
|
<section class="hrl-card">
|
|
35
36
|
<h2 class="hrl-card__title">Where they punched</h2>
|
|
37
|
+
<% all_punches = HrLite::AttendancePunch.where(user_id: @employee.id, date: @punches.map(&:date)).order(:at, :id).group_by(&:date) # one query, not one a day %>
|
|
36
38
|
<% @punches.each do |record| %>
|
|
37
39
|
<div class="hrl-feed__item hrl-small">
|
|
38
40
|
<div class="hrl-feed__body">
|
|
@@ -47,7 +49,7 @@
|
|
|
47
49
|
<% end %>
|
|
48
50
|
</div>
|
|
49
51
|
<% end %>
|
|
50
|
-
<% if record.check_in_place %><%= render "hr_lite/attendance/trail", record: record %><% end %>
|
|
52
|
+
<% if record.check_in_place %><%= render "hr_lite/attendance/trail", record: record, punches: all_punches.fetch(record.date, []) %><% end %>
|
|
51
53
|
<% if (gap = record.punch_gap_m) %>
|
|
52
54
|
<div class="<%= gap > HrLite::AttendanceRecord::PUNCH_GAP_ALERT_M ? "hrl-badge hrl-badge--warn" : "hrl-muted" %>"><%= (gap / 1000.0).round(1) %> km apart</div>
|
|
53
55
|
<% end %>
|
|
@@ -25,14 +25,17 @@
|
|
|
25
25
|
<% end %>
|
|
26
26
|
</section>
|
|
27
27
|
|
|
28
|
+
<% fixes_pending = HrLite::RegularizationRequest.pending.where(user_id: @employee.id, date: @period.from..@period.to).pluck(:date) %>
|
|
28
29
|
<section class="hrl-card">
|
|
29
30
|
<h2 class="hrl-card__title">Days</h2>
|
|
30
31
|
<% (@period.from..@period.to).each do |date| %>
|
|
31
|
-
<% day = @days.for(date); rec = day.record; punches = @punches[date].to_a
|
|
32
|
+
<% day = @days.for(date); rec = day.record; punches = @punches[date].to_a
|
|
33
|
+
not_in_yet = date == Date.current && day.kind == :absent # the day is not over %>
|
|
32
34
|
<div class="hrl-feed__item hrl-row">
|
|
33
35
|
<div class="hrl-feed__body hrl-small">
|
|
34
36
|
<strong><%= date.strftime("%a %-d %b") %></strong>
|
|
35
|
-
<span class="hrl-badge <%= tones[day.kind] %>"><%= HrLite::ApplicationHelper::DAY_STATES[day.kind][1] %></span>
|
|
37
|
+
<span class="hrl-badge <%= not_in_yet ? "hrl-badge--muted" : tones[day.kind] %>"><%= not_in_yet ? "Not in yet" : HrLite::ApplicationHelper::DAY_STATES[day.kind][1] %></span>
|
|
38
|
+
<% if fixes_pending.include?(date) %><span class="hrl-badge hrl-badge--warn">Fix pending</span><% end %>
|
|
36
39
|
<% if @profile&.hours_allowance_minutes && (length = HrLite::EmployeeProfile.day_minutes_for(@employee.id, on: date)) < HrLite::Setting.instance.day_minutes %>
|
|
37
40
|
<span class="hrl-badge hrl-badge--muted">Day <%= hrl_duration(length * 60) %></span>
|
|
38
41
|
<% end %>
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
<% content_for(:page_title) { "Audit trail" } %>
|
|
1
2
|
<div class="hrl-page__head">
|
|
2
3
|
<h1 class="hrl-page__title">Audit trail</h1>
|
|
3
|
-
<p class="hrl-page__sub">Every policy, settings and payroll change — append-only
|
|
4
|
+
<p class="hrl-page__sub">Every policy, settings and payroll change — append-only.
|
|
5
|
+
<% if params[:views] %><a href="<%= hr_lite.admin_audit_logs_path %>">Hide page views</a><% else %><a href="<%= hr_lite.admin_audit_logs_path(views: 1) %>">Show page views too</a><% end %></p>
|
|
4
6
|
</div>
|
|
5
7
|
|
|
6
8
|
<% if @audit_logs.any? %>
|
|
@@ -13,15 +15,15 @@
|
|
|
13
15
|
<% @audit_logs.each do |log| %>
|
|
14
16
|
<tr>
|
|
15
17
|
<td data-label="When"><%= log.created_at.strftime("%d %b %Y, %H:%M") %></td>
|
|
16
|
-
<td data-label="Who"><%= hr_display_name(log.actor) %></td>
|
|
17
|
-
<td data-label="Action"><span class="hrl-badge hrl-badge--muted"><%= log.action %></span></td>
|
|
18
|
+
<td data-label="Who"><%= log.actor ? hr_display_name(log.actor) : "System" %></td>
|
|
19
|
+
<td data-label="Action"><span class="hrl-badge hrl-badge--muted"><%= log.action.tr("._", " ").humanize %></span></td>
|
|
18
20
|
<td data-label="Subject"><%= log.subject_type.demodulize.underscore.humanize %> #<%= log.subject_id %></td>
|
|
19
21
|
<td data-label="Changes">
|
|
20
22
|
<% log.audited_changes.each do |attr, change| %>
|
|
21
23
|
<div class="hrl-small">
|
|
22
24
|
<span class="hrl-muted"><%= attr.humanize %>:</span>
|
|
23
25
|
<% if change.is_a?(Array) %>
|
|
24
|
-
<%= change[0].
|
|
26
|
+
<%= change[0].to_s.presence || "blank" %> → <%= change[1].to_s.presence || "blank" %>
|
|
25
27
|
<% else %>
|
|
26
28
|
<%= change %>
|
|
27
29
|
<% end %>
|
|
@@ -22,12 +22,12 @@
|
|
|
22
22
|
</div>
|
|
23
23
|
|
|
24
24
|
<div class="hrl-row hrl-row--mb" role="tablist">
|
|
25
|
-
<a class="hrl-btn <%= "
|
|
26
|
-
<a class="hrl-btn <%= "
|
|
25
|
+
<a class="hrl-btn" <%= "aria-current=true" if @tab == "slips" %> href="<%= hr_lite.admin_ca_reviews_path(keep.(tab: "slips", status: @status)) %>">Salary slips</a>
|
|
26
|
+
<a class="hrl-btn" <%= "aria-current=true" if @tab == "declarations" %> href="<%= hr_lite.admin_ca_reviews_path(keep.(tab: "declarations", status: @status)) %>">Tax declarations</a>
|
|
27
27
|
</div>
|
|
28
28
|
<div class="hrl-row hrl-row--mb">
|
|
29
29
|
<% [ [ nil, "All" ], [ "unreviewed", "To review" ], [ "flagged", "Flagged" ], [ "verified", "Verified" ], [ "resolved", "Resolved" ] ].each do |value, label| %>
|
|
30
|
-
<a class="hrl-btn <%= "
|
|
30
|
+
<a class="hrl-btn" <%= "aria-current=true" if @status == value %> href="<%= hr_lite.admin_ca_reviews_path(keep.(status: value)) %>"><%= label %></a>
|
|
31
31
|
<% end %>
|
|
32
32
|
</div>
|
|
33
33
|
|
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
<section class="hrl-card">
|
|
5
5
|
<div class="hrl-row">
|
|
6
6
|
<% HrLite::ChecklistTemplate::KINDS.each do |kind| %>
|
|
7
|
-
|
|
8
|
-
href="<%= hr_lite.admin_checklists_path(kind: kind) %>"><%= kind.humanize %></a>
|
|
7
|
+
<%= link_to kind.humanize, hr_lite.admin_checklists_path(kind: kind), class: "hrl-btn", aria: { current: ("true" if kind == @kind) } %>
|
|
9
8
|
<% end %>
|
|
10
9
|
</div>
|
|
11
10
|
</section>
|
|
@@ -37,7 +36,8 @@
|
|
|
37
36
|
<td data-label="Due"><%= item.due_on&.strftime("%d %b %Y") || "—" %></td>
|
|
38
37
|
<td data-label="">
|
|
39
38
|
<%= form_with url: hr_lite.complete_admin_checklist_path(item), method: :post do %>
|
|
40
|
-
<%=
|
|
39
|
+
<%= label_tag "checklist-note-#{item.id}", "Note (optional)", class: "hrl-sr-only" %>
|
|
40
|
+
<%= text_field_tag :note, nil, id: "checklist-note-#{item.id}", placeholder: "Note (optional)", class: "hrl-input" %>
|
|
41
41
|
<%= submit_tag "Done", class: "hrl-btn hrl-btn--primary" %>
|
|
42
42
|
<% end %>
|
|
43
43
|
</td>
|
|
@@ -6,8 +6,7 @@
|
|
|
6
6
|
<div class="hrl-row hrl-row--mb">
|
|
7
7
|
<span class="hrl-small hrl-muted">Status</span>
|
|
8
8
|
<% HrLite::CompOffRequest::STATUSES.each do |status| %>
|
|
9
|
-
|
|
10
|
-
href="<%= hr_lite.admin_comp_off_requests_path(status: status) %>"><%= status.humanize %></a>
|
|
9
|
+
<%= link_to status.humanize, hr_lite.admin_comp_off_requests_path(status: status), class: "hrl-btn", aria: { current: ("true" if @status == status) } %>
|
|
11
10
|
<% end %>
|
|
12
11
|
</div>
|
|
13
12
|
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
<% content_for(:page_title) { "Comp-off — #{hr_display_name(@request.user)}" } %>
|
|
2
|
+
<a class="hrl-backlink" href="<%= hr_lite.admin_comp_off_requests_path %>"><span aria-hidden="true">‹</span> Approvals</a>
|
|
2
3
|
<div class="hrl-page__head">
|
|
3
4
|
<h1 class="hrl-page__title">Comp-off — <%= hr_display_name(@request.user) %></h1>
|
|
4
|
-
<div class="hrl-page__actions">
|
|
5
|
-
<a class="hrl-btn" href="<%= hr_lite.admin_comp_off_requests_path %>">All requests</a>
|
|
6
|
-
</div>
|
|
7
5
|
</div>
|
|
8
6
|
|
|
9
7
|
<section class="hrl-card">
|
|
@@ -34,7 +32,8 @@
|
|
|
34
32
|
`formaction:` can never pass verification on the second endpoint. %>
|
|
35
33
|
<section class="hrl-card">
|
|
36
34
|
<h2 class="hrl-card__title">Approve</h2>
|
|
37
|
-
<%= form_with url: hr_lite.approve_admin_comp_off_request_path(@request), method: :post, local: true
|
|
35
|
+
<%= form_with url: hr_lite.approve_admin_comp_off_request_path(@request), method: :post, local: true,
|
|
36
|
+
html: { data: { turbo_confirm: "Credit #{hrl_days(@request.credit_days)} day of comp-off to #{hr_display_name(@request.user)}?" } } do |f| %>
|
|
38
37
|
<div class="hrl-field">
|
|
39
38
|
<%= f.label :decision_note, "Note (optional)", for: "approve_note" %>
|
|
40
39
|
<%= f.text_area :decision_note, id: "approve_note" %>
|
|
@@ -48,7 +47,8 @@
|
|
|
48
47
|
|
|
49
48
|
<section class="hrl-card">
|
|
50
49
|
<h2 class="hrl-card__title">Reject</h2>
|
|
51
|
-
<%= form_with url: hr_lite.reject_admin_comp_off_request_path(@request), method: :post, local: true
|
|
50
|
+
<%= form_with url: hr_lite.reject_admin_comp_off_request_path(@request), method: :post, local: true,
|
|
51
|
+
html: { data: { turbo_confirm: "Reject #{hr_display_name(@request.user)}'s comp-off for #{@request.date_worked.strftime('%d %b %Y')}?" } } do |f| %>
|
|
52
52
|
<div class="hrl-field">
|
|
53
53
|
<%= f.label :decision_note, "Reason (required)", for: "reject_note" %>
|
|
54
54
|
<%= f.text_area :decision_note, id: "reject_note", required: true %>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
<% content_for(:page_title) { "
|
|
1
|
+
<% content_for(:page_title) { "Designation change" } %>
|
|
2
2
|
<div class="hrl-page__head">
|
|
3
|
-
<h1 class="hrl-page__title">
|
|
3
|
+
<h1 class="hrl-page__title">Designation change — <%= hr_display_name(@profile.user) %></h1>
|
|
4
4
|
</div>
|
|
5
5
|
|
|
6
6
|
<section class="hrl-card">
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
<div class="hrl-field"><%= f.label :effective_date %><%= f.date_field :effective_date %></div>
|
|
13
13
|
<div class="hrl-field"><%= f.label :note, "Note (optional)" %><%= f.text_area :note %></div>
|
|
14
14
|
<div class="hrl-form-actions">
|
|
15
|
-
<%= f.submit "Record change", class: "hrl-btn hrl-btn--primary"
|
|
15
|
+
<%= f.submit "Record change", class: "hrl-btn hrl-btn--primary",
|
|
16
|
+
data: { turbo_confirm: "Record this designation change? #{hr_display_name(@profile.user)} is told at once." } %>
|
|
16
17
|
<a class="hrl-btn" href="<%= hr_lite.admin_employee_path(@profile) %>">Cancel</a>
|
|
17
18
|
</div>
|
|
18
19
|
<% end %>
|
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
visibility allows.
|
|
9
9
|
</p>
|
|
10
10
|
<div class="hrl-row">
|
|
11
|
-
<a class="hrl-btn <%= "
|
|
11
|
+
<a class="hrl-btn" <%= "aria-current=true" if @category.nil? %>
|
|
12
12
|
href="<%= hr_lite.admin_documents_path %>">All</a>
|
|
13
13
|
<% @categories.each do |category| %>
|
|
14
|
-
<a class="hrl-btn <%= "
|
|
14
|
+
<a class="hrl-btn" <%= "aria-current=true" if @category == category %>
|
|
15
15
|
href="<%= hr_lite.admin_documents_path(category: category) %>"><%= category.humanize %></a>
|
|
16
16
|
<% end %>
|
|
17
17
|
</div>
|
|
@@ -44,7 +44,8 @@
|
|
|
44
44
|
<%= button_to "Verify", hr_lite.verify_admin_document_path(doc),
|
|
45
45
|
method: :post, class: "hrl-btn hrl-btn--primary" %>
|
|
46
46
|
<%= form_with url: hr_lite.reject_admin_document_path(doc), method: :post, local: true do %>
|
|
47
|
-
<%=
|
|
47
|
+
<%= label_tag "reject-doc-#{doc.id}", "What is wrong with it", class: "hrl-sr-only" %>
|
|
48
|
+
<%= text_field_tag :note, nil, id: "reject-doc-#{doc.id}", placeholder: "What is wrong with it", class: "hrl-input", required: true %>
|
|
48
49
|
<%= submit_tag "Reject", class: "hrl-btn" %>
|
|
49
50
|
<% end %>
|
|
50
51
|
</td>
|
|
@@ -58,6 +59,9 @@
|
|
|
58
59
|
|
|
59
60
|
<section class="hrl-card">
|
|
60
61
|
<h2 class="hrl-card__title">Everything on file</h2>
|
|
62
|
+
<% if @documents.empty? %>
|
|
63
|
+
<p class="hrl-muted">No documents on file yet. People upload them from Me › Documents; you can upload for someone from their page.</p>
|
|
64
|
+
<% else %>
|
|
61
65
|
<div class="hrl-table-wrap">
|
|
62
66
|
<table class="hrl-table hrl-table--stack">
|
|
63
67
|
<thead><tr><th>Person</th><th>Document</th><th>Expires</th><th>Checked</th></tr></thead>
|
|
@@ -85,5 +89,6 @@
|
|
|
85
89
|
</tbody>
|
|
86
90
|
</table>
|
|
87
91
|
</div>
|
|
92
|
+
<% end %>
|
|
88
93
|
<%= hrl_pagination %>
|
|
89
94
|
</section>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<% content_for(:page_title) { hr_display_name(@employee) } %>
|
|
2
2
|
<% content_for(:tabrow) { render "hr_lite/shared/person_tabs", user: @employee } %>
|
|
3
|
+
<% content_for(:back, "Documents to verify") %>
|
|
3
4
|
<div class="hrl-page__head">
|
|
4
5
|
<h1 class="hrl-page__title"><%= hr_display_name(@employee) %> — documents</h1>
|
|
5
6
|
</div>
|
|
@@ -31,7 +32,7 @@
|
|
|
31
32
|
</td>
|
|
32
33
|
<td data-label="">
|
|
33
34
|
<% if doc.readable_by?(hr_current_user) && doc.file.attached? %>
|
|
34
|
-
<a class="hrl-
|
|
35
|
+
<a class="hrl-btn" href="<%= hr_lite.download_document_path(doc) %>">Open</a>
|
|
35
36
|
<% end %>
|
|
36
37
|
</td>
|
|
37
38
|
</tr>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<section class="hrl-card">
|
|
2
2
|
<%= form_with model: profile, url: url, method: method, scope: :employee_profile, local: true do |f| %>
|
|
3
3
|
<%= render "hr_lite/shared/form_errors", record: profile %>
|
|
4
|
+
<h2 class="hrl-card__title">Identity</h2>
|
|
4
5
|
<% if profile.new_record? && profile.user_id.blank? %>
|
|
5
6
|
<div class="hrl-field">
|
|
6
7
|
<%= f.label :user_id, "Existing staff member" %>
|
|
@@ -22,7 +23,7 @@
|
|
|
22
23
|
</div>
|
|
23
24
|
<div class="hrl-field">
|
|
24
25
|
<%= f.label :new_user_password, "Starting password (optional)" %>
|
|
25
|
-
<%= f.
|
|
26
|
+
<%= f.password_field :new_user_password, autocomplete: "new-password" %>
|
|
26
27
|
<p class="hrl-hint">Leave blank (recommended): they get an email invite and set their own
|
|
27
28
|
password. Fill it only if you want to hand a password over yourself.</p>
|
|
28
29
|
</div>
|
|
@@ -40,6 +41,7 @@
|
|
|
40
41
|
<p class="hrl-hint">The employee code is assigned automatically
|
|
41
42
|
(<%= HrLite::Setting.instance.employee_code_prefix %> + next number).</p>
|
|
42
43
|
<% end %>
|
|
44
|
+
<h2 class="hrl-card__title hrl-mt">Work</h2>
|
|
43
45
|
<div class="hrl-field"><%= f.label :designation %><%= f.text_field :designation %></div>
|
|
44
46
|
<div class="hrl-field">
|
|
45
47
|
<%= f.label :manager_id, "Reports to (their L1)" %>
|
|
@@ -64,7 +66,7 @@
|
|
|
64
66
|
<%= f.select :office_location_id, offices, { include_blank: "None — only all-office holidays" }, data: { hrl_filter: ("Type an office" if offices.size > 5) } %></div>
|
|
65
67
|
<% end %>
|
|
66
68
|
<div class="hrl-field"><%= f.label :date_of_birth %><%= f.date_field :date_of_birth %></div>
|
|
67
|
-
<div class="hrl-field"><%= f.label :date_of_joining %><%= f.date_field :date_of_joining %></div>
|
|
69
|
+
<div class="hrl-field"><%= f.label :date_of_joining %><%= f.date_field :date_of_joining, required: true %></div>
|
|
68
70
|
<div class="hrl-field">
|
|
69
71
|
<%= f.label :blood_group, id: "hrl-blood-group", for: nil %>
|
|
70
72
|
<div class="hrl-chiprow" role="radiogroup" aria-labelledby="hrl-blood-group">
|
|
@@ -79,6 +81,7 @@
|
|
|
79
81
|
<%= f.label :probation_until, "On probation until (blank = not on probation)" %>
|
|
80
82
|
<%= f.date_field :probation_until %>
|
|
81
83
|
</div>
|
|
84
|
+
<h2 class="hrl-card__title hrl-mt">Attendance rules</h2>
|
|
82
85
|
<% if HrLite.config.attendance_slots %>
|
|
83
86
|
<div class="hrl-field">
|
|
84
87
|
<%= f.label :buffer_minutes, "Late buffer (delays late penalties; colleagues see the reason category)" %>
|
|
@@ -99,12 +102,16 @@
|
|
|
99
102
|
<%= f.label :date_of_exit, "Date of exit (leave blank while employed)" %>
|
|
100
103
|
<%= f.date_field :date_of_exit %>
|
|
101
104
|
</div>
|
|
102
|
-
<
|
|
103
|
-
<div class="hrl-field"><%= f.label :
|
|
105
|
+
<h2 class="hrl-card__title hrl-mt">Pay & statutory</h2>
|
|
106
|
+
<div class="hrl-field"><%= f.label :pan_number, "PAN" %><%= f.text_field :pan_number %>
|
|
107
|
+
<p class="hrl-hint">10 characters in capitals, like ABCDE1234F.</p></div>
|
|
108
|
+
<div class="hrl-field"><%= f.label :pf_uan, "PF UAN" %><%= f.text_field :pf_uan %>
|
|
109
|
+
<p class="hrl-hint">12 digits.</p></div>
|
|
104
110
|
<div class="hrl-field"><%= f.label :esi_number, "ESI number" %><%= f.text_field :esi_number %></div>
|
|
105
111
|
<div class="hrl-field"><%= f.label :bank_name %><%= f.text_field :bank_name %></div>
|
|
106
112
|
<div class="hrl-field"><%= f.label :bank_account_number %><%= f.text_field :bank_account_number %></div>
|
|
107
|
-
<div class="hrl-field"><%= f.label :bank_ifsc, "IFSC" %><%= f.text_field :bank_ifsc
|
|
113
|
+
<div class="hrl-field"><%= f.label :bank_ifsc, "IFSC" %><%= f.text_field :bank_ifsc %>
|
|
114
|
+
<p class="hrl-hint">11 characters in capitals, fifth is a zero, like HDFC0001234.</p></div>
|
|
108
115
|
<div class="hrl-field">
|
|
109
116
|
<%= f.label :tax_regime %>
|
|
110
117
|
<%= f.select :tax_regime, HrLite::EmployeeProfile::TAX_REGIMES.map { |r| [ "#{r.humanize} regime", r ] } %>
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
<% content_for(:page_title) { @profile.employee_code } %>
|
|
2
2
|
<% content_for(:tabrow) { render "hr_lite/shared/person_tabs", user: @profile.user } %>
|
|
3
|
+
<% content_for(:back, "Employees") %>
|
|
4
|
+
<% own = @profile.user_id == hr_current_user.id && !hr_superadmin? # your own pay and record are for someone else to change, unless you are Super Admin %>
|
|
3
5
|
<div class="hrl-page__head">
|
|
4
6
|
<h1 class="hrl-page__title"><%= hr_display_name(@profile.user) %> <span class="hrl-muted">(<%= @profile.employee_code %>)</span></h1>
|
|
5
7
|
<div class="hrl-page__actions">
|
|
8
|
+
<% unless own %>
|
|
6
9
|
<a class="hrl-btn" href="<%= hr_lite.edit_admin_employee_path(@profile) %>">Edit</a>
|
|
7
|
-
<%# Their records are the tabs above; the HR actions fold into one
|
|
10
|
+
<%# Their records are the tabs above; the HR actions fold into one More actions button. %>
|
|
8
11
|
<% if hr_superadmin? || hr_can?("salary.manage", scope: :all) %>
|
|
9
12
|
<details>
|
|
10
|
-
<summary class="hrl-btn">
|
|
13
|
+
<summary class="hrl-btn">More actions (appraisal, designation change, PIP, salary)</summary>
|
|
11
14
|
<div class="hrl-row">
|
|
12
15
|
<% if hr_superadmin? %>
|
|
13
16
|
<a class="hrl-btn" href="<%= hr_lite.new_admin_employee_appraisal_path(@profile) %>">New appraisal</a>
|
|
14
|
-
<a class="hrl-btn" href="<%= hr_lite.new_admin_employee_designation_change_path(@profile) %>">
|
|
17
|
+
<a class="hrl-btn" href="<%= hr_lite.new_admin_employee_designation_change_path(@profile) %>">Designation change</a>
|
|
15
18
|
<a class="hrl-btn" href="<%= hr_lite.new_admin_performance_plan_path(user_id: @profile.user_id) %>">Start PIP</a>
|
|
16
19
|
<% end %>
|
|
17
20
|
<% if hr_can?("salary.manage", scope: :all) %>
|
|
@@ -20,6 +23,7 @@
|
|
|
20
23
|
</div>
|
|
21
24
|
</details>
|
|
22
25
|
<% end %>
|
|
26
|
+
<% end %>
|
|
23
27
|
</div>
|
|
24
28
|
</div>
|
|
25
29
|
|
|
@@ -48,34 +52,6 @@
|
|
|
48
52
|
</section>
|
|
49
53
|
<% end %>
|
|
50
54
|
|
|
51
|
-
<%# Stays on the page after an exit date is stamped. Accepting a resignation
|
|
52
|
-
stamps one, and hiding this card at that moment removed the only control
|
|
53
|
-
that revokes sign-in — during the notice period, when it is needed. %>
|
|
54
|
-
<section class="hrl-card">
|
|
55
|
-
<h2 class="hrl-card__title"><%= @profile.date_of_exit ? "Revoke access" : "Offboard" %></h2>
|
|
56
|
-
<% if @profile.date_of_exit %>
|
|
57
|
-
<p class="hrl-small hrl-muted">Last day is <%= @profile.date_of_exit.strftime("%d %b %Y") %> —
|
|
58
|
-
attendance and payroll already clip to it. Run this on or after that day to revoke
|
|
59
|
-
sign-in. Records are never deleted.</p>
|
|
60
|
-
<% else %>
|
|
61
|
-
<p class="hrl-small hrl-muted">Stamps the last day (attendance and payroll clip to it) and revokes sign-in.
|
|
62
|
-
Records are never deleted.</p>
|
|
63
|
-
<% end %>
|
|
64
|
-
<%= form_with url: hr_lite.offboard_admin_employee_path(@profile), method: :post, local: true,
|
|
65
|
-
html: { data: { turbo_confirm: "Offboard #{hr_display_name(@profile.user)}?" } } do %>
|
|
66
|
-
<div class="hrl-field">
|
|
67
|
-
<label for="off_date">Last working day</label>
|
|
68
|
-
<input type="date" id="off_date" name="date_of_exit" class="hrl-input"
|
|
69
|
-
value="<%= @profile.date_of_exit || Date.current %>">
|
|
70
|
-
</div>
|
|
71
|
-
<div class="hrl-form-actions">
|
|
72
|
-
<button class="hrl-btn hrl-btn--danger" type="submit">
|
|
73
|
-
<%= @profile.date_of_exit ? "Revoke access now" : "Offboard employee" %>
|
|
74
|
-
</button>
|
|
75
|
-
</div>
|
|
76
|
-
<% end %>
|
|
77
|
-
</section>
|
|
78
|
-
|
|
79
55
|
<div class="hrl-grid hrl-grid--2">
|
|
80
56
|
<section class="hrl-card">
|
|
81
57
|
<h2 class="hrl-card__title">Profile</h2>
|
|
@@ -107,7 +83,7 @@
|
|
|
107
83
|
<td data-label="Effective"><%= structure.effective_from.strftime("%b %Y") %></td>
|
|
108
84
|
<td data-label="Basic" class="hrl-num"><%= hrl_money(structure.basic) %></td>
|
|
109
85
|
<td data-label="Gross" class="hrl-num"><%= hrl_money(structure.monthly_gross) %></td>
|
|
110
|
-
<td data-label=""
|
|
86
|
+
<td data-label=""><% unless own %><a class="hrl-btn" href="<%= hr_lite.edit_admin_employee_salary_structure_path(@profile, structure) %>">Edit</a><% end %></td>
|
|
111
87
|
</tr>
|
|
112
88
|
<% end %>
|
|
113
89
|
</tbody>
|
|
@@ -146,3 +122,33 @@
|
|
|
146
122
|
<% end %>
|
|
147
123
|
</section>
|
|
148
124
|
<% end %>
|
|
125
|
+
|
|
126
|
+
<%# Stays on the page after an exit date is stamped. Accepting a resignation
|
|
127
|
+
stamps one, and hiding this card at that moment removed the only control
|
|
128
|
+
that revokes sign-in — during the notice period, when it is needed. %>
|
|
129
|
+
<% unless own %>
|
|
130
|
+
<section class="hrl-card">
|
|
131
|
+
<h2 class="hrl-card__title"><%= @profile.date_of_exit ? "Revoke access" : "Offboard" %></h2>
|
|
132
|
+
<% if @profile.date_of_exit %>
|
|
133
|
+
<p class="hrl-small hrl-muted">Last day is <%= @profile.date_of_exit.strftime("%d %b %Y") %> —
|
|
134
|
+
attendance and payroll already clip to it. Run this on or after that day to revoke
|
|
135
|
+
sign-in. Records are never deleted.</p>
|
|
136
|
+
<% else %>
|
|
137
|
+
<p class="hrl-small hrl-muted">Stamps the last day (attendance and payroll clip to it) and revokes sign-in.
|
|
138
|
+
Records are never deleted.</p>
|
|
139
|
+
<% end %>
|
|
140
|
+
<%= form_with url: hr_lite.offboard_admin_employee_path(@profile), method: :post, local: true,
|
|
141
|
+
html: { data: { turbo_confirm: "Offboard #{hr_display_name(@profile.user)}?" } } do %>
|
|
142
|
+
<div class="hrl-field">
|
|
143
|
+
<label for="off_date">Last working day</label>
|
|
144
|
+
<input type="date" id="off_date" name="date_of_exit" class="hrl-input"
|
|
145
|
+
value="<%= @profile.date_of_exit || Date.current %>">
|
|
146
|
+
</div>
|
|
147
|
+
<div class="hrl-form-actions">
|
|
148
|
+
<button class="hrl-btn hrl-btn--danger" type="submit">
|
|
149
|
+
<%= @profile.date_of_exit ? "Revoke access now" : "Offboard employee" %>
|
|
150
|
+
</button>
|
|
151
|
+
</div>
|
|
152
|
+
<% end %>
|
|
153
|
+
</section>
|
|
154
|
+
<% end %>
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<section class="hrl-card">
|
|
5
5
|
<div class="hrl-row">
|
|
6
6
|
<% HrLite::Expense::STATUSES.each do |status| %>
|
|
7
|
-
<a class="hrl-btn <%= "
|
|
7
|
+
<a class="hrl-btn" <%= "aria-current=true" if status == @status %>
|
|
8
8
|
href="<%= hr_lite.admin_expenses_path(status: status) %>"><%= status.humanize %></a>
|
|
9
9
|
<% end %>
|
|
10
10
|
</div>
|
|
@@ -41,8 +41,9 @@
|
|
|
41
41
|
<% end %>
|
|
42
42
|
<% elsif expense.approved? %>
|
|
43
43
|
<%= form_with url: hr_lite.reimburse_admin_expense_path(expense), method: :post do %>
|
|
44
|
-
<%=
|
|
45
|
-
<%=
|
|
44
|
+
<%= label_tag "reimburse-month-#{expense.id}", "Paid with the payroll of", class: "hrl-sr-only" %>
|
|
45
|
+
<%= month_field_tag :period_month, (expense.reimbursed_in || Date.current).strftime("%Y-%m"), id: "reimburse-month-#{expense.id}", required: true, class: "hrl-input" %>
|
|
46
|
+
<%= submit_tag "Pay with payroll", class: "hrl-btn" %>
|
|
46
47
|
<% end %>
|
|
47
48
|
<% end %>
|
|
48
49
|
</td>
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
<div class="hrl-page__head">
|
|
3
3
|
<h1 class="hrl-page__title">Holidays <%= @year %></h1>
|
|
4
4
|
<div class="hrl-page__actions">
|
|
5
|
-
<a class="hrl-btn" href="
|
|
6
|
-
<a class="hrl-btn" href="<%= hr_lite.admin_holidays_path(year: @year
|
|
5
|
+
<a class="hrl-btn hrl-btn--primary" href="#add-holiday">Add a holiday</a>
|
|
6
|
+
<a class="hrl-btn" href="<%= hr_lite.admin_holidays_path(year: @year - 1) %>">‹ <%= @year - 1 %></a>
|
|
7
|
+
<a class="hrl-btn" href="<%= hr_lite.admin_holidays_path(year: @year + 1) %>"><%= @year + 1 %> ›</a>
|
|
7
8
|
</div>
|
|
8
9
|
</div>
|
|
9
10
|
|
|
@@ -35,7 +36,7 @@
|
|
|
35
36
|
</section>
|
|
36
37
|
|
|
37
38
|
<div class="hrl-grid hrl-grid--2">
|
|
38
|
-
<section class="hrl-card">
|
|
39
|
+
<section class="hrl-card" id="add-holiday">
|
|
39
40
|
<h2 class="hrl-card__title">Add one</h2>
|
|
40
41
|
<%= form_with model: @holiday, url: hr_lite.admin_holidays_path, local: true do |f| %>
|
|
41
42
|
<div class="hrl-field"><%= f.label :date %><%= f.date_field :date %></div>
|
|
@@ -62,7 +63,7 @@
|
|
|
62
63
|
<textarea name="lines" id="bulk-lines" class="hrl-input" rows="6" placeholder="2026-11-09, Diwali 2026-03-04, Holi"></textarea>
|
|
63
64
|
</div>
|
|
64
65
|
<div class="hrl-form-actions">
|
|
65
|
-
<button type="submit" class="hrl-btn
|
|
66
|
+
<button type="submit" class="hrl-btn">Add all</button>
|
|
66
67
|
</div>
|
|
67
68
|
<% end %>
|
|
68
69
|
</section>
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<section class="hrl-card">
|
|
5
5
|
<div class="hrl-row">
|
|
6
6
|
<% HrLite::HrRequest::STATUSES.each do |status| %>
|
|
7
|
-
<a class="hrl-btn <%= "
|
|
7
|
+
<a class="hrl-btn" <%= "aria-current=true" if status == @status %>
|
|
8
8
|
href="<%= hr_lite.admin_hr_requests_path(status: status) %>"><%= status.humanize %></a>
|
|
9
9
|
<% end %>
|
|
10
10
|
</div>
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<section class="hrl-card">
|
|
5
5
|
<p class="hrl-small hrl-muted">
|
|
6
6
|
<%= @request.category_label %> · <%= hr_display_name(@request.user) %> ·
|
|
7
|
-
<%= @request.created_at.to_date.strftime("%d %b %Y") %>
|
|
7
|
+
<%= @request.created_at.to_date.strftime("%d %b %Y") %>
|
|
8
8
|
<%= hrl_request_status_badge(@request.status) %>
|
|
9
9
|
</p>
|
|
10
10
|
<% if @request.category == "id_card" %>
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
<h2 class="hrl-card__title">Answer</h2>
|
|
21
21
|
<%= form_with url: hr_lite.resolve_admin_hr_request_path(@request), method: :post do %>
|
|
22
22
|
<div class="hrl-field">
|
|
23
|
-
<%= label_tag :resolution, "
|
|
23
|
+
<%= label_tag :resolution, "Answer to #{hr_display_name(@request.user)}" %>
|
|
24
24
|
<%= text_area_tag :resolution, nil, rows: 4, required: true %>
|
|
25
25
|
</div>
|
|
26
26
|
<div class="hrl-form-actions">
|
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
<%= label_tag :assignee_id, "Or hand it to somebody" %>
|
|
34
34
|
<%= select_tag :assignee_id,
|
|
35
35
|
options_for_select(HrLite.users_holding("hr_request.manage")
|
|
36
|
-
.map { |u| [ hr_display_name(u), u.id ] })
|
|
36
|
+
.map { |u| [ hr_display_name(u), u.id ] }),
|
|
37
|
+
include_blank: "Choose…", required: true, data: { hrl_filter: "Type a name to filter" } %>
|
|
37
38
|
</div>
|
|
38
39
|
<div class="hrl-form-actions">
|
|
39
40
|
<%= submit_tag "Assign", class: "hrl-btn" %>
|