From 82cc2921d1b13959833b49cf0591aa3816aaf0bc Mon Sep 17 00:00:00 2001 From: Neil Trini Lasrado Date: Fri, 12 Jun 2015 16:14:25 +0530 Subject: [PATCH 1/7] Validation added to prevent user from creating salary structure with 'From Date' before employee 'Date of joining' --- .../salary_structure/salary_structure.py | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.py b/erpnext/hr/doctype/salary_structure/salary_structure.py index 8580f2e4d4..69f341bb3c 100644 --- a/erpnext/hr/doctype/salary_structure/salary_structure.py +++ b/erpnext/hr/doctype/salary_structure/salary_structure.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import frappe -from frappe.utils import cstr, flt +from frappe.utils import cstr, flt, getdate from frappe.model.naming import make_autoname from frappe import _ from frappe.model.mapper import get_mapped_doc @@ -14,6 +14,13 @@ from erpnext.hr.utils import set_employee_name class SalaryStructure(Document): def autoname(self): self.name = make_autoname(self.employee + '/.SST' + '/.#####') + + def validate(self): + self.check_existing() + self.validate_amount() + self.validate_employee() + self.validate_joining_date() + set_employee_name(self) def get_employee_details(self): ret = {} @@ -77,14 +84,11 @@ class SalaryStructure(Document): old_employee = frappe.db.get_value("Salary Structure", self.name, "employee") if old_employee and self.employee != old_employee: frappe.throw(_("Employee can not be changed")) - - - def validate(self): - self.check_existing() - self.validate_amount() - self.validate_employee() - set_employee_name(self) - + + def validate_joining_date(self): + joining_date = getdate(frappe.db.get_value("Employee", self.employee, "date_of_joining")) + if getdate(self.from_date) < joining_date: + frappe.throw(_("From Date in Salary Structure cannot be lesser than Employee Joining Date.")) @frappe.whitelist() def make_salary_slip(source_name, target_doc=None): From 3c1a4a0b9b580c8eac48e056a8dbc7911aef9086 Mon Sep 17 00:00:00 2001 From: Neil Trini Lasrado Date: Fri, 12 Jun 2015 18:31:36 +0530 Subject: [PATCH 2/7] percent_complete made no-copy in Project --- erpnext/projects/doctype/project/project.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/projects/doctype/project/project.json b/erpnext/projects/doctype/project/project.json index 2aca991877..486d86112e 100644 --- a/erpnext/projects/doctype/project/project.json +++ b/erpnext/projects/doctype/project/project.json @@ -163,6 +163,7 @@ "fieldtype": "Percent", "in_list_view": 0, "label": "% Tasks Completed", + "no_copy": 1, "permlevel": 0, "read_only": 1 }, @@ -356,7 +357,7 @@ "icon": "icon-puzzle-piece", "idx": 1, "max_attachments": 4, - "modified": "2015-04-27 07:37:44.239930", + "modified": "2015-06-12 09:00:54.080220", "modified_by": "Administrator", "module": "Projects", "name": "Project", From f2a0161709e791bb6b487c50728860c3712b89d2 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Fri, 12 Jun 2015 18:58:36 -0400 Subject: [PATCH 3/7] [fix] Don't create Time Logs against Production Order if Workstation is not specified in Operations --- .../doctype/production_order/production_order.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py index 6de0d7b46d..ca5f6d972c 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order.py +++ b/erpnext/manufacturing/doctype/production_order/production_order.py @@ -217,12 +217,14 @@ class ProductionOrder(Document): for i, d in enumerate(self.operations): self.set_operation_start_end_time(i, d) + if not d.workstation: + continue + time_log = make_time_log(self.name, d.operation, d.planned_start_time, d.planned_end_time, flt(self.qty) - flt(d.completed_qty), self.project_name, d.workstation, operation_id=d.name) - if d.workstation: - # validate operating hours if workstation [not mandatory] is specified - self.check_operation_fits_in_working_hours(d) + # validate operating hours if workstation [not mandatory] is specified + self.check_operation_fits_in_working_hours(d) original_start_time = time_log.from_time while True: From 63e4d31aa63826470127690308b4fc0291a1e025 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Fri, 12 Jun 2015 18:59:18 -0400 Subject: [PATCH 4/7] [fix] Task should be mandatory in Time Log only when Project is mentioned but Production Order is not --- erpnext/projects/doctype/time_log/time_log.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/erpnext/projects/doctype/time_log/time_log.py b/erpnext/projects/doctype/time_log/time_log.py index a0fa23b64a..aa5647e8e8 100644 --- a/erpnext/projects/doctype/time_log/time_log.py +++ b/erpnext/projects/doctype/time_log/time_log.py @@ -128,7 +128,7 @@ class TimeLog(Document): def update_production_order(self): """Updates `start_date`, `end_date`, `status` for operation in Production Order.""" - + if self.production_order and self.for_manufacturing: if not self.operation_id: frappe.throw(_("Operation ID not set")) @@ -208,22 +208,23 @@ class TimeLog(Document): self.production_order = None self.operation = None self.quantity = None - + def update_cost(self): rate = get_activity_cost(self.employee, self.activity_type) if rate: self.costing_rate = rate.get('costing_rate') - self.billing_rate = rate.get('billing_rate') + self.billing_rate = rate.get('billing_rate') self.costing_amount = self.costing_rate * self.hours if self.billable: self.billing_amount = self.billing_rate * self.hours else: self.billing_amount = 0 - + def validate_task(self): - if self.project and not self.task: + # if a time log is being created against a project without production order + if (self.project and not self.production_order) and not self.task: frappe.throw(_("Task is Mandatory if Time Log is against a project")) - + def update_task(self): if self.task and frappe.db.exists("Task", self.task): task = frappe.get_doc("Task", self.task) @@ -266,7 +267,7 @@ def get_events(start, end, filters=None): d.title += " for Project: " + d.project return data - + @frappe.whitelist() def get_activity_cost(employee=None, activity_type=None): rate = frappe.db.sql("""select costing_rate, billing_rate from `tabActivity Cost` where employee= %s From 810041cbe33733f4f286aa962d73e82981378f02 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 15 Jun 2015 10:20:04 +0530 Subject: [PATCH 5/7] [fix] Fixed error due to performance upgrade cleanup --- .../accounts/report/accounts_receivable/accounts_receivable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index bdfdf0ede3..19703be8eb 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -171,7 +171,7 @@ class ReceivablePayableReport(object): def get_gl_entries(self, party_type): if not hasattr(self, "gl_entries"): conditions, values = self.prepare_conditions(party_type) - self.gl_entries = frappe.db.sql("""select posting_date, account, party_type, party, debit, credit, + self.gl_entries = frappe.db.sql("""select name, posting_date, account, party_type, party, debit, credit, voucher_type, voucher_no, against_voucher_type, against_voucher from `tabGL Entry` where docstatus < 2 and party_type=%s {0} order by posting_date, party""" .format(conditions), values, as_dict=True) From 65922d307900f58adca867681ae79bab35089a32 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 15 Jun 2015 10:23:53 +0530 Subject: [PATCH 6/7] [fix] supplier invoice date can not be after posting date --- erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 2516ded589..8820c87b40 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import frappe -from frappe.utils import cint, formatdate, flt +from frappe.utils import cint, formatdate, flt, getdate from frappe import msgprint, _, throw from erpnext.setup.utils import get_company_currency import frappe.defaults @@ -389,7 +389,7 @@ class PurchaseInvoice(BuyingController): def validate_supplier_invoice(self): if self.bill_date: - if self.bill_date > self.posting_date: + if getdate(self.bill_date) > getdate(self.posting_date): frappe.throw("Supplier Invoice Date cannot be greater than Posting Date") if self.bill_no: if cint(frappe.db.get_single_value("Accounts Settings", "check_supplier_invoice_uniqueness")): From d1d3237784e1eb3611fe6a9b213c54f217c50c03 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 15 Jun 2015 11:05:39 +0600 Subject: [PATCH 7/7] bumped to version 5.0.24 --- erpnext/__version__.py | 2 +- erpnext/hooks.py | 2 +- setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/__version__.py b/erpnext/__version__.py index 18ebfccd22..e571e3d286 100644 --- a/erpnext/__version__.py +++ b/erpnext/__version__.py @@ -1,2 +1,2 @@ from __future__ import unicode_literals -__version__ = '5.0.23' +__version__ = '5.0.24' diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 1e9e5c82e9..cd55d2fa28 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -5,7 +5,7 @@ app_publisher = "Frappe Technologies Pvt. Ltd. and Contributors" app_description = "Open Source Enterprise Resource Planning for Small and Midsized Organizations" app_icon = "icon-th" app_color = "#e74c3c" -app_version = "5.0.23" +app_version = "5.0.24" error_report_email = "support@erpnext.com" diff --git a/setup.py b/setup.py index 16213d1ce2..103dd770f3 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ from setuptools import setup, find_packages -version = "5.0.23" +version = "5.0.24" with open("requirements.txt", "r") as f: install_requires = f.readlines()