From 40f7dd4e774ac56776e7b7a42061a1fa0c4d074f Mon Sep 17 00:00:00 2001 From: Khushal Trivedi Date: Tue, 26 Nov 2019 18:31:40 +0530 Subject: [PATCH 01/40] fix: date validation on inpatient record, else condition removing on clinical prcd templ which is not req --- .../clinical_procedure_template.py | 5 +++-- .../doctype/inpatient_record/inpatient_record.py | 11 ++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py index 141329b3db..7cec362200 100644 --- a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py +++ b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py @@ -63,10 +63,11 @@ def updating_rate(self): item_code=%s""",(self.template, self.rate, self.item)) def create_item_from_template(doc): + disabled = 1 + if(doc.is_billable == 1): disabled = 0 - else: - disabled = 1 + #insert item item = frappe.get_doc({ "doctype": "Item", diff --git a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py index c107cd7335..835b38bedf 100644 --- a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py +++ b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe from frappe import _ -from frappe.utils import today, now_datetime +from frappe.utils import today, now_datetime, getdate from frappe.model.document import Document from frappe.desk.reportview import get_match_cond @@ -15,11 +15,20 @@ class InpatientRecord(Document): frappe.db.set_value("Patient", self.patient, "inpatient_record", self.name) def validate(self): + self.validate_dates() self.validate_already_scheduled_or_admitted() if self.status == "Discharged": frappe.db.set_value("Patient", self.patient, "inpatient_status", None) frappe.db.set_value("Patient", self.patient, "inpatient_record", None) + def validate_dates(self): + if (getdate(self.scheduled_date) < getdate(today())) or \ + (getdate(self.admitted_datetime) < getdate(today())): + frappe.throw(_("Scheduled and Admitted dates can not be less than today")) + if (getdate(self.expected_discharge) < getdate(self.scheduled_date)) or \ + (getdate(self.discharge_date) < getdate(self.scheduled_date)): + frappe.throw(_("Expected and Discharge dates cannot be less than Admission Schedule date")) + def validate_already_scheduled_or_admitted(self): query = """ select name, status From 213e071b214893ac951f313a84ffada18a145358 Mon Sep 17 00:00:00 2001 From: Khushal Trivedi Date: Mon, 2 Dec 2019 15:08:52 +0530 Subject: [PATCH 02/40] fix:Pricing Rule error AttributeError: 'str' object has no attribute 'get' #19770 --- erpnext/accounts/doctype/pricing_rule/pricing_rule.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index 430dce7ddb..e81d186c73 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -33,9 +33,9 @@ class PricingRule(Document): if not self.margin_type: self.margin_rate_or_amount = 0.0 def validate_duplicate_apply_on(self): + print("##############",self.apply_on) field = apply_on_dict.get(self.apply_on) - values = [d.get(frappe.scrub(self.apply_on)) for d in self.get(field)] - + values = [d.get(frappe.scrub(self.apply_on)) for d in self.get(field) if field] if len(values) != len(set(values)): frappe.throw(_("Duplicate {0} found in the table").format(self.apply_on)) From db8911b05d79c98b10d1ff6b0dd723216961dc3d Mon Sep 17 00:00:00 2001 From: Khushal Trivedi Date: Mon, 2 Dec 2019 15:14:11 +0530 Subject: [PATCH 03/40] fix:Pricing Rule error AttributeError: 'str' object has no attribute 'get' #19770 --- erpnext/accounts/doctype/pricing_rule/pricing_rule.py | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index e81d186c73..e871d98af6 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -33,7 +33,6 @@ class PricingRule(Document): if not self.margin_type: self.margin_rate_or_amount = 0.0 def validate_duplicate_apply_on(self): - print("##############",self.apply_on) field = apply_on_dict.get(self.apply_on) values = [d.get(frappe.scrub(self.apply_on)) for d in self.get(field) if field] if len(values) != len(set(values)): From 8af51e1f900ce49361b5766ef0468ab8e7c16433 Mon Sep 17 00:00:00 2001 From: Khushal Trivedi Date: Tue, 3 Dec 2019 19:28:16 +0530 Subject: [PATCH 04/40] fix: joining and relieving Date can be on same date as valid use case --- erpnext/hr/doctype/employee/employee.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py index 2f88e1e363..6f4e0eaac8 100755 --- a/erpnext/hr/doctype/employee/employee.py +++ b/erpnext/hr/doctype/employee/employee.py @@ -152,7 +152,7 @@ class Employee(NestedSet): elif self.date_of_retirement and self.date_of_joining and (getdate(self.date_of_retirement) <= getdate(self.date_of_joining)): throw(_("Date Of Retirement must be greater than Date of Joining")) - elif self.relieving_date and self.date_of_joining and (getdate(self.relieving_date) <= getdate(self.date_of_joining)): + elif self.relieving_date and self.date_of_joining and (getdate(self.relieving_date) < getdate(self.date_of_joining)): throw(_("Relieving Date must be greater than Date of Joining")) elif self.contract_end_date and self.date_of_joining and (getdate(self.contract_end_date) <= getdate(self.date_of_joining)): From 9f0699f7e310df03c0a6417feb671855f8ca7112 Mon Sep 17 00:00:00 2001 From: Khushal Trivedi Date: Mon, 9 Dec 2019 18:02:06 +0530 Subject: [PATCH 05/40] fix-education: date of birth validation --- erpnext/education/doctype/student/student.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/erpnext/education/doctype/student/student.py b/erpnext/education/doctype/student/student.py index 76825cec1b..8e4b4e16f9 100644 --- a/erpnext/education/doctype/student/student.py +++ b/erpnext/education/doctype/student/student.py @@ -5,12 +5,14 @@ from __future__ import unicode_literals import frappe from frappe.model.document import Document +from frappe.utils import getdate,today from frappe import _ from frappe.desk.form.linked_with import get_linked_doctypes from erpnext.education.utils import check_content_completion, check_quiz_completion class Student(Document): def validate(self): self.title = " ".join(filter(None, [self.first_name, self.middle_name, self.last_name])) + self.validate_dates() if self.student_applicant: self.check_unique() @@ -19,6 +21,10 @@ class Student(Document): if frappe.get_value("Student", self.name, "title") != self.title: self.update_student_name_in_linked_doctype() + def validate_dates(self): + if self.date_of_birth and getdate(self.date_of_birth) >= getdate(today()): + frappe.throw(_("Date of Birth cannot be greater than today.")) + def update_student_name_in_linked_doctype(self): linked_doctypes = get_linked_doctypes("Student") for d in linked_doctypes: From e89d521848d91dac8d11b8eccabdd3c2f2c39196 Mon Sep 17 00:00:00 2001 From: Khushal Trivedi Date: Wed, 11 Dec 2019 14:02:07 +0530 Subject: [PATCH 06/40] fix:Sibling child table filtering for duplacacy on student form --- erpnext/education/doctype/student/student.js | 21 +++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/erpnext/education/doctype/student/student.js b/erpnext/education/doctype/student/student.js index b6e741c4da..66df6b977e 100644 --- a/erpnext/education/doctype/student/student.js +++ b/erpnext/education/doctype/student/student.js @@ -31,8 +31,9 @@ frappe.ui.form.on('Student', { frappe.ui.form.on('Student Guardian', { guardians_add: function(frm){ frm.fields_dict['guardians'].grid.get_field('guardian').get_query = function(doc){ - var guardian_list = []; + let guardian_list = []; if(!doc.__islocal) guardian_list.push(doc.guardian); + $.each(doc.guardians, function(idx, val){ if (val.guardian) guardian_list.push(val.guardian); }); @@ -40,3 +41,21 @@ frappe.ui.form.on('Student Guardian', { }; } }); + + +frappe.ui.form.on('Student Sibling', { + siblings_add: function(frm){ + frm.fields_dict['siblings'].grid.get_field('student').get_query = function(doc){ + let sibling_list = [frm.doc.name]; + if(!doc.__islocal) sibling_list.push(doc.student); + + $.each(doc.siblings, function(idx, val){ + if (val.student && val.studying_in_same_institute == 'YES') { + sibling_list.push(val.student); + } + + }); + return { filters: [['Student', 'name', 'not in', sibling_list]] }; + }; + } +}); \ No newline at end of file From 4c24fb1efc6a2e3111f8a7d7e03fa1717dc73aa8 Mon Sep 17 00:00:00 2001 From: Khushal Trivedi Date: Wed, 11 Dec 2019 15:16:56 +0530 Subject: [PATCH 07/40] fix:Sibling child table filtering for duplacacy on student form --- erpnext/education/doctype/student/student.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/erpnext/education/doctype/student/student.js b/erpnext/education/doctype/student/student.js index 66df6b977e..ea01b5ded2 100644 --- a/erpnext/education/doctype/student/student.js +++ b/erpnext/education/doctype/student/student.js @@ -33,7 +33,6 @@ frappe.ui.form.on('Student Guardian', { frm.fields_dict['guardians'].grid.get_field('guardian').get_query = function(doc){ let guardian_list = []; if(!doc.__islocal) guardian_list.push(doc.guardian); - $.each(doc.guardians, function(idx, val){ if (val.guardian) guardian_list.push(val.guardian); }); @@ -48,12 +47,10 @@ frappe.ui.form.on('Student Sibling', { frm.fields_dict['siblings'].grid.get_field('student').get_query = function(doc){ let sibling_list = [frm.doc.name]; if(!doc.__islocal) sibling_list.push(doc.student); - $.each(doc.siblings, function(idx, val){ if (val.student && val.studying_in_same_institute == 'YES') { sibling_list.push(val.student); - } - + } }); return { filters: [['Student', 'name', 'not in', sibling_list]] }; }; From 03e770782a30bb6ffa9ba010f2d642c1573aece3 Mon Sep 17 00:00:00 2001 From: Khushal Trivedi Date: Wed, 11 Dec 2019 15:24:39 +0530 Subject: [PATCH 08/40] fix:Sibling child table filtering for duplacacy on student form --- erpnext/education/doctype/student/student.js | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/education/doctype/student/student.js b/erpnext/education/doctype/student/student.js index ea01b5ded2..1936dcbd3e 100644 --- a/erpnext/education/doctype/student/student.js +++ b/erpnext/education/doctype/student/student.js @@ -46,7 +46,6 @@ frappe.ui.form.on('Student Sibling', { siblings_add: function(frm){ frm.fields_dict['siblings'].grid.get_field('student').get_query = function(doc){ let sibling_list = [frm.doc.name]; - if(!doc.__islocal) sibling_list.push(doc.student); $.each(doc.siblings, function(idx, val){ if (val.student && val.studying_in_same_institute == 'YES') { sibling_list.push(val.student); From ee9aea4febee1dfa0113809053df526395ea02fe Mon Sep 17 00:00:00 2001 From: Khushal Trivedi Date: Tue, 24 Dec 2019 13:37:10 +0530 Subject: [PATCH 09/40] fix: date validation on student form, instructor duplicacy fix on student grp, instructor with same employee id fix --- erpnext/education/doctype/instructor/instructor.py | 9 +++++++++ erpnext/education/doctype/student/student.py | 3 +++ .../education/doctype/student_group/student_group.js | 12 ++++++++++++ 3 files changed, 24 insertions(+) diff --git a/erpnext/education/doctype/instructor/instructor.py b/erpnext/education/doctype/instructor/instructor.py index 0756b5f01a..058d476f5b 100644 --- a/erpnext/education/doctype/instructor/instructor.py +++ b/erpnext/education/doctype/instructor/instructor.py @@ -22,3 +22,12 @@ class Instructor(Document): self.name = self.employee elif naming_method == 'Full Name': self.name = self.instructor_name + + def validate(self): + self.validate_duplicate_employee() + + def validate_duplicate_employee(self): + if self.employee and frappe.db.get_value("Instructor", {'employee': self.employee}, 'name'): + frappe.throw(_("Employee ID is linked with another instructor")) + + diff --git a/erpnext/education/doctype/student/student.py b/erpnext/education/doctype/student/student.py index 8e4b4e16f9..99c4c0e908 100644 --- a/erpnext/education/doctype/student/student.py +++ b/erpnext/education/doctype/student/student.py @@ -25,6 +25,9 @@ class Student(Document): if self.date_of_birth and getdate(self.date_of_birth) >= getdate(today()): frappe.throw(_("Date of Birth cannot be greater than today.")) + if self.joining_date and self.date_of_leaving and getdate(self.joining_date) > getdate(self.date_of_leaving): + frappe.throw(_("Joining Date can not be greater than Leaving Date")) + def update_student_name_in_linked_doctype(self): linked_doctypes = get_linked_doctypes("Student") for d in linked_doctypes: diff --git a/erpnext/education/doctype/student_group/student_group.js b/erpnext/education/doctype/student_group/student_group.js index c29c134843..372e190af9 100644 --- a/erpnext/education/doctype/student_group/student_group.js +++ b/erpnext/education/doctype/student_group/student_group.js @@ -122,3 +122,15 @@ frappe.ui.form.on("Student Group", { } } }); + +frappe.ui.form.on('Student Group Instructor', { + instructors_add: function(frm){ + frm.fields_dict['instructors'].grid.get_field('instructor').get_query = function(doc){ + let instructor_list = []; + $.each(doc.instructors, function(idx, val){ + instructor_list.push(val.instructor); + }); + return { filters: [['Instructor', 'name', 'not in', instructor_list]] }; + }; + } +}); \ No newline at end of file From e57f1c995d1e0c35788eb1b4d437cb5b03d96f04 Mon Sep 17 00:00:00 2001 From: Khushal Trivedi Date: Tue, 24 Dec 2019 14:02:31 +0530 Subject: [PATCH 10/40] fix: date validation on student form, instructor duplicacy fix on student grp, instructor with same employee id fix --- erpnext/education/doctype/student_group/student_group.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/education/doctype/student_group/student_group.js b/erpnext/education/doctype/student_group/student_group.js index 372e190af9..4165ce0f2e 100644 --- a/erpnext/education/doctype/student_group/student_group.js +++ b/erpnext/education/doctype/student_group/student_group.js @@ -128,7 +128,7 @@ frappe.ui.form.on('Student Group Instructor', { frm.fields_dict['instructors'].grid.get_field('instructor').get_query = function(doc){ let instructor_list = []; $.each(doc.instructors, function(idx, val){ - instructor_list.push(val.instructor); + instructor_list.push(val.instructor); }); return { filters: [['Instructor', 'name', 'not in', instructor_list]] }; }; From 0d9c151d9f61d03e57f815d99158e1b90c9dca5e Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 24 Dec 2019 18:06:49 +0530 Subject: [PATCH 11/40] fix: Exclude current record while validating duplicate employee --- erpnext/education/doctype/instructor/instructor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/education/doctype/instructor/instructor.py b/erpnext/education/doctype/instructor/instructor.py index 058d476f5b..28df2fcdc1 100644 --- a/erpnext/education/doctype/instructor/instructor.py +++ b/erpnext/education/doctype/instructor/instructor.py @@ -27,7 +27,7 @@ class Instructor(Document): self.validate_duplicate_employee() def validate_duplicate_employee(self): - if self.employee and frappe.db.get_value("Instructor", {'employee': self.employee}, 'name'): + if self.employee and frappe.db.get_value("Instructor", {'employee': self.employee, 'name': ['!=', self.name]}, 'name'): frappe.throw(_("Employee ID is linked with another instructor")) From 3496104ebe8c1d04cb9300699fdc57e1c62c5be2 Mon Sep 17 00:00:00 2001 From: Anurag Mishra Date: Tue, 28 Jan 2020 13:11:49 +0530 Subject: [PATCH 12/40] fix: odometer value was not syncing properly --- erpnext/hr/doctype/vehicle_log/vehicle_log.js | 38 +- .../hr/doctype/vehicle_log/vehicle_log.json | 842 ++++-------------- erpnext/hr/doctype/vehicle_log/vehicle_log.py | 18 +- 3 files changed, 201 insertions(+), 697 deletions(-) diff --git a/erpnext/hr/doctype/vehicle_log/vehicle_log.js b/erpnext/hr/doctype/vehicle_log/vehicle_log.js index 7694cfed7c..4c192a0234 100644 --- a/erpnext/hr/doctype/vehicle_log/vehicle_log.js +++ b/erpnext/hr/doctype/vehicle_log/vehicle_log.js @@ -2,19 +2,10 @@ // For license information, please see license.txt frappe.ui.form.on("Vehicle Log", { - refresh: function(frm,cdt,cdn) { - var vehicle_log=frappe.model.get_doc(cdt,cdn); - if (vehicle_log.license_plate) { - frappe.call({ - method: "erpnext.hr.doctype.vehicle_log.vehicle_log.get_make_model", - args: { - license_plate: vehicle_log.license_plate - }, - callback: function(r) { - frappe.model.set_value(cdt, cdn, ("model"), r.message[0]); - frappe.model.set_value(cdt, cdn, ("make"), r.message[1]); - } - }) + refresh: function(frm) { + + if(frm.doc.license_plate && frm.doc.__islocal){ + frm.events.set_vehicle_details(frm) } if(frm.doc.docstatus == 1) { @@ -25,6 +16,27 @@ frappe.ui.form.on("Vehicle Log", { } }, + license_plate: function(frm){ + if(frm.doc.license_plate){ + frm.events.set_vehicle_details(frm) + } + }, + + set_vehicle_details: function(frm){ + frappe.call({ + method: "erpnext.hr.doctype.vehicle_log.vehicle_log.get_make_model", + args: { + license_plate: frm.doc.license_plate + }, + callback: function(r) { + frappe.model.set_value(cur_frm.doctype, cur_frm.docname, "model", r.message[0]); + frappe.model.set_value(cur_frm.doctype, cur_frm.docname, "make", r.message[1]); + frappe.model.set_value(cur_frm.doctype, cur_frm.docname, "last_odometer", r.message[2]); + frappe.model.set_value(cur_frm.doctype, cur_frm.docname, "employee", r.message[3]); + } + }); + }, + expense_claim: function(frm){ frappe.call({ method: "erpnext.hr.doctype.vehicle_log.vehicle_log.make_expense_claim", diff --git a/erpnext/hr/doctype/vehicle_log/vehicle_log.json b/erpnext/hr/doctype/vehicle_log/vehicle_log.json index cde39e7ee4..52effffc06 100644 --- a/erpnext/hr/doctype/vehicle_log/vehicle_log.json +++ b/erpnext/hr/doctype/vehicle_log/vehicle_log.json @@ -1,706 +1,192 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "naming_series:", - "beta": 0, - "creation": "2016-09-03 14:14:51.788550", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Document", - "editable_grid": 1, + "actions": [], + "autoname": "naming_series:", + "creation": "2016-09-03 14:14:51.788550", + "doctype": "DocType", + "document_type": "Document", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "vehicle_section", + "naming_series", + "license_plate", + "employee", + "column_break_4", + "column_break_7", + "model", + "make", + "odometer_reading", + "date", + "odometer", + "column_break_12", + "last_odometer", + "refuelling_details", + "fuel_qty", + "price", + "column_break_15", + "supplier", + "invoice", + "service_details", + "service_detail", + "amended_from" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "vehicle_section", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "options": "fa fa-user", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "vehicle_section", + "fieldtype": "Section Break", + "options": "fa fa-user" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "fieldname": "naming_series", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Series", - "length": 0, - "no_copy": 1, - "options": "HR-VLOG-.YYYY.-", - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 1, - "translatable": 0, - "unique": 0 - }, + "fieldname": "naming_series", + "fieldtype": "Select", + "label": "Series", + "no_copy": 1, + "options": "HR-VLOG-.YYYY.-", + "print_hide": 1, + "reqd": 1, + "set_only_once": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "license_plate", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "License Plate", - "length": 0, - "no_copy": 0, - "options": "Vehicle", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "license_plate", + "fieldtype": "Link", + "in_global_search": 1, + "in_list_view": 1, + "label": "License Plate", + "options": "Vehicle", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "employee", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Employee", - "length": 0, - "no_copy": 0, - "options": "Employee", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "employee", + "fieldtype": "Link", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Employee", + "options": "Employee", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_4", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_4", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_7", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_7", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "model", - "fieldtype": "Read Only", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Model", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "model", + "fieldtype": "Read Only", + "label": "Model" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "make", - "fieldtype": "Read Only", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Make", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "make", + "fieldtype": "Read Only", + "label": "Make" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "odometer_reading", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Odometer Reading", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "odometer_reading", + "fieldtype": "Section Break", + "label": "Odometer Reading" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "date", - "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "date", + "fieldtype": "Date", + "label": "Date", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "odometer", - "fieldtype": "Int", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Odometer", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "odometer", + "fieldtype": "Int", + "label": "Current Odometer value ", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "refuelling_details", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Refuelling Details", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "collapsible": 1, + "fieldname": "refuelling_details", + "fieldtype": "Section Break", + "label": "Refuelling Details" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "fuel_qty", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Fuel Qty", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "fuel_qty", + "fieldtype": "Float", + "label": "Fuel Qty" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "price", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Fuel Price", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "price", + "fieldtype": "Currency", + "label": "Fuel Price" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_15", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_15", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "supplier", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Supplier", - "length": 0, - "no_copy": 0, - "options": "Supplier", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "supplier", + "fieldtype": "Link", + "label": "Supplier", + "options": "Supplier" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "invoice", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Invoice Ref", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "invoice", + "fieldtype": "Data", + "label": "Invoice Ref" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 1, - "columns": 0, - "fieldname": "service_details", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Service Details", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "collapsible": 1, + "fieldname": "service_details", + "fieldtype": "Section Break", + "label": "Service Details" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "service_detail", - "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Service Detail", - "length": 0, - "no_copy": 0, - "options": "Vehicle Service", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "service_detail", + "fieldtype": "Table", + "label": "Service Detail", + "options": "Vehicle Service" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "amended_from", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Amended From", - "length": 0, - "no_copy": 1, - "options": "Vehicle Log", - "permlevel": 0, - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldname": "amended_from", + "fieldtype": "Link", + "label": "Amended From", + "no_copy": 1, + "options": "Vehicle Log", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "last_odometer", + "fieldtype": "Int", + "label": "last Odometer Value ", + "read_only": 1, + "reqd": 1 + }, + { + "fieldname": "column_break_12", + "fieldtype": "Column Break" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 1, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2018-08-21 14:44:51.131186", - "modified_by": "Administrator", - "module": "HR", - "name": "Vehicle Log", - "name_case": "", - "owner": "Administrator", + ], + "is_submittable": 1, + "links": [], + "modified": "2020-01-28 12:43:34.419647", + "modified_by": "Administrator", + "module": "HR", + "name": "Vehicle Log", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 1, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Fleet Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Fleet Manager", + "share": 1, + "submit": 1, "write": 1 } - ], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "title_field": "", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/hr/doctype/vehicle_log/vehicle_log.py b/erpnext/hr/doctype/vehicle_log/vehicle_log.py index df633611be..0dbf1ceb96 100644 --- a/erpnext/hr/doctype/vehicle_log/vehicle_log.py +++ b/erpnext/hr/doctype/vehicle_log/vehicle_log.py @@ -11,22 +11,28 @@ from frappe.model.document import Document class VehicleLog(Document): def validate(self): - last_odometer=frappe.db.get_value("Vehicle", self.license_plate, "last_odometer") - if flt(self.odometer) < flt(last_odometer): - frappe.throw(_("Current Odometer reading entered should be greater than initial Vehicle Odometer {0}").format(last_odometer)) + if flt(self.odometer) < flt(self.last_odometer): + frappe.throw(_("Current Odometer reading entered should be greater than initial Vehicle Odometer {0}").format(self.last_odometer)) for service_detail in self.service_detail: if (service_detail.service_item or service_detail.type or service_detail.frequency or service_detail.expense_amount): if not (service_detail.service_item and service_detail.type and service_detail.frequency and service_detail.expense_amount): frappe.throw(_("Service Item,Type,frequency and expense amount are required")) def on_submit(self): - frappe.db.sql("update `tabVehicle` set last_odometer=%s where license_plate=%s", - (self.odometer, self.license_plate)) + print("I am here") + frappe.db.set_value("Vehicle", self.license_plate, "last_odometer", self.odometer) + + def on_cancel(self): + print("sel"*10, self.last_odometer, self.odometer) + distance_travelled = self.odometer - self.last_odometer + if(distance_travelled > 0): + updated_odometer_value = int(frappe.db.get_value("Vehicle", self.license_plate, "last_odometer")) - distance_travelled + frappe.db.set_value("Vehicle", self.license_plate, "last_odometer", updated_odometer_value) @frappe.whitelist() def get_make_model(license_plate): vehicle=frappe.get_doc("Vehicle",license_plate) - return (vehicle.make,vehicle.model) + return (vehicle.make,vehicle.model,vehicle.last_odometer,vehicle.employee) @frappe.whitelist() def make_expense_claim(docname): From eacc1bc2dc9363e8622d60a7b24bba990066bbbe Mon Sep 17 00:00:00 2001 From: Anurag Mishra Date: Wed, 5 Feb 2020 12:45:43 +0530 Subject: [PATCH 13/40] fix: requested changes --- erpnext/hr/doctype/vehicle_log/vehicle_log.js | 14 +++++++------- erpnext/hr/doctype/vehicle_log/vehicle_log.py | 11 ++++++++--- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/erpnext/hr/doctype/vehicle_log/vehicle_log.js b/erpnext/hr/doctype/vehicle_log/vehicle_log.js index 4c192a0234..bdb37d2b73 100644 --- a/erpnext/hr/doctype/vehicle_log/vehicle_log.js +++ b/erpnext/hr/doctype/vehicle_log/vehicle_log.js @@ -5,32 +5,32 @@ frappe.ui.form.on("Vehicle Log", { refresh: function(frm) { if(frm.doc.license_plate && frm.doc.__islocal){ - frm.events.set_vehicle_details(frm) + frm.events.set_vehicle_details(frm); } if(frm.doc.docstatus == 1) { frm.add_custom_button(__('Expense Claim'), function() { - frm.events.expense_claim(frm) + frm.events.expense_claim(frm); }, __('Create')); frm.page.set_inner_btn_group_as_primary(__('Create')); } }, - license_plate: function(frm){ + license_plate: function(frm) { if(frm.doc.license_plate){ - frm.events.set_vehicle_details(frm) + frm.events.set_vehicle_details(frm); } }, - set_vehicle_details: function(frm){ + set_vehicle_details: function(frm) { frappe.call({ method: "erpnext.hr.doctype.vehicle_log.vehicle_log.get_make_model", args: { license_plate: frm.doc.license_plate }, callback: function(r) { - frappe.model.set_value(cur_frm.doctype, cur_frm.docname, "model", r.message[0]); - frappe.model.set_value(cur_frm.doctype, cur_frm.docname, "make", r.message[1]); + frappe.model.set_value(cur_frm.doctype, cur_frm.docname, "make", r.message[0]); + frappe.model.set_value(cur_frm.doctype, cur_frm.docname, "model", r.message[1]); frappe.model.set_value(cur_frm.doctype, cur_frm.docname, "last_odometer", r.message[2]); frappe.model.set_value(cur_frm.doctype, cur_frm.docname, "employee", r.message[3]); } diff --git a/erpnext/hr/doctype/vehicle_log/vehicle_log.py b/erpnext/hr/doctype/vehicle_log/vehicle_log.py index 0dbf1ceb96..dfdfc0d720 100644 --- a/erpnext/hr/doctype/vehicle_log/vehicle_log.py +++ b/erpnext/hr/doctype/vehicle_log/vehicle_log.py @@ -18,12 +18,17 @@ class VehicleLog(Document): if not (service_detail.service_item and service_detail.type and service_detail.frequency and service_detail.expense_amount): frappe.throw(_("Service Item,Type,frequency and expense amount are required")) + def before_save(self): + model_details = get_make_model(self.license_plate) + self.make = model_details[0] + self.model = model_details[1] + self.last_odometer = model_details[2] + self.employee = model_details[3] + def on_submit(self): - print("I am here") frappe.db.set_value("Vehicle", self.license_plate, "last_odometer", self.odometer) def on_cancel(self): - print("sel"*10, self.last_odometer, self.odometer) distance_travelled = self.odometer - self.last_odometer if(distance_travelled > 0): updated_odometer_value = int(frappe.db.get_value("Vehicle", self.license_plate, "last_odometer")) - distance_travelled @@ -32,7 +37,7 @@ class VehicleLog(Document): @frappe.whitelist() def get_make_model(license_plate): vehicle=frappe.get_doc("Vehicle",license_plate) - return (vehicle.make,vehicle.model,vehicle.last_odometer,vehicle.employee) + return (vehicle.make, vehicle.model, vehicle.last_odometer, vehicle.employee) @frappe.whitelist() def make_expense_claim(docname): From 4fb897728bbb3e19e277512b5fbe3f2f5c3b75e4 Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Thu, 13 Feb 2020 17:02:01 +0100 Subject: [PATCH 14/40] EXTF must be in quotes --- erpnext/regional/report/datev/datev.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py index bd70639ef2..0b0bb76f25 100644 --- a/erpnext/regional/report/datev/datev.py +++ b/erpnext/regional/report/datev/datev.py @@ -282,7 +282,7 @@ def get_header(filters, csv_class): # A = DATEV format # DTVF = created by DATEV software, # EXTF = created by other software - "EXTF", + '"EXTF"', # B = version of the DATEV format # 141 = 1.41, # 510 = 5.10, From 7d2777870ead35aba2e16d0f02183d4fe191f538 Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Thu, 13 Feb 2020 17:05:37 +0100 Subject: [PATCH 15/40] bump version number --- erpnext/regional/report/datev/datev.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py index 0b0bb76f25..abbc56b5f5 100644 --- a/erpnext/regional/report/datev/datev.py +++ b/erpnext/regional/report/datev/datev.py @@ -287,7 +287,7 @@ def get_header(filters, csv_class): # 141 = 1.41, # 510 = 5.10, # 720 = 7.20 - "510", + "700", csv_class.DATA_CATEGORY, csv_class.FORMAT_NAME, # E = Format version (regarding format name) From 0070805bbbe939c6216d30d4eebbe3f0ed893fb4 Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Thu, 13 Feb 2020 17:06:06 +0100 Subject: [PATCH 16/40] add format version (data type) --- erpnext/regional/report/datev/datev.py | 2 +- erpnext/regional/report/datev/datev_constants.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py index abbc56b5f5..a3cc180004 100644 --- a/erpnext/regional/report/datev/datev.py +++ b/erpnext/regional/report/datev/datev.py @@ -291,7 +291,7 @@ def get_header(filters, csv_class): csv_class.DATA_CATEGORY, csv_class.FORMAT_NAME, # E = Format version (regarding format name) - "", + csv_class.FORMAT_VERSION, # F = Generated on datetime.datetime.now().strftime("%Y%m%d"), # G = Imported on -- stays empty diff --git a/erpnext/regional/report/datev/datev_constants.py b/erpnext/regional/report/datev/datev_constants.py index 1c9bd23ee1..1ca480c376 100644 --- a/erpnext/regional/report/datev/datev_constants.py +++ b/erpnext/regional/report/datev/datev_constants.py @@ -499,14 +499,17 @@ class FormatName(): class Transactions(): DATA_CATEGORY = DataCategory.TRANSACTIONS FORMAT_NAME = FormatName.TRANSACTIONS + FORMAT_VERSION = "9" COLUMNS = TRANSACTION_COLUMNS class DebtorsCreditors(): DATA_CATEGORY = DataCategory.DEBTORS_CREDITORS FORMAT_NAME = FormatName.DEBTORS_CREDITORS + FORMAT_VERSION = "5" COLUMNS = DEBTOR_CREDITOR_COLUMNS class AccountNames(): DATA_CATEGORY = DataCategory.ACCOUNT_NAMES FORMAT_NAME = FormatName.ACCOUNT_NAMES + FORMAT_VERSION = "2" COLUMNS = ACCOUNT_NAME_COLUMNS From 46cf20825b07af61f4f20704e0b7820d2b6fb64e Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Thu, 13 Feb 2020 17:09:22 +0100 Subject: [PATCH 17/40] generated on is datetime, not date --- erpnext/regional/report/datev/datev.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py index a3cc180004..fe2add9bf4 100644 --- a/erpnext/regional/report/datev/datev.py +++ b/erpnext/regional/report/datev/datev.py @@ -293,7 +293,7 @@ def get_header(filters, csv_class): # E = Format version (regarding format name) csv_class.FORMAT_VERSION, # F = Generated on - datetime.datetime.now().strftime("%Y%m%d"), + datetime.datetime.now().strftime("%Y%m%d%H%M%S"), # G = Imported on -- stays empty "", # H = Origin (SV = other (?), RE = KARE) From 8818850174dc45a83bae1a18010b492e22b3b753 Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Thu, 13 Feb 2020 17:13:15 +0100 Subject: [PATCH 18/40] consutant number and client number are mandatory --- erpnext/regional/report/datev/datev.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py index fe2add9bf4..bf6ac20e7e 100644 --- a/erpnext/regional/report/datev/datev.py +++ b/erpnext/regional/report/datev/datev.py @@ -303,10 +303,10 @@ def get_header(filters, csv_class): # J = Imported by -- stays empty "", # K = Tax consultant number (Beraternummer) - frappe.get_value("DATEV Settings", filters.get("company"), "consultant_number") or "", + frappe.get_value("DATEV Settings", filters.get("company"), "consultant_number"), "", # L = Tax client number (Mandantennummer) - frappe.get_value("DATEV Settings", filters.get("company"), "client_number") or "", + frappe.get_value("DATEV Settings", filters.get("company"), "client_number"), "", # M = Start of the fiscal year (Wirtschaftsjahresbeginn) frappe.utils.formatdate(frappe.defaults.get_user_default("year_start_date"), "yyyyMMdd"), From b555ed0cba85b10d3713d0e5d2044510133b9d73 Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Thu, 13 Feb 2020 20:05:27 +0100 Subject: [PATCH 19/40] update header accoding to "DATEV Format v7.0" --- erpnext/regional/report/datev/datev.py | 73 +++++++++++++++++--------- 1 file changed, 48 insertions(+), 25 deletions(-) diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py index bf6ac20e7e..05d817718b 100644 --- a/erpnext/regional/report/datev/datev.py +++ b/erpnext/regional/report/datev/datev.py @@ -274,66 +274,89 @@ def get_datev_csv(data, filters, csv_class): if not six.PY2: data = data.encode('latin_1') - return header + b'\r\n' + data + # 1st Row: Header with meta data + # 2nd Row: Data heading (Überschrift der Nutzdaten) + # 3rd Row: – n: Data (Nutzdaten) + return header + b'\r\n\r\n' + data def get_header(filters, csv_class): + coa = frappe.get_value("Company", filters.get("company"), "chart_of_accounts") + coa_used = "SKR04" if "SKR04" in coa else ("SKR03" if "SKR03" in coa else "") + header = [ - # A = DATEV format - # DTVF = created by DATEV software, - # EXTF = created by other software + # DATEV format + # "DTVF" = created by DATEV software, + # "EXTF" = created by other software '"EXTF"', - # B = version of the DATEV format + # version of the DATEV format # 141 = 1.41, # 510 = 5.10, # 720 = 7.20 - "700", + '700', csv_class.DATA_CATEGORY, csv_class.FORMAT_NAME, - # E = Format version (regarding format name) + # Format version (regarding format name) csv_class.FORMAT_VERSION, - # F = Generated on + # Generated on datetime.datetime.now().strftime("%Y%m%d%H%M%S"), - # G = Imported on -- stays empty - "", - # H = Origin (SV = other (?), RE = KARE) - "SV", + # Imported on -- stays empty + '', + # Origin. Any two symbols, will be replaced by "SV" on import. + '"EN"', # I = Exported by - frappe.session.user, + '"%s"' % frappe.session.user, # J = Imported by -- stays empty - "", + '', # K = Tax consultant number (Beraternummer) frappe.get_value("DATEV Settings", filters.get("company"), "consultant_number"), - "", # L = Tax client number (Mandantennummer) frappe.get_value("DATEV Settings", filters.get("company"), "client_number"), - "", # M = Start of the fiscal year (Wirtschaftsjahresbeginn) frappe.utils.formatdate(frappe.defaults.get_user_default("year_start_date"), "yyyyMMdd"), # N = Length of account numbers (Sachkontenlänge) - "4", + # minimum of 4, 5 if debtors/creditors are included + '5', # O = Transaction batch start date (YYYYMMDD) frappe.utils.formatdate(filters.get('from_date'), "yyyyMMdd"), # P = Transaction batch end date (YYYYMMDD) frappe.utils.formatdate(filters.get('to_date'), "yyyyMMdd"), # Q = Description (for example, "January - February 2019 Transactions") - "{} - {} {}".format( + '"{} - {} {}"'.format( frappe.utils.formatdate(filters.get('from_date'), "MMMM yyyy"), frappe.utils.formatdate(filters.get('to_date'), "MMMM yyyy"), csv_class.FORMAT_NAME ), # R = Diktatkürzel - "", + '', # S = Buchungstyp - # 1 = Transaction batch (Buchungsstapel), + # 1 = Transaction batch (Finanzbuchführung), # 2 = Annual financial statement (Jahresabschluss) - "1" if csv_class.DATA_CATEGORY == DataCategory.TRANSACTIONS else "", + '1' if csv_class.DATA_CATEGORY == DataCategory.TRANSACTIONS else '', # T = Rechnungslegungszweck - "", + '', # U = Festschreibung - "", - # V = Kontoführungs-Währungskennzeichen des Geldkontos - frappe.get_value("Company", filters.get("company"), "default_currency") + '', + # V = Default currency, for example, "EUR" + '"%s"' % frappe.get_value("Company", filters.get("company"), "default_currency"), + # reserviert + '', + # Derivatskennzeichen + '', + # reserviert + '', + # reserviert + '', + # SKR + '"%s"' % coa_used, + # Branchen-Lösungs-ID + '', + # reserviert + '', + # reserviert + '', + # Anwendungsinformation (Verarbeitungskennzeichen der abgebenden Anwendung) + '' ] return header From 96b66dfae6e4bcca6de5efbac07da54d2fe62a75 Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Thu, 13 Feb 2020 20:37:37 +0100 Subject: [PATCH 20/40] update TRANSACTION_COLUMNS according to "DATEV Format v7.0" --- erpnext/regional/report/datev/datev.py | 3 +- .../regional/report/datev/datev_constants.py | 93 +++++++++++++------ 2 files changed, 64 insertions(+), 32 deletions(-) diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py index 05d817718b..ddc973ddae 100644 --- a/erpnext/regional/report/datev/datev.py +++ b/erpnext/regional/report/datev/datev.py @@ -315,8 +315,7 @@ def get_header(filters, csv_class): # M = Start of the fiscal year (Wirtschaftsjahresbeginn) frappe.utils.formatdate(frappe.defaults.get_user_default("year_start_date"), "yyyyMMdd"), # N = Length of account numbers (Sachkontenlänge) - # minimum of 4, 5 if debtors/creditors are included - '5', + '4', # O = Transaction batch start date (YYYYMMDD) frappe.utils.formatdate(filters.get('from_date'), "yyyyMMdd"), # P = Transaction batch end date (YYYYMMDD) diff --git a/erpnext/regional/report/datev/datev_constants.py b/erpnext/regional/report/datev/datev_constants.py index 1ca480c376..501f2cea17 100644 --- a/erpnext/regional/report/datev/datev_constants.py +++ b/erpnext/regional/report/datev/datev_constants.py @@ -13,24 +13,27 @@ TRANSACTION_COLUMNS = [ "Basis-Umsatz", "WKZ Basis-Umsatz", # Konto/Gegenkonto - "Kontonummer", + "Konto", "Gegenkonto (ohne BU-Schlüssel)", "BU-Schlüssel", # Datum "Belegdatum", - # Belegfelder + # Rechnungs- / Belegnummer "Belegfeld 1", + # z.B. Fälligkeitsdatum Format: TTMMJJ "Belegfeld 2", - # Weitere Felder + # Skonto-Betrag / -Abzug (Der Wert 0 ist unzulässig) "Skonto", + # Beschreibung des Buchungssatzes "Buchungstext", - # OPOS-Informationen + # Mahn- / Zahl-Sperre (1 = Postensperre) "Postensperre", "Diverse Adressnummer", "Geschäftspartnerbank", "Sachverhalt", + # Keine Mahnzinsen "Zinssperre", - # Digitaler Beleg + # Link auf den Buchungsbeleg (Programmkürzel + GUID) "Beleglink", # Beleginfo "Beleginfo - Art 1", @@ -49,22 +52,30 @@ TRANSACTION_COLUMNS = [ "Beleginfo - Inhalt 7", "Beleginfo - Art 8", "Beleginfo - Inhalt 8", - # Kostenrechnung - "Kost 1 - Kostenstelle", - "Kost 2 - Kostenstelle", - "Kost-Menge", - # Steuerrechnung - "EU-Land u. UStID", + # Zuordnung des Geschäftsvorfalls für die Kostenrechnung + "KOST1 - Kostenstelle", + "KOST2 - Kostenstelle", + "KOST-Menge", + # USt-ID-Nummer (Beispiel: DE133546770) + "EU-Mitgliedstaat u. USt-IdNr.", + # Der im EU-Bestimmungsland gültige Steuersatz "EU-Steuersatz", + # I = Ist-Versteuerung, + # K = keine Umsatzsteuerrechnung + # P = Pauschalierung (z. B. für Land- und Forstwirtschaft), + # S = Soll-Versteuerung "Abw. Versteuerungsart", - # L+L Sachverhalt + # Sachverhalte gem. § 13b Abs. 1 Satz 1 Nrn. 1.-5. UStG "Sachverhalt L+L", + # Steuersatz / Funktion zum L+L-Sachverhalt (Beispiel: Wert 190 für 19%) "Funktionsergänzung L+L", - # Funktion Steuerschlüssel 49 + # Bei Verwendung des BU-Schlüssels 49 für „andere Steuersätze“ muss der + # steuerliche Sachverhalt mitgegeben werden "BU 49 Hauptfunktionstyp", "BU 49 Hauptfunktionsnummer", "BU 49 Funktionsergänzung", - # Zusatzinformationen + # Zusatzinformationen, besitzen den Charakter eines Notizzettels und können + # frei erfasst werden. "Zusatzinformation - Art 1", "Zusatzinformation - Inhalt 1", "Zusatzinformation - Art 2", @@ -105,54 +116,76 @@ TRANSACTION_COLUMNS = [ "Zusatzinformation - Inhalt 19", "Zusatzinformation - Art 20", "Zusatzinformation - Inhalt 20", - # Mengenfelder LuF + # Wirkt sich nur bei Sachverhalt mit SKR 14 Land- und Forstwirtschaft aus, + # für andere SKR werden die Felder beim Import / Export überlesen bzw. + # leer exportiert. "Stück", "Gewicht", - # Forderungsart + # 1 = Lastschrift + # 2 = Mahnung + # 3 = Zahlung "Zahlweise", "Forderungsart", + # JJJJ "Veranlagungsjahr", + # TTMMJJJJ "Zugeordnete Fälligkeit", - # Weitere Felder + # 1 = Einkauf von Waren + # 2 = Erwerb von Roh-Hilfs- und Betriebsstoffen "Skontotyp", - # Anzahlungen + # Allgemeine Bezeichnung, des Auftrags / Projekts. "Auftragsnummer", + # AA = Angeforderte Anzahlung / Abschlagsrechnung + # AG = Erhaltene Anzahlung (Geldeingang) + # AV = Erhaltene Anzahlung (Verbindlichkeit) + # SR = Schlussrechnung + # SU = Schlussrechnung (Umbuchung) + # SG = Schlussrechnung (Geldeingang) + # SO = Sonstige "Buchungstyp", "USt-Schlüssel (Anzahlungen)", - "EU-Land (Anzahlungen)", + "EU-Mitgliedstaat (Anzahlungen)", "Sachverhalt L+L (Anzahlungen)", "EU-Steuersatz (Anzahlungen)", "Erlöskonto (Anzahlungen)", - # Stapelinformationen + # Wird beim Import durch SV (Stapelverarbeitung) ersetzt. "Herkunft-Kz", - # Technische Identifikation - "Buchungs GUID", - # Kostenrechnung - "Kost-Datum", - # OPOS-Informationen + # Wird von DATEV verwendet. + "Leerfeld", + # Format TTMMJJJJ + "KOST-Datum", + # Vom Zahlungsempfänger individuell vergebenes Kennzeichen eines Mandats + # (z.B. Rechnungs- oder Kundennummer). "SEPA-Mandatsreferenz", + # 1 = Skontosperre + # 0 = Keine Skontosperre "Skontosperre", # Gesellschafter und Sonderbilanzsachverhalt "Gesellschaftername", + # Amtliche Nummer aus der Feststellungserklärung "Beteiligtennummer", "Identifikationsnummer", "Zeichnernummer", - # OPOS-Informationen + # Format TTMMJJJJ "Postensperre bis", # Gesellschafter und Sonderbilanzsachverhalt "Bezeichnung SoBil-Sachverhalt", "Kennzeichen SoBil-Buchung", - # Stapelinformationen + # 0 = keine Festschreibung + # 1 = Festschreibung "Festschreibung", - # Datum + # Format TTMMJJJJ "Leistungsdatum", + # Format TTMMJJJJ "Datum Zuord. Steuerperiode", - # OPOS-Informationen + # OPOS-Informationen, Format TTMMJJJJ "Fälligkeit", - # Konto/Gegenkonto + # G oder 1 = Generalumkehr + # 0 = keine Generalumkehr "Generalumkehr (GU)", # Steuersatz für Steuerschlüssel "Steuersatz", + # Beispiel: DE für Deutschland "Land" ] From 3bacdf1f4b3436697d90c11a71914cfcf7122d71 Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Thu, 13 Feb 2020 20:40:15 +0100 Subject: [PATCH 21/40] quote format name --- erpnext/regional/report/datev/datev.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py index ddc973ddae..a2ff442af4 100644 --- a/erpnext/regional/report/datev/datev.py +++ b/erpnext/regional/report/datev/datev.py @@ -295,7 +295,7 @@ def get_header(filters, csv_class): # 720 = 7.20 '700', csv_class.DATA_CATEGORY, - csv_class.FORMAT_NAME, + '"%s"' % csv_class.FORMAT_NAME, # Format version (regarding format name) csv_class.FORMAT_VERSION, # Generated on From 54717fa993a2490cba50672d9fdaadb0962de3df Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Thu, 13 Feb 2020 20:58:44 +0100 Subject: [PATCH 22/40] update cloumn names --- erpnext/regional/report/datev/datev.py | 9 ++++---- .../regional/report/datev/datev_constants.py | 21 +++++++------------ 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py index a2ff442af4..d4f480196c 100644 --- a/erpnext/regional/report/datev/datev.py +++ b/erpnext/regional/report/datev/datev.py @@ -72,17 +72,16 @@ def get_transactions(filters, as_dict=1): case gl.debit when 0 then 'H' else 'S' end as 'Soll/Haben-Kennzeichen', /* account number or, if empty, party account number */ - coalesce(acc.account_number, acc_pa.account_number) as 'Kontonummer', + coalesce(acc.account_number, acc_pa.account_number) as 'Konto', /* against number or, if empty, party against number */ coalesce(acc_against.account_number, acc_against_pa.account_number) as 'Gegenkonto (ohne BU-Schlüssel)', gl.posting_date as 'Belegdatum', + gl.voucher_no as 'Belegfeld 1', gl.remarks as 'Buchungstext', - gl.voucher_type as 'Beleginfo - Art 1', - gl.voucher_no as 'Beleginfo - Inhalt 1', - gl.against_voucher_type as 'Beleginfo - Art 2', - gl.against_voucher as 'Beleginfo - Inhalt 2' + gl.against_voucher_type as 'Beleginfo - Art 1', + gl.against_voucher as 'Beleginfo - Inhalt 1' FROM `tabGL Entry` gl diff --git a/erpnext/regional/report/datev/datev_constants.py b/erpnext/regional/report/datev/datev_constants.py index 501f2cea17..a4cd5fc10e 100644 --- a/erpnext/regional/report/datev/datev_constants.py +++ b/erpnext/regional/report/datev/datev_constants.py @@ -472,8 +472,8 @@ QUERY_REPORT_COLUMNS = [ "fieldtype": "Data", }, { - "label": "Kontonummer", - "fieldname": "Kontonummer", + "label": "Konto", + "fieldname": "Konto", "fieldtype": "Data", }, { @@ -486,6 +486,11 @@ QUERY_REPORT_COLUMNS = [ "fieldname": "Belegdatum", "fieldtype": "Date", }, + { + "label": "Belegfeld 1", + "fieldname": "Belegfeld 1", + "fieldtype": "Data", + }, { "label": "Buchungstext", "fieldname": "Buchungstext", @@ -493,21 +498,11 @@ QUERY_REPORT_COLUMNS = [ }, { "label": "Beleginfo - Art 1", - "fieldname": "Beleginfo - Art 1", - "fieldtype": "Data", - }, - { - "label": "Beleginfo - Inhalt 1", - "fieldname": "Beleginfo - Inhalt 1", - "fieldtype": "Data", - }, - { - "label": "Beleginfo - Art 2", "fieldname": "Beleginfo - Art 2", "fieldtype": "Data", }, { - "label": "Beleginfo - Inhalt 2", + "label": "Beleginfo - Inhalt 1", "fieldname": "Beleginfo - Inhalt 2", "fieldtype": "Data", } From 772394b95aef049852361ab1b62712c40a1a576a Mon Sep 17 00:00:00 2001 From: Raffael Meyer Date: Thu, 13 Feb 2020 20:58:59 +0100 Subject: [PATCH 23/40] fix header --- erpnext/regional/report/datev/datev.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py index d4f480196c..7ceaf50134 100644 --- a/erpnext/regional/report/datev/datev.py +++ b/erpnext/regional/report/datev/datev.py @@ -239,8 +239,6 @@ def get_datev_csv(data, filters, csv_class): filters -- dict csv_class -- defines DATA_CATEGORY, FORMAT_NAME and COLUMNS """ - header = get_header(filters, csv_class) - empty_df = pd.DataFrame(columns=csv_class.COLUMNS) data_df = pd.DataFrame.from_records(data) @@ -252,7 +250,6 @@ def get_datev_csv(data, filters, csv_class): if csv_class.DATA_CATEGORY == DataCategory.ACCOUNT_NAMES: result['Sprach-ID'] = 'de-DE' - header = ';'.join(header).encode('latin_1') data = result.to_csv( # Reason for str(';'): https://github.com/pandas-dev/pandas/issues/6035 sep=str(';'), @@ -273,10 +270,13 @@ def get_datev_csv(data, filters, csv_class): if not six.PY2: data = data.encode('latin_1') + header = get_header(filters, csv_class) + header = ';'.join(header).encode('latin_1') + # 1st Row: Header with meta data - # 2nd Row: Data heading (Überschrift der Nutzdaten) - # 3rd Row: – n: Data (Nutzdaten) - return header + b'\r\n\r\n' + data + # 2nd Row: Data heading (Überschrift der Nutzdaten), included in `data` here. + # 3rd - nth Row: Data (Nutzdaten) + return header + b'\r\n' + data def get_header(filters, csv_class): From dc39b4ba130024f7c246e2110bd9b93a29ca8360 Mon Sep 17 00:00:00 2001 From: Khushal Trivedi Date: Sat, 15 Feb 2020 15:38:16 +0530 Subject: [PATCH 24/40] fix: validation on max group strength student group form --- erpnext/education/doctype/student_group/student_group.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/education/doctype/student_group/student_group.py b/erpnext/education/doctype/student_group/student_group.py index aa542ddfbf..9ec94384d5 100644 --- a/erpnext/education/doctype/student_group/student_group.py +++ b/erpnext/education/doctype/student_group/student_group.py @@ -26,6 +26,8 @@ class StudentGroup(Document): frappe.throw(_("Please select Program")) def validate_strength(self): + if self.max_strength < 0: + frappe.throw(_("""Cannot enroll less than 0 students for this student group.""")) if self.max_strength and len(self.students) > self.max_strength: frappe.throw(_("""Cannot enroll more than {0} students for this student group.""").format(self.max_strength)) From 8773dc3ffeee8b3e3d258d0b34a842bd328a88b7 Mon Sep 17 00:00:00 2001 From: Khushal Trivedi Date: Tue, 18 Feb 2020 19:37:21 +0530 Subject: [PATCH 25/40] fix: student max gropu cannot be zero or less than zero --- erpnext/education/doctype/student_group/student_group.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/education/doctype/student_group/student_group.py b/erpnext/education/doctype/student_group/student_group.py index 9ec94384d5..c92c69b6b4 100644 --- a/erpnext/education/doctype/student_group/student_group.py +++ b/erpnext/education/doctype/student_group/student_group.py @@ -26,8 +26,8 @@ class StudentGroup(Document): frappe.throw(_("Please select Program")) def validate_strength(self): - if self.max_strength < 0: - frappe.throw(_("""Cannot enroll less than 0 students for this student group.""")) + if self.max_strength <= 0: + frappe.throw(_("""Cannot enroll less than or equal to 0 students for this student group.""")) if self.max_strength and len(self.students) > self.max_strength: frappe.throw(_("""Cannot enroll more than {0} students for this student group.""").format(self.max_strength)) From e5b59c781f56e32884812f220ae428e825c5fb91 Mon Sep 17 00:00:00 2001 From: Rohan Bansal Date: Wed, 19 Feb 2020 13:08:18 +0530 Subject: [PATCH 26/40] fix: show priority in Issue list view --- erpnext/support/doctype/issue/issue.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/erpnext/support/doctype/issue/issue.json b/erpnext/support/doctype/issue/issue.json index 222554bda1..53af80cb5e 100644 --- a/erpnext/support/doctype/issue/issue.json +++ b/erpnext/support/doctype/issue/issue.json @@ -1,4 +1,5 @@ { + "actions": [], "allow_import": 1, "allow_rename": 1, "autoname": "naming_series:", @@ -119,6 +120,7 @@ "default": "Medium", "fieldname": "priority", "fieldtype": "Link", + "in_list_view": 1, "in_standard_filter": 1, "label": "Priority", "options": "Issue Priority" @@ -363,8 +365,9 @@ ], "icon": "fa fa-ticket", "idx": 7, - "modified": "2019-09-11 09:03:57.465623", - "modified_by": "himanshu@erpnext.com", + "links": [], + "modified": "2020-02-18 21:26:35.636013", + "modified_by": "Administrator", "module": "Support", "name": "Issue", "owner": "Administrator", From 1a11cb5a07ef701c298f2c95256effb7ec7ab0bf Mon Sep 17 00:00:00 2001 From: Anurag Mishra Date: Wed, 19 Feb 2020 16:46:00 +0530 Subject: [PATCH 27/40] test: syncing of odometer value --- .../doctype/vehicle_log/test_vehicle_log.py | 60 ++++++++++++------- erpnext/hr/doctype/vehicle_log/vehicle_log.py | 2 +- 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py b/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py index 35400b0ca8..3770da73fc 100644 --- a/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py +++ b/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py @@ -8,25 +8,9 @@ import unittest from frappe.utils import nowdate,flt, cstr,random_string # test_records = frappe.get_test_records('Vehicle Log') class TestVehicleLog(unittest.TestCase): - def test_make_vehicle_log(self): - license_plate=random_string(10).upper() + def test_make_vehicle_log_and_syncing_of_odometer_value(self): employee_id=frappe.db.sql("""select name from `tabEmployee` order by modified desc limit 1""")[0][0] - vehicle = frappe.get_doc({ - "doctype": "Vehicle", - "license_plate": cstr(license_plate), - "make": "Maruti", - "model": "PCM", - "last_odometer":5000, - "acquisition_date":frappe.utils.nowdate(), - "location": "Mumbai", - "chassis_no": "1234ABCD", - "uom": "Litre", - "vehicle_value":frappe.utils.flt(500000) - }) - try: - vehicle.insert() - except frappe.DuplicateEntryError: - pass + license_plate = get_vehicle(employee_id) vehicle_log = frappe.get_doc({ "doctype": "Vehicle Log", "license_plate": cstr(license_plate), @@ -36,5 +20,41 @@ class TestVehicleLog(unittest.TestCase): "fuel_qty":frappe.utils.flt(50), "price": frappe.utils.flt(500) }) - vehicle_log.insert() - vehicle_log.submit() \ No newline at end of file + vehicle_log.save() + vehicle_log.submit() + + #checking value of vehicle odometer value on submit. + vehicle = frappe.get_doc("Vehicle", license_plate) + self.assertEqual(vehicle.last_odometer, vehicle_log.odometer) + + #checking value vehicle odometer on vehicle log cancellation. + last_odometer = vehicle_log.last_odometer + current_odometer = vehicle_log.odometer + distance_travelled = current_odometer - last_odometer + + vehicle_log.cancel() + vehicle.reload() + + self.assertEqual(vehicle.last_odometer, current_odometer - distance_travelled) + + +def get_vehicle(employee_id): + license_plate=random_string(10).upper() + vehicle = frappe.get_doc({ + "doctype": "Vehicle", + "license_plate": cstr(license_plate), + "make": "Maruti", + "model": "PCM", + "employee": employee_id, + "last_odometer":5000, + "acquisition_date":frappe.utils.nowdate(), + "location": "Mumbai", + "chassis_no": "1234ABCD", + "uom": "Litre", + "vehicle_value":frappe.utils.flt(500000) + }) + try: + vehicle.insert() + except frappe.DuplicateEntryError: + pass + return license_plate \ No newline at end of file diff --git a/erpnext/hr/doctype/vehicle_log/vehicle_log.py b/erpnext/hr/doctype/vehicle_log/vehicle_log.py index dfdfc0d720..12cc1dd03a 100644 --- a/erpnext/hr/doctype/vehicle_log/vehicle_log.py +++ b/erpnext/hr/doctype/vehicle_log/vehicle_log.py @@ -18,7 +18,7 @@ class VehicleLog(Document): if not (service_detail.service_item and service_detail.type and service_detail.frequency and service_detail.expense_amount): frappe.throw(_("Service Item,Type,frequency and expense amount are required")) - def before_save(self): + def before_insert(self): model_details = get_make_model(self.license_plate) self.make = model_details[0] self.model = model_details[1] From 56837bc09d81c8fcbb51bf428937091ba00841a7 Mon Sep 17 00:00:00 2001 From: Saqib Date: Thu, 20 Feb 2020 12:23:08 +0530 Subject: [PATCH 28/40] fix: check for available stock in product bundle's website warehouse (#20681) --- erpnext/utilities/product.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/utilities/product.py b/erpnext/utilities/product.py index 1c0d4c38c7..c23c1f7096 100644 --- a/erpnext/utilities/product.py +++ b/erpnext/utilities/product.py @@ -129,6 +129,7 @@ def get_non_stock_item_status(item_code, item_warehouse_field): #if item belongs to product bundle, check if bundle items are in stock if frappe.db.exists("Product Bundle", item_code): items = frappe.get_doc("Product Bundle", item_code).get_all_children() - return all([ get_qty_in_stock(d.item_code, item_warehouse_field).in_stock for d in items ]) + bundle_warehouse = frappe.db.get_value('Item', item_code, item_warehouse_field) + return all([ get_qty_in_stock(d.item_code, item_warehouse_field, bundle_warehouse).in_stock for d in items ]) else: return 1 From 2d7e024f00107c14dd846b190eeced720c7eccb2 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Thu, 20 Feb 2020 12:24:29 +0530 Subject: [PATCH 29/40] fix: use system language to translate strings (#20673) --- .../connectors/woocommerce_connection.py | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py index 28c2ab9e54..4422d23e38 100644 --- a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py +++ b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py @@ -47,11 +47,12 @@ def _order(*args, **kwargs): return "success" if event == "created": + sys_lang = frappe.get_single("System Settings").language or 'en' raw_billing_data = order.get("billing") customer_name = raw_billing_data.get("first_name") + " " + raw_billing_data.get("last_name") link_customer_and_address(raw_billing_data, customer_name) - link_items(order.get("line_items"), woocommerce_settings) - create_sales_order(order, woocommerce_settings, customer_name) + link_items(order.get("line_items"), woocommerce_settings, sys_lang) + create_sales_order(order, woocommerce_settings, customer_name, sys_lang) def link_customer_and_address(raw_billing_data, customer_name): customer_woo_com_email = raw_billing_data.get("email") @@ -100,7 +101,7 @@ def link_customer_and_address(raw_billing_data, customer_name): frappe.rename_doc("Address", old_address_title, new_address_title) -def link_items(items_list, woocommerce_settings): +def link_items(items_list, woocommerce_settings, sys_lang): for item_data in items_list: item_woo_com_id = item_data.get("product_id") @@ -112,14 +113,14 @@ def link_items(items_list, woocommerce_settings): item = frappe.new_doc("Item") item.item_name = item_data.get("name") - item.item_code = _("woocommerce - {0}").format(item_data.get("product_id")) + item.item_code = _("woocommerce - {0}", sys_lang).format(item_data.get("product_id")) item.woocommerce_id = item_data.get("product_id") - item.item_group = _("WooCommerce Products") - item.stock_uom = woocommerce_settings.uom or _("Nos") + item.item_group = _("WooCommerce Products", sys_lang) + item.stock_uom = woocommerce_settings.uom or _("Nos", sys_lang) item.flags.ignore_mandatory = True item.save() -def create_sales_order(order, woocommerce_settings, customer_name): +def create_sales_order(order, woocommerce_settings, customer_name, sys_lang): new_sales_order = frappe.new_doc("Sales Order") new_sales_order.customer = customer_name @@ -133,14 +134,14 @@ def create_sales_order(order, woocommerce_settings, customer_name): new_sales_order.company = woocommerce_settings.company - set_items_in_sales_order(new_sales_order, woocommerce_settings, order) + set_items_in_sales_order(new_sales_order, woocommerce_settings, order, sys_lang) new_sales_order.flags.ignore_mandatory = True new_sales_order.insert() new_sales_order.submit() frappe.db.commit() -def set_items_in_sales_order(new_sales_order, woocommerce_settings, order): +def set_items_in_sales_order(new_sales_order, woocommerce_settings, order, sys_lang): company_abbr = frappe.db.get_value('Company', woocommerce_settings.company, 'abbr') for item in order.get("line_items"): @@ -154,10 +155,10 @@ def set_items_in_sales_order(new_sales_order, woocommerce_settings, order): "item_name": found_item.item_name, "description": found_item.item_name, "delivery_date": new_sales_order.delivery_date, - "uom": woocommerce_settings.uom or _("Nos"), + "uom": woocommerce_settings.uom or _("Nos", sys_lang), "qty": item.get("quantity"), "rate": item.get("price"), - "warehouse": woocommerce_settings.warehouse or _("Stores - {0}").format(company_abbr) + "warehouse": woocommerce_settings.warehouse or _("Stores - {0}", sys_lang).format(company_abbr) }) add_tax_details(new_sales_order, ordered_items_tax, "Ordered Item tax", woocommerce_settings.tax_account) From f3acb6b79ffc4b80a4e6ea64d886404d08614fb2 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Thu, 20 Feb 2020 12:24:45 +0530 Subject: [PATCH 30/40] fix: use system language to translate strings (#20682) From cfe2db6d776d007728c70bb44eb7cf9cbe4cb16c Mon Sep 17 00:00:00 2001 From: Saqib Date: Thu, 20 Feb 2020 12:29:44 +0530 Subject: [PATCH 31/40] fix: mandatory on hold comment for purchase invoice (#20666) --- erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 80be2c803f..a68c36846d 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -1058,7 +1058,7 @@ def unblock_invoice(name): @frappe.whitelist() -def block_invoice(name, hold_comment, release_date): +def block_invoice(name, release_date, hold_comment=None): if frappe.db.exists('Purchase Invoice', name): pi = frappe.get_doc('Purchase Invoice', name) pi.block_invoice(hold_comment, release_date) From ca7f53b4eaae616261a6c639cb992ccdf4f27771 Mon Sep 17 00:00:00 2001 From: Saqib Date: Thu, 20 Feb 2020 12:32:05 +0530 Subject: [PATCH 32/40] chore: SINV set_status remove redundant function calls (#20660) * chore: SINV set_status remove redundant function calls * Update erpnext/accounts/doctype/sales_invoice/sales_invoice.py Co-Authored-By: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Co-authored-by: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> --- .../accounts/doctype/sales_invoice/sales_invoice.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 8b4923fd4f..ad3640cb72 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1243,25 +1243,28 @@ class SalesInvoice(SellingController): precision = self.precision("outstanding_amount") outstanding_amount = flt(self.outstanding_amount, precision) + due_date = getdate(self.due_date) + nowdate = getdate() + discountng_status = self.get_discounting_status() if not status: if self.docstatus == 2: status = "Cancelled" elif self.docstatus == 1: - if outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed': + if outstanding_amount > 0 and due_date < nowdate and self.is_discounted and discountng_status=='Disbursed': self.status = "Overdue and Discounted" - elif outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()): + elif outstanding_amount > 0 and due_date < nowdate: self.status = "Overdue" - elif outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed': + elif outstanding_amount > 0 and due_date >= nowdate and self.is_discounted and discountng_status=='Disbursed': self.status = "Unpaid and Discounted" - elif outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()): + elif outstanding_amount > 0 and due_date >= nowdate: self.status = "Unpaid" #Check if outstanding amount is 0 due to credit note issued against invoice elif outstanding_amount <= 0 and self.is_return == 0 and frappe.db.get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1}): self.status = "Credit Note Issued" elif self.is_return == 1: self.status = "Return" - elif outstanding_amount <=0: + elif outstanding_amount<=0: self.status = "Paid" else: self.status = "Submitted" From 45ea2bfc004eed852274790cf9ddc5bc8eb0b575 Mon Sep 17 00:00:00 2001 From: Mathieu Brunot Date: Thu, 20 Feb 2020 08:19:54 +0100 Subject: [PATCH 33/40] chore(ci-coverage): Pin coverage 4.5.4 #20646 (#20647) * chore(ci-coverage): Pin coveralls 4.5.4 #20646 Signed-off-by: mathieu.brunot * chore: Pin coverage Signed-off-by: mathieu.brunot --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 365eb67f3d..213445b806 100644 --- a/.travis.yml +++ b/.travis.yml @@ -77,5 +77,6 @@ install: - bench --site test_site reinstall --yes after_script: + - pip install coverage==4.5.4 - pip install python-coveralls - coveralls -b apps/erpnext -d ../../sites/.coverage From 51cf0eb1592e6ca774c2bfa4f4717f5f4efdde17 Mon Sep 17 00:00:00 2001 From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Date: Thu, 20 Feb 2020 12:52:56 +0530 Subject: [PATCH 34/40] fix: changed field type which was affecting filters (#20671) --- erpnext/hr/doctype/attendance/attendance.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/hr/doctype/attendance/attendance.json b/erpnext/hr/doctype/attendance/attendance.json index ab2dc4a90f..eaca9f6ebe 100644 --- a/erpnext/hr/doctype/attendance/attendance.json +++ b/erpnext/hr/doctype/attendance/attendance.json @@ -58,11 +58,12 @@ { "fetch_from": "employee.employee_name", "fieldname": "employee_name", - "fieldtype": "Read Only", + "fieldtype": "Data", "in_global_search": 1, "label": "Employee Name", "oldfieldname": "employee_name", - "oldfieldtype": "Data" + "oldfieldtype": "Data", + "read_only": 1 }, { "depends_on": "working_hours", @@ -174,8 +175,7 @@ "icon": "fa fa-ok", "idx": 1, "is_submittable": 1, - "links": [], - "modified": "2020-01-27 20:25:29.572281", + "modified": "2020-02-19 14:25:32.945842", "modified_by": "Administrator", "module": "HR", "name": "Attendance", From 60713139656f7ba6e018b391c668c261e54a9275 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Thu, 20 Feb 2020 12:57:21 +0530 Subject: [PATCH 35/40] fix: document creation via onboarding slide (#20644) * fix: defaults not set in doc created via Onboarding Slide * fix: default company not set in Supplier --- erpnext/buying/doctype/supplier/supplier.py | 6 ++++-- erpnext/selling/doctype/customer/customer.py | 5 ++++- erpnext/stock/doctype/item/item.py | 10 ++++++---- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/erpnext/buying/doctype/supplier/supplier.py b/erpnext/buying/doctype/supplier/supplier.py index 62a04f37b1..df143eefa0 100644 --- a/erpnext/buying/doctype/supplier/supplier.py +++ b/erpnext/buying/doctype/supplier/supplier.py @@ -58,7 +58,9 @@ class Supplier(TransactionBase): frappe.db.set(self, "supplier_name", newdn) def create_onboarding_docs(self, args): - defaults = frappe.defaults.get_defaults() + company = frappe.defaults.get_defaults().get('company') or \ + frappe.db.get_single_value('Global Defaults', 'default_company') + for i in range(1, args.get('max_count')): supplier = args.get('supplier_name_' + str(i)) if supplier: @@ -67,7 +69,7 @@ class Supplier(TransactionBase): 'doctype': self.doctype, 'supplier_name': supplier, 'supplier_group': _('Local'), - 'company': defaults.get('company') + 'company': company }).insert() if args.get('supplier_email_' + str(i)): diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index 7f2fe60f59..9261289773 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -213,6 +213,9 @@ class Customer(TransactionBase): def create_onboarding_docs(self, args): defaults = frappe.defaults.get_defaults() + company = defaults.get('company') or \ + frappe.db.get_single_value('Global Defaults', 'default_company') + for i in range(1, args.get('max_count')): customer = args.get('customer_name_' + str(i)) if customer: @@ -223,7 +226,7 @@ class Customer(TransactionBase): 'customer_type': 'Company', 'customer_group': _('Commercial'), 'territory': defaults.get('country'), - 'company': defaults.get('company') + 'company': company }).insert() if args.get('customer_email_' + str(i)): diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index d036a0a1fb..a2a913a73f 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -877,14 +877,16 @@ class Item(WebsiteGenerator): frappe.msgprint(msg=_("You have to enable auto re-order in Stock Settings to maintain re-order levels."), title=_("Enable Auto Re-Order"), indicator="orange") def create_onboarding_docs(self, args): - defaults = frappe.defaults.get_defaults() + company = frappe.defaults.get_defaults().get('company') or \ + frappe.db.get_single_value('Global Defaults', 'default_company') + for i in range(1, args.get('max_count')): item = args.get('item_' + str(i)) if item: default_warehouse = '' default_warehouse = frappe.db.get_value('Warehouse', filters={ 'warehouse_name': _('Finished Goods'), - 'company': defaults.get('company_name') + 'company': company }) try: @@ -901,7 +903,7 @@ class Item(WebsiteGenerator): 'stock_uom': _(args.get('item_uom_' + str(i))), 'item_defaults': [{ 'default_warehouse': default_warehouse, - 'company': defaults.get('company_name') + 'company': company }] }).insert() @@ -909,7 +911,7 @@ class Item(WebsiteGenerator): pass else: if args.get('item_price_' + str(i)): - item_price = flt(args.get('tem_price_' + str(i))) + item_price = flt(args.get('item_price_' + str(i))) price_list_name = frappe.db.get_value('Price List', {'selling': 1}) make_item_price(item, price_list_name, item_price) From 6f6e3a940bcaae2729268698d98f092dd6231e4b Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Thu, 20 Feb 2020 12:58:54 +0530 Subject: [PATCH 36/40] fix: return null for attribute (#20674) --- .../doctype/amazon_mws_settings/amazon_methods.py | 6 ++++++ .../doctype/amazon_mws_settings/amazon_mws_settings.py | 5 ++--- .../doctype/amazon_mws_settings/xml_utils.py | 5 ++++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py index 2f39dc596b..3bc8db5e78 100644 --- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py +++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py @@ -165,6 +165,9 @@ def create_item_code(amazon_item_json, sku): return item.name def create_manufacturer(amazon_item_json): + if not amazon_item_json.Product.AttributeSets.ItemAttributes.Manufacturer: + return None + existing_manufacturer = frappe.db.get_value("Manufacturer", filters={"short_name":amazon_item_json.Product.AttributeSets.ItemAttributes.Manufacturer}) @@ -177,6 +180,9 @@ def create_manufacturer(amazon_item_json): return existing_manufacturer def create_brand(amazon_item_json): + if not amazon_item_json.Product.AttributeSets.ItemAttributes.Brand: + return None + existing_brand = frappe.db.get_value("Brand", filters={"brand":amazon_item_json.Product.AttributeSets.ItemAttributes.Brand}) if not existing_brand: diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.py index 249a73f9fb..c222afbb6c 100644 --- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.py +++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.py @@ -7,7 +7,6 @@ import frappe from frappe.model.document import Document import dateutil from frappe.custom.doctype.custom_field.custom_field import create_custom_fields -from erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_methods import get_products_details, get_orders class AmazonMWSSettings(Document): def validate(self): @@ -19,12 +18,12 @@ class AmazonMWSSettings(Document): def get_products_details(self): if self.enable_amazon == 1: - get_products_details() + frappe.enqueue('erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_methods.get_products_details') def get_order_details(self): if self.enable_amazon == 1: after_date = dateutil.parser.parse(self.after_date).strftime("%Y-%m-%d") - get_orders(after_date = after_date) + frappe.enqueue('erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_methods.get_orders', after_date=after_date) def schedule_get_order_details(): mws_settings = frappe.get_doc("Amazon MWS Settings") diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/xml_utils.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/xml_utils.py index 58db669411..a25a29f9e5 100644 --- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/xml_utils.py +++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/xml_utils.py @@ -33,7 +33,10 @@ class object_dict(dict): def __getattr__(self, item): - d = self.__getitem__(item) + try: + d = self.__getitem__(item) + except KeyError: + return None if isinstance(d, dict) and 'value' in d and len(d) == 1: return d['value'] From 395b2b15b2b4f9692159ff8e5e16b97ec6e6ffb5 Mon Sep 17 00:00:00 2001 From: Rohan Date: Thu, 20 Feb 2020 12:59:32 +0530 Subject: [PATCH 37/40] fix: apply url encoding to project names (#20642) --- erpnext/templates/includes/projects/project_row.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/templates/includes/projects/project_row.html b/erpnext/templates/includes/projects/project_row.html index 55b02e2004..73c83ef560 100644 --- a/erpnext/templates/includes/projects/project_row.html +++ b/erpnext/templates/includes/projects/project_row.html @@ -1,6 +1,6 @@ {% if doc.status=="Open" %}
- +
From a0021969ad4a403443a6103b94ff1e55aae791a6 Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Thu, 20 Feb 2020 13:22:28 +0530 Subject: [PATCH 38/40] fix: Validation message --- erpnext/education/doctype/student_group/student_group.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/education/doctype/student_group/student_group.py b/erpnext/education/doctype/student_group/student_group.py index c92c69b6b4..2925469312 100644 --- a/erpnext/education/doctype/student_group/student_group.py +++ b/erpnext/education/doctype/student_group/student_group.py @@ -27,7 +27,7 @@ class StudentGroup(Document): def validate_strength(self): if self.max_strength <= 0: - frappe.throw(_("""Cannot enroll less than or equal to 0 students for this student group.""")) + frappe.throw(_("""Max strength must be greater than zero.""")) if self.max_strength and len(self.students) > self.max_strength: frappe.throw(_("""Cannot enroll more than {0} students for this student group.""").format(self.max_strength)) From 5d5f5b4f8ea432746b7ab58bafee22240b6703bf Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Thu, 20 Feb 2020 13:25:55 +0530 Subject: [PATCH 39/40] fix(HR): skip earned leaves check for max leaves set to zero or less (#20535) * fix: skip earned leaves check for max leaves set to zero or less * test: earned leaves creation --- .../leave_application/test_leave_application.py | 10 +++++++++- erpnext/hr/utils.py | 4 +++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.py b/erpnext/hr/doctype/leave_application/test_leave_application.py index b6216424de..6e909c3f01 100644 --- a/erpnext/hr/doctype/leave_application/test_leave_application.py +++ b/erpnext/hr/doctype/leave_application/test_leave_application.py @@ -409,7 +409,7 @@ class TestLeaveApplication(unittest.TestCase): self.assertEqual(get_leave_balance_on(employee.name, leave_type.name, nowdate(), add_days(nowdate(), 8)), 21) - def test_earned_leave(self): + def test_earned_leaves_creation(self): leave_period = get_leave_period() employee = get_employee() leave_type = 'Test Earned Leave Type' @@ -437,6 +437,14 @@ class TestLeaveApplication(unittest.TestCase): i += 1 self.assertEqual(get_leave_balance_on(employee.name, leave_type, nowdate()), 6) + # validate earned leaves creation without maximum leaves + frappe.db.set_value('Leave Type', leave_type, 'max_leaves_allowed', 0) + i = 0 + while(i<6): + allocate_earned_leaves() + i += 1 + self.assertEqual(get_leave_balance_on(employee.name, leave_type, nowdate()), 9) + # test to not consider current leave in leave balance while submitting def test_current_leave_on_submit(self): employee = get_employee() diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py index c3e8d27557..ef276001c5 100644 --- a/erpnext/hr/utils.py +++ b/erpnext/hr/utils.py @@ -316,7 +316,9 @@ def allocate_earned_leaves(): allocation = frappe.get_doc('Leave Allocation', allocation.name) new_allocation = flt(allocation.total_leaves_allocated) + flt(earned_leaves) - new_allocation = new_allocation if new_allocation <= e_leave_type.max_leaves_allowed else e_leave_type.max_leaves_allowed + + if new_allocation > e_leave_type.max_leaves_allowed and e_leave_type.max_leaves_allowed > 0: + new_allocation = e_leave_type.max_leaves_allowed if new_allocation == allocation.total_leaves_allocated: continue From a29c87cfda48a7754ee97deb18fef98911e0437c Mon Sep 17 00:00:00 2001 From: Rohan Date: Thu, 20 Feb 2020 13:28:03 +0530 Subject: [PATCH 40/40] feat: remove unused route creation variable (#20558) --- erpnext/public/js/conf.js | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/erpnext/public/js/conf.js b/erpnext/public/js/conf.js index 0f88f13350..615f6a43f9 100644 --- a/erpnext/public/js/conf.js +++ b/erpnext/public/js/conf.js @@ -29,19 +29,6 @@ $(document).bind('toolbar_setup', function() { }); - - -// doctypes created via tree -$.extend(frappe.create_routes, { - "Customer Group": "Tree/Customer Group", - "Territory": "Tree/Territory", - "Item Group": "Tree/Item Group", - "Sales Person": "Tree/Sales Person", - "Account": "Tree/Account", - "Cost Center": "Tree/Cost Center", - "Department": "Tree/Department", -}); - // preferred modules for breadcrumbs $.extend(frappe.breadcrumbs.preferred, { "Item Group": "Stock",