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''' 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/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.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"); + } } }); } 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): 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")) 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; }); }, 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 diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index 8f0a25dc43..f58b40e26f 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_production_order_operations() prod_order.save() production_orders.append(prod_order.name) else: 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 %}