From 2c8ce5a717ab48b3060402b464dc5fd7bcbda50a Mon Sep 17 00:00:00 2001 From: Vinayak Jethe Date: Wed, 24 Jan 2018 13:51:26 +0530 Subject: [PATCH 01/13] Fixes issue #12512 --- erpnext/stock/dashboard/item_dashboard.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/dashboard/item_dashboard.js b/erpnext/stock/dashboard/item_dashboard.js index 3c334c46b6..5e5dc0a142 100644 --- a/erpnext/stock/dashboard/item_dashboard.js +++ b/erpnext/stock/dashboard/item_dashboard.js @@ -75,13 +75,21 @@ erpnext.stock.ItemDashboard = Class.extend({ this.content.find('.more').addClass('hidden'); } - // If not any stock in any warehouses provide a message to end user + // If not any stock in any warehouses provide a message to end user if (context.data.length > 0) { $(frappe.render_template('item_dashboard_list', context)).appendTo(this.result); } else { var message = __(" Currently no stock available in any warehouse") $(""+message+"").appendTo(this.result); } + + if (frappe.boot.user.can_write.indexOf("Stock Entry")>=0){ + $(".btn-move").show(); + + $(".btn-add").show(); + }else{ + $(".btn-move").hide(); + + $(".btn-add").hide(); + } }, get_item_dashboard_data: function(data, max_count, show_item) { if(!max_count) max_count = 0; From 46c82c45e076223039720f5efe4c91497d3b2312 Mon Sep 17 00:00:00 2001 From: Vinayak Jethe Date: Wed, 24 Jan 2018 14:24:58 +0530 Subject: [PATCH 02/13] Revised changes for codacy --- erpnext/stock/dashboard/item_dashboard.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/dashboard/item_dashboard.js b/erpnext/stock/dashboard/item_dashboard.js index 5e5dc0a142..0422026084 100644 --- a/erpnext/stock/dashboard/item_dashboard.js +++ b/erpnext/stock/dashboard/item_dashboard.js @@ -85,10 +85,10 @@ erpnext.stock.ItemDashboard = Class.extend({ if (frappe.boot.user.can_write.indexOf("Stock Entry")>=0){ $(".btn-move").show(); - + $(".btn-add").show(); + $(".btn-add").show(); }else{ $(".btn-move").hide(); - + $(".btn-add").hide(); + $(".btn-add").hide(); } }, get_item_dashboard_data: function(data, max_count, show_item) { From cadd31cb0c4f024f4cff890bb60bb954434cfece Mon Sep 17 00:00:00 2001 From: Saurabh Date: Wed, 24 Jan 2018 16:38:22 +0530 Subject: [PATCH 03/13] [Fix] Solves issue #12588 --- erpnext/selling/doctype/customer/customer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/selling/doctype/customer/customer.js b/erpnext/selling/doctype/customer/customer.js index 9603290998..92734cc6f7 100644 --- a/erpnext/selling/doctype/customer/customer.js +++ b/erpnext/selling/doctype/customer/customer.js @@ -43,7 +43,7 @@ frappe.ui.form.on("Customer", { frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Customer'} - frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal); + frm.toggle_display(['address_html','contact_html','primary_contact_detail'], !frm.doc.__islocal); if(!frm.doc.__islocal) { frappe.contacts.render_address_and_contact(frm); From 549c196bebf2a116f1e38b66d6884e20bf909a46 Mon Sep 17 00:00:00 2001 From: Vinayak Jethe Date: Wed, 24 Jan 2018 19:47:59 +0530 Subject: [PATCH 04/13] Fixes issue #12512 --- erpnext/stock/dashboard/item_dashboard.js | 18 +++++++------- .../stock/dashboard/item_dashboard_list.html | 24 ++++++++++--------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/erpnext/stock/dashboard/item_dashboard.js b/erpnext/stock/dashboard/item_dashboard.js index 0422026084..4a525261b8 100644 --- a/erpnext/stock/dashboard/item_dashboard.js +++ b/erpnext/stock/dashboard/item_dashboard.js @@ -82,18 +82,11 @@ erpnext.stock.ItemDashboard = Class.extend({ var message = __(" Currently no stock available in any warehouse") $(""+message+"").appendTo(this.result); } - - if (frappe.boot.user.can_write.indexOf("Stock Entry")>=0){ - $(".btn-move").show(); - $(".btn-add").show(); - }else{ - $(".btn-move").hide(); - $(".btn-add").hide(); - } }, get_item_dashboard_data: function(data, max_count, show_item) { if(!max_count) max_count = 0; if(!data) data = []; + data.forEach(function(d) { d.actual_or_pending = d.projected_qty + d.reserved_qty + d.reserved_qty_for_production; d.pending_qty = 0; @@ -105,9 +98,16 @@ erpnext.stock.ItemDashboard = Class.extend({ max_count = Math.max(d.actual_or_pending, d.actual_qty, d.total_reserved, max_count); }); + + var can_write = 0; + if(frappe.boot.user.can_write.indexOf("Stock Entry")>=0){ + can_write = 1; + } + return { data: data, max_count: max_count, + can_write:can_write, show_item: show_item || false } } @@ -195,4 +195,4 @@ erpnext.stock.move_item = function(item, source, target, actual_qty, rate, callb frappe.set_route('Form', doc.doctype, doc.name); }) }); -} +} \ No newline at end of file diff --git a/erpnext/stock/dashboard/item_dashboard_list.html b/erpnext/stock/dashboard/item_dashboard_list.html index 63f248043c..7d7f7e4c71 100644 --- a/erpnext/stock/dashboard/item_dashboard_list.html +++ b/erpnext/stock/dashboard/item_dashboard_list.html @@ -40,18 +40,20 @@
- {% if d.actual_qty %} -
-{% endfor %} +{% endfor %} \ No newline at end of file From 5743ce2b6b1ae4c545f3555a6b0813bccffb04e0 Mon Sep 17 00:00:00 2001 From: Vinayak Jethe Date: Thu, 25 Jan 2018 13:37:20 +0530 Subject: [PATCH 05/13] Made changes as per suggestions --- erpnext/stock/dashboard/item_dashboard_list.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/dashboard/item_dashboard_list.html b/erpnext/stock/dashboard/item_dashboard_list.html index 7d7f7e4c71..1abb086778 100644 --- a/erpnext/stock/dashboard/item_dashboard_list.html +++ b/erpnext/stock/dashboard/item_dashboard_list.html @@ -39,8 +39,8 @@ + {% if can_write %}
- {% if can_write %} {% if d.actual_qty %}
+ {% endif %} {% endfor %} \ No newline at end of file From 3574c96c8c0be7eb3e484b03f4b7f9d846e3f3a3 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Thu, 25 Jan 2018 17:11:52 +0530 Subject: [PATCH 06/13] Update item_dashboard_list.html --- .../stock/dashboard/item_dashboard_list.html | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/erpnext/stock/dashboard/item_dashboard_list.html b/erpnext/stock/dashboard/item_dashboard_list.html index 1abb086778..e0b3431839 100644 --- a/erpnext/stock/dashboard/item_dashboard_list.html +++ b/erpnext/stock/dashboard/item_dashboard_list.html @@ -41,19 +41,19 @@ {% if can_write %}
- {% if d.actual_qty %} -
{% endif %} -{% endfor %} \ No newline at end of file +{% endfor %} From 4c58299eb0fe86e8dd1b6dd0f9c4aafcba86c903 Mon Sep 17 00:00:00 2001 From: Prateeksha Singh Date: Thu, 25 Jan 2018 17:29:57 +0530 Subject: [PATCH 07/13] [fix] encode if letterhead --- erpnext/utilities/user_progress_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/utilities/user_progress_utils.py b/erpnext/utilities/user_progress_utils.py index 18d38c0fe8..58a03e3af3 100644 --- a/erpnext/utilities/user_progress_utils.py +++ b/erpnext/utilities/user_progress_utils.py @@ -40,12 +40,12 @@ def create_customers(args_data): @frappe.whitelist() def create_letterhead(args_data): args = json.loads(args_data) - letterhead = args.get("letterhead").encode('utf-8') + letterhead = args.get("letterhead") if letterhead: try: frappe.get_doc({ "doctype":"Letter Head", - "content":"""

""".format(letterhead), + "content":"""

""".format(letterhead.encode('utf-8')), "letter_head_name": _("Standard"), "is_default": 1 }).insert() From f9b5c748715646886cca0004d2578ae326e2c89b Mon Sep 17 00:00:00 2001 From: tundebabzy Date: Thu, 25 Jan 2018 19:21:05 +0100 Subject: [PATCH 08/13] set batch number only in Sales Invoice and Delivery Note --- erpnext/selling/sales_common.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index 3d174b78f7..5ca26181e3 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -340,7 +340,8 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ conversion_factor: function(doc, cdt, cdn, dont_fetch_price_list_rate) { this._super(doc, cdt, cdn, dont_fetch_price_list_rate); - if(frappe.meta.get_docfield(cdt, "stock_qty", cdn)) { + if(frappe.meta.get_docfield(cdt, "stock_qty", cdn) && + in_list(['Delivery Note', 'Sales Invoice'], doc.doctype)) { this.set_batch_number(cdt, cdn); } }, From bfa898ff9b56e0cca833abc1888e53acd76c5043 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Fri, 26 Jan 2018 10:59:00 +0530 Subject: [PATCH 09/13] [Fix] System pull the valuation rate even if allow zero valuation rate is enabled (#12537) --- erpnext/stock/doctype/stock_entry/stock_entry.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 6a6c667961..7d5af5fcf4 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -288,7 +288,7 @@ class StockEntry(StockController): # get basic rate if not d.bom_no: - if not flt(d.basic_rate) or d.s_warehouse or force: + if (not flt(d.basic_rate) and not d.allow_zero_valuation_rate) or d.s_warehouse or force: basic_rate = flt(get_incoming_rate(args), self.precision("basic_rate", d)) if basic_rate > 0: d.basic_rate = basic_rate @@ -299,7 +299,8 @@ class StockEntry(StockController): # get scrap items basic rate if d.bom_no: - if not flt(d.basic_rate) and getattr(self, "pro_doc", frappe._dict()).scrap_warehouse == d.t_warehouse: + if not flt(d.basic_rate) and not d.allow_zero_valuation_rate and \ + getattr(self, "pro_doc", frappe._dict()).scrap_warehouse == d.t_warehouse: basic_rate = flt(get_incoming_rate(args), self.precision("basic_rate", d)) if basic_rate > 0: d.basic_rate = basic_rate From 89850776527775fc760d20caeb38c4f5e5c5a842 Mon Sep 17 00:00:00 2001 From: Manas Solanki Date: Fri, 26 Jan 2018 11:20:33 +0530 Subject: [PATCH 10/13] Assessment Module Report (#12605) * updated course wise assessment report * added new report Final assessment grades --- erpnext/education/api.py | 5 +- .../assessment_criteria.py | 6 +- .../course_wise_assessment_report.html | 8 +- .../course_wise_assessment_report.js | 28 +- .../course_wise_assessment_report.py | 298 ++++++++++-------- .../final_assessment_grades/__init__.py | 0 .../final_assessment_grades.js | 38 +++ .../final_assessment_grades.json | 20 ++ .../final_assessment_grades.py | 85 +++++ 9 files changed, 349 insertions(+), 139 deletions(-) create mode 100644 erpnext/education/report/final_assessment_grades/__init__.py create mode 100644 erpnext/education/report/final_assessment_grades/final_assessment_grades.js create mode 100644 erpnext/education/report/final_assessment_grades/final_assessment_grades.json create mode 100644 erpnext/education/report/final_assessment_grades/final_assessment_grades.py diff --git a/erpnext/education/api.py b/erpnext/education/api.py index ea4da69504..99fb36e52c 100644 --- a/erpnext/education/api.py +++ b/erpnext/education/api.py @@ -269,7 +269,10 @@ def get_grade(grading_scale, percentage): :param Percentage: Score Percentage Percentage """ grading_scale_intervals = {} - for d in frappe.get_all("Grading Scale Interval", fields=["grade_code", "threshold"], filters={"parent": grading_scale}): + if not hasattr(frappe.local, 'grading_scale'): + grading_scale = frappe.get_all("Grading Scale Interval", fields=["grade_code", "threshold"], filters={"parent": grading_scale}) + frappe.local.grading_scale = grading_scale + for d in frappe.local.grading_scale: grading_scale_intervals.update({d.threshold:d.grade_code}) intervals = sorted(grading_scale_intervals.keys(), key=float, reverse=True) for interval in intervals: diff --git a/erpnext/education/doctype/assessment_criteria/assessment_criteria.py b/erpnext/education/doctype/assessment_criteria/assessment_criteria.py index e666a74959..eadc0de95b 100644 --- a/erpnext/education/doctype/assessment_criteria/assessment_criteria.py +++ b/erpnext/education/doctype/assessment_criteria/assessment_criteria.py @@ -6,5 +6,9 @@ from __future__ import unicode_literals import frappe from frappe.model.document import Document +STD_CRITERIA = ["total", "total score", "total grade", "maximum score", "score", "grade"] + class AssessmentCriteria(Document): - pass + def validate(self): + if self.assessment_criteria.lower() in STD_CRITERIA: + frappe.throw("Can't create standard criteria. Please rename the criteria") \ No newline at end of file diff --git a/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.html b/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.html index 60300b0528..e46a5e764a 100644 --- a/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.html +++ b/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.html @@ -6,9 +6,15 @@ {% } %}

{%= __("Assessment Report") %}


+
{%= __("Academic Year: ") %} {%= filters.academic_year %}
+{% if (filters.academic_term){ %} +
{%= __("Academic Term: ") %} {%= filters.academic_term %}
+{% } %}
{%= __("Course Code: ") %} {%= filters.course %}
{%= __("Assessment Group: ") %} {%= filters.assessment_group %}
-
{%= __("Assessment Plan: ") %} {%= data_to_be_printed[0]["assessment_plan"] %}
+{% if (filters.student_group){ %} +
{%= __("Student Group: ") %} {%= filters.student_group %}
+{% } %}
diff --git a/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.js b/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.js index 42b19ebf06..8c42d48641 100644 --- a/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.js +++ b/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.js @@ -4,18 +4,17 @@ frappe.query_reports["Course wise Assessment Report"] = { "filters": [ { - "fieldname":"assessment_group", - "label": __("Assessment Group"), + "fieldname":"academic_year", + "label": __("Academic Year"), "fieldtype": "Link", - "options": "Assessment Group", - "reqd": 1, - "get_query": function() { - return{ - filters: { - 'is_group': 0 - } - }; - } + "options": "Academic Year", + "reqd": 1 + }, + { + "fieldname":"academic_term", + "label": __("Academic Term"), + "fieldtype": "Link", + "options": "Academic Term" }, { "fieldname":"course", @@ -29,6 +28,13 @@ frappe.query_reports["Course wise Assessment Report"] = { "label": __("Student Group"), "fieldtype": "Link", "options": "Student Group" + }, + { + "fieldname":"assessment_group", + "label": __("Assessment Group"), + "fieldtype": "Link", + "options": "Assessment Group", + "reqd": 1 } ] }; diff --git a/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.py b/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.py index ff172381b3..a50ad7b91e 100644 --- a/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.py +++ b/erpnext/education/report/course_wise_assessment_report/course_wise_assessment_report.py @@ -5,129 +5,189 @@ from __future__ import unicode_literals import frappe from frappe import _ from frappe.utils import flt -from collections import defaultdict +from collections import defaultdict, OrderedDict from erpnext.education.api import get_grade def execute(filters=None): - data = [] - + data, chart, grades = [], [], [] args = frappe._dict() + grade_wise_analysis = defaultdict(dict) + + args["academic_year"] = filters.get("academic_year") + args["course"] = filters.get("course") args["assessment_group"] = filters.get("assessment_group") + + args["academic_term"] = filters.get("academic_term") + args["student_group"] = filters.get("student_group") + if args["assessment_group"] == "All Assessment Groups": frappe.throw(_("Please select the assessment group other than 'All Assessment Groups'")) - args["course"] = filters.get("course") - args["student_group"] = filters.get("student_group") + returned_values = get_formatted_result(args, get_assessment_criteria=True) + student_dict = returned_values["student_details"] + result_dict = returned_values["assessment_result"] + assessment_criteria_dict = returned_values["assessment_criteria"] + + for student in result_dict: + student_row = {} + student_row["student"] = student + student_row["student_name"] = student_dict[student] + for criteria in assessment_criteria_dict: + scrub_criteria = frappe.scrub(criteria) + if criteria in result_dict[student][args.course][args.assessment_group]: + student_row[scrub_criteria] = result_dict[student][args.course][args.assessment_group][criteria]["grade"] + student_row[scrub_criteria + "_score"] = result_dict[student][args.course][args.assessment_group][criteria]["score"] + + # create the list of possible grades + if student_row[scrub_criteria] not in grades: + grades.append(student_row[scrub_criteria]) + + # create the dict of for gradewise analysis + if student_row[scrub_criteria] not in grade_wise_analysis[criteria]: + grade_wise_analysis[criteria][student_row[scrub_criteria]] = 1 + else: + grade_wise_analysis[criteria][student_row[scrub_criteria]] += 1 + else: + student_row[frappe.scrub(criteria)] = "" + student_row[frappe.scrub(criteria)+ "_score"] = "" + data.append(student_row) + + assessment_criteria_list = [d for d in assessment_criteria_dict] + columns = get_column(assessment_criteria_dict) + chart = get_chart_data(grades, assessment_criteria_list, grade_wise_analysis) + + return columns, data, None, chart - # find all assessment plan and related details linked with the given filters - def get_assessment_details(): - if args["student_group"]: - cond = "and ap.student_group=%(student_group)s" +def get_formatted_result(args, get_assessment_criteria=False, get_course=False): + cond, cond1, cond2, cond3, cond4 = " ", " ", " ", " ", " " + args_list = [args.academic_year] + + if args.course: + cond = " and ar.course=%s" + args_list.append(args.course) + + if args.academic_term: + cond1 = " and ar.academic_term=%s" + args_list.append(args.academic_term) + + if args.student_group: + cond2 = " and ar.student_group=%s" + args_list.append(args.student_group) + + create_total_dict = False + group_type = frappe.get_value("Assessment Group", args.assessment_group, "is_group") + if group_type: + from frappe.desk.treeview import get_children + assessment_groups = [d.get("value") for d in get_children("Assessment Group", + args.assessment_group) if d.get("value") and not d.get("expandable")] + cond3 = " and ar.assessment_group in (%s)"%(', '.join(['%s']*len(assessment_groups))) + else: + assessment_groups = [args.assessment_group] + cond3 = " and ar.assessment_group=%s" + args_list += assessment_groups + + if args.students: + cond4 = " and ar.student in (%s)"%(', '.join(['%s']*len(args.students))) + args_list += args.students + + assessment_result = frappe.db.sql(''' + SELECT + ar.student, ar.student_name, ar.academic_year, ar.academic_term, ar.program, ar.course, + ar.assessment_plan, ar.grading_scale, ar.assessment_group, ar.student_group, + ard.assessment_criteria, ard.maximum_score, ard.grade, ard.score + FROM + `tabAssessment Result` ar, `tabAssessment Result Detail` ard + WHERE + ar.name=ard.parent and ar.docstatus=1 and ar.academic_year=%s {0} {1} {2} {3} {4} + ORDER BY + ard.assessment_criteria'''.format(cond, cond1, cond2, cond3, cond4), + tuple(args_list), as_dict=1) + + # create the nested dictionary structure as given below: + # ..... + # "Total Score" -> assessment criteria used for totaling and args.assessment_group -> for totaling all the assesments + + student_details = {} + formatted_assessment_result = defaultdict(dict) + assessment_criteria_dict = OrderedDict() + course_dict = OrderedDict() + total_maximum_score = None + if not (len(assessment_groups) == 1 and assessment_groups[0] == args.assessment_group): + create_total_dict = True + + # add the score for a given score and recalculate the grades + def add_score_and_recalculate_grade(result, assessment_group, assessment_criteria): + formatted_assessment_result[result.student][result.course][assessment_group]\ + [assessment_criteria]["maximum_score"] += result.maximum_score + formatted_assessment_result[result.student][result.course][assessment_group]\ + [assessment_criteria]["score"] += result.score + tmp_grade = get_grade(result.grading_scale, ((formatted_assessment_result[result.student][result.course] + [assessment_group][assessment_criteria]["score"])/(formatted_assessment_result[result.student] + [result.course][assessment_group][assessment_criteria]["maximum_score"]))*100) + formatted_assessment_result[result.student][result.course][assessment_group]\ + [assessment_criteria]["grade"] = tmp_grade + + # create the assessment criteria "Total Score" with the sum of all the scores of the assessment criteria in a given assessment group + def add_total_score(result, assessment_group): + if "Total Score" not in formatted_assessment_result[result.student][result.course][assessment_group]: + formatted_assessment_result[result.student][result.course][assessment_group]["Total Score"] = frappe._dict({ + "assessment_criteria": "Total Score", "maximum_score": result.maximum_score, "score": result.score, "grade": result.grade}) else: - cond = '' + add_score_and_recalculate_grade(result, assessment_group, "Total Score") - assessment_plan = frappe.db.sql(''' - select - ap.name, ap.student_group, ap.grading_scale, apc.assessment_criteria, apc.maximum_score as max_score - from - `tabAssessment Plan` ap, `tabAssessment Plan Criteria` apc - where - ap.assessment_group=%(assessment_group)s and ap.course=%(course)s and - ap.name=apc.parent and ap.docstatus=1 {0} - order by - apc.assessment_criteria'''.format(cond), (args), as_dict=1) + for result in assessment_result: + if result.student not in student_details: + student_details[result.student] = result.student_name - assessment_plan_list = list(set([d["name"] for d in assessment_plan])) - if not assessment_plan_list: - frappe.throw(_("No assessment plan linked with this assessment group")) + assessment_criteria_details = frappe._dict({"assessment_criteria": result.assessment_criteria, + "maximum_score": result.maximum_score, "score": result.score, "grade": result.grade}) - assessment_criteria_list = list(set([(d["assessment_criteria"],d["max_score"]) for d in assessment_plan])) - student_group_list = list(set([d["student_group"] for d in assessment_plan])) - total_maximum_score = flt(sum([flt(d[1]) for d in assessment_criteria_list])) - grading_scale = assessment_plan[0]["grading_scale"] + if not formatted_assessment_result[result.student]: + formatted_assessment_result[result.student] = defaultdict(dict) + if not formatted_assessment_result[result.student][result.course]: + formatted_assessment_result[result.student][result.course] = defaultdict(dict) - return assessment_plan_list, assessment_criteria_list, total_maximum_score, grading_scale, student_group_list + if not create_total_dict: + formatted_assessment_result[result.student][result.course][result.assessment_group]\ + [result.assessment_criteria] = assessment_criteria_details + add_total_score(result, result.assessment_group) + + # create the total of all the assessment groups criteria-wise + elif create_total_dict: + if not formatted_assessment_result[result.student][result.course][args.assessment_group]: + formatted_assessment_result[result.student][result.course][args.assessment_group] = defaultdict(dict) + formatted_assessment_result[result.student][result.course][args.assessment_group]\ + [result.assessment_criteria] = assessment_criteria_details + elif result.assessment_criteria not in formatted_assessment_result[result.student][result.course][args.assessment_group]: + formatted_assessment_result[result.student][result.course][args.assessment_group]\ + [result.assessment_criteria] = assessment_criteria_details + elif result.assessment_criteria in formatted_assessment_result[result.student][result.course][args.assessment_group]: + add_score_and_recalculate_grade(result, args.assessment_group, result.assessment_criteria) + + add_total_score(result, args.assessment_group) + + total_maximum_score = formatted_assessment_result[result.student][result.course][args.assessment_group]\ + ["Total Score"]["maximum_score"] + if get_assessment_criteria: + assessment_criteria_dict[result.assessment_criteria] = formatted_assessment_result[result.student][result.course]\ + [args.assessment_group][result.assessment_criteria]["maximum_score"] + if get_course: + course_dict[result.course] = total_maximum_score + + if get_assessment_criteria and total_maximum_score: + assessment_criteria_dict["Total Score"] = total_maximum_score + + return { + "student_details": student_details, + "assessment_result": formatted_assessment_result, + "assessment_criteria": assessment_criteria_dict, + "course_dict": course_dict + } - # get all the result and make a dict map student as the key and value as dict of result - def get_result_map(): - result_dict = defaultdict(dict) - kounter = defaultdict(dict) - assessment_result = frappe.db.sql('''select ar.student, ard.assessment_criteria, ard.grade, ard.score - from `tabAssessment Result` ar, `tabAssessment Result Detail` ard - where ar.assessment_plan in (%s) and ar.name=ard.parent and ar.docstatus=1 - order by ard.assessment_criteria''' %', '.join(['%s']*len(assessment_plan_list)), - tuple(assessment_plan_list), as_dict=1) - - for result in assessment_result: - if "total_score" in result_dict[result.student]: - total_score = result_dict[result.student]["total_score"] + result.score - else: - total_score = result.score - total = get_grade(grading_scale, (total_score/total_maximum_score)*100) - - if result.grade in kounter[result.assessment_criteria]: - kounter[result.assessment_criteria][result.grade] += 1 - else: - kounter[result.assessment_criteria].update({result.grade: 1}) - - if "Total" not in kounter: - kounter["Total"] = {} - - if "total" in result_dict[result.student]: - prev_grade = result_dict[result.student]["total"] - prev_grade_count = kounter["Total"].get(prev_grade) - 1 - kounter["Total"].update({prev_grade: prev_grade_count}) - latest_grade_count = kounter["Total"].get(total)+1 if kounter["Total"].get(total) else 1 - kounter["Total"].update({total: latest_grade_count}) - - result_dict[result.student].update({ - frappe.scrub(result.assessment_criteria): result.grade, - frappe.scrub(result.assessment_criteria)+"_score": result.score, - "total_score": total_score, - "total": total - }) - - return result_dict, kounter - - # make data from the result dict - def get_data(): - student_list = frappe.db.sql('''select sgs.student, sgs.student_name - from `tabStudent Group` sg, `tabStudent Group Student` sgs - where sg.name = sgs.parent and sg.name in (%s) - order by sgs.group_roll_number asc''' %', '.join(['%s']*len(student_group_list)), - tuple(student_group_list), as_dict=1) - - for student in student_list: - student.update(result_dict[student.student]) - return student_list - - - # get chart data - def get_chart(): - grading_scale = frappe.db.get_value("Assessment Plan", list(assessment_plan_list)[0], "grading_scale") - grades = frappe.db.sql_list('''select grade_code from `tabGrading Scale Interval` where parent=%s''', - (grading_scale)) - criteria_list = [d[0] for d in assessment_criteria_list] + ["Total"] - return get_chart_data(grades, criteria_list, kounter) - - - assessment_plan_list, assessment_criteria_list, total_maximum_score, grading_scale,\ - student_group_list = get_assessment_details() - result_dict, kounter = get_result_map() - data = get_data() - - columns = get_column(assessment_criteria_list, total_maximum_score) - chart = get_chart() - data_to_be_printed = [{ - "assessment_plan": ", ".join(assessment_plan_list) - }] - - return columns, data, None, chart, data_to_be_printed - -def get_column(assessment_criteria, total_maximum_score): +def get_column(assessment_criteria): columns = [{ "fieldname": "student", "label": _("Student ID"), @@ -143,40 +203,28 @@ def get_column(assessment_criteria, total_maximum_score): }] for d in assessment_criteria: columns.append({ - "fieldname": frappe.scrub(d[0]), - "label": d[0], + "fieldname": frappe.scrub(d), + "label": d, "fieldtype": "Data", "width": 110 }) columns.append({ - "fieldname": frappe.scrub(d[0]) +"_score", - "label": "Score(" + str(int(d[1])) + ")", + "fieldname": frappe.scrub(d) +"_score", + "label": "Score(" + str(int(assessment_criteria[d])) + ")", "fieldtype": "Float", "width": 100 }) - columns += [{ - "fieldname": "total", - "label": "Total", - "fieldtype": "Data", - "width": 100 - }, - { - "fieldname": "total_score", - "label": "Total Score("+ str(int(total_maximum_score)) + ")", - "fieldtype": "Float", - "width": 110 - }] - return columns -def get_chart_data(grades, assessment_criteria_list, kounter): + +def get_chart_data(grades, criteria_list, kounter): grades = sorted(grades) datasets = [] for grade in grades: tmp = frappe._dict({"values":[], "title": grade}) - for criteria in assessment_criteria_list: + for criteria in criteria_list: if grade in kounter[criteria]: tmp["values"].append(kounter[criteria][grade]) else: @@ -185,7 +233,7 @@ def get_chart_data(grades, assessment_criteria_list, kounter): return { "data": { - "labels": assessment_criteria_list, + "labels": criteria_list, "datasets": datasets }, "type": 'bar', diff --git a/erpnext/education/report/final_assessment_grades/__init__.py b/erpnext/education/report/final_assessment_grades/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/education/report/final_assessment_grades/final_assessment_grades.js b/erpnext/education/report/final_assessment_grades/final_assessment_grades.js new file mode 100644 index 0000000000..ba0a42ff90 --- /dev/null +++ b/erpnext/education/report/final_assessment_grades/final_assessment_grades.js @@ -0,0 +1,38 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["Final Assessment Grades"] = { + "filters": [ + { + "fieldname":"academic_year", + "label": __("Academic Year"), + "fieldtype": "Link", + "options": "Academic Year", + "reqd": 1 + }, + { + "fieldname":"student_group", + "label": __("Student Group"), + "fieldtype": "Link", + "options": "Student Group", + "reqd": 1, + "get_query": function() { + return{ + filters: { + "group_based_on": "Batch", + "academic_year": frappe.query_report_filters_by_name.academic_year.value + } + }; + } + }, + { + "fieldname":"assessment_group", + "label": __("Assessment Group"), + "fieldtype": "Link", + "options": "Assessment Group", + "reqd": 1 + } + + ] +} diff --git a/erpnext/education/report/final_assessment_grades/final_assessment_grades.json b/erpnext/education/report/final_assessment_grades/final_assessment_grades.json new file mode 100644 index 0000000000..1efbb6e66d --- /dev/null +++ b/erpnext/education/report/final_assessment_grades/final_assessment_grades.json @@ -0,0 +1,20 @@ +{ + "add_total_row": 0, + "apply_user_permissions": 1, + "creation": "2018-01-22 17:04:43.412054", + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "letter_head": "Shishuvan Secondary School", + "modified": "2018-01-22 17:04:43.412054", + "modified_by": "Administrator", + "module": "Education", + "name": "Final Assessment Grades", + "owner": "Administrator", + "ref_doctype": "Assessment Result", + "report_name": "Final Assessment Grades", + "report_type": "Script Report", + "roles": [] +} \ No newline at end of file diff --git a/erpnext/education/report/final_assessment_grades/final_assessment_grades.py b/erpnext/education/report/final_assessment_grades/final_assessment_grades.py new file mode 100644 index 0000000000..efc9aff083 --- /dev/null +++ b/erpnext/education/report/final_assessment_grades/final_assessment_grades.py @@ -0,0 +1,85 @@ +# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from frappe import _ +from collections import defaultdict + +from erpnext.education.report.course_wise_assessment_report.course_wise_assessment_report import get_formatted_result +from erpnext.education.report.course_wise_assessment_report.course_wise_assessment_report import get_chart_data + + +def execute(filters=None): + columns, data, grades = [], [], [] + args = frappe._dict() + course_wise_analysis = defaultdict(dict) + + args["academic_year"] = filters.get("academic_year") + assessment_group = args["assessment_group"] = filters.get("assessment_group") + + student_group = filters.get("student_group") + args.students = frappe.db.sql_list("select student from `tabStudent Group Student` where parent=%s", (student_group)) + + values = get_formatted_result(args, get_course=True) + student_details = values.get("student_details") + assessment_result = values.get("assessment_result") + course_dict = values.get("course_dict") + + for student in args.students: + student_row = {} + student_row["student"] = student + student_row["student_name"] = student_details[student] + for course in course_dict: + scrub_course = frappe.scrub(course) + if assessment_group in assessment_result[student][course]: + student_row["grade_" + scrub_course] = assessment_result[student][course][assessment_group]["Total Score"]["grade"] + student_row["score_" + scrub_course] = assessment_result[student][course][assessment_group]["Total Score"]["score"] + + # create the list of possible grades + if student_row["grade_" + scrub_course] not in grades: + grades.append(student_row["grade_" + scrub_course]) + + # create the dict of for gradewise analysis + if student_row["grade_" + scrub_course] not in course_wise_analysis[course]: + course_wise_analysis[course][student_row["grade_" + scrub_course]] = 1 + else: + course_wise_analysis[course][student_row["grade_" + scrub_course]] += 1 + + data.append(student_row) + + course_list = [d for d in course_dict] + columns = get_column(course_dict) + chart = get_chart_data(grades, course_list, course_wise_analysis) + return columns, data, None, chart + + +def get_column(course_dict): + columns = [{ + "fieldname": "student", + "label": _("Student ID"), + "fieldtype": "Link", + "options": "Student", + "width": 90 + }, + { + "fieldname": "student_name", + "label": _("Student Name"), + "fieldtype": "Data", + "width": 160 + }] + for course in course_dict: + columns.append({ + "fieldname": "grade_" + frappe.scrub(course), + "label": course, + "fieldtype": "Data", + "width": 110 + }) + columns.append({ + "fieldname": "score_" + frappe.scrub(course), + "label": "Score(" + str(course_dict[course]) + ")", + "fieldtype": "Float", + "width": 100 + }) + + return columns From 794ecda61892e4f1d0dff7b85b557a1aed0f04ba Mon Sep 17 00:00:00 2001 From: tundebabzy Date: Sat, 27 Jan 2018 05:47:18 +0100 Subject: [PATCH 11/13] corrected wrong get_diff arguments --- erpnext/stock/doctype/batch/batch_list.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/batch/batch_list.js b/erpnext/stock/doctype/batch/batch_list.js index 2138fa1da7..7ee81aa7e9 100644 --- a/erpnext/stock/doctype/batch/batch_list.js +++ b/erpnext/stock/doctype/batch/batch_list.js @@ -1,7 +1,7 @@ frappe.listview_settings['Batch'] = { add_fields: ["item", "expiry_date"], get_indicator: function(doc) { - if(doc.expiry_date && frappe.datetime.get_diff(doc.expiry_date) <= 0) { + if(doc.expiry_date && frappe.datetime.get_diff(doc.expiry_date, frappe.datetime.nowdate()) <= 0) { return [__("Expired"), "red", "expiry_date,>=,Today"] } else if(doc.expiry_date) { return [__("Not Expired"), "green", "expiry_date,<,Today"] From cfa9d1adb7e5abdf9f9dd563322d47121e8004e0 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 29 Jan 2018 16:07:21 +0530 Subject: [PATCH 12/13] Patch: Create Payment Terms based on default credit days set in company and use it while setting due_date (#12685) * Patch: Create Payment Terms based on default credit days set in company and use it while setting due_date * Payment Terms patch for credit days defined in customer group --- .../purchase_invoice/purchase_invoice.py | 2 +- .../doctype/sales_invoice/sales_invoice.py | 2 +- erpnext/accounts/party.py | 39 +++++-- .../buying/doctype/supplier/test_records.json | 1 - erpnext/controllers/accounts_controller.py | 4 +- erpnext/patches.txt | 2 +- ..._default_payment_terms_based_on_company.py | 37 +++++++ .../patches/v5_1/fix_credit_days_based_on.py | 9 -- .../change_default_customer_credit_days.py | 3 +- erpnext/public/js/controllers/transaction.js | 9 +- erpnext/setup/doctype/company/company.json | 101 ++++++------------ .../customer_group/customer_group.json | 41 ++----- 12 files changed, 118 insertions(+), 132 deletions(-) create mode 100644 erpnext/patches/v10_0/set_default_payment_terms_based_on_company.py delete mode 100644 erpnext/patches/v5_1/fix_credit_days_based_on.py diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 07853d0e4a..28d51ce0c7 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -96,7 +96,7 @@ class PurchaseInvoice(BuyingController): if not self.credit_to: self.credit_to = get_party_account("Supplier", self.supplier, self.company) if not self.due_date: - self.due_date = get_due_date(self.posting_date, "Supplier", self.supplier) + self.due_date = get_due_date(self.posting_date, "Supplier", self.supplier, self.company) super(PurchaseInvoice, self).set_missing_values(for_validate) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index f6d43c7f70..b6c84052a6 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -237,7 +237,7 @@ class SalesInvoice(SellingController): if not self.debit_to: self.debit_to = get_party_account("Customer", self.customer, self.company) if not self.due_date and self.customer: - self.due_date = get_due_date(self.posting_date, "Customer", self.customer) + self.due_date = get_due_date(self.posting_date, "Customer", self.customer, self.company) super(SalesInvoice, self).set_missing_values(for_validate) diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index 7bccfe89f3..5237a71949 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -51,7 +51,7 @@ def _get_party_details(party=None, account=None, party_type="Customer", company= set_other_values(out, party, party_type) set_price_list(out, party, party_type, price_list) out["taxes_and_charges"] = set_taxes(party.name, party_type, posting_date, company, out.customer_group, out.supplier_type) - out["payment_terms_template"] = get_pyt_term_template(party.name, party_type) + out["payment_terms_template"] = get_pyt_term_template(party.name, party_type, company) if not out.get("currency"): out["currency"] = currency @@ -164,7 +164,7 @@ def set_account_and_due_date(party, account, party_type, company, posting_date, out = { party_type.lower(): party, account_fieldname : account, - "due_date": get_due_date(posting_date, party_type, party) + "due_date": get_due_date(posting_date, party_type, party, company) } return out @@ -267,12 +267,12 @@ def validate_party_accounts(doc): @frappe.whitelist() -def get_due_date(posting_date, party_type, party): +def get_due_date(posting_date, party_type, party, company=None): """Get due date from `Payment Terms Template`""" due_date = None if posting_date and party: due_date = posting_date - template_name = get_pyt_term_template(party, party_type) + template_name = get_pyt_term_template(party, party_type, company) if template_name: due_date = get_due_date_from_template(template_name, posting_date).strftime("%Y-%m-%d") else: @@ -305,12 +305,11 @@ def get_due_date_from_template(template_name, posting_date): return due_date - -def validate_due_date(posting_date, due_date, party_type, party): +def validate_due_date(posting_date, due_date, party_type, party, company=None): if getdate(due_date) < getdate(posting_date): frappe.throw(_("Due Date cannot be before Posting Date")) else: - default_due_date = get_due_date(posting_date, party_type, party) + default_due_date = get_due_date(posting_date, party_type, party, company) if not default_due_date: return @@ -360,14 +359,32 @@ def set_taxes(party, party_type, posting_date, company, customer_group=None, sup @frappe.whitelist() -def get_pyt_term_template(party_name, party_type): +def get_pyt_term_template(party_name, party_type, company=None): + if party_type not in ("Customer", "Supplier"): + return + template = None - if party_type in ('Customer', 'Supplier'): - template = frappe.db.get_value(party_type, party_name, fieldname='payment_terms') + if party_type == 'Customer': + customer = frappe.db.get_value("Customer", party_name, + fieldname=['payment_terms', "customer_group"], as_dict=1) + template = customer.payment_terms + + if not template and customer.customer_group: + template = frappe.db.get_value("Customer Group", + customer.customer_group, fieldname='payment_terms') + else: + supplier = frappe.db.get_value("Supplier", party_name, + fieldname=['payment_terms', "supplier_type"], as_dict=1) + template = supplier.payment_terms + + if not template and supplier.supplier_type: + template = frappe.db.get_value("Supplier Type", supplier.supplier_type, fieldname='payment_terms') + + if not template and company: + template = frappe.db.get_value("Company", company, fieldname='payment_terms') return template - def validate_party_frozen_disabled(party_type, party_name): if party_type and party_name: if party_type in ("Customer", "Supplier"): diff --git a/erpnext/buying/doctype/supplier/test_records.json b/erpnext/buying/doctype/supplier/test_records.json index 7479f55650..370ce8dad1 100644 --- a/erpnext/buying/doctype/supplier/test_records.json +++ b/erpnext/buying/doctype/supplier/test_records.json @@ -9,7 +9,6 @@ "doctype": "Supplier", "supplier_name": "_Test Supplier P", "supplier_type": "_Test Supplier Type", - "credit_days_based_on": "Fixed Days" }, { "doctype": "Supplier", diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index c7b520608e..b3672cbde3 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -135,9 +135,9 @@ class AccountsController(TransactionBase): if not self.due_date: frappe.throw(_("Due Date is mandatory")) - validate_due_date(self.posting_date, self.due_date, "Customer", self.customer) + validate_due_date(self.posting_date, self.due_date, "Customer", self.customer, self.company) elif self.doctype == "Purchase Invoice": - validate_due_date(self.posting_date, self.due_date, "Supplier", self.supplier) + validate_due_date(self.posting_date, self.due_date, "Supplier", self.supplier, self.company) def set_price_list_currency(self, buying_or_selling): if self.meta.get_field("posting_date"): diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 8fa382cf7f..3a18efc1a6 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -183,7 +183,6 @@ erpnext.patches.v5_0.index_on_account_and_gl_entry execute:frappe.db.sql("""delete from `tabProject Task`""") erpnext.patches.v5_0.update_item_desc_in_invoice erpnext.patches.v5_1.fix_against_account -erpnext.patches.v5_1.fix_credit_days_based_on execute:frappe.rename_doc("DocType", "Salary Manager", "Process Payroll", force=True) erpnext.patches.v5_1.rename_roles erpnext.patches.v5_1.default_bom @@ -487,3 +486,4 @@ erpnext.patches.v10_0.add_guardian_role_for_parent_portal erpnext.patches.v10_0.set_numeric_ranges_in_template_if_blank erpnext.patches.v10_0.update_assessment_plan erpnext.patches.v10_0.update_assessment_result +erpnext.patches.v10_0.set_default_payment_terms_based_on_company \ No newline at end of file diff --git a/erpnext/patches/v10_0/set_default_payment_terms_based_on_company.py b/erpnext/patches/v10_0/set_default_payment_terms_based_on_company.py new file mode 100644 index 0000000000..1b5963393a --- /dev/null +++ b/erpnext/patches/v10_0/set_default_payment_terms_based_on_company.py @@ -0,0 +1,37 @@ +from __future__ import unicode_literals +import frappe +from erpnext.patches.v8_10.change_default_customer_credit_days import make_payment_term, make_template + +def execute(): + for dt in ("Company", "Customer Group"): + frappe.reload_doc("setup", "doctype", frappe.scrub(dt)) + + credit_records = frappe.db.sql(""" + SELECT DISTINCT `credit_days`, `credit_days_based_on`, `name` + from `tab{0}` + where + ((credit_days_based_on='Fixed Days' or credit_days_based_on is null) and credit_days is not null) + or credit_days_based_on='Last Day of the Next Month' + """.format(dt), as_dict=1) + + for d in credit_records: + template = create_payment_terms_template(d) + + frappe.db.sql(""" + update `tab{0}` + set `payment_terms` = %s + where name = %s + """.format(dt), (template, d.name)) + +def create_payment_terms_template(data): + if data.credit_days_based_on == "Fixed Days": + pyt_template_name = 'Default Payment Term - N{0}'.format(data.credit_days) + else: + pyt_template_name = 'Default Payment Term - EO2M' + + if not frappe.db.exists("Payment Terms Template", pyt_template_name): + payment_term = make_payment_term(data.credit_days, data.credit_days_based_on) + template = make_template(payment_term) + else: + template = frappe.get_doc("Payment Terms Template", pyt_template_name) + return template \ No newline at end of file diff --git a/erpnext/patches/v5_1/fix_credit_days_based_on.py b/erpnext/patches/v5_1/fix_credit_days_based_on.py deleted file mode 100644 index 6df19f201a..0000000000 --- a/erpnext/patches/v5_1/fix_credit_days_based_on.py +++ /dev/null @@ -1,9 +0,0 @@ -from __future__ import unicode_literals - -import frappe - -def execute(): - for dt in ("Customer", "Customer Group", "Company"): - frappe.reload_doctype(dt, force=True) - frappe.db.sql("""update `tab{0}` set credit_days_based_on='Fixed Days' - where ifnull(credit_days, 0) > 0""".format(dt)) diff --git a/erpnext/patches/v8_10/change_default_customer_credit_days.py b/erpnext/patches/v8_10/change_default_customer_credit_days.py index 640c8aa752..eddafb5634 100644 --- a/erpnext/patches/v8_10/change_default_customer_credit_days.py +++ b/erpnext/patches/v8_10/change_default_customer_credit_days.py @@ -17,7 +17,8 @@ def execute(): SELECT DISTINCT `credit_days`, `credit_days_based_on`, `name` from `tab{0}` where - (credit_days_based_on='Fixed Days' and credit_days is not null) + ((credit_days_based_on='Fixed Days' or credit_days_based_on is null) + and credit_days is not null) or credit_days_based_on='Last Day of the Next Month' """.format(doctype)) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index d06a76a517..31488de237 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -523,7 +523,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ }, callback: function(r, rt) { if(r.message) { - me.frm.set_value("due_date", r.message); + me.frm.doc.due_date = r.message; + refresh_field("due_date"); frappe.ui.form.trigger(me.frm.doc.doctype, "currency"); me.recalculate_terms(); } @@ -538,7 +539,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ due_date: function() { // due_date is to be changed, payment terms template and/or payment schedule must // be removed as due_date is automatically changed based on payment terms - if (this.frm.doc.due_date) { + if (this.frm.doc.due_date && !this.frm.updating_party_details) { if (this.frm.doc.payment_terms_template || (this.frm.doc.payment_schedule && this.frm.doc.payment_schedule.length)) { var message1 = ""; @@ -555,11 +556,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ if (message1.length !== 0) message2 = " and " + message2; final_message = final_message + message2; } - frappe.msgprint(final_message); } - - } + } }, recalculate_terms: function() { diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json index 9824c706cf..d444417b16 100644 --- a/erpnext/setup/doctype/company/company.json +++ b/erpnext/setup/doctype/company/company.json @@ -1180,6 +1180,35 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_26", + "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, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -1219,8 +1248,9 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "column_break_26", - "fieldtype": "Column Break", + "depends_on": "", + "fieldname": "payment_terms", + "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -1228,8 +1258,10 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, + "label": "Default Payment Terms Template", "length": 0, "no_copy": 0, + "options": "Payment Terms Template", "permlevel": 0, "precision": "", "print_hide": 0, @@ -1242,69 +1274,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "credit_days_based_on", - "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": "Credit Days Based On", - "length": 0, - "no_copy": 0, - "options": "\nFixed Days\nLast Day of the Next Month", - "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, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:(!doc.__islocal && doc.credit_days_based_on=='Fixed Days')", - "fieldname": "credit_days", - "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": "Credit Days", - "length": 0, - "no_copy": 0, - "oldfieldname": "credit_days", - "oldfieldtype": "Int", - "permlevel": 0, - "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, - "unique": 0 - }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -2052,7 +2021,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2017-12-07 18:40:24.646920", + "modified": "2018-01-29 12:40:24.646920", "modified_by": "Administrator", "module": "Setup", "name": "Company", diff --git a/erpnext/setup/doctype/customer_group/customer_group.json b/erpnext/setup/doctype/customer_group/customer_group.json index 316f11badf..062a49a9ad 100644 --- a/erpnext/setup/doctype/customer_group/customer_group.json +++ b/erpnext/setup/doctype/customer_group/customer_group.json @@ -162,12 +162,14 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "credit_days_based_on", - "fieldtype": "Select", + "depends_on": "", + "fieldname": "payment_terms", + "fieldtype": "Link", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -175,10 +177,10 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Credit Days Based On", + "label": "Default Payment Terms Template", "length": 0, "no_copy": 0, - "options": "\nFixed Days\nLast Day of the Next Month", + "options": "Payment Terms Template", "permlevel": 0, "precision": "", "print_hide": 0, @@ -191,35 +193,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.credit_days_based_on=='Fixed Days'", - "fieldname": "credit_days", - "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": "Credit Days", - "length": 0, - "no_copy": 0, - "permlevel": 1, - "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, - "unique": 0 - }, { "allow_on_submit": 0, "bold": 0, @@ -411,7 +384,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-02-20 13:25:31.549874", + "modified": "2018-01-29 13:25:31.549874", "modified_by": "Administrator", "module": "Setup", "name": "Customer Group", From 05eed01eec3851f6d3295debe17c8b969d7f75d0 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Mon, 29 Jan 2018 16:54:55 +0600 Subject: [PATCH 13/13] bumped to version 10.0.15 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index f4876bd46f..029d066c4b 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '10.0.14' +__version__ = '10.0.15' def get_default_company(user=None): '''Get default company for user'''