mirror of
https://github.com/itsdave-de/msp.git
synced 2026-09-28 04:02:42 -03:00
fix(msp): Performance-Chart — Abwesenheiten aus itsdave_hr statt hrms-Attendance
get_attendance_list fragte den DocType `Attendance` ab, den es seit dem v16-Stand ohne hrms nicht mehr gibt. Der DoesNotExistError riss die gesamte Kette get_data -> compare_hours -> get_target_hours mit, der Dashboard-Chart "Meine Performance" blieb fuer alle Nutzer auf "Loading" haengen (ITSD-22440). Quelle sind jetzt genehmigte HR Absence Requests, deren Abwesenheitsart das Soll reduziert (HR Absence Type.affects_target_hours). Halbe Tage (half_day_start/half_day_end) halbieren das Tagessoll. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+56
-11
@@ -3,6 +3,7 @@ import json
|
|||||||
from datetime import datetime, date, timedelta
|
from datetime import datetime, date, timedelta
|
||||||
import math
|
import math
|
||||||
from frappe.database import get_db
|
from frappe.database import get_db
|
||||||
|
from frappe.utils import getdate
|
||||||
from erpnext.stock.utils import get_stock_balance
|
from erpnext.stock.utils import get_stock_balance
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import requests
|
import requests
|
||||||
@@ -251,20 +252,64 @@ def get_holidays_list(from_date, to_date):
|
|||||||
|
|
||||||
return holidays_list
|
return holidays_list
|
||||||
|
|
||||||
|
def get_hr_employee(employee):
|
||||||
|
"""Loest einen ERPNext-Employee auf den zugehoerigen HR Employee auf."""
|
||||||
|
if not frappe.db.exists("DocType", "HR Employee"):
|
||||||
|
return None
|
||||||
|
|
||||||
|
hr_employee = frappe.db.get_value("HR Employee", {"source_employee": employee}, "name")
|
||||||
|
if not hr_employee and frappe.db.exists("HR Employee", employee):
|
||||||
|
hr_employee = employee
|
||||||
|
|
||||||
|
return hr_employee
|
||||||
|
|
||||||
|
|
||||||
def get_attendance_list(employee, from_date, to_date):
|
def get_attendance_list(employee, from_date, to_date):
|
||||||
|
"""Soll-mindernde Abwesenheiten je Tag aus itsdave_hr.
|
||||||
|
|
||||||
# List of attendance data for the employee in the specified period
|
Liefert {Datum: "On Leave"} fuer ganze und {Datum: "Half Day"} fuer halbe
|
||||||
attendance_data = frappe.get_all("Attendance",
|
Abwesenheitstage. Beruecksichtigt werden nur genehmigte Antraege, deren
|
||||||
filters={
|
Abwesenheitsart das Soll reduziert (HR Absence Type.affects_target_hours).
|
||||||
"employee": employee,
|
"""
|
||||||
"attendance_date": (">=", from_date),
|
hr_employee = get_hr_employee(employee)
|
||||||
"attendance_date": ("<=", to_date)
|
if not hr_employee:
|
||||||
},
|
return {}
|
||||||
fields=["attendance_date", "status"])
|
|
||||||
|
|
||||||
# Dictionary with date as key and attendance status as value
|
from_date = getdate(from_date)
|
||||||
attendance_dict = {entry["attendance_date"]: entry["status"] for entry in attendance_data}
|
to_date = getdate(to_date)
|
||||||
return attendance_dict
|
|
||||||
|
absences = frappe.get_all("HR Absence Request",
|
||||||
|
filters={
|
||||||
|
"employee": hr_employee,
|
||||||
|
"status": "Approved",
|
||||||
|
"from_date": ("<=", to_date),
|
||||||
|
"to_date": (">=", from_date)
|
||||||
|
},
|
||||||
|
fields=["absence_type", "from_date", "to_date",
|
||||||
|
"half_day_start", "half_day_end"],
|
||||||
|
order_by="from_date asc, name asc")
|
||||||
|
|
||||||
|
day_factors = {}
|
||||||
|
|
||||||
|
for absence in absences:
|
||||||
|
if not frappe.get_cached_value("HR Absence Type", absence["absence_type"], "affects_target_hours"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
absence_from = getdate(absence["from_date"])
|
||||||
|
absence_to = getdate(absence["to_date"])
|
||||||
|
|
||||||
|
current_date = max(from_date, absence_from)
|
||||||
|
last_date = min(to_date, absence_to)
|
||||||
|
|
||||||
|
while current_date <= last_date:
|
||||||
|
half_day = ((absence["half_day_start"] and current_date == absence_from)
|
||||||
|
or (absence["half_day_end"] and current_date == absence_to))
|
||||||
|
factor = 0.5 if half_day else 1.0
|
||||||
|
day_factors[current_date] = min(1.0, day_factors.get(current_date, 0.0) + factor)
|
||||||
|
current_date += timedelta(days=1)
|
||||||
|
|
||||||
|
return {day: ("On Leave" if factor >= 1.0 else "Half Day")
|
||||||
|
for day, factor in day_factors.items()}
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
|||||||
Reference in New Issue
Block a user