From 3cf0d51e65e27d8e660f10538439481ccdef37e2 Mon Sep 17 00:00:00 2001 From: Vishal Dhayagude Date: Wed, 9 May 2018 10:42:39 +0530 Subject: [PATCH 1/9] [fix] Compounding error in task weight (#13958) * [fix] Compounding error in task weight * [minor] minor changes * [fix] Requested Changes added --- erpnext/projects/doctype/project/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index 979c4fcace..44b0c00e65 100644 --- a/erpnext/projects/doctype/project/project.py +++ b/erpnext/projects/doctype/project/project.py @@ -75,7 +75,7 @@ class Project(Document): sum = 0 for task in self.tasks: if task.task_weight > 0: - sum = sum + task.task_weight + sum = flt(sum + task.task_weight, task.precision('task_weight')) if sum > 0 and sum != 1: frappe.throw(_("Total of all task weights should be 1. Please adjust weights of all Project tasks accordingly")) From 9d215c2d9b72310dfa4f486b04e48d4802baa068 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 9 May 2018 18:32:38 +0530 Subject: [PATCH 2/9] Set operations on production order while making from Material Request --- erpnext/stock/doctype/material_request/material_request.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index 8f0a25dc43..9383f912ba 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -417,6 +417,7 @@ def raise_production_orders(material_request): prod_order.material_request_item = d.name prod_order.planned_start_date = mr.transaction_date prod_order.company = mr.company + prod_order.set_work_order_operations() prod_order.save() production_orders.append(prod_order.name) else: From f2b3307136e5fb945872e2e5bdb78c84aa1ac18a Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Fri, 11 May 2018 21:07:27 +0530 Subject: [PATCH 3/9] Remove escaped customer string (#13986) - no need to escape strings that are passed to the values parameter of the sql method - this query was failing for inputs like "D'Arby" which have quotes --- erpnext/selling/doctype/customer/customer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index 0ea1119c76..7232fadb56 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -316,7 +316,7 @@ def make_address(args, is_primary_address=1): return address def get_customer_primary_contact(doctype, txt, searchfield, start, page_len, filters): - customer = frappe.db.escape(filters.get('customer')) + customer = filters.get('customer') return frappe.db.sql(""" select `tabContact`.name from `tabContact`, `tabDynamic Link` where `tabContact`.name = `tabDynamic Link`.parent and `tabDynamic Link`.link_name = %(customer)s From ebe1ebead2c4b0d0d5899e06020ebb72cf00b539 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 14 May 2018 13:21:45 +0530 Subject: [PATCH 4/9] [Fix] 'ProductionOrder' object has no attribute 'set_work_order_operations' --- erpnext/stock/doctype/material_request/material_request.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index 9383f912ba..f58b40e26f 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -417,7 +417,7 @@ def raise_production_orders(material_request): prod_order.material_request_item = d.name prod_order.planned_start_date = mr.transaction_date prod_order.company = mr.company - prod_order.set_work_order_operations() + prod_order.set_production_order_operations() prod_order.save() production_orders.append(prod_order.name) else: From 69b0535e10733574cfbbd2f051e3621676b88d80 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Mon, 14 May 2018 14:19:31 +0530 Subject: [PATCH 5/9] [fix] Incorrect currency conversion in Itemised Tax Breakup (#14006) --- erpnext/controllers/taxes_and_totals.py | 3 ++- erpnext/templates/includes/itemised_tax_breakup.html | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index e968e61d74..a4d9daedd6 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -558,7 +558,8 @@ def get_itemised_tax_breakup_html(doc): itemised_tax=itemised_tax, itemised_taxable_amount=itemised_taxable_amount, tax_accounts=tax_accounts, - company_currency=erpnext.get_company_currency(doc.company) + conversion_rate=doc.conversion_rate, + currency=doc.currency ) ) diff --git a/erpnext/templates/includes/itemised_tax_breakup.html b/erpnext/templates/includes/itemised_tax_breakup.html index 4162b3ab5a..982397e133 100644 --- a/erpnext/templates/includes/itemised_tax_breakup.html +++ b/erpnext/templates/includes/itemised_tax_breakup.html @@ -16,16 +16,16 @@ {{ item }} - {{ frappe.utils.fmt_money(itemised_taxable_amount.get(item), None, company_currency) }} + {{ frappe.utils.fmt_money(itemised_taxable_amount.get(item), None, currency) }} {% for tax_account in tax_accounts %} {% set tax_details = taxes.get(tax_account) %} {% if tax_details %} {% if tax_details.tax_rate or not tax_details.tax_amount %} - ({{ tax_details.tax_rate }}%) + ({{ tax_details.tax_rate }}%) {% endif %} - {{ frappe.utils.fmt_money(tax_details.tax_amount, None, company_currency) }} + {{ frappe.utils.fmt_money(tax_details.tax_amount / conversion_rate, None, currency) }} {% else %} From bbee9b6cc441357e96500cc1180beb49b1e7ba3a Mon Sep 17 00:00:00 2001 From: Shreya Shah Date: Mon, 14 May 2018 14:30:58 +0530 Subject: [PATCH 6/9] [Enhancement] Monthly Attendance Report (#13970) * Update Attendance on Approval of Leave * Separate out leaves on the basis of its type * Remove commented code * Make attendance records if not found * Fix Codacy * Replace bad code in attendance.py --- erpnext/hr/doctype/attendance/attendance.py | 18 +++--- .../leave_application/leave_application.py | 61 +++++++++++++------ .../monthly_attendance_sheet.py | 31 +++++++++- 3 files changed, 82 insertions(+), 28 deletions(-) diff --git a/erpnext/hr/doctype/attendance/attendance.py b/erpnext/hr/doctype/attendance/attendance.py index 458b2dd5c1..d1809c60cb 100644 --- a/erpnext/hr/doctype/attendance/attendance.py +++ b/erpnext/hr/doctype/attendance/attendance.py @@ -20,17 +20,19 @@ class Attendance(Document): set_employee_name(self) def check_leave_record(self): - leave_record = frappe.db.sql("""select leave_type, half_day from `tabLeave Application` + leave_record = frappe.db.sql("""select leave_type, half_day, half_day_date from `tabLeave Application` where employee = %s and %s between from_date and to_date and status = 'Approved' and docstatus = 1""", (self.employee, self.attendance_date), as_dict=True) if leave_record: - if leave_record[0].half_day: - self.status = 'Half Day' - frappe.msgprint(_("Employee {0} on Half day on {1}").format(self.employee, self.attendance_date)) - else: - self.status = 'On Leave' - self.leave_type = leave_record[0].leave_type - frappe.msgprint(_("Employee {0} on Leave on {1}").format(self.employee, self.attendance_date)) + for d in leave_record: + if d.half_day_date == getdate(self.attendance_date): + self.status = 'Half Day' + frappe.msgprint(_("Employee {0} on Half day on {1}").format(self.employee, self.attendance_date)) + else: + self.status = 'On Leave' + self.leave_type = d.leave_type + frappe.msgprint(_("Employee {0} on Leave on {1}").format(self.employee, self.attendance_date)) + if self.status == "On Leave" and not leave_record: frappe.throw(_("No leave record found for employee {0} for {1}").format(self.employee, self.attendance_date)) diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py index 8d19510624..4e1b54b95b 100755 --- a/erpnext/hr/doctype/leave_application/leave_application.py +++ b/erpnext/hr/doctype/leave_application/leave_application.py @@ -5,12 +5,12 @@ from __future__ import unicode_literals import frappe from frappe import _ from frappe.utils import cint, cstr, date_diff, flt, formatdate, getdate, get_link_to_form, \ - comma_or, get_fullname + comma_or, get_fullname, nowdate from erpnext.hr.utils import set_employee_name from erpnext.hr.doctype.leave_block_list.leave_block_list import get_applicable_block_dates from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee from erpnext.hr.doctype.employee_leave_approver.employee_leave_approver import get_approver_list - +from erpnext.buying.doctype.supplier_scorecard.supplier_scorecard import daterange class LeaveDayBlockedError(frappe.ValidationError): pass class OverlapError(frappe.ValidationError): pass @@ -52,6 +52,7 @@ class LeaveApplication(Document): frappe.throw(_("Only Leave Applications with status 'Approved' and 'Rejected' can be submitted")) self.validate_back_dated_application() + self.update_attendance() # notify leave applier about approval self.notify_employee(self.status) @@ -100,6 +101,41 @@ class LeaveApplication(Document): frappe.throw(_("Leave cannot be applied/cancelled before {0}, as leave balance has already been carry-forwarded in the future leave allocation record {1}") .format(formatdate(future_allocation[0].from_date), future_allocation[0].name)) + def update_attendance(self): + if self.status == "Approved": + attendance = frappe.db.sql("""select name from `tabAttendance` where employee = %s\ + and (attendance_date between %s and %s) and docstatus < 2""",(self.employee, self.from_date, self.to_date), as_dict=1) + + if attendance: + for d in attendance: + doc = frappe.get_doc("Attendance", d.name) + if getdate(self.half_day_date) == doc.attendance_date: + status = "Half Day" + else: + status = "On Leave" + frappe.db.sql("""update `tabAttendance` set status = %s, leave_type = %s\ + where name = %s""",(status, self.leave_type, d.name)) + + elif self.from_date <= nowdate(): + for dt in daterange(getdate(self.from_date), getdate(self.to_date)): + date = dt.strftime("%Y-%m-%d") + if not date == self.half_day_date: + doc = frappe.new_doc("Attendance") + doc.employee = self.employee + doc.attendance_date = date + doc.company = self.company + doc.status = "On Leave" + doc.leave_type = self.leave_type + doc.submit() + else: + doc = frappe.new_doc("Attendance") + doc.employee = self.employee + doc.attendance_date = date + doc.company = self.company + doc.status = "Half Day" + doc.leave_type = self.leave_type + doc.submit() + def validate_salary_processed_days(self): if not frappe.db.get_value("Leave Type", self.leave_type, "is_lwp"): return @@ -436,30 +472,17 @@ def add_department_leaves(events, start, end, employee, company): and company=%s""", (department, company)) match_conditions = "and employee in (\"%s\")" % '", "'.join(department_employees) - add_leaves(events, start, end, filter_conditions=match_conditions) - -def add_leaves(events, start, end, filter_conditions=None): - conditions = [] - - if filter_conditions: - conditions.append(filter_conditions) - - if not cint(frappe.db.get_value("HR Settings", None, "show_leaves_of_all_department_members_in_calendar")): - from frappe.desk.reportview import build_match_conditions - match_conditions = build_match_conditions("Leave Application") - - if match_conditions: - conditions.append(match_conditions) + add_leaves(events, start, end, match_conditions=match_conditions) +def add_leaves(events, start, end, match_conditions=None): query = """select name, from_date, to_date, employee_name, half_day, status, employee, docstatus from `tabLeave Application` where from_date <= %(end)s and to_date >= %(start)s <= to_date and docstatus < 2 and status!="Rejected" """ - - if conditions: - query += ' and '.join(conditions) + if match_conditions: + query += match_conditions for d in frappe.db.sql(query, {"start":start, "end": end}, as_dict=True): e = { diff --git a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py index 698c4fbd7c..0c338e0136 100644 --- a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py +++ b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py @@ -22,6 +22,10 @@ def execute(filters=None): holiday_map = get_holiday(holiday_list, filters["month"]) data = [] + leave_types = frappe.db.sql("""select name from `tabLeave Type`""", as_list=True) + leave_list = [d[0] for d in leave_types] + columns.extend(leave_list) + for emp in sorted(att_map): emp_det = emp_map.get(emp) if not emp_det: @@ -49,10 +53,35 @@ def execute(filters=None): elif status == "Half Day": total_p += 0.5 total_a += 0.5 + total_l += 0.5 row += [total_p, total_l, total_a] - data.append(row) + if not filters.get("employee"): + filters.update({"employee": emp}) + conditions += " and employee = %(employee)s" + elif not filters.get("employee") == emp: + filters.update({"employee": emp}) + + leave_details = frappe.db.sql("""select leave_type, status, count(*) as count from `tabAttendance`\ + where leave_type is not NULL %s group by leave_type, status""" % conditions, filters, as_dict=1) + + leaves = {} + for d in leave_details: + if d.status == "Half Day": + d.count = d.count * 0.5 + if d.leave_type in leaves: + leaves[d.leave_type] += d.count + else: + leaves[d.leave_type] = d.count + + for d in leave_list: + if d in leaves: + row.append(leaves[d]) + else: + row.append("0.0") + + data.append(row) return columns, data def get_columns(filters): From 404f39d3737263e076b64d26dfba79a5506fe939 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Mon, 14 May 2018 15:46:45 +0530 Subject: [PATCH 7/9] [fix] apply price list in_apply_price_list flag remains true if server exception occurs --- erpnext/public/js/controllers/transaction.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 4ab413b321..d9bd50c226 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -106,7 +106,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ } if( - this.frm.docstatus < 2 + this.frm.docstatus < 2 && this.frm.fields_dict["payment_terms_template"] && this.frm.fields_dict["payment_schedule"] && this.frm.doc.payment_terms_template @@ -1094,6 +1094,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ me.in_apply_price_list = false; } } + }).always(() => { + me.in_apply_price_list = false; }); }, From dbb67fb4fdbd2c3959c6d9754091e049e9abf0fa Mon Sep 17 00:00:00 2001 From: Shreya Date: Mon, 14 May 2018 23:02:09 +0530 Subject: [PATCH 8/9] Clear leave balance on changing leave type --- erpnext/hr/doctype/leave_application/leave_application.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/hr/doctype/leave_application/leave_application.js b/erpnext/hr/doctype/leave_application/leave_application.js index 2eb155dee1..06eee618cb 100755 --- a/erpnext/hr/doctype/leave_application/leave_application.js +++ b/erpnext/hr/doctype/leave_application/leave_application.js @@ -95,6 +95,9 @@ frappe.ui.form.on("Leave Application", { if (!r.exc && r.message) { frm.set_value('leave_balance', r.message); } + else { + frm.set_value('leave_balance', "0"); + } } }); } From f8c26bb778e67a613a6f8effb5da8e76a6f67631 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Tue, 15 May 2018 13:28:15 +0600 Subject: [PATCH 9/9] bumped to version 10.1.32 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index a20b21a6d0..1df3c7d691 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '10.1.31' +__version__ = '10.1.32' def get_default_company(user=None): '''Get default company for user'''