Fixed merge conflict
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 076baea..235b1b0 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -2,7 +2,7 @@
from __future__ import unicode_literals
import frappe
-__version__ = '8.0.37'
+__version__ = '8.0.38'
def get_default_company(user=None):
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index f32cfcd..6d88326 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -415,10 +415,10 @@
throw(_("Customer {0} does not belong to project {1}").format(self.customer,self.project))
def validate_pos(self):
- if flt(self.paid_amount) + flt(self.write_off_amount) \
- - flt(self.grand_total) > 1/(10**(self.precision("grand_total") + 1)) and self.is_return:
- frappe.throw(_("""Paid amount + Write Off Amount can not be greater than Grand Total"""))
-
+ if self.is_return:
+ if flt(self.paid_amount) + flt(self.write_off_amount) - flt(self.grand_total) < \
+ 1/(10**(self.precision("grand_total") + 1)):
+ frappe.throw(_("Paid amount + Write Off Amount can not be greater than Grand Total"))
def validate_item_code(self):
for d in self.get('items'):
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index f0c29bc..0501d38 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -7,10 +7,13 @@
import datetime
from frappe import _, msgprint, scrub
from frappe.defaults import get_user_permissions
-from frappe.utils import add_days, getdate, formatdate, get_first_day, date_diff, add_years, get_timestamp
+from frappe.utils import add_days, getdate, formatdate, get_first_day, date_diff, \
+ add_years, get_timestamp, nowdate
from frappe.geo.doctype.address.address import get_address_display, get_default_address
from frappe.email.doctype.contact.contact import get_contact_details, get_default_contact
from erpnext.exceptions import PartyFrozen, InvalidCurrency, PartyDisabled, InvalidAccountCurrency
+from erpnext.accounts.utils import get_fiscal_year
+from erpnext import get_default_currency
class DuplicatePartyAccountError(frappe.ValidationError): pass
@@ -359,4 +362,37 @@
timestamp = get_timestamp(date)
out.update({ timestamp: count })
- return out
\ No newline at end of file
+ return out
+
+def get_dashboard_info(party_type, party):
+ current_fiscal_year = get_fiscal_year(nowdate(), as_dict=True)
+ party_account_currency = get_party_account_currency(party_type, party, frappe.db.get_default("company"))
+ company_default_currency = get_default_currency()
+
+ if party_account_currency==company_default_currency:
+ total_field = "base_grand_total"
+ else:
+ total_field = "grand_total"
+
+ doctype = "Sales Invoice" if party_type=="Customer" else "Purchase Invoice"
+
+ billing_this_year = frappe.db.sql("""
+ select sum({0})
+ from `tab{1}`
+ where {2}=%s and docstatus=1 and posting_date between %s and %s
+ """.format(total_field, doctype, party_type.lower()),
+ (party, current_fiscal_year.year_start_date, current_fiscal_year.year_end_date))
+
+ total_unpaid = frappe.db.sql("""
+ select sum(debit_in_account_currency) - sum(credit_in_account_currency)
+ from `tabGL Entry`
+ where party_type = %s and party=%s""", (party_type, party))
+
+ info = {}
+ info["billing_this_year"] = billing_this_year[0][0] if billing_this_year else 0
+ info["currency"] = party_account_currency
+ info["total_unpaid"] = total_unpaid[0][0] if total_unpaid else 0
+ if party_type == "Supplier":
+ info["total_unpaid"] = -1 * info["total_unpaid"]
+
+ return info
\ No newline at end of file
diff --git a/erpnext/buying/doctype/supplier/supplier.py b/erpnext/buying/doctype/supplier/supplier.py
index 704e828..3b6ae62 100644
--- a/erpnext/buying/doctype/supplier/supplier.py
+++ b/erpnext/buying/doctype/supplier/supplier.py
@@ -6,11 +6,9 @@
import frappe.defaults
from frappe import msgprint, _
from frappe.model.naming import make_autoname
-from frappe.geo.address_and_contact import (load_address_and_contact,
- delete_contact_and_address)
-
+from frappe.geo.address_and_contact import load_address_and_contact, delete_contact_and_address
from erpnext.utilities.transaction_base import TransactionBase
-from erpnext.accounts.party import validate_party_accounts, get_timeline_data # keep this
+from erpnext.accounts.party import validate_party_accounts, get_dashboard_info, get_timeline_data # keep this
class Supplier(TransactionBase):
def get_feed(self):
@@ -22,22 +20,7 @@
self.load_dashboard_info()
def load_dashboard_info(self):
- billing_this_year = frappe.db.sql("""
- select sum(credit_in_account_currency) - sum(debit_in_account_currency)
- from `tabGL Entry`
- where voucher_type='Purchase Invoice' and party_type = 'Supplier'
- and party=%s and fiscal_year = %s""",
- (self.name, frappe.db.get_default("fiscal_year")))
-
- total_unpaid = frappe.db.sql("""select sum(outstanding_amount)
- from `tabPurchase Invoice`
- where supplier=%s and docstatus = 1""", self.name)
-
-
- info = {}
- info["billing_this_year"] = billing_this_year[0][0] if billing_this_year else 0
- info["total_unpaid"] = total_unpaid[0][0] if total_unpaid else 0
-
+ info = get_dashboard_info(self.doctype, self.name)
self.set_onload('dashboard_info', info)
def autoname(self):
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 0faf98e..fef0872 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -396,4 +396,5 @@
erpnext.patches.v8_0.rename_total_margin_to_rate_with_margin # 11-05-2017
erpnext.patches.v8_0.fix_status_for_invoices_with_negative_outstanding
erpnext.patches.v8_0.make_payments_table_blank_for_non_pos_invoice
-erpnext.patches.v8_0.set_sales_invoice_serial_number_from_delivery_note
\ No newline at end of file
+erpnext.patches.v8_0.set_sales_invoice_serial_number_from_delivery_note
+erpnext.patches.v8_0.delete_schools_depricated_doctypes
diff --git a/erpnext/patches/v7_2/update_assessment_modules.py b/erpnext/patches/v7_2/update_assessment_modules.py
index 9c00902..9075bbf 100644
--- a/erpnext/patches/v7_2/update_assessment_modules.py
+++ b/erpnext/patches/v7_2/update_assessment_modules.py
@@ -3,26 +3,32 @@
def execute():
#Rename Grading Structure to Grading Scale
- frappe.rename_doc("DocType", "Grading Structure", "Grading Scale", force=True)
- frappe.rename_doc("DocType", "Grade Interval", "Grading Scale Interval", force=True)
+ if not frappe.db.exists("DocType", "Grading Scale"):
+ frappe.rename_doc("DocType", "Grading Structure", "Grading Scale", force=True)
+ if not frappe.db.exists("DocType", "Grading Scale Interval"):
+ frappe.rename_doc("DocType", "Grade Interval", "Grading Scale Interval", force=True)
frappe.reload_doc("schools", "doctype", "grading_scale_interval")
- rename_field("Grading Scale Interval", "to_score", "threshold")
+ if "to_score" in frappe.db.get_table_columns("Grading Scale Interval"):
+ rename_field("Grading Scale Interval", "to_score", "threshold")
- frappe.rename_doc("DocType", "Assessment", "Assessment Plan", force=True)
+ if not frappe.db.exists("DocType", "Assessment Plan"):
+ frappe.rename_doc("DocType", "Assessment", "Assessment Plan", force=True)
#Rename Assessment Results
frappe.reload_doc("schools", "doctype", "assessment_plan")
- rename_field("Assessment Plan", "grading_structure", "grading_scale")
+ if "grading_structure" in frappe.db.get_table_columns("Assessment Plan"):
+ rename_field("Assessment Plan", "grading_structure", "grading_scale")
frappe.reload_doc("schools", "doctype", "assessment_result")
frappe.reload_doc("schools", "doctype", "assessment_result_detail")
frappe.reload_doc("schools", "doctype", "assessment_criteria")
- for assessment in frappe.get_all("Assessment Plan", fields=["name", "grading_scale"], filters = [["docstatus", "!=", 2 ]]):
- print assessment
- for stud_result in frappe.db.sql("select * from `tabAssessment Result` where parent= %s", assessment.name, as_dict=True):
+ for assessment in frappe.get_all("Assessment Plan",
+ fields=["name", "grading_scale"], filters = [["docstatus", "!=", 2 ]]):
+ for stud_result in frappe.db.sql("select * from `tabAssessment Result` where parent= %s",
+ assessment.name, as_dict=True):
if stud_result.result:
assessment_result = frappe.new_doc("Assessment Result")
assessment_result.student = stud_result.student
diff --git a/erpnext/patches/v8_0/delete_schools_depricated_doctypes.py b/erpnext/patches/v8_0/delete_schools_depricated_doctypes.py
new file mode 100644
index 0000000..09a78ed
--- /dev/null
+++ b/erpnext/patches/v8_0/delete_schools_depricated_doctypes.py
@@ -0,0 +1,14 @@
+# Copyright (c) 2017, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+ """ delete doctypes """
+
+ if frappe.db.exists("DocType", "Grading Structure"):
+ frappe.delete_doc("DocType", "Grading Structure", force=1)
+
+ if frappe.db.exists("DocType", "Grade Interval"):
+ frappe.delete_doc("DocType", "Grade Interval", force=1)
\ No newline at end of file
diff --git a/erpnext/public/js/pos/pos.html b/erpnext/public/js/pos/pos.html
index 181a41f..6065e60 100644
--- a/erpnext/public/js/pos/pos.html
+++ b/erpnext/public/js/pos/pos.html
@@ -68,12 +68,12 @@
</div>
<div class="col-xs-6 numeric_keypad hidden-xs" style="display:none">
- {% var chartData = [__("Qty"), __("Disc"), __("Price")] %} {% for(var i=0; i
+ {% var chartData = ["Qty", "Disc", "Price"] %} {% for(var i=0; i
<3; i++) { %} <div class="row text-right">
{% for(var j=i*3; j
<(i+1)*3; j++) { %} <button type="button" class="btn btn-default numeric-keypad" val="{{j+1}}">{{j+1}}</button>
{% } %}
- <button type="button" id="pos-item-{{ chartData[i].toLowerCase() }}" class="btn text-center btn-default numeric-keypad pos-operation">{{ chartData[i] }}</button>
+ <button type="button" id="pos-item-{{ chartData[i].toLowerCase() }}" class="btn text-center btn-default numeric-keypad pos-operation">{{ __(chartData[i]) }}</button>
</div>
{% } %}
<div class="row text-right">
@@ -120,8 +120,8 @@
<div class="cell search-item"></div>
</div>
<div class="app-listing item-list image-view-container">
-
+
</div>
</div>
</div>
-</div>
\ No newline at end of file
+</div>
diff --git a/erpnext/schools/doctype/grade_interval/__init__.py b/erpnext/schools/doctype/grade_interval/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/schools/doctype/grade_interval/__init__.py
+++ /dev/null
diff --git a/erpnext/schools/doctype/grade_interval/grade_interval.json b/erpnext/schools/doctype/grade_interval/grade_interval.json
deleted file mode 100644
index c9c5949..0000000
--- a/erpnext/schools/doctype/grade_interval/grade_interval.json
+++ /dev/null
@@ -1,122 +0,0 @@
-{
- "allow_copy": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2016-08-26 03:11:09.591049",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "grade_code",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Grade Code",
- "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,
- "unique": 0
- },
- {
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "min_score",
- "fieldtype": "Percent",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Min Score",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "1",
- "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,
- "unique": 0
- },
- {
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "grade_description",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Grade Description",
- "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
- }
- ],
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "in_dialog": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2016-12-14 12:54:56.902465",
- "modified_by": "Administrator",
- "module": "Schools",
- "name": "Grade Interval",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/schools/doctype/grade_interval/grade_interval.py b/erpnext/schools/doctype/grade_interval/grade_interval.py
deleted file mode 100644
index c8ded13..0000000
--- a/erpnext/schools/doctype/grade_interval/grade_interval.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.document import Document
-
-class GradeInterval(Document):
- def validate(self):
- pass
\ No newline at end of file
diff --git a/erpnext/schools/doctype/grading_structure/__init__.py b/erpnext/schools/doctype/grading_structure/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/schools/doctype/grading_structure/__init__.py
+++ /dev/null
diff --git a/erpnext/schools/doctype/grading_structure/grading_structure.js b/erpnext/schools/doctype/grading_structure/grading_structure.js
deleted file mode 100644
index 36f4504..0000000
--- a/erpnext/schools/doctype/grading_structure/grading_structure.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Grading Structure', {
- refresh: function(frm) {
-
- }
-});
diff --git a/erpnext/schools/doctype/grading_structure/grading_structure.json b/erpnext/schools/doctype/grading_structure/grading_structure.json
deleted file mode 100644
index 3c30f29..0000000
--- a/erpnext/schools/doctype/grading_structure/grading_structure.json
+++ /dev/null
@@ -1,202 +0,0 @@
-{
- "allow_copy": 0,
- "allow_import": 0,
- "allow_rename": 1,
- "autoname": "field:grading_system_name",
- "beta": 0,
- "creation": "2016-08-26 03:06:53.922972",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "grading_system_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Grading System Name",
- "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,
- "unique": 0
- },
- {
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_2",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 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_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "description",
- "fieldtype": "Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Description",
- "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_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "grading_intervals_section",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Grading Intervals",
- "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_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "grade_intervals",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Grade Intervals",
- "length": 0,
- "no_copy": 0,
- "options": "Grade Interval",
- "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,
- "unique": 0
- }
- ],
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "in_dialog": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2016-12-14 12:35:39.690256",
- "modified_by": "Administrator",
- "module": "Schools",
- "name": "Grading Structure",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "is_custom": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Academics User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "grading_system_name",
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/schools/doctype/grading_structure/grading_structure.py b/erpnext/schools/doctype/grading_structure/grading_structure.py
deleted file mode 100644
index 1b5d6a8..0000000
--- a/erpnext/schools/doctype/grading_structure/grading_structure.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.document import Document
-from frappe import _
-from frappe.utils import cstr
-
-class GradingStructure(Document):
- def validate(self):
- grade_intervals = self.get("grade_intervals")
- check_overlap(grade_intervals, self)
-
-#Check if any of the grade intervals for this grading structure overlap
-def check_overlap(grade_intervals, parent_doc):
- for interval1 in grade_intervals:
- for interval2 in grade_intervals:
- if interval1.name == interval2.name:
- pass
- else:
- if (interval1.from_score <= interval2.from_score and interval1.to_score >= interval2.from_score) or (interval1.from_score <= interval2.to_score and interval1.to_score >= interval2.to_score):
- frappe.throw(_("""The intervals for Grade Code {0} overlaps with the grade intervals for other grades.
- Please check intervals {0} and {1} and try again""".format(interval1.grade_code, interval2.grade_code)))
\ No newline at end of file
diff --git a/erpnext/schools/doctype/grading_structure/test_grading_structure.py b/erpnext/schools/doctype/grading_structure/test_grading_structure.py
deleted file mode 100644
index 0e36080..0000000
--- a/erpnext/schools/doctype/grading_structure/test_grading_structure.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-from __future__ import unicode_literals
-
-import frappe
-import unittest
-
-# test_records = frappe.get_test_records('Grading Structure')
-
-class TestGradingStructure(unittest.TestCase):
- pass
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index e4101af..c0b3b84 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -10,8 +10,7 @@
from frappe.desk.reportview import build_match_conditions
from erpnext.utilities.transaction_base import TransactionBase
from frappe.geo.address_and_contact import load_address_and_contact, delete_contact_and_address
-from erpnext.accounts.party import validate_party_accounts, get_timeline_data # keep this
-from erpnext import get_default_currency
+from erpnext.accounts.party import validate_party_accounts, get_dashboard_info, get_timeline_data # keep this
class Customer(TransactionBase):
def get_feed(self):
@@ -23,25 +22,9 @@
self.load_dashboard_info()
def load_dashboard_info(self):
- billing_this_year = frappe.db.sql("""
- select sum(debit_in_account_currency) - sum(credit_in_account_currency), account_currency
- from `tabGL Entry`
- where voucher_type='Sales Invoice' and party_type = 'Customer'
- and party=%s and fiscal_year = %s""",
- (self.name, frappe.db.get_default("fiscal_year")))
-
- total_unpaid = frappe.db.sql("""select sum(outstanding_amount)
- from `tabSales Invoice`
- where customer=%s and docstatus = 1""", self.name)
-
- info = {}
- info["billing_this_year"] = billing_this_year[0][0] if billing_this_year else 0
- info["currency"] = billing_this_year[0][1] if billing_this_year else get_default_currency()
- info["total_unpaid"] = total_unpaid[0][0] if total_unpaid else 0
-
+ info = get_dashboard_info(self.doctype, self.name)
self.set_onload('dashboard_info', info)
-
def autoname(self):
cust_master_name = frappe.defaults.get_global_default('cust_master_name')
if cust_master_name == 'Customer Name':
diff --git a/erpnext/setup/utils.py b/erpnext/setup/utils.py
index 55a0fd3..46e4d5c 100644
--- a/erpnext/setup/utils.py
+++ b/erpnext/setup/utils.py
@@ -91,8 +91,7 @@
response.raise_for_status()
value = response.json()["rates"][to_currency]
cache.setex(key, value, 6 * 60 * 60)
-
return flt(value)
except:
- frappe.msgprint(_("Unable to find exchange rate for {0} to {1} for key date {2}").format(from_currency, to_currency, transaction_date))
+ frappe.msgprint(_("Unable to find exchange rate for {0} to {1} for key date {2}. Please create a Currency Exchange record manually").format(from_currency, to_currency, transaction_date))
return 0.0
\ No newline at end of file
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index 057c78a..86c6959 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -44,8 +44,6 @@
}, __("View"));
}
- // make sensitive fields(has_serial_no, is_stock_item, valuation_method)
- // read only if any stock ledger entry exists
if(!frm.doc.is_fixed_asset) {
erpnext.item.make_dashboard(frm);
}
@@ -77,6 +75,8 @@
erpnext.item.edit_prices_button(frm);
+ // make sensitive fields(has_serial_no, is_stock_item, valuation_method, has_batch_no)
+ // read only if any stock ledger entry exists
if (!frm.doc.__islocal && frm.doc.is_stock_item) {
frm.toggle_enable(['has_serial_no', 'is_stock_item', 'valuation_method', 'has_batch_no'],
(frm.doc.__onload && frm.doc.__onload.sle_exists=="exists") ? false : true);
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 055b9c4..c11965e 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -74,7 +74,8 @@
"Purchase Order Item": {
"ref_dn_field": "purchase_order_item",
"compare_fields": [["project", "="], ["uom", "="], ["item_code", "="]],
- "is_child_table": True
+ "is_child_table": True,
+ "allow_duplicate_prev_row_id": True
}
})
diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.py b/erpnext/stock/doctype/stock_settings/stock_settings.py
index 68d64a2..d9d9568 100644
--- a/erpnext/stock/doctype/stock_settings/stock_settings.py
+++ b/erpnext/stock/doctype/stock_settings/stock_settings.py
@@ -26,3 +26,19 @@
# show/hide barcode field
frappe.make_property_setter({'fieldname': 'barcode', 'property': 'hidden',
'value': 0 if self.show_barcode_field else 1})
+
+ self.cant_change_valuation_method()
+
+ def cant_change_valuation_method(self):
+ db_valuation_method = frappe.db.get_single_value("Stock Settings", "valuation_method")
+
+ if db_valuation_method and db_valuation_method != self.valuation_method:
+ # check if there are any stock ledger entries against items
+ # which does not have it's own valuation method
+ sle = frappe.db.sql("""select name from `tabStock Ledger Entry` sle
+ where exists(select name from tabItem
+ where name=sle.item_code and (valuation_method is null or valuation_method=''))
+ """)
+
+ if sle:
+ frappe.throw(_("Can't change valuation method, as there are transactions against some items which does not have it's own valuation method"))
\ No newline at end of file