From 4e37d25374766f314e154c334d84778d21ac767d Mon Sep 17 00:00:00 2001 From: Afshan Date: Tue, 23 Jun 2020 14:10:40 +0530 Subject: [PATCH 01/10] fix: removed condition that considered "Standard working hours" while creating "timesheet" as it was setting wrong time #20848 --- .../projects/doctype/timesheet/timesheet.js | 33 ++++--------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js index defc18bf4e..5de2930c1c 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.js +++ b/erpnext/projects/doctype/timesheet/timesheet.js @@ -162,19 +162,11 @@ frappe.ui.form.on("Timesheet Detail", { to_time: function(frm, cdt, cdn) { var child = locals[cdt][cdn]; - var time_diff = (moment(child.to_time).diff(moment(child.from_time),"seconds")) / ( 60 * 60 * 24); - var std_working_hours = 0; if(frm._setting_hours) return; var hours = moment(child.to_time).diff(moment(child.from_time), "seconds") / 3600; - std_working_hours = time_diff * frappe.working_hours; - - if (std_working_hours < hours && std_working_hours > 0) { - frappe.model.set_value(cdt, cdn, "hours", std_working_hours); - } else { - frappe.model.set_value(cdt, cdn, "hours", hours); - } + frappe.model.set_value(cdt, cdn, "hours", hours); }, time_logs_add: function(frm) { @@ -236,23 +228,12 @@ var calculate_end_time = function(frm, cdt, cdn) { let d = moment(child.from_time); if(child.hours) { - var time_diff = (moment(child.to_time).diff(moment(child.from_time),"seconds")) / (60 * 60 * 24); - var std_working_hours = 0; - var hours = moment(child.to_time).diff(moment(child.from_time), "seconds") / 3600; - - std_working_hours = time_diff * frappe.working_hours; - - if (std_working_hours < hours && std_working_hours > 0) { - frappe.model.set_value(cdt, cdn, "hours", std_working_hours); - frappe.model.set_value(cdt, cdn, "to_time", d.add(hours, "hours").format(frappe.defaultDatetimeFormat)); - } else { - d.add(child.hours, "hours"); - frm._setting_hours = true; - frappe.model.set_value(cdt, cdn, "to_time", - d.format(frappe.defaultDatetimeFormat)).then(() => { - frm._setting_hours = false; - }); - } + d.add(child.hours, "hours"); + frm._setting_hours = true; + frappe.model.set_value(cdt, cdn, "to_time", + d.format(frappe.defaultDatetimeFormat)).then(() => { + frm._setting_hours = false; + }); } }; From a07a548622a3b4e4a9dc4868f21f2bde906c450b Mon Sep 17 00:00:00 2001 From: Afshan Date: Wed, 24 Jun 2020 13:07:59 +0530 Subject: [PATCH 02/10] fix: removed "standard working hours" also fixed test cases --- .../doctype/timesheet/test_timesheet.py | 46 ------------------- .../projects/doctype/timesheet/timesheet.py | 12 ----- erpnext/setup/doctype/company/company.json | 8 +--- 3 files changed, 1 insertion(+), 65 deletions(-) diff --git a/erpnext/projects/doctype/timesheet/test_timesheet.py b/erpnext/projects/doctype/timesheet/test_timesheet.py index 03b67b1023..a5ce44dcf2 100644 --- a/erpnext/projects/doctype/timesheet/test_timesheet.py +++ b/erpnext/projects/doctype/timesheet/test_timesheet.py @@ -140,52 +140,6 @@ class TestTimesheet(unittest.TestCase): settings.ignore_employee_time_overlap = initial_setting settings.save() - def test_timesheet_std_working_hours(self): - emp = make_employee("test_employee_6@salary.com") - - company = frappe.get_doc('Company', "_Test Company") - company.standard_working_hours = 8 - company.save() - - timesheet = frappe.new_doc("Timesheet") - timesheet.employee = emp - timesheet.company = '_Test Company' - timesheet.append( - 'time_logs', - { - "activity_type": "_Test Activity Type", - "from_time": now_datetime(), - "to_time": now_datetime() + datetime.timedelta(days= 4) - } - ) - timesheet.save() - - ts = frappe.get_doc('Timesheet', timesheet.name) - self.assertEqual(ts.total_hours, 32) - ts.submit() - ts.cancel() - - company = frappe.get_doc('Company', "_Test Company") - company.standard_working_hours = 0 - company.save() - - timesheet = frappe.new_doc("Timesheet") - timesheet.employee = emp - timesheet.company = '_Test Company' - timesheet.append( - 'time_logs', - { - "activity_type": "_Test Activity Type", - "from_time": now_datetime(), - "to_time": now_datetime() + datetime.timedelta(days= 4) - } - ) - timesheet.save() - - ts = frappe.get_doc('Timesheet', timesheet.name) - self.assertEqual(ts.total_hours, 96) - ts.submit() - ts.cancel() def make_salary_structure_for_timesheet(employee): salary_structure_name = "Timesheet Salary Structure Test" diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py index e90821689b..7fe22bec4b 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.py +++ b/erpnext/projects/doctype/timesheet/timesheet.py @@ -24,7 +24,6 @@ class Timesheet(Document): self.set_status() self.validate_dates() self.validate_time_logs() - self.calculate_std_hours() self.update_cost() self.calculate_total_amounts() self.calculate_percentage_billed() @@ -91,17 +90,6 @@ class Timesheet(Document): self.start_date = getdate(start_date) self.end_date = getdate(end_date) - def calculate_std_hours(self): - std_working_hours = frappe.get_value("Company", self.company, 'standard_working_hours') - - for time in self.time_logs: - if time.from_time and time.to_time: - if flt(std_working_hours) and date_diff(time.to_time, time.from_time): - time.hours = flt(std_working_hours) * date_diff(time.to_time, time.from_time) - else: - if not time.hours: - time.hours = time_diff_in_hours(time.to_time, time.from_time) - def before_cancel(self): self.set_status() diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json index 020a93ff6a..ceae634a84 100644 --- a/erpnext/setup/doctype/company/company.json +++ b/erpnext/setup/doctype/company/company.json @@ -22,7 +22,6 @@ "default_letter_head", "default_holiday_list", "default_finance_book", - "standard_working_hours", "default_selling_terms", "default_buying_terms", "default_warehouse_for_sales_return", @@ -238,11 +237,6 @@ "label": "Default Holiday List", "options": "Holiday List" }, - { - "fieldname": "standard_working_hours", - "fieldtype": "Float", - "label": "Standard Working Hours" - }, { "fieldname": "default_warehouse_for_sales_return", "fieldtype": "Link", @@ -730,7 +724,7 @@ "image_field": "company_logo", "is_tree": 1, "links": [], - "modified": "2020-03-21 18:09:53.534211", + "modified": "2020-06-24 12:45:31.462195", "modified_by": "Administrator", "module": "Setup", "name": "Company", From 5374e7ae1ffe9c32ae50bb227e61b6c073c0e789 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 25 Jun 2020 19:41:42 +0530 Subject: [PATCH 03/10] fix: add company filter in email digest --- .../setup/doctype/email_digest/email_digest.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/erpnext/setup/doctype/email_digest/email_digest.py b/erpnext/setup/doctype/email_digest/email_digest.py index 7c0be3bff6..b30bd7814b 100644 --- a/erpnext/setup/doctype/email_digest/email_digest.py +++ b/erpnext/setup/doctype/email_digest/email_digest.py @@ -405,8 +405,8 @@ class EmailDigest(Document): value, count = frappe.db.sql("""select ifnull((sum(grand_total)) - (sum(grand_total*per_billed/100)),0), count(*) from `tabSales Order` - where (transaction_date <= %(to_date)s) and billing_status != "Fully Billed" - and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date})[0] + where (transaction_date <= %(to_date)s) and billing_status != "Fully Billed" and company = %(company)s + and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date, "company": self.company})[0] label = get_link_to_report('Sales Order', label=self.meta.get_label("sales_orders_to_bill"), report_type="Report Builder", @@ -430,8 +430,8 @@ class EmailDigest(Document): value, count = frappe.db.sql("""select ifnull((sum(grand_total)) - (sum(grand_total*per_delivered/100)),0), count(*) from `tabSales Order` - where (transaction_date <= %(to_date)s) and delivery_status != "Fully Delivered" - and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date})[0] + where (transaction_date <= %(to_date)s) and delivery_status != "Fully Delivered" and company = %(company)s + and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date, "company": self.company})[0] label = get_link_to_report('Sales Order', label=self.meta.get_label("sales_orders_to_deliver"), report_type="Report Builder", @@ -455,8 +455,8 @@ class EmailDigest(Document): value, count = frappe.db.sql("""select ifnull((sum(grand_total))-(sum(grand_total*per_received/100)),0), count(*) from `tabPurchase Order` - where (transaction_date <= %(to_date)s) and per_received < 100 - and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date})[0] + where (transaction_date <= %(to_date)s) and per_received < 100 and company = %(company)s + and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date, "company": self.company})[0] label = get_link_to_report('Purchase Order', label=self.meta.get_label("purchase_orders_to_receive"), report_type="Report Builder", @@ -480,8 +480,8 @@ class EmailDigest(Document): value, count = frappe.db.sql("""select ifnull((sum(grand_total)) - (sum(grand_total*per_billed/100)),0), count(*) from `tabPurchase Order` - where (transaction_date <= %(to_date)s) and per_billed < 100 - and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date})[0] + where (transaction_date <= %(to_date)s) and per_billed < 100 and company = %(company)s + and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date, "company": self.company})[0] label = get_link_to_report('Purchase Order', label=self.meta.get_label("purchase_orders_to_bill"), report_type="Report Builder", From c8f590bc8f4b589b7f0991ccc0bccc37c357375b Mon Sep 17 00:00:00 2001 From: marination Date: Thu, 25 Jun 2020 21:30:45 +0530 Subject: [PATCH 04/10] fix: Handling Empty tables in Production Plan --- .../production_plan/production_plan.py | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index 560286e68a..016ab14d5f 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -98,11 +98,17 @@ class ProductionPlan(Document): elif self.get_items_from == "Material Request": self.get_mr_items() + def get_so_mr_list(self, field, table): + """Returns a list of Sales Orders or Material Requests from the respective tables""" + so_mr_list = [d.get(field) for d in self.get(table) if d.get(field)] + return so_mr_list + def get_so_items(self): - so_list = [d.sales_order for d in self.sales_orders if d.sales_order] - if not so_list: - msgprint(_("Please enter Sales Orders in the above table")) - return [] + # Check for empty table or empty rows + if not self.get("sales_orders") or not self.get_so_mr_list("sales_order", "sales_orders"): + frappe.throw(_("Please fill the Sales Orders table"), title=_("Sales Orders Required")) + + so_list = self.get_so_mr_list("sales_order", "sales_orders") item_condition = "" if self.item_code: @@ -134,10 +140,11 @@ class ProductionPlan(Document): self.calculate_total_planned_qty() def get_mr_items(self): - mr_list = [d.material_request for d in self.material_requests if d.material_request] - if not mr_list: - msgprint(_("Please enter Material Requests in the above table")) - return [] + # Check for empty table or empty rows + if not self.get("material_requests") or not self.get_so_mr_list("material_request", "material_requests"): + frappe.throw(_("Please fill the Material Requests table"), title=_("Material Requests Required")) + + mr_list = self.get_so_mr_list("material_request", "material_requests") item_condition = "" if self.item_code: @@ -628,16 +635,18 @@ def get_items_for_material_requests(doc, warehouses=None): if warehouse_list: warehouses = list(set(warehouse_list)) - + if doc.get("for_warehouse") and doc.get("for_warehouse") in warehouses: warehouses.remove(doc.get("for_warehouse")) warehouse_list = None doc['mr_items'] = [] - po_items = doc.get('po_items') if doc.get('po_items') else doc.get('items') - if not po_items: - frappe.throw(_("Items are required to pull the raw materials which is associated with it.")) + + po_items = doc.get('po_items') + if not po_items or not [row.get('item_code') for row in po_items if row.get('item_code')]: + frappe.throw(_("Items to Manufacture are required to pull the Raw Materials associated with it."), + title=_("Items Required")) company = doc.get('company') ignore_existing_ordered_qty = doc.get('ignore_existing_ordered_qty') From 978722621fb804abc31d791c4176a90dc024cdac Mon Sep 17 00:00:00 2001 From: Michelle Alva <50285544+michellealva@users.noreply.github.com> Date: Thu, 25 Jun 2020 22:35:33 +0530 Subject: [PATCH 05/10] fix: grammatical fix on error message Before: Fiscal Year: 2020 does not exists After: Fiscal Year 2020 Does Not Exist --- erpnext/controllers/trends.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/controllers/trends.py b/erpnext/controllers/trends.py index 092baa4018..9b4b0eb917 100644 --- a/erpnext/controllers/trends.py +++ b/erpnext/controllers/trends.py @@ -33,7 +33,7 @@ def validate_filters(filters): frappe.throw(_("{0} is mandatory").format(f)) if not frappe.db.exists("Fiscal Year", filters.get("fiscal_year")): - frappe.throw(_("Fiscal Year: {0} does not exists").format(filters.get("fiscal_year"))) + frappe.throw(_("Fiscal Year {0} Does Not Exist").format(filters.get("fiscal_year"))) if filters.get("based_on") == filters.get("group_by"): frappe.throw(_("'Based On' and 'Group By' can not be same")) From 27d27c924dde64d846f2200b7f4570e819058d7c Mon Sep 17 00:00:00 2001 From: Anupam K Date: Fri, 26 Jun 2020 12:46:40 +0530 Subject: [PATCH 06/10] enable show_configure_button when shopping cart is enabled --- .../shopping_cart_settings/shopping_cart_settings.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.js b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.js index e1510f5335..45889872dc 100644 --- a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.js +++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.js @@ -13,6 +13,12 @@ $.extend(cur_frm.cscript, { }, enable_checkout: function(){ toggle_mandatory(cur_frm) + }, + enabled: function() { + if(cur_frm.doc.enabled == 1) { + cur_frm.doc.show_configure_button = 1; + cur_frm.refresh_field('show_configure_button'); + } } }); From 0ff5af222a5842e93f4b9e1bdbc31011abbe105d Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 26 Jun 2020 12:46:42 +0530 Subject: [PATCH 07/10] fix: Send email to credit controllers to increase credit limit --- erpnext/selling/doctype/customer/customer.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index 682dfede72..d70c64fce4 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -388,8 +388,7 @@ def check_credit_limit(customer, company, ignore_outstanding_sales_order=False, credit_controller_users = get_users_with_role(credit_controller_role or "Sales Master Manager") # form a list of emails and names to show to the user - credit_controller_users_list = [user for user in credit_controller_users if frappe.db.exists("Employee", {"prefered_email": user})] - credit_controller_users = [get_formatted_email(user).replace("<", "(").replace(">", ")") for user in credit_controller_users_list] + credit_controller_users = [get_formatted_email(user).replace("<", "(").replace(">", ")") for user in credit_controller_users] if not credit_controller_users: frappe.throw(_("Please contact your administrator to extend the credit limits for {0}.".format(customer))) @@ -409,7 +408,7 @@ def check_credit_limit(customer, company, ignore_outstanding_sales_order=False, 'customer': customer, 'customer_outstanding': customer_outstanding, 'credit_limit': credit_limit, - 'credit_controller_users_list': credit_controller_users_list + 'credit_controller_users_list': credit_controller_users } } ) From 0f056ec51d73aa6f2e6914921bd8a7aa8548c81a Mon Sep 17 00:00:00 2001 From: marination Date: Fri, 26 Jun 2020 14:12:11 +0530 Subject: [PATCH 08/10] fix: Sales Order to MR test failing --- .../manufacturing/doctype/production_plan/production_plan.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index 016ab14d5f..c8892376b7 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -643,7 +643,8 @@ def get_items_for_material_requests(doc, warehouses=None): doc['mr_items'] = [] - po_items = doc.get('po_items') + po_items = doc.get('po_items') if doc.get('po_items') else doc.get('items') + # Check for empty table or empty rows if not po_items or not [row.get('item_code') for row in po_items if row.get('item_code')]: frappe.throw(_("Items to Manufacture are required to pull the Raw Materials associated with it."), title=_("Items Required")) From 13e8c3217247dca8d17e1330b512d35a9a94d956 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Fri, 26 Jun 2020 15:07:32 +0530 Subject: [PATCH 09/10] Update shopping_cart_settings.js --- .../doctype/shopping_cart_settings/shopping_cart_settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.js b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.js index 45889872dc..ffc5daba62 100644 --- a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.js +++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.js @@ -15,7 +15,7 @@ $.extend(cur_frm.cscript, { toggle_mandatory(cur_frm) }, enabled: function() { - if(cur_frm.doc.enabled == 1) { + if (cur_frm.doc.enabled === 1) { cur_frm.doc.show_configure_button = 1; cur_frm.refresh_field('show_configure_button'); } From e9cec2ff760beb986f532a5b3b384a7fa597233d Mon Sep 17 00:00:00 2001 From: michellealva Date: Fri, 26 Jun 2020 19:29:25 +0530 Subject: [PATCH 10/10] fix: remove redundant label in salary slip --- erpnext/payroll/doctype/salary_slip/salary_slip.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.json b/erpnext/payroll/doctype/salary_slip/salary_slip.json index 663a3ef9ea..88931c2a4b 100644 --- a/erpnext/payroll/doctype/salary_slip/salary_slip.json +++ b/erpnext/payroll/doctype/salary_slip/salary_slip.json @@ -381,7 +381,6 @@ { "fieldname": "earning", "fieldtype": "Column Break", - "label": "Earning", "oldfieldtype": "Column Break", "show_days": 1, "show_seconds": 1, @@ -400,7 +399,6 @@ { "fieldname": "deduction", "fieldtype": "Column Break", - "label": "Deduction", "oldfieldtype": "Column Break", "show_days": 1, "show_seconds": 1, @@ -616,7 +614,7 @@ "idx": 9, "is_submittable": 1, "links": [], - "modified": "2020-06-22 14:42:43.921828", + "modified": "2020-06-25 14:42:43.921828", "modified_by": "Administrator", "module": "Payroll", "name": "Salary Slip",