diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 99981bd713e..a4647e3b0ac 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '10.1.6' +__version__ = '10.1.7' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.json b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.json index 029421990bd..3ab73b717d1 100644 --- a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.json +++ b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.json @@ -159,6 +159,36 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "include_pos_transactions", + "fieldtype": "Check", + "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": "Include POS Transactions", + "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, @@ -292,7 +322,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2017-04-21 16:58:26.902732", + "modified": "2018-03-07 18:58:48.658687", "modified_by": "Administrator", "module": "Accounts", "name": "Bank Reconciliation", diff --git a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py index e8b60ac09a2..7814b0883da 100644 --- a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py +++ b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py @@ -53,10 +53,26 @@ class BankReconciliation(Document): posting_date ASC, name DESC """.format(condition), {"account":self.bank_account, "from":self.from_date, "to":self.to_date}, as_dict=1) - - entries = sorted(list(payment_entries)+list(journal_entries), + + pos_entries = [] + if self.include_pos_transactions: + pos_entries = frappe.db.sql(""" + select + "Sales Invoice Payment" as payment_document, sip.name as payment_entry, sip.amount as debit, + si.posting_date, si.debit_to as against_account, sip.clearance_date, + account.account_currency, 0 as credit + from `tabSales Invoice Payment` sip, `tabSales Invoice` si, `tabAccount` account + where + sip.account=%(account)s and si.docstatus=1 and sip.parent = si.name + and account.name = sip.account and si.posting_date >= %(from)s and si.posting_date <= %(to)s {0} + order by + si.posting_date ASC, si.name DESC + """.format(condition), + {"account":self.bank_account, "from":self.from_date, "to":self.to_date}, as_dict=1) + + entries = sorted(list(payment_entries)+list(journal_entries+list(pos_entries)), key=lambda k: k['posting_date'] or getdate(nowdate())) - + self.set('payment_entries', []) self.total_amount = 0.0 diff --git a/erpnext/accounts/doctype/bank_reconciliation/test_bank_reconciliation.py b/erpnext/accounts/doctype/bank_reconciliation/test_bank_reconciliation.py new file mode 100644 index 00000000000..932fb3384cf --- /dev/null +++ b/erpnext/accounts/doctype/bank_reconciliation/test_bank_reconciliation.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals +import unittest + +class TestBankReconciliation(unittest.TestCase): + pass diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 8800a0a7e48..7bdb6fbd12a 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -685,6 +685,24 @@ def get_company_defaults(company): return ret +def get_outstanding_on_journal_entry(name): + res = frappe.db.sql( + 'SELECT ' + 'CASE WHEN party_type IN ("Customer", "Student") ' + 'THEN ifnull(sum(debit_in_account_currency - credit_in_account_currency), 0) ' + 'ELSE ifnull(sum(credit_in_account_currency - debit_in_account_currency), 0) ' + 'END as outstanding_amount ' + 'FROM `tabGL Entry` WHERE (voucher_no=%s OR against_voucher=%s) ' + 'AND party_type IS NOT NULL ' + 'AND party_type != ""', + (name, name), as_dict=1 + ) + + outstanding_amount = res[0].get('outstanding_amount', 0) if res else 0 + + return outstanding_amount + + @frappe.whitelist() def get_reference_details(reference_doctype, reference_name, party_account_currency): total_amount = outstanding_amount = exchange_rate = None @@ -695,6 +713,13 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre total_amount = ref_doc.get("grand_total") exchange_rate = 1 outstanding_amount = ref_doc.get("outstanding_amount") + elif reference_doctype == "Journal Entry" and ref_doc.docstatus == 1: + total_amount = ref_doc.get("total_amount") + if ref_doc.multi_currency: + exchange_rate = get_exchange_rate(party_account_currency, company_currency, ref_doc.posting_date) + else: + exchange_rate = 1 + outstanding_amount = get_outstanding_on_journal_entry(reference_name) elif reference_doctype != "Journal Entry": if party_account_currency == company_currency: if ref_doc.doctype == "Expense Claim": diff --git a/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.json b/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.json index 531622d6ac5..b9e5c8d517e 100644 --- a/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.json +++ b/erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.json @@ -227,6 +227,36 @@ "search_index": 0, "set_only_once": 0, "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "clearance_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": "Clearance Date", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "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, + "unique": 0 } ], "has_web_view": 0, @@ -239,7 +269,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-07-24 17:25:03.765856", + "modified": "2018-03-07 18:34:39.552769", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice Payment", diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js index ccb5553bf5d..e5bcba498d1 100644 --- a/erpnext/accounts/page/pos/pos.js +++ b/erpnext/accounts/page/pos/pos.js @@ -394,7 +394,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ this.frm = {} this.frm.doc = this.doc this.set_transaction_defaults("Customer"); - this.frm.doc["allow_user_to_edit_rate"] = this.pos_profile_data["allow_user_to_edit_rate"] ? true : false, + this.frm.doc["allow_user_to_edit_rate"] = this.pos_profile_data["allow_user_to_edit_rate"] ? true : false; + this.frm.doc["allow_user_to_edit_discount"] = this.pos_profile_data["allow_user_to_edit_discount"] ? true : false; this.wrapper.html(frappe.render_template("pos", this.frm.doc)); this.make_search(); this.make_customer(); @@ -1257,6 +1258,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ $(this.wrapper).find('.selected-item').empty(); if(this.child_doc.length) { this.child_doc[0]["allow_user_to_edit_rate"] = this.pos_profile_data["allow_user_to_edit_rate"] ? true : false, + this.child_doc[0]["allow_user_to_edit_discount"] = this.pos_profile_data["allow_user_to_edit_discount"] ? true : false; this.selected_row = $(frappe.render_template("pos_selected_item", this.child_doc[0])) $(this.wrapper).find('.selected-item').html(this.selected_row) } @@ -1692,7 +1694,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ setInterval(function () { me.freeze_screen = false; me.sync_sales_invoice() - }, 60000) + }, 180000) }, sync_sales_invoice: function () { diff --git a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.js b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.js index 0f9fdd7c023..57fe4b05be4 100644 --- a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.js +++ b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.js @@ -28,5 +28,10 @@ frappe.query_reports["Bank Reconciliation Statement"] = { "default": frappe.datetime.get_today(), "reqd": 1 }, + { + "fieldname":"include_pos_transactions", + "label": __("Include POS Transactions"), + "fieldtype": "Check" + }, ] -} +} \ No newline at end of file diff --git a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py index 95b7ff7545f..eca59750d5b 100644 --- a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py +++ b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py @@ -138,7 +138,23 @@ def get_entries(filters): and ifnull(clearance_date, '4000-01-01') > %(report_date)s """, filters, as_dict=1) - return sorted(list(payment_entries)+list(journal_entries), + pos_entries = [] + if filters.include_pos_transactions: + pos_entries = frappe.db.sql(""" + select + "Sales Invoice Payment" as payment_document, sip.name as payment_entry, sip.amount as debit, + si.posting_date, si.debit_to as against_account, sip.clearance_date, + account.account_currency, 0 as credit + from `tabSales Invoice Payment` sip, `tabSales Invoice` si, `tabAccount` account + where + sip.account=%(account)s and si.docstatus=1 and sip.parent = si.name + and account.name = sip.account and si.posting_date <= %(report_date)s and + ifnull(sip.clearance_date, '4000-01-01') > %(report_date)s + order by + si.posting_date ASC, si.name DESC + """, filters, as_dict=1) + + return sorted(list(payment_entries)+list(journal_entries+list(pos_entries)), key=lambda k: k['posting_date'] or getdate(nowdate())) def get_amounts_not_reflected_in_system(filters): diff --git a/erpnext/config/crm.py b/erpnext/config/crm.py index e51275c260f..dd67005ecf6 100644 --- a/erpnext/config/crm.py +++ b/erpnext/config/crm.py @@ -126,6 +126,11 @@ def get_data(): "link": "Tree/Sales Person", "description": _("Manage Sales Person Tree."), }, + { + "type": "doctype", + "name": "Lead Source", + "description": _("Track Leads by Lead Source.") + }, ] }, { diff --git a/erpnext/config/selling.py b/erpnext/config/selling.py index fef902e32d1..b48cafc99ab 100644 --- a/erpnext/config/selling.py +++ b/erpnext/config/selling.py @@ -173,6 +173,11 @@ def get_data(): "name": "Industry Type", "description": _("Track Leads by Industry Type.") }, + { + "type": "doctype", + "name": "Lead Source", + "description": _("Track Leads by Lead Source.") + }, ] }, { diff --git a/erpnext/controllers/item_variant.py b/erpnext/controllers/item_variant.py index e8260d9e3d0..7749ac5f054 100644 --- a/erpnext/controllers/item_variant.py +++ b/erpnext/controllers/item_variant.py @@ -94,7 +94,10 @@ def validate_is_incremental(numeric_attribute, attribute, value, item): InvalidItemAttributeValueError, title=_('Invalid Attribute')) def validate_item_attribute_value(attributes_list, attribute, attribute_value, item): - if attribute_value not in attributes_list: + allow_rename_attribute_value = frappe.db.get_single_value('Item Variant Settings', 'allow_rename_attribute_value') + if allow_rename_attribute_value: + pass + elif attribute_value not in attributes_list: frappe.throw(_("Value {0} for Attribute {1} does not exist in the list of valid Item Attribute Values for Item {2}").format( attribute_value, attribute, item), InvalidItemAttributeValueError, title=_('Invalid Attribute')) diff --git a/erpnext/education/report/final_assessment_grades/final_assessment_grades.py b/erpnext/education/report/final_assessment_grades/final_assessment_grades.py index efc9aff083e..e6e0ba2ebc2 100644 --- a/erpnext/education/report/final_assessment_grades/final_assessment_grades.py +++ b/erpnext/education/report/final_assessment_grades/final_assessment_grades.py @@ -27,26 +27,27 @@ def execute(filters=None): 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"] + if student_details.get(student): + 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 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 + # 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) + data.append(student_row) course_list = [d for d in course_dict] columns = get_column(course_dict) diff --git a/erpnext/healthcare/doctype/consultation/consultation.js b/erpnext/healthcare/doctype/consultation/consultation.js index b0dbff5a554..dc4870fc633 100644 --- a/erpnext/healthcare/doctype/consultation/consultation.js +++ b/erpnext/healthcare/doctype/consultation/consultation.js @@ -15,23 +15,7 @@ frappe.ui.form.on('Consultation', { {fieldname: 'test_comment', columns: 4} ]; }, - onload: function(frm){ - if(frm.doc.patient){ - frappe.call({ - "method": "erpnext.healthcare.doctype.patient.patient.get_patient_detail", - args: { - patient: frm.doc.patient - }, - callback: function (data) { - var age = null; - if(data.message.dob){ - age = calculate_age(data.message.dob); - } - frappe.model.set_value(frm.doctype,frm.docname, "patient_age", age); - } - }); - } - }, + refresh: function(frm) { refresh_field('drug_prescription'); refresh_field('test_prescription'); diff --git a/erpnext/public/js/pos/pos.html b/erpnext/public/js/pos/pos.html index 1d9fd7c20f4..af90756963b 100644 --- a/erpnext/public/js/pos/pos.html +++ b/erpnext/public/js/pos/pos.html @@ -37,20 +37,22 @@