feat: Add report table data generation
This commit is contained in:
parent
2b85a81a1c
commit
1a0229eb36
@ -2,8 +2,128 @@
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
# import frappe
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import flt, getdate
|
||||
from six import iteritems
|
||||
|
||||
def execute(filters=None):
|
||||
columns, data = [], []
|
||||
return columns, data
|
||||
return EmployeeHoursReport(filters).run()
|
||||
|
||||
class EmployeeHoursReport:
|
||||
'''Employee Hours Utilisation Report Based On Timesheet'''
|
||||
def __init__(self, filters=None):
|
||||
self.filters = frappe._dict(filters or {})
|
||||
|
||||
self.from_date = getdate(self.filters.from_date)
|
||||
self.to_date = getdate(self.filters.to_date)
|
||||
|
||||
self.validate_dates()
|
||||
|
||||
def validate_dates(self):
|
||||
self.day_span = (self.to_date - self.from_date).days
|
||||
|
||||
if self.day_span < 0:
|
||||
frappe.throw(_('From Date must come before To Date'))
|
||||
|
||||
def run(self):
|
||||
self.generate_columns()
|
||||
self.generate_data()
|
||||
|
||||
return self.columns, self.data
|
||||
|
||||
def generate_columns(self):
|
||||
self.columns = [
|
||||
{
|
||||
'label': _('Employee'),
|
||||
'options': 'Employee',
|
||||
'fieldname': 'employee',
|
||||
'fieldtype': 'Link',
|
||||
'width': 200
|
||||
},
|
||||
{
|
||||
'label': _('Total Hours'),
|
||||
'fieldname': 'total_hours',
|
||||
'fieldtype': 'Float',
|
||||
'width': 150
|
||||
},
|
||||
{
|
||||
'label': _('Billed Hours'),
|
||||
'fieldname': 'billed_hours',
|
||||
'fieldtype': 'Float',
|
||||
'width': 150
|
||||
},
|
||||
{
|
||||
'label': _('Non-Billed Hours'),
|
||||
'fieldname': 'non_billed_hours',
|
||||
'fieldtype': 'Float',
|
||||
'width': 150
|
||||
},
|
||||
{
|
||||
'label': _('Untracked Hours'),
|
||||
'fieldname': 'untracked_hours',
|
||||
'fieldtype': 'Float',
|
||||
'width': 150
|
||||
},
|
||||
{
|
||||
'label': _('% Utilization'),
|
||||
'fieldname': 'per_util',
|
||||
'fieldtype': 'Percentage',
|
||||
'width': 200
|
||||
}
|
||||
]
|
||||
|
||||
def generate_data(self):
|
||||
self.generate_filtered_time_logs()
|
||||
self.generate_stats_by_employee()
|
||||
self.calculate_utilisations()
|
||||
|
||||
self.data = []
|
||||
|
||||
for emp, data in iteritems(self.stats_by_employee):
|
||||
row = frappe._dict()
|
||||
row['employee'] = emp
|
||||
row.update(data)
|
||||
self.data.append(row)
|
||||
|
||||
def generate_filtered_time_logs(self):
|
||||
additional_filters = ''
|
||||
|
||||
if self.filters.employee:
|
||||
additional_filters += f'AND tt.employee = {self.filters.employee}'
|
||||
|
||||
if self.filters.project:
|
||||
additional_filters += f'AND ttd.project = {self.filters.project}'
|
||||
|
||||
self.filtered_time_logs = frappe.db.sql('''
|
||||
SELECT tt.employee AS employee, ttd.hours AS hours, ttd.billable AS billable, ttd.project AS project
|
||||
FROM `tabTimesheet Detail` AS ttd
|
||||
JOIN `tabTimesheet` AS tt
|
||||
ON ttd.parent = tt.name
|
||||
WHERE tt.start_date BETWEEN '{0}' AND '{1}'
|
||||
AND tt.end_date BETWEEN '{0}' AND '{1}'
|
||||
{2};
|
||||
'''.format(self.filters.from_date, self.filters.to_date, additional_filters))
|
||||
|
||||
def generate_stats_by_employee(self):
|
||||
self.stats_by_employee = frappe._dict()
|
||||
|
||||
for emp, hours, billable, project in self.filtered_time_logs:
|
||||
self.stats_by_employee.setdefault(
|
||||
emp, frappe._dict()
|
||||
).setdefault('billed_hours', 0.0)
|
||||
|
||||
self.stats_by_employee[emp].setdefault('non_billed_hours', 0.0)
|
||||
|
||||
if billable:
|
||||
self.stats_by_employee[emp]['billed_hours'] += flt(hours, 2)
|
||||
else:
|
||||
self.stats_by_employee[emp]['non_billed_hours'] += flt(hours, 2)
|
||||
|
||||
def calculate_utilisations(self):
|
||||
# (9.0) Will be fetched from HR settings
|
||||
TOTAL_HOURS = flt(9.0 * self.day_span, 2)
|
||||
for emp, data in iteritems(self.stats_by_employee):
|
||||
data['total_hours'] = TOTAL_HOURS
|
||||
data['untracked_hours'] = flt(TOTAL_HOURS - data['billed_hours'] - data['non_billed_hours'], 2)
|
||||
data['per_util'] = flt(((data['billed_hours'] + data['non_billed_hours']) / TOTAL_HOURS) * 100, 2)
|
Loading…
x
Reference in New Issue
Block a user