Employee dashboards
This commit is contained in:
parent
0219b31b79
commit
a707df36cf
|
|
@ -189,19 +189,16 @@ class HrmsEmployeeDashboard(http.Controller):
|
|||
return self._yearly_attendance_calendar(month_start, month_end, attendances, leaves, public_holidays)
|
||||
|
||||
today = fields.Date.context_today(request.env.user)
|
||||
attendance_by_day = defaultdict(float)
|
||||
for attendance in attendances:
|
||||
day = fields.Datetime.context_timestamp(request.env.user, attendance.check_in).date()
|
||||
attendance_by_day[day] += attendance.worked_hours or 0.0
|
||||
attendance_by_day = self._attendance_hours_by_day(attendances)
|
||||
|
||||
leave_by_day = self._days_from_date_range_records(leaves, "request_date_from", "request_date_to", "holiday_status_id")
|
||||
leave_by_day = self._leave_days(leaves)
|
||||
holiday_by_day = self._days_from_datetime_range_records(public_holidays, "date_from", "date_to")
|
||||
|
||||
days = []
|
||||
cursor = month_start
|
||||
if calendar_view == "monthly":
|
||||
cursor = month_start - timedelta(days=(month_start.weekday() + 1) % 7)
|
||||
end_cursor = month_end + timedelta(days=(5 - month_end.weekday()) % 7)
|
||||
cursor = month_start - timedelta(days=month_start.weekday())
|
||||
end_cursor = month_end + timedelta(days=(6 - month_end.weekday()))
|
||||
else:
|
||||
end_cursor = month_end
|
||||
|
||||
|
|
@ -209,34 +206,91 @@ class HrmsEmployeeDashboard(http.Controller):
|
|||
outside_period = cursor < month_start or cursor > month_end
|
||||
status = "future" if cursor > today else "absent"
|
||||
label = ""
|
||||
hours = round(attendance_by_day.get(cursor, 0.0), 2)
|
||||
attendance_hours = attendance_by_day.get(cursor, {})
|
||||
hours = round(attendance_hours.get("worked_hours", 0.0), 2)
|
||||
break_hours = round(attendance_hours.get("break_hours", 0.0), 2)
|
||||
has_worked_hours = hours > 0.004
|
||||
is_holiday = cursor in holiday_by_day
|
||||
is_leave = cursor in leave_by_day
|
||||
is_half_day_leave = bool(leave_by_day.get(cursor, {}).get("is_half_day"))
|
||||
is_weekend = cursor.weekday() in (5, 6)
|
||||
expected_hours = 0.0
|
||||
if not outside_period and not is_holiday and not (is_weekend and not has_worked_hours):
|
||||
expected_hours = self._expected_hours_for_day(request.env.user.employee_id.sudo(), cursor)
|
||||
leave_hours = expected_hours if is_leave else 0.0
|
||||
show_metrics = (
|
||||
has_worked_hours
|
||||
or (
|
||||
not is_weekend
|
||||
and not is_holiday
|
||||
and (not is_leave or is_half_day_leave)
|
||||
)
|
||||
)
|
||||
if outside_period:
|
||||
status = "empty"
|
||||
elif hours:
|
||||
status = "present"
|
||||
elif cursor in holiday_by_day:
|
||||
show_metrics = False
|
||||
elif is_leave:
|
||||
status = "leave"
|
||||
label = _("Time Off")
|
||||
show_metrics = is_half_day_leave
|
||||
elif is_holiday:
|
||||
status = "holiday"
|
||||
label = holiday_by_day[cursor]
|
||||
elif cursor in leave_by_day:
|
||||
status = "leave"
|
||||
label = leave_by_day[cursor]
|
||||
elif cursor.weekday() in (5, 6):
|
||||
show_metrics = has_worked_hours
|
||||
elif has_worked_hours:
|
||||
status = "present"
|
||||
elif is_weekend:
|
||||
status = "weekend"
|
||||
label = _("Weekend")
|
||||
show_metrics = False
|
||||
days.append({
|
||||
"type": "day",
|
||||
"date": cursor.strftime("%Y-%m-%d"),
|
||||
"day": cursor.day,
|
||||
"weekday": cursor.strftime("%a"),
|
||||
"is_weekend": cursor.weekday() in (5, 6),
|
||||
"is_weekend": is_weekend,
|
||||
"outside_period": outside_period,
|
||||
"status": status,
|
||||
"label": label,
|
||||
"show_metrics": show_metrics,
|
||||
"is_half_day_leave": is_half_day_leave,
|
||||
"hours": hours,
|
||||
"worked_hours": hours,
|
||||
"break_hours": break_hours,
|
||||
"expected_hours": round(expected_hours, 2),
|
||||
"leave_hours": round(leave_hours, 2),
|
||||
"balance_hours": round(hours - expected_hours, 2),
|
||||
"worked_display": self._format_hours(hours),
|
||||
"break_display": self._format_hours(break_hours),
|
||||
"expected_display": self._format_hours(expected_hours),
|
||||
"leave_display": self._format_hours(leave_hours),
|
||||
"balance_display": self._format_signed_hours(hours - expected_hours),
|
||||
})
|
||||
cursor += timedelta(days=1)
|
||||
return days
|
||||
|
||||
def _leave_days(self, leaves):
|
||||
result = {}
|
||||
for leave in leaves:
|
||||
start = fields.Date.to_date(leave.request_date_from)
|
||||
end = fields.Date.to_date(leave.request_date_to)
|
||||
is_half_day = self._is_half_day_leave(leave)
|
||||
while start and end and start <= end:
|
||||
result[start] = {
|
||||
"label": _("Time Off"),
|
||||
"is_half_day": is_half_day,
|
||||
}
|
||||
start += timedelta(days=1)
|
||||
return result
|
||||
|
||||
def _is_half_day_leave(self, leave):
|
||||
if "request_unit_half" in leave._fields and leave.request_unit_half:
|
||||
return True
|
||||
if "request_unit_type" in leave._fields and leave.request_unit_type == "half_day":
|
||||
return True
|
||||
if "request_unit" in leave._fields and leave.request_unit == "half_day":
|
||||
return True
|
||||
return bool(leave.number_of_days and leave.number_of_days < 1)
|
||||
|
||||
def _yearly_attendance_calendar(self, range_start, range_end, attendances, leaves, public_holidays):
|
||||
days = self._attendance_calendar(range_start, range_end, attendances, leaves, public_holidays, "monthly")
|
||||
months = []
|
||||
|
|
@ -259,10 +313,59 @@ class HrmsEmployeeDashboard(http.Controller):
|
|||
"leave": counts["leave"],
|
||||
"holiday": counts["holiday"],
|
||||
"hours": round(sum(day["hours"] for day in month_days), 2),
|
||||
"worked_hours": round(sum(day["worked_hours"] for day in month_days), 2),
|
||||
"break_hours": round(sum(day["break_hours"] for day in month_days), 2),
|
||||
"expected_hours": round(sum(day["expected_hours"] for day in month_days), 2),
|
||||
"worked_display": self._format_hours(sum(day["worked_hours"] for day in month_days)),
|
||||
"break_display": self._format_hours(sum(day["break_hours"] for day in month_days)),
|
||||
"expected_display": self._format_hours(sum(day["expected_hours"] for day in month_days)),
|
||||
})
|
||||
cursor += relativedelta(months=1)
|
||||
return months
|
||||
|
||||
def _attendance_hours_by_day(self, attendances):
|
||||
grouped = defaultdict(list)
|
||||
for attendance in attendances:
|
||||
check_in = fields.Datetime.context_timestamp(request.env.user, attendance.check_in)
|
||||
grouped[check_in.date()].append(attendance)
|
||||
|
||||
result = {}
|
||||
for day, day_attendances in grouped.items():
|
||||
sorted_attendances = sorted(day_attendances, key=lambda attendance: attendance.check_in)
|
||||
worked_hours = sum(attendance.worked_hours or 0.0 for attendance in sorted_attendances)
|
||||
break_hours = 0.0
|
||||
for previous, current in zip(sorted_attendances, sorted_attendances[1:]):
|
||||
if previous.check_out and current.check_in:
|
||||
previous_out = fields.Datetime.context_timestamp(request.env.user, previous.check_out)
|
||||
current_in = fields.Datetime.context_timestamp(request.env.user, current.check_in)
|
||||
if current_in > previous_out:
|
||||
break_hours += (current_in - previous_out).total_seconds() / 3600
|
||||
result[day] = {
|
||||
"worked_hours": worked_hours,
|
||||
"break_hours": break_hours,
|
||||
}
|
||||
return result
|
||||
|
||||
def _expected_hours_for_day(self, employee, day):
|
||||
calendar = employee.resource_calendar_id or employee.company_id.resource_calendar_id
|
||||
if not calendar:
|
||||
return 0.0
|
||||
start_dt = datetime.combine(day, time.min)
|
||||
end_dt = datetime.combine(day, time.max)
|
||||
return round(calendar.get_work_hours_count(start_dt, end_dt, compute_leaves=False), 2)
|
||||
|
||||
def _format_hours(self, hours):
|
||||
hours = abs(hours or 0.0)
|
||||
total_minutes = int(round(hours * 60))
|
||||
hour_part, minute_part = divmod(total_minutes, 60)
|
||||
if minute_part:
|
||||
return "%sh %02dm" % (hour_part, minute_part)
|
||||
return "%sh" % hour_part
|
||||
|
||||
def _format_signed_hours(self, hours):
|
||||
sign = "+" if (hours or 0.0) >= 0 else "-"
|
||||
return "%s%s" % (sign, self._format_hours(hours))
|
||||
|
||||
def _days_from_date_range_records(self, records, start_field, end_field, label_field=False):
|
||||
result = {}
|
||||
for record in records:
|
||||
|
|
@ -289,12 +392,27 @@ class HrmsEmployeeDashboard(http.Controller):
|
|||
counts = defaultdict(int)
|
||||
for day in days:
|
||||
counts[day["status"]] += 1
|
||||
expected_hours = sum(day["expected_hours"] for day in days if not day["outside_period"])
|
||||
worked_hours = sum(attendances.mapped("worked_hours"))
|
||||
break_hours = sum(day["break_hours"] for day in days if not day["outside_period"])
|
||||
leave_hours = sum(day["leave_hours"] for day in days if not day["outside_period"])
|
||||
remaining_hours = expected_hours - worked_hours - leave_hours
|
||||
return {
|
||||
"present": counts["present"],
|
||||
"absent": counts["absent"],
|
||||
"leave": counts["leave"],
|
||||
"holiday": counts["holiday"],
|
||||
"hours": round(sum(attendances.mapped("worked_hours")), 2),
|
||||
"hours": round(worked_hours, 2),
|
||||
"worked_hours": round(worked_hours, 2),
|
||||
"break_hours": round(break_hours, 2),
|
||||
"expected_hours": round(expected_hours, 2),
|
||||
"leave_hours": round(leave_hours, 2),
|
||||
"remaining_hours": round(remaining_hours, 2),
|
||||
"worked_display": self._format_hours(worked_hours),
|
||||
"break_display": self._format_hours(break_hours),
|
||||
"expected_display": self._format_hours(expected_hours),
|
||||
"leave_display": self._format_hours(leave_hours),
|
||||
"remaining_display": self._format_signed_hours(remaining_hours),
|
||||
}
|
||||
|
||||
def _holiday_list(self, holidays):
|
||||
|
|
@ -317,25 +435,15 @@ class HrmsEmployeeDashboard(http.Controller):
|
|||
totals[month.strftime("%Y-%m")] += 0.0
|
||||
month += relativedelta(months=1)
|
||||
|
||||
HrExpense = request.env["hr.expense"].sudo()
|
||||
emp_expenses = HrExpense.search([
|
||||
expenses = request.env["hr.expense"].sudo().search([
|
||||
("employee_id", "=", employee.id),
|
||||
("date", ">=", date_from),
|
||||
("date", "<=", date_to),
|
||||
])
|
||||
for expense in emp_expenses:
|
||||
totals[expense.date.strftime("%Y-%m")] += expense.total_amount or 0.0
|
||||
state_totals[expense.state or "draft"] += expense.total_amount or 0.0
|
||||
|
||||
if request.env.registry.get("hr.expense"):
|
||||
hr_expenses = request.env["hr.expense"].sudo().search([
|
||||
("employee_id", "=", employee.id),
|
||||
("date", ">=", date_from),
|
||||
("date", "<=", date_to),
|
||||
])
|
||||
for expense in hr_expenses:
|
||||
totals[expense.date.strftime("%Y-%m")] += expense.total_amount_currency or expense.total_amount or 0.0
|
||||
state_totals[expense.state or "draft"] += expense.total_amount_currency or expense.total_amount or 0.0
|
||||
for expense in expenses:
|
||||
amount = self._expense_amount(expense)
|
||||
totals[expense.date.strftime("%Y-%m")] += amount
|
||||
state_totals[expense.state or "draft"] += amount
|
||||
|
||||
return {
|
||||
"labels": labels,
|
||||
|
|
@ -345,6 +453,11 @@ class HrmsEmployeeDashboard(http.Controller):
|
|||
"currency": employee.company_id.currency_id.symbol or "",
|
||||
}
|
||||
|
||||
def _expense_amount(self, expense):
|
||||
if "total_amount_currency" in expense._fields and expense.total_amount_currency:
|
||||
return expense.total_amount_currency
|
||||
return expense.total_amount or 0.0
|
||||
|
||||
def _month_keys(self, first_month, last_month):
|
||||
keys = []
|
||||
month = first_month
|
||||
|
|
|
|||
|
|
@ -184,8 +184,11 @@
|
|||
|
||||
.hrms-kpi.present strong { color: #16a34a; }
|
||||
.hrms-kpi.absent strong { color: #dc2626; }
|
||||
.hrms-kpi.break strong { color: #2563eb; }
|
||||
.hrms-kpi.leave strong,
|
||||
.hrms-kpi.holiday strong { color: #f97316; }
|
||||
.hrms-kpi.remaining.positive strong { color: #16a34a; }
|
||||
.hrms-kpi.remaining.negative strong { color: #dc2626; }
|
||||
|
||||
.hrms-grid {
|
||||
display: grid;
|
||||
|
|
@ -230,65 +233,217 @@
|
|||
|
||||
.hrms-calendar {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, minmax(82px, 1fr));
|
||||
gap: 10px;
|
||||
grid-template-columns: repeat(7, minmax(130px, 1fr));
|
||||
gap: 0;
|
||||
overflow-x: auto;
|
||||
border: 1px solid #dbe3ed;
|
||||
border-radius: 8px;
|
||||
background: #dbe3ed;
|
||||
}
|
||||
|
||||
.hrms-calendar-weekdays {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, minmax(82px, 1fr));
|
||||
gap: 10px;
|
||||
margin-bottom: 8px;
|
||||
grid-template-columns: repeat(7, minmax(130px, 1fr));
|
||||
gap: 0;
|
||||
overflow-x: auto;
|
||||
border: 1px solid #dbe3ed;
|
||||
border-bottom: 0;
|
||||
border-radius: 8px 8px 0 0;
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.hrms-calendar-weekdays span {
|
||||
color: #64748b;
|
||||
font-size: 11px;
|
||||
padding: 10px 8px;
|
||||
color: #0f172a;
|
||||
font-size: 13px;
|
||||
font-weight: 800;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
border-right: 1px solid #dbe3ed;
|
||||
}
|
||||
|
||||
.hrms-calendar-weekdays span:last-child {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.hrms-calendar.yearly {
|
||||
grid-template-columns: repeat(4, minmax(160px, 1fr));
|
||||
gap: 10px;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.hrms-day {
|
||||
min-height: 82px;
|
||||
padding: 8px;
|
||||
min-height: 132px;
|
||||
padding: 10px;
|
||||
border: 0;
|
||||
border-right: 1px solid #dbe3ed;
|
||||
border-bottom: 1px solid #dbe3ed;
|
||||
border-radius: 0;
|
||||
background: #fff;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hrms-calendar.yearly .hrms-day {
|
||||
min-height: 126px;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.hrms-day span,
|
||||
.hrms-day small {
|
||||
display: block;
|
||||
color: #64748b;
|
||||
font-size: 11px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.hrms-day strong {
|
||||
display: block;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
line-height: 31px;
|
||||
margin-top: 6px;
|
||||
.hrms-day-top {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 6px;
|
||||
min-height: 24px;
|
||||
}
|
||||
|
||||
.hrms-day-top strong {
|
||||
color: #0f172a;
|
||||
font-size: 13px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.hrms-day-top strong span {
|
||||
display: inline;
|
||||
margin-left: 4px;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.hrms-day-badge {
|
||||
max-width: 76px;
|
||||
padding: 2px 6px;
|
||||
border-radius: 6px;
|
||||
background: #eef2ff;
|
||||
color: #4338ca;
|
||||
font-size: 10px;
|
||||
font-weight: 800;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.hrms-day-balance {
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
margin: 10px 0 8px;
|
||||
border-radius: 999px;
|
||||
text-align: center;
|
||||
border: 2px solid #cbd5e1;
|
||||
color: #0f172a;
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.hrms-day.present strong { border-color: #16a34a; background: #dcfce7; }
|
||||
.hrms-day.absent strong { border-color: #dc2626; color: #dc2626; background: #fff; }
|
||||
.hrms-day.leave strong,
|
||||
.hrms-day.holiday strong { border-color: #f97316; background: #ffedd5; color: #9a3412; }
|
||||
.hrms-day.weekend strong { border-color: #94a3b8; background: #f1f5f9; color: #475569; }
|
||||
.hrms-day-balance.positive {
|
||||
background: #dcfce7;
|
||||
color: #16a34a;
|
||||
}
|
||||
|
||||
.hrms-day-balance.negative {
|
||||
background: #fee2e2;
|
||||
color: #dc2626;
|
||||
}
|
||||
|
||||
.hrms-day-message {
|
||||
min-height: 76px;
|
||||
margin-top: 10px;
|
||||
padding: 12px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hrms-day-message-icon {
|
||||
color: inherit;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.hrms-day-message strong {
|
||||
color: inherit;
|
||||
font-size: 13px;
|
||||
line-height: 1.25;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.hrms-day-metrics {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.hrms-day-metrics div {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.hrms-day-metrics span {
|
||||
display: block;
|
||||
color: #64748b;
|
||||
font-size: 10px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.hrms-day-metrics strong {
|
||||
display: block;
|
||||
margin-top: 3px;
|
||||
color: #0f172a;
|
||||
font-size: 13px;
|
||||
line-height: 1.15;
|
||||
word-break: keep-all;
|
||||
}
|
||||
|
||||
.hrms-calendar-month-stats {
|
||||
display: grid;
|
||||
gap: 5px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.hrms-calendar-month-stats small {
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.hrms-day.present { box-shadow: inset 0 3px 0 #22c55e; }
|
||||
.hrms-day.absent { box-shadow: inset 0 3px 0 #ef4444; }
|
||||
.hrms-day.leave {
|
||||
background: #fff5f5;
|
||||
box-shadow: inset 0 3px 0 #ef4444;
|
||||
}
|
||||
.hrms-day.leave .hrms-day-message {
|
||||
background: #fee2e2;
|
||||
color: #b91c1c;
|
||||
border: 1px solid #fecaca;
|
||||
}
|
||||
.hrms-day.holiday {
|
||||
background: #f8fafc;
|
||||
box-shadow: inset 0 3px 0 #94a3b8;
|
||||
}
|
||||
.hrms-day.holiday .hrms-day-message {
|
||||
background: #e5e7eb;
|
||||
color: #334155;
|
||||
border: 1px solid #cbd5e1;
|
||||
}
|
||||
.hrms-day.weekend {
|
||||
background: #f8fafc;
|
||||
box-shadow: none;
|
||||
}
|
||||
.hrms-day.weekend .hrms-day-message {
|
||||
min-height: 58px;
|
||||
background: transparent;
|
||||
color: #94a3b8;
|
||||
border: 1px dashed #e2e8f0;
|
||||
}
|
||||
.hrms-day.future { opacity: 0.55; }
|
||||
.hrms-day.empty {
|
||||
background: #f8fafc;
|
||||
border-style: dashed;
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
|
|
@ -416,13 +571,17 @@
|
|||
@media (max-width: 700px) {
|
||||
.hrms-kpi-row,
|
||||
.hrms-equipment-grid,
|
||||
.hrms-calendar,
|
||||
.hrms-calendar.yearly,
|
||||
.hrms-leave-summary,
|
||||
.hrms-custom-dates {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.hrms-calendar,
|
||||
.hrms-calendar-weekdays {
|
||||
grid-template-columns: repeat(7, minmax(118px, 1fr));
|
||||
}
|
||||
|
||||
.hrms-panel-header,
|
||||
.hrms-panel-actions,
|
||||
.hrms-action-buttons {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class HrmsEmployeeDashboard extends Component {
|
|||
const monthStart = new Date(today.getFullYear(), today.getMonth(), 1);
|
||||
const monthEnd = new Date(today.getFullYear(), today.getMonth() + 1, 0);
|
||||
const weekStart = new Date(today);
|
||||
weekStart.setDate(today.getDate() - today.getDay());
|
||||
weekStart.setDate(today.getDate() - ((today.getDay() + 6) % 7));
|
||||
|
||||
const weekEnd = new Date(weekStart);
|
||||
weekEnd.setDate(weekStart.getDate() + 6);
|
||||
|
|
@ -107,7 +107,6 @@ class HrmsEmployeeDashboard extends Component {
|
|||
}
|
||||
this.destroyCharts();
|
||||
const leaves = this.state.data.leave_balances || [];
|
||||
debugger;
|
||||
this.renderLeaveChart(leaves);
|
||||
this.renderExpenseChart();
|
||||
this.renderExpenseStateChart();
|
||||
|
|
@ -155,7 +154,6 @@ class HrmsEmployeeDashboard extends Component {
|
|||
return;
|
||||
}
|
||||
const expenses = this.state.data.expenses;
|
||||
debugger;
|
||||
this.chartBase("#hrmsExpenseChart", {
|
||||
chart: {
|
||||
type: "area",
|
||||
|
|
@ -183,8 +181,6 @@ class HrmsEmployeeDashboard extends Component {
|
|||
type: "donut",
|
||||
events: {
|
||||
dataPointSelection: (event, chartContext, config) => {
|
||||
debugger;
|
||||
const stateIndex = chartContext.dataPointIndex;
|
||||
const state = expenses.state_labels[config.dataPointIndex];
|
||||
this.openExpenses(state);
|
||||
},
|
||||
|
|
@ -242,7 +238,7 @@ class HrmsEmployeeDashboard extends Component {
|
|||
this.state.calendarDateTo = this.formatDate(new Date(today.getFullYear(), 11, 31));
|
||||
} else if (this.state.calendarView === "weekly") {
|
||||
const weekStart = new Date(today);
|
||||
weekStart.setDate(weekStart.getDate() - weekStart.getDay());
|
||||
weekStart.setDate(weekStart.getDate() - ((weekStart.getDay() + 6) % 7));
|
||||
const weekEnd = new Date(weekStart);
|
||||
weekEnd.setDate(weekStart.getDate() + 6);
|
||||
this.state.calendarDateFrom = this.formatDate(weekStart);
|
||||
|
|
@ -400,7 +396,6 @@ class HrmsEmployeeDashboard extends Component {
|
|||
}
|
||||
|
||||
openExpenses(state = false) {
|
||||
debugger;
|
||||
const domain = [["employee_id", "=", this.state.data.employee.id]];
|
||||
if (state) {
|
||||
domain.push(["state", "=", state.toLowerCase()]);
|
||||
|
|
|
|||
|
|
@ -74,11 +74,14 @@
|
|||
</section>
|
||||
|
||||
<section class="hrms-kpi-row">
|
||||
<div class="hrms-kpi present"><span>Present</span><strong t-esc="state.data.attendance_summary.present"/></div>
|
||||
<div class="hrms-kpi absent"><span>No Check-In</span><strong t-esc="state.data.attendance_summary.absent"/></div>
|
||||
<div class="hrms-kpi leave"><span>Leaves</span><strong t-esc="state.data.attendance_summary.leave"/></div>
|
||||
<div class="hrms-kpi holiday"><span>Holidays</span><strong t-esc="state.data.attendance_summary.holiday"/></div>
|
||||
<div class="hrms-kpi"><span>Hours</span><strong><t t-esc="state.data.attendance_summary.hours"/>h</strong></div>
|
||||
<div class="hrms-kpi"><span>Expected Hours</span><strong t-esc="state.data.attendance_summary.expected_display"/></div>
|
||||
<div class="hrms-kpi present"><span>Worked Hours</span><strong t-esc="state.data.attendance_summary.worked_display"/></div>
|
||||
<div class="hrms-kpi break"><span>Break Hours</span><strong t-esc="state.data.attendance_summary.break_display"/></div>
|
||||
<div class="hrms-kpi leave"><span>Leave Hours</span><strong t-esc="state.data.attendance_summary.leave_display"/></div>
|
||||
<div t-att-class="'hrms-kpi remaining ' + (state.data.attendance_summary.remaining_hours >= 0 ? 'positive' : 'negative')">
|
||||
<span>Remaining Hours</span>
|
||||
<strong t-esc="state.data.attendance_summary.remaining_display"/>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="hrms-grid">
|
||||
|
|
@ -97,30 +100,61 @@
|
|||
</div>
|
||||
</div>
|
||||
<div t-if="state.calendarView !== 'yearly'" class="hrms-calendar-weekdays">
|
||||
<span>Sun</span>
|
||||
<span>Mon</span>
|
||||
<span>Tue</span>
|
||||
<span>Wed</span>
|
||||
<span>Thu</span>
|
||||
<span>Fri</span>
|
||||
<span>Sat</span>
|
||||
<span>Sun</span>
|
||||
</div>
|
||||
<div class="hrms-calendar" t-att-class="state.calendarView === 'yearly' ? 'yearly' : ''">
|
||||
<div t-foreach="state.data.attendance_calendar" t-as="day" t-key="day.date" class="hrms-day" t-att-class="day.status" t-att-title="day.label || day.hours + 'h'">
|
||||
<div t-foreach="state.data.attendance_calendar" t-as="day" t-key="day.date" class="hrms-day" t-att-class="day.status" t-att-title="day.label || day.worked_display">
|
||||
<t t-if="day.status === 'empty'">
|
||||
<span/>
|
||||
</t>
|
||||
<t t-elif="day.type === 'month'">
|
||||
<div class="hrms-day-top">
|
||||
<span t-esc="day.weekday"/>
|
||||
<strong t-esc="day.day"/>
|
||||
<small><t t-esc="day.present"/> present · <t t-esc="day.hours"/>h</small>
|
||||
</div>
|
||||
<div class="hrms-calendar-month-stats">
|
||||
<small><t t-esc="day.present"/> present</small>
|
||||
<small><t t-esc="day.worked_display"/> worked</small>
|
||||
<small><t t-esc="day.break_display"/> break</small>
|
||||
<small><t t-esc="day.leave"/> leave · <t t-esc="day.holiday"/> holidays</small>
|
||||
</div>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<div class="hrms-day-top">
|
||||
<strong>
|
||||
<t t-esc="day.day"/>
|
||||
<span t-esc="day.weekday"/>
|
||||
<strong t-esc="day.day"/>
|
||||
<small t-if="day.hours"><t t-esc="day.hours"/>h</small>
|
||||
<small t-elif="day.label" t-esc="day.label"/>
|
||||
</strong>
|
||||
<span t-if="day.label and day.show_metrics" class="hrms-day-badge" t-esc="day.label"/>
|
||||
</div>
|
||||
<div t-if="!day.show_metrics and day.label" class="hrms-day-message">
|
||||
<span t-if="day.status === 'leave'" class="hrms-day-message-icon"><i class="fa fa-calendar-times-o"/></span>
|
||||
<span t-elif="day.status === 'holiday'" class="hrms-day-message-icon"><i class="fa fa-calendar"/></span>
|
||||
<strong t-esc="day.label || '-'"/>
|
||||
</div>
|
||||
<div t-if="day.show_metrics" t-att-class="'hrms-day-balance ' + (day.balance_hours >= 0 ? 'positive' : 'negative')">
|
||||
<t t-esc="day.balance_display"/>
|
||||
</div>
|
||||
<div t-if="day.show_metrics" class="hrms-day-metrics">
|
||||
<div>
|
||||
<span>Wrk.</span>
|
||||
<strong t-esc="day.worked_display"/>
|
||||
</div>
|
||||
<div>
|
||||
<span>Break</span>
|
||||
<strong t-esc="day.break_display"/>
|
||||
</div>
|
||||
<div>
|
||||
<span>Exp.</span>
|
||||
<strong t-esc="day.expected_display"/>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue