Merge pull request #4251 from saurabh6790/hr

Leave allocation based on Date range
This commit is contained in:
Rushabh Mehta 2015-11-02 15:19:55 +05:30
commit a938b81e1c
12 changed files with 226 additions and 117 deletions

View File

@ -147,20 +147,18 @@
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"default": "Today", "fieldname": "from_date",
"fieldname": "posting_date",
"fieldtype": "Date", "fieldtype": "Date",
"hidden": 0, "hidden": 0,
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"in_filter": 0, "in_filter": 0,
"in_list_view": 1, "in_list_view": 0,
"label": "Posting Date", "label": "From Date",
"no_copy": 1, "no_copy": 0,
"oldfieldname": "date",
"oldfieldtype": "Date",
"permlevel": 0, "permlevel": 0,
"precision": "",
"print_hide": 0, "print_hide": 0,
"read_only": 1, "read_only": 0,
"report_hide": 0, "report_hide": 0,
"reqd": 1, "reqd": 1,
"search_index": 0, "search_index": 0,
@ -171,23 +169,21 @@
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"fieldname": "fiscal_year", "fieldname": "to_date",
"fieldtype": "Link", "fieldtype": "Date",
"hidden": 0, "hidden": 0,
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"in_filter": 1, "in_filter": 0,
"in_list_view": 0, "in_list_view": 0,
"label": "Fiscal Year", "label": "To Date",
"no_copy": 0, "no_copy": 0,
"oldfieldname": "fiscal_year",
"oldfieldtype": "Data",
"options": "Fiscal Year",
"permlevel": 0, "permlevel": 0,
"precision": "",
"print_hide": 0, "print_hide": 0,
"read_only": 0, "read_only": 0,
"report_hide": 0, "report_hide": 0,
"reqd": 1, "reqd": 1,
"search_index": 1, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
}, },
@ -310,7 +306,7 @@
"is_submittable": 1, "is_submittable": 1,
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"modified": "2015-10-02 07:38:55.314632", "modified": "2015-10-28 18:18:29.137427",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "HR", "module": "HR",
"name": "Leave Allocation", "name": "Leave Allocation",
@ -359,7 +355,7 @@
], ],
"read_only": 0, "read_only": 0,
"read_only_onload": 0, "read_only_onload": 0,
"search_fields": "employee,employee_name,leave_type,total_leaves_allocated,fiscal_year", "search_fields": "employee,employee_name,leave_type,total_leaves_allocated",
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC" "sort_order": "DESC"
} }

View File

@ -3,13 +3,14 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
from frappe.utils import cint, flt from frappe.utils import cint, flt, date_diff
from frappe import _ from frappe import _
from frappe.model.document import Document from frappe.model.document import Document
from erpnext.hr.utils import set_employee_name from erpnext.hr.utils import set_employee_name
class LeaveAllocation(Document): class LeaveAllocation(Document):
def validate(self): def validate(self):
self.validate_period()
self.validate_new_leaves_allocated_value() self.validate_new_leaves_allocated_value()
self.check_existing_leave_allocation() self.check_existing_leave_allocation()
if not self.total_leaves_allocated: if not self.total_leaves_allocated:
@ -23,6 +24,10 @@ class LeaveAllocation(Document):
def on_update(self): def on_update(self):
self.get_total_allocated_leaves() self.get_total_allocated_leaves()
def validate_period(self):
if date_diff(self.to_date, self.from_date) <= 0:
frappe.throw(_("Invalid period"))
def validate_new_leaves_allocated_value(self): def validate_new_leaves_allocated_value(self):
"""validate that leave allocation is in multiples of 0.5""" """validate that leave allocation is in multiples of 0.5"""
if flt(self.new_leaves_allocated) % 0.5: if flt(self.new_leaves_allocated) % 0.5:
@ -31,28 +36,29 @@ class LeaveAllocation(Document):
def check_existing_leave_allocation(self): def check_existing_leave_allocation(self):
"""check whether leave for same type is already allocated or not""" """check whether leave for same type is already allocated or not"""
leave_allocation = frappe.db.sql("""select name from `tabLeave Allocation` leave_allocation = frappe.db.sql("""select name from `tabLeave Allocation`
where employee=%s and leave_type=%s and fiscal_year=%s and docstatus=1""", where employee='%s' and leave_type='%s' and to_date >= '%s' and from_date <= '%s' and docstatus=1
(self.employee, self.leave_type, self.fiscal_year)) """%(self.employee, self.leave_type, self.from_date, self.to_date))
if leave_allocation: if leave_allocation:
frappe.msgprint(_("Leaves for type {0} already allocated for Employee {1} for Fiscal Year {0}").format(self.leave_type, frappe.msgprint(_("Leaves for type {0} already allocated for Employee {1} for period {2} - {3}").format(self.leave_type,
self.employee, self.fiscal_year)) self.employee, self.from_date, self.to_date))
frappe.throw('<a href="#Form/Leave Allocation/{0}">{0}</a>'.format(leave_allocation[0][0])) frappe.throw('<a href="#Form/Leave Allocation/{0}">{0}</a>'.format(leave_allocation[0][0]))
def get_leave_bal(self, prev_fyear): def get_leave_bal(self):
return self.get_leaves_allocated(prev_fyear) - self.get_leaves_applied(prev_fyear) return self.get_leaves_allocated() - self.get_leaves_applied()
def get_leaves_applied(self, fiscal_year): def get_leaves_applied(self):
leaves_applied = frappe.db.sql("""select SUM(ifnull(total_leave_days, 0)) leaves_applied = frappe.db.sql("""select SUM(ifnull(total_leave_days, 0))
from `tabLeave Application` where employee=%s and leave_type=%s from `tabLeave Application` where employee=%s and leave_type=%s
and fiscal_year=%s and docstatus=1""", and to_date<=%s and docstatus=1""",
(self.employee, self.leave_type, fiscal_year)) (self.employee, self.leave_type, self.from_date))
return leaves_applied and flt(leaves_applied[0][0]) or 0 return leaves_applied and flt(leaves_applied[0][0]) or 0
def get_leaves_allocated(self, fiscal_year): def get_leaves_allocated(self):
leaves_allocated = frappe.db.sql("""select SUM(ifnull(total_leaves_allocated, 0)) leaves_allocated = frappe.db.sql("""select SUM(ifnull(total_leaves_allocated, 0))
from `tabLeave Allocation` where employee=%s and leave_type=%s from `tabLeave Allocation` where employee=%s and leave_type=%s
and fiscal_year=%s and docstatus=1 and name!=%s""", and to_date<=%s and docstatus=1 and name!=%s""",
(self.employee, self.leave_type, fiscal_year, self.name)) (self.employee, self.leave_type, self.from_date, self.name))
return leaves_allocated and flt(leaves_allocated[0][0]) or 0 return leaves_allocated and flt(leaves_allocated[0][0]) or 0
def allow_carry_forward(self): def allow_carry_forward(self):
@ -67,14 +73,11 @@ class LeaveAllocation(Document):
def get_carry_forwarded_leaves(self): def get_carry_forwarded_leaves(self):
if self.carry_forward: if self.carry_forward:
self.allow_carry_forward() self.allow_carry_forward()
prev_fiscal_year = frappe.db.sql("""select name from `tabFiscal Year`
where year_start_date = (select date_add(year_start_date, interval -1 year)
from `tabFiscal Year` where name=%s)
order by name desc limit 1""", self.fiscal_year)
prev_fiscal_year = prev_fiscal_year and prev_fiscal_year[0][0] or ''
prev_bal = 0 prev_bal = 0
if prev_fiscal_year and cint(self.carry_forward) == 1: if cint(self.carry_forward) == 1:
prev_bal = self.get_leave_bal(prev_fiscal_year) prev_bal = self.get_leave_bal()
ret = { ret = {
'carry_forwarded_leaves': prev_bal, 'carry_forwarded_leaves': prev_bal,
'total_leaves_allocated': flt(prev_bal) + flt(self.new_leaves_allocated) 'total_leaves_allocated': flt(prev_bal) + flt(self.new_leaves_allocated)
@ -83,6 +86,11 @@ class LeaveAllocation(Document):
def get_total_allocated_leaves(self): def get_total_allocated_leaves(self):
leave_det = self.get_carry_forwarded_leaves() leave_det = self.get_carry_forwarded_leaves()
self.validate_total_leaves_allocated(leave_det)
frappe.db.set(self,'carry_forwarded_leaves',flt(leave_det['carry_forwarded_leaves'])) frappe.db.set(self,'carry_forwarded_leaves',flt(leave_det['carry_forwarded_leaves']))
frappe.db.set(self,'total_leaves_allocated',flt(leave_det['total_leaves_allocated'])) frappe.db.set(self,'total_leaves_allocated',flt(leave_det['total_leaves_allocated']))
def validate_total_leaves_allocated(self, leave_det):
if date_diff(self.to_date, self.from_date) <= leave_det['total_leaves_allocated']:
frappe.throw(_("Total allocated leaves are more than period"))

View File

@ -1,4 +1,69 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
import unittest
from frappe.utils import getdate
test_records = frappe.get_test_records('Leave Allocation') class TestLeaveAllocation(unittest.TestCase):
def test_overlapping_allocation(self):
employee = frappe.get_doc("Employee", frappe.db.sql_list("select name from tabEmployee limit 1")[0])
leaves = [
{
"doctype": "Leave Allocation",
"__islocal": 1,
"employee": employee.name,
"employee_name": employee.employee_name,
"leave_type": "_Test Leave Type",
"from_date": getdate("2015-10-1"),
"to_date": getdate("2015-10-31"),
"new_leaves_allocated": 5,
"docstatus": 1
},
{
"doctype": "Leave Allocation",
"__islocal": 1,
"employee": employee.name,
"employee_name": employee.employee_name,
"leave_type": "_Test Leave Type",
"from_date": getdate("2015-09-1"),
"to_date": getdate("2015-11-30"),
"new_leaves_allocated": 5
}
]
frappe.get_doc(leaves[0]).save()
self.assertRaises(frappe.ValidationError, frappe.get_doc(leaves[1]).save)
def test_invalid_period(self):
employee = frappe.get_doc("Employee", frappe.db.sql_list("select name from tabEmployee limit 1")[0])
d = frappe.get_doc({
"doctype": "Leave Allocation",
"__islocal": 1,
"employee": employee.name,
"employee_name": employee.employee_name,
"leave_type": "_Test Leave Type",
"from_date": getdate("2015-09-30"),
"to_date": getdate("2015-09-1"),
"new_leaves_allocated": 5
})
#invalid period
self.assertRaises(frappe.ValidationError, d.save)
def test_allocated_leave_days_over_period(self):
employee = frappe.get_doc("Employee", frappe.db.sql_list("select name from tabEmployee limit 1")[0])
d = frappe.get_doc({
"doctype": "Leave Allocation",
"__islocal": 1,
"employee": employee.name,
"employee_name": employee.employee_name,
"leave_type": "_Test Leave Type",
"from_date": getdate("2015-09-1"),
"to_date": getdate("2015-09-30"),
"new_leaves_allocated": 35
})
#allocated leave more than period
self.assertRaises(frappe.ValidationError, d.save)
test_dependencies = ["Employee", "Leave Type"]

View File

@ -3,7 +3,8 @@
"docstatus": 1, "docstatus": 1,
"doctype": "Leave Allocation", "doctype": "Leave Allocation",
"employee": "_T-Employee-0001", "employee": "_T-Employee-0001",
"fiscal_year": "_Test Fiscal Year 2013", "from_date": "2013-01-01",
"to_date": "2013-12-31",
"leave_type": "_Test Leave Type", "leave_type": "_Test Leave Type",
"new_leaves_allocated": 15 "new_leaves_allocated": 15
}, },
@ -11,7 +12,8 @@
"docstatus": 1, "docstatus": 1,
"doctype": "Leave Allocation", "doctype": "Leave Allocation",
"employee": "_T-Employee-0002", "employee": "_T-Employee-0002",
"fiscal_year": "_Test Fiscal Year 2013", "from_date": "2013-01-01",
"to_date": "2013-12-31",
"leave_type": "_Test Leave Type", "leave_type": "_Test Leave Type",
"new_leaves_allocated": 15 "new_leaves_allocated": 15
} }

View File

@ -53,10 +53,6 @@ frappe.ui.form.on("Leave Application", {
frm.trigger("get_leave_balance"); frm.trigger("get_leave_balance");
}, },
fiscal_year: function(frm) {
frm.trigger("get_leave_balance");
},
leave_type: function(frm) { leave_type: function(frm) {
frm.trigger("get_leave_balance"); frm.trigger("get_leave_balance");
}, },
@ -85,12 +81,13 @@ frappe.ui.form.on("Leave Application", {
}, },
get_leave_balance: function(frm) { get_leave_balance: function(frm) {
if(frm.doc.docstatus==0 && frm.doc.employee && frm.doc.leave_type && frm.doc.fiscal_year) { if(frm.doc.docstatus==0 && frm.doc.employee && frm.doc.leave_type && frm.doc.from_date && frm.doc.to_date) {
return frm.call({ return frm.call({
method: "get_leave_balance", method: "get_leave_balance",
args: { args: {
employee: frm.doc.employee, employee: frm.doc.employee,
fiscal_year: frm.doc.fiscal_year, from_date: frm.doc.from_date,
to_date: frm.doc.to_date,
leave_type: frm.doc.leave_type leave_type: frm.doc.leave_type
} }
}); });
@ -109,6 +106,7 @@ frappe.ui.form.on("Leave Application", {
callback: function(response) { callback: function(response) {
if (response && response.message) { if (response && response.message) {
frm.set_value('total_leave_days', response.message.total_leave_days); frm.set_value('total_leave_days', response.message.total_leave_days);
frm.trigger("get_leave_balance");
} }
} }
}); });

View File

@ -559,7 +559,7 @@
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 3, "max_attachments": 3,
"modified": "2015-10-02 07:38:55.471712", "modified": "2015-10-28 16:14:25.640730",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "HR", "module": "HR",
"name": "Leave Application", "name": "Leave Application",

View File

@ -100,7 +100,7 @@ class LeaveApplication(Document):
if not is_lwp(self.leave_type): if not is_lwp(self.leave_type):
self.leave_balance = get_leave_balance(self.employee, self.leave_balance = get_leave_balance(self.employee,
self.leave_type, self.fiscal_year)["leave_balance"] self.leave_type, self.from_date, self.to_date)["leave_balance"]
if self.status != "Rejected" \ if self.status != "Rejected" \
and self.leave_balance - self.total_leave_days < 0: and self.leave_balance - self.total_leave_days < 0:
@ -122,9 +122,8 @@ class LeaveApplication(Document):
employee = %(employee)s employee = %(employee)s
and docstatus < 2 and docstatus < 2
and status in ("Open", "Approved") and status in ("Open", "Approved")
and (from_date between %(from_date)s and %(to_date)s and to_date >= %(from_date)s
or to_date between %(from_date)s and %(to_date)s and from_date <= %(to_date)s
or %(from_date)s between from_date and to_date)
and name != %(name)s""", { and name != %(name)s""", {
"employee": self.employee, "employee": self.employee,
"from_date": self.from_date, "from_date": self.from_date,
@ -251,18 +250,18 @@ def get_total_leave_days(leave_app):
return ret return ret
@frappe.whitelist() @frappe.whitelist()
def get_leave_balance(employee, leave_type, fiscal_year): def get_leave_balance(employee, leave_type, from_date, to_date):
leave_all = frappe.db.sql("""select total_leaves_allocated leave_all = frappe.db.sql("""select total_leaves_allocated
from `tabLeave Allocation` where employee = %s and leave_type = %s from `tabLeave Allocation` where employee = %s and leave_type = %s
and fiscal_year = %s and docstatus = 1""", (employee, and from_date<=%s and to_date>=%s and docstatus = 1""", (employee,
leave_type, fiscal_year)) leave_type, from_date, to_date))
leave_all = leave_all and flt(leave_all[0][0]) or 0 leave_all = leave_all and flt(leave_all[0][0]) or 0
leave_app = frappe.db.sql("""select SUM(total_leave_days) leave_app = frappe.db.sql("""select SUM(total_leave_days)
from `tabLeave Application` from `tabLeave Application`
where employee = %s and leave_type = %s and fiscal_year = %s where employee = %s and leave_type = %s and to_date>=%s and from_date<=%s
and status="Approved" and docstatus = 1""", (employee, leave_type, fiscal_year)) and status="Approved" and docstatus = 1""", (employee, leave_type, from_date, to_date))
leave_app = leave_app and flt(leave_app[0][0]) or 0 leave_app = leave_app and flt(leave_app[0][0]) or 0
ret = {'leave_balance': leave_all - leave_app} ret = {'leave_balance': leave_all - leave_app}

View File

@ -145,16 +145,38 @@
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"fieldname": "fiscal_year", "fieldname": "from_date",
"fieldtype": "Link", "fieldtype": "Date",
"hidden": 0, "hidden": 0,
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"in_filter": 1, "in_filter": 0,
"in_list_view": 0, "in_list_view": 0,
"label": "Fiscal Year", "label": "From Date",
"no_copy": 0, "no_copy": 0,
"options": "Fiscal Year",
"permlevel": 0, "permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "to_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "To Date",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0, "print_hide": 0,
"read_only": 0, "read_only": 0,
"report_hide": 0, "report_hide": 0,
@ -260,7 +282,7 @@
"is_submittable": 0, "is_submittable": 0,
"issingle": 1, "issingle": 1,
"istable": 0, "istable": 0,
"modified": "2015-06-05 11:38:19.994852", "modified": "2015-10-28 16:23:57.733900",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "HR", "module": "HR",
"name": "Leave Control Panel", "name": "Leave Control Panel",

View File

@ -4,7 +4,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
from frappe.utils import cint, cstr, flt, nowdate, comma_and from frappe.utils import cint, cstr, flt, nowdate, comma_and, date_diff
from frappe import msgprint, _ from frappe import msgprint, _
from frappe.model.document import Document from frappe.model.document import Document
@ -27,10 +27,14 @@ class LeaveControlPanel(Document):
return e return e
def validate_values(self): def validate_values(self):
for f in ["fiscal_year", "leave_type", "no_of_days"]: for f in ["from_date", "to_date", "leave_type", "no_of_days"]:
if not self.get(f): if not self.get(f):
frappe.throw(_("{0} is required").format(self.meta.get_label(f))) frappe.throw(_("{0} is required").format(self.meta.get_label(f)))
def to_date_validation(self):
if date_diff(self.to_date, self.from_date) <= 0:
return "Invalid period"
def allocate_leave(self): def allocate_leave(self):
self.validate_values() self.validate_values()
leave_allocated_for = [] leave_allocated_for = []
@ -45,8 +49,8 @@ class LeaveControlPanel(Document):
la.employee = cstr(d[0]) la.employee = cstr(d[0])
la.employee_name = frappe.db.get_value('Employee',cstr(d[0]),'employee_name') la.employee_name = frappe.db.get_value('Employee',cstr(d[0]),'employee_name')
la.leave_type = self.leave_type la.leave_type = self.leave_type
la.fiscal_year = self.fiscal_year la.from_date = self.from_date
la.posting_date = nowdate() la.to_date = self.to_date
la.carry_forward = cint(self.carry_forward) la.carry_forward = cint(self.carry_forward)
la.new_leaves_allocated = flt(self.no_of_days) la.new_leaves_allocated = flt(self.no_of_days)
la.docstatus = 1 la.docstatus = 1

View File

@ -4,11 +4,16 @@
frappe.query_reports["Employee Leave Balance"] = { frappe.query_reports["Employee Leave Balance"] = {
"filters": [ "filters": [
{ {
"fieldname":"fiscal_year", "fieldname":"from_date",
"label": __("Fiscal Year"), "label": __("From Date"),
"fieldtype": "Link", "fieldtype": "Date",
"options": "Fiscal Year", "default": frappe.datetime.year_start()
"default": frappe.defaults.get_user_default("fiscal_year") },
{
"fieldname":"to_date",
"label": __("To Date"),
"fieldtype": "Date",
"default": frappe.datetime.year_end()
}, },
{ {
"fieldname":"company", "fieldname":"company",

View File

@ -24,50 +24,45 @@ def execute(filters=None):
leave_types = frappe.db.sql_list("select name from `tabLeave Type`") leave_types = frappe.db.sql_list("select name from `tabLeave Type`")
if filters.get("fiscal_year"):
fiscal_years = [filters["fiscal_year"]]
else:
fiscal_years = frappe.db.sql_list("select name from `tabFiscal Year` order by name desc")
employee_names = [d.name for d in employees] employee_names = [d.name for d in employees]
allocations = frappe.db.sql("""select employee, fiscal_year, leave_type, total_leaves_allocated allocations = frappe.db.sql("""select employee, leave_type, sum(new_leaves_allocated) as leaves_allocated
from `tabLeave Allocation` from `tabLeave Allocation`
where docstatus=1 and employee in (%s)""" % where docstatus=1 and employee in (%s) and from_date >= '%s' and to_date <= '%s'""" %
','.join(['%s']*len(employee_names)), employee_names, as_dict=True) (','.join(['%s']*len(employee_names)), filters.get("from_date"),
filters.get("to_date")), employee_names, as_dict=True)
applications = frappe.db.sql("""select employee, fiscal_year, leave_type, applications = frappe.db.sql("""select employee, leave_type,
SUM(total_leave_days) as leaves SUM(total_leave_days) as leaves
from `tabLeave Application` from `tabLeave Application`
where status="Approved" and docstatus = 1 and employee in (%s) where status="Approved" and docstatus = 1 and employee in (%s)
group by employee, fiscal_year, leave_type""" % and from_date >= '%s' and to_date <= '%s'
','.join(['%s']*len(employee_names)), employee_names, as_dict=True) group by employee, leave_type""" %
(','.join(['%s']*len(employee_names)), filters.get("from_date"),
filters.get("to_date")), employee_names, as_dict=True)
columns = [ columns = [
_("Fiscal Year"), _("Employee") + ":Link/Employee:150", _("Employee Name") + "::200", _("Department") +"::150" _("Employee") + ":Link/Employee:150", _("Employee Name") + "::200", _("Department") +"::150"
] ]
for leave_type in leave_types: for leave_type in leave_types:
columns.append(_(leave_type) + " " + _("Allocated") + ":Float") columns.append(_(leave_type) + " " + _("Opening") + ":Float")
columns.append(_(leave_type) + " " + _("Taken") + ":Float") columns.append(_(leave_type) + " " + _("Taken") + ":Float")
columns.append(_(leave_type) + " " + _("Balance") + ":Float") columns.append(_(leave_type) + " " + _("Balance") + ":Float")
data = {} data = {}
for d in allocations: for d in allocations:
data.setdefault((d.fiscal_year, d.employee, data.setdefault((d.employee,d.leave_type), frappe._dict()).allocation = d.leaves_allocated
d.leave_type), frappe._dict()).allocation = d.total_leaves_allocated
for d in applications: for d in applications:
data.setdefault((d.fiscal_year, d.employee, data.setdefault((d.employee, d.leave_type), frappe._dict()).leaves = d.leaves
d.leave_type), frappe._dict()).leaves = d.leaves
result = [] result = []
for fiscal_year in fiscal_years:
for employee in employees: for employee in employees:
row = [fiscal_year, employee.name, employee.employee_name, employee.department] row = [employee.name, employee.employee_name, employee.department]
result.append(row) result.append(row)
for leave_type in leave_types: for leave_type in leave_types:
tmp = data.get((fiscal_year, employee.name, leave_type), frappe._dict()) tmp = data.get((employee.name, leave_type), frappe._dict())
row.append(tmp.allocation or 0) row.append(tmp.allocation or 0)
row.append(tmp.leaves or 0) row.append(tmp.leaves or 0)
row.append((tmp.allocation or 0) - (tmp.leaves or 0)) row.append((tmp.allocation or 0) - (tmp.leaves or 0))

View File

@ -0,0 +1,15 @@
from __future__ import unicode_literals
import frappe
def execute():
for leave_allocation in frappe.db.sql("select name, fiscal_year from `tabLeave Allocation`", as_dict=True):
year_start_date, year_end_date = frappe.db.get_value("Fiscal Year", leave_allocation["fiscal_year"],
["year_start_date", "year_end_date"])
frappe.db.sql("""update `tabLeave Allocation`
set from_date=%s, to_date=%s where name=%s""",
(year_start_date, year_end_date, leave_allocation["name"]))
frappe.db.commit()