Merge branch 'develop' into email-camp-end-date
diff --git a/erpnext/accounts/doctype/account_subtype/account_subtype.json b/erpnext/accounts/doctype/account_subtype/account_subtype.json
deleted file mode 100644
index 6b1f2a2..0000000
--- a/erpnext/accounts/doctype/account_subtype/account_subtype.json
+++ /dev/null
@@ -1,134 +0,0 @@
-{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "field:account_subtype",
- "beta": 0,
- "creation": "2018-10-25 15:46:08.054586",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "account_subtype",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Account Subtype",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 1
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-10-25 15:47:03.841390",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "Account Subtype",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- },
- {
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Accounts Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- },
- {
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Accounts User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/account_type/account_type.js b/erpnext/accounts/doctype/account_type/account_type.js
deleted file mode 100644
index 858b56c..0000000
--- a/erpnext/accounts/doctype/account_type/account_type.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Account Type', {
- refresh: function() {
-
- }
-});
diff --git a/erpnext/accounts/doctype/account_type/account_type.json b/erpnext/accounts/doctype/account_type/account_type.json
deleted file mode 100644
index 6b8f724..0000000
--- a/erpnext/accounts/doctype/account_type/account_type.json
+++ /dev/null
@@ -1,134 +0,0 @@
-{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "field:account_type",
- "beta": 0,
- "creation": "2018-10-25 15:45:45.789963",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "account_type",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Account Type",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 1
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-10-25 15:46:51.042604",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "Account Type",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- },
- {
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Accounts Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- },
- {
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Accounts User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
-}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/account_type/test_account_type.js b/erpnext/accounts/doctype/account_type/test_account_type.js
deleted file mode 100644
index 76e434f..0000000
--- a/erpnext/accounts/doctype/account_type/test_account_type.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Account Type", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(1);
-
- frappe.run_serially([
- // insert a new Account Type
- () => frappe.tests.make('Account Type', [
- // values to be set
- {key: 'value'}
- ]),
- () => {
- assert.equal(cur_frm.doc.key, 'value');
- },
- () => done()
- ]);
-
-});
diff --git a/erpnext/accounts/doctype/account_type/test_account_type.py b/erpnext/accounts/doctype/account_type/test_account_type.py
deleted file mode 100644
index 824c2f6..0000000
--- a/erpnext/accounts/doctype/account_type/test_account_type.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-from __future__ import unicode_literals
-
-import unittest
-
-class TestAccountType(unittest.TestCase):
- pass
diff --git a/erpnext/accounts/doctype/bank_account/bank_account.json b/erpnext/accounts/doctype/bank_account/bank_account.json
index aa9c434..65a0a51 100644
--- a/erpnext/accounts/doctype/bank_account/bank_account.json
+++ b/erpnext/accounts/doctype/bank_account/bank_account.json
@@ -64,13 +64,13 @@
"fieldname": "account_type",
"fieldtype": "Link",
"label": "Account Type",
- "options": "Account Type"
+ "options": "Bank Account Type"
},
{
"fieldname": "account_subtype",
"fieldtype": "Link",
"label": "Account Subtype",
- "options": "Account Subtype"
+ "options": "Bank Account Subtype"
},
{
"fieldname": "column_break_7",
@@ -200,7 +200,7 @@
}
],
"links": [],
- "modified": "2020-01-30 20:42:26.458316",
+ "modified": "2020-04-06 21:00:45.379804",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Account",
diff --git a/erpnext/accounts/doctype/account_subtype/__init__.py b/erpnext/accounts/doctype/bank_account_subtype/__init__.py
similarity index 100%
rename from erpnext/accounts/doctype/account_subtype/__init__.py
rename to erpnext/accounts/doctype/bank_account_subtype/__init__.py
diff --git a/erpnext/accounts/doctype/account_subtype/account_subtype.js b/erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.js
similarity index 77%
rename from erpnext/accounts/doctype/account_subtype/account_subtype.js
rename to erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.js
index 30144ad..f045665 100644
--- a/erpnext/accounts/doctype/account_subtype/account_subtype.js
+++ b/erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.js
@@ -1,7 +1,7 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
-frappe.ui.form.on('Account Subtype', {
+frappe.ui.form.on('Bank Account Subtype', {
refresh: function() {
}
diff --git a/erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.json b/erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.json
new file mode 100644
index 0000000..f875db8
--- /dev/null
+++ b/erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.json
@@ -0,0 +1,134 @@
+{
+ "allow_copy": 0,
+ "allow_events_in_timeline": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:account_subtype",
+ "beta": 0,
+ "creation": "2018-10-25 15:46:08.054586",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "fields": [
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "account_subtype",
+ "fieldtype": "Data",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Account Subtype",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 1
+ }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2018-10-25 15:47:03.841390",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Bank Account Subtype",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "amend": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ },
+ {
+ "amend": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ },
+ {
+ "amend": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts User",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 0,
+ "track_seen": 0,
+ "track_views": 0
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/account_subtype/account_subtype.py b/erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.py
similarity index 86%
rename from erpnext/accounts/doctype/account_subtype/account_subtype.py
rename to erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.py
index 46c45cc..ab52c4a 100644
--- a/erpnext/accounts/doctype/account_subtype/account_subtype.py
+++ b/erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.py
@@ -5,5 +5,5 @@
from __future__ import unicode_literals
from frappe.model.document import Document
-class AccountSubtype(Document):
+class BankAccountSubtype(Document):
pass
diff --git a/erpnext/accounts/doctype/account_subtype/test_account_subtype.js b/erpnext/accounts/doctype/bank_account_subtype/test_bank_account_subtype.js
similarity index 69%
rename from erpnext/accounts/doctype/account_subtype/test_account_subtype.js
rename to erpnext/accounts/doctype/bank_account_subtype/test_bank_account_subtype.js
index 5646763..f599998 100644
--- a/erpnext/accounts/doctype/account_subtype/test_account_subtype.js
+++ b/erpnext/accounts/doctype/bank_account_subtype/test_bank_account_subtype.js
@@ -2,15 +2,15 @@
// rename this file from _test_[name] to test_[name] to activate
// and remove above this line
-QUnit.test("test: Account Subtype", function (assert) {
+QUnit.test("test: Bank Account Subtype", function (assert) {
let done = assert.async();
// number of asserts
assert.expect(1);
frappe.run_serially([
- // insert a new Account Subtype
- () => frappe.tests.make('Account Subtype', [
+ // insert a new Bank Account Subtype
+ () => frappe.tests.make('Bank Account Subtype', [
// values to be set
{key: 'value'}
]),
diff --git a/erpnext/accounts/doctype/account_subtype/test_account_subtype.py b/erpnext/accounts/doctype/bank_account_subtype/test_bank_account_subtype.py
similarity index 77%
rename from erpnext/accounts/doctype/account_subtype/test_account_subtype.py
rename to erpnext/accounts/doctype/bank_account_subtype/test_bank_account_subtype.py
index c37b5b9..ca3addc 100644
--- a/erpnext/accounts/doctype/account_subtype/test_account_subtype.py
+++ b/erpnext/accounts/doctype/bank_account_subtype/test_bank_account_subtype.py
@@ -5,5 +5,5 @@
import unittest
-class TestAccountSubtype(unittest.TestCase):
+class TestBankAccountSubtype(unittest.TestCase):
pass
diff --git a/erpnext/accounts/doctype/account_type/__init__.py b/erpnext/accounts/doctype/bank_account_type/__init__.py
similarity index 100%
rename from erpnext/accounts/doctype/account_type/__init__.py
rename to erpnext/accounts/doctype/bank_account_type/__init__.py
diff --git a/erpnext/accounts/doctype/bank_account_type/bank_account_type.js b/erpnext/accounts/doctype/bank_account_type/bank_account_type.js
new file mode 100644
index 0000000..4cfabe3
--- /dev/null
+++ b/erpnext/accounts/doctype/bank_account_type/bank_account_type.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Bank Account Type', {
+ // refresh: function(frm) {
+
+ // }
+});
diff --git a/erpnext/accounts/doctype/bank_account_type/bank_account_type.json b/erpnext/accounts/doctype/bank_account_type/bank_account_type.json
new file mode 100644
index 0000000..5a297cc
--- /dev/null
+++ b/erpnext/accounts/doctype/bank_account_type/bank_account_type.json
@@ -0,0 +1,68 @@
+{
+ "actions": [],
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:account_type",
+ "creation": "2018-10-25 15:45:45.789963",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "account_type"
+ ],
+ "fields": [
+ {
+ "fieldname": "account_type",
+ "fieldtype": "Data",
+ "label": "Account Type",
+ "unique": 1
+ }
+ ],
+ "links": [],
+ "modified": "2020-04-10 21:13:09.137898",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Bank Account Type",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts Manager",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts User",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC"
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/account_type/account_type.py b/erpnext/accounts/doctype/bank_account_type/bank_account_type.py
similarity index 60%
rename from erpnext/accounts/doctype/account_type/account_type.py
rename to erpnext/accounts/doctype/bank_account_type/bank_account_type.py
index 3e64293..b7dc0e0 100644
--- a/erpnext/accounts/doctype/account_type/account_type.py
+++ b/erpnext/accounts/doctype/bank_account_type/bank_account_type.py
@@ -1,9 +1,10 @@
# -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
+# Copyright (c) 2020, 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 AccountType(Document):
+class BankAccountType(Document):
pass
diff --git a/erpnext/accounts/doctype/bank_account_type/test_bank_account_type.py b/erpnext/accounts/doctype/bank_account_type/test_bank_account_type.py
new file mode 100644
index 0000000..f04725a
--- /dev/null
+++ b/erpnext/accounts/doctype/bank_account_type/test_bank_account_type.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestBankAccountType(unittest.TestCase):
+ pass
diff --git a/erpnext/accounts/doctype/budget/budget.py b/erpnext/accounts/doctype/budget/budget.py
index 084514c..d93b6ff 100644
--- a/erpnext/accounts/doctype/budget/budget.py
+++ b/erpnext/accounts/doctype/budget/budget.py
@@ -9,6 +9,7 @@
from frappe.model.naming import make_autoname
from erpnext.accounts.utils import get_fiscal_year
from frappe.model.document import Document
+from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
class BudgetError(frappe.ValidationError): pass
class DuplicateBudgetError(frappe.ValidationError): pass
@@ -98,30 +99,32 @@
if not (args.get('account') and args.get('cost_center')) and args.item_code:
args.cost_center, args.account = get_item_details(args)
- if not (args.cost_center or args.project) and not args.account:
+ if not args.account:
return
- for budget_against in ['project', 'cost_center']:
+ for budget_against in ['project', 'cost_center'] + get_accounting_dimensions():
if (args.get(budget_against) and args.account
and frappe.db.get_value("Account", {"name": args.account, "root_type": "Expense"})):
- if args.project and budget_against == 'project':
- condition = "and b.project=%s" % frappe.db.escape(args.project)
- args.budget_against_field = "Project"
+ doctype = frappe.unscrub(budget_against)
- elif args.cost_center and budget_against == 'cost_center':
- cc_lft, cc_rgt = frappe.db.get_value("Cost Center", args.cost_center, ["lft", "rgt"])
- condition = """and exists(select name from `tabCost Center`
- where lft<=%s and rgt>=%s and name=b.cost_center)""" % (cc_lft, cc_rgt)
- args.budget_against_field = "Cost Center"
+ if frappe.get_cached_value('DocType', doctype, 'is_tree'):
+ lft, rgt = frappe.db.get_value(doctype, args.get(budget_against), ["lft", "rgt"])
+ condition = """and exists(select name from `tab%s`
+ where lft<=%s and rgt>=%s and name=b.%s)""" % (doctype, lft, rgt, budget_against) #nosec
+ args.is_tree = True
+ else:
+ condition = "and b.%s=%s" % (budget_against, frappe.db.escape(args.get(budget_against)))
+ args.is_tree = False
- args.budget_against = args.get(budget_against)
+ args.budget_against_field = budget_against
+ args.budget_against_doctype = doctype
budget_records = frappe.db.sql("""
select
b.{budget_against_field} as budget_against, ba.budget_amount, b.monthly_distribution,
ifnull(b.applicable_on_material_request, 0) as for_material_request,
- ifnull(applicable_on_purchase_order,0) as for_purchase_order,
+ ifnull(applicable_on_purchase_order, 0) as for_purchase_order,
ifnull(applicable_on_booking_actual_expenses,0) as for_actual_expenses,
b.action_if_annual_budget_exceeded, b.action_if_accumulated_monthly_budget_exceeded,
b.action_if_annual_budget_exceeded_on_mr, b.action_if_accumulated_monthly_budget_exceeded_on_mr,
@@ -132,9 +135,7 @@
b.name=ba.parent and b.fiscal_year=%s
and ba.account=%s and b.docstatus=1
{condition}
- """.format(condition=condition,
- budget_against_field=frappe.scrub(args.get("budget_against_field"))),
- (args.fiscal_year, args.account), as_dict=True)
+ """.format(condition=condition, budget_against_field=budget_against), (args.fiscal_year, args.account), as_dict=True) #nosec
if budget_records:
validate_budget_records(args, budget_records)
@@ -230,10 +231,10 @@
def get_other_condition(args, budget, for_doc):
condition = "expense_account = '%s'" % (args.expense_account)
- budget_against_field = frappe.scrub(args.get("budget_against_field"))
+ budget_against_field = args.get("budget_against_field")
if budget_against_field and args.get(budget_against_field):
- condition += " and child.%s = '%s'" %(budget_against_field, args.get(budget_against_field))
+ condition += " and child.%s = '%s'" % (budget_against_field, args.get(budget_against_field))
if args.get('fiscal_year'):
date_field = 'schedule_date' if for_doc == 'Material Request' else 'transaction_date'
@@ -246,19 +247,30 @@
return condition
def get_actual_expense(args):
+ if not args.budget_against_doctype:
+ args.budget_against_doctype = frappe.unscrub(args.budget_against_field)
+
+ budget_against_field = args.get('budget_against_field')
condition1 = " and gle.posting_date <= %(month_end_date)s" \
if args.get("month_end_date") else ""
- if args.budget_against_field == "Cost Center":
- lft_rgt = frappe.db.get_value(args.budget_against_field,
- args.budget_against, ["lft", "rgt"], as_dict=1)
+
+ if args.is_tree:
+ lft_rgt = frappe.db.get_value(args.budget_against_doctype,
+ args.get(budget_against_field), ["lft", "rgt"], as_dict=1)
+
args.update(lft_rgt)
- condition2 = """and exists(select name from `tabCost Center`
- where lft>=%(lft)s and rgt<=%(rgt)s and name=gle.cost_center)"""
- elif args.budget_against_field == "Project":
- condition2 = "and exists(select name from `tabProject` where name=gle.project and gle.project = %(budget_against)s)"
+ condition2 = """and exists(select name from `tab{doctype}`
+ where lft>=%(lft)s and rgt<=%(rgt)s
+ and name=gle.{budget_against_field})""".format(doctype=args.budget_against_doctype, #nosec
+ budget_against_field=budget_against_field)
+ else:
+ condition2 = """and exists(select name from `tab{doctype}`
+ where name=gle.{budget_against} and
+ gle.{budget_against} = %({budget_against})s)""".format(doctype=args.budget_against_doctype,
+ budget_against = budget_against_field)
- return flt(frappe.db.sql("""
+ amount = flt(frappe.db.sql("""
select sum(gle.debit) - sum(gle.credit)
from `tabGL Entry` gle
where gle.account=%(account)s
@@ -267,7 +279,9 @@
and gle.company=%(company)s
and gle.docstatus=1
{condition2}
- """.format(condition1=condition1, condition2=condition2), (args))[0][0])
+ """.format(condition1=condition1, condition2=condition2), (args))[0][0]) #nosec
+
+ return amount
def get_accumulated_monthly_budget(monthly_distribution, posting_date, fiscal_year, annual_budget):
distribution = {}
diff --git a/erpnext/accounts/doctype/budget/test_budget.py b/erpnext/accounts/doctype/budget/test_budget.py
index 33aefd6..9c19791 100644
--- a/erpnext/accounts/doctype/budget/test_budget.py
+++ b/erpnext/accounts/doctype/budget/test_budget.py
@@ -13,7 +13,7 @@
class TestBudget(unittest.TestCase):
def test_monthly_budget_crossed_ignore(self):
- set_total_expense_zero("2013-02-28", "Cost Center")
+ set_total_expense_zero("2013-02-28", "cost_center")
budget = make_budget(budget_against="Cost Center")
@@ -26,7 +26,7 @@
budget.cancel()
def test_monthly_budget_crossed_stop1(self):
- set_total_expense_zero("2013-02-28", "Cost Center")
+ set_total_expense_zero("2013-02-28", "cost_center")
budget = make_budget(budget_against="Cost Center")
@@ -41,7 +41,7 @@
budget.cancel()
def test_exception_approver_role(self):
- set_total_expense_zero("2013-02-28", "Cost Center")
+ set_total_expense_zero("2013-02-28", "cost_center")
budget = make_budget(budget_against="Cost Center")
@@ -114,7 +114,7 @@
budget.cancel()
def test_monthly_budget_crossed_stop2(self):
- set_total_expense_zero("2013-02-28", "Project")
+ set_total_expense_zero("2013-02-28", "project")
budget = make_budget(budget_against="Project")
@@ -129,7 +129,7 @@
budget.cancel()
def test_yearly_budget_crossed_stop1(self):
- set_total_expense_zero("2013-02-28", "Cost Center")
+ set_total_expense_zero("2013-02-28", "cost_center")
budget = make_budget(budget_against="Cost Center")
@@ -141,7 +141,7 @@
budget.cancel()
def test_yearly_budget_crossed_stop2(self):
- set_total_expense_zero("2013-02-28", "Project")
+ set_total_expense_zero("2013-02-28", "project")
budget = make_budget(budget_against="Project")
@@ -153,7 +153,7 @@
budget.cancel()
def test_monthly_budget_on_cancellation1(self):
- set_total_expense_zero("2013-02-28", "Cost Center")
+ set_total_expense_zero("2013-02-28", "cost_center")
budget = make_budget(budget_against="Cost Center")
@@ -177,7 +177,7 @@
budget.cancel()
def test_monthly_budget_on_cancellation2(self):
- set_total_expense_zero("2013-02-28", "Project")
+ set_total_expense_zero("2013-02-28", "project")
budget = make_budget(budget_against="Project")
@@ -201,8 +201,8 @@
budget.cancel()
def test_monthly_budget_against_group_cost_center(self):
- set_total_expense_zero("2013-02-28", "Cost Center")
- set_total_expense_zero("2013-02-28", "Cost Center", "_Test Cost Center 2 - _TC")
+ set_total_expense_zero("2013-02-28", "cost_center")
+ set_total_expense_zero("2013-02-28", "cost_center", "_Test Cost Center 2 - _TC")
budget = make_budget(budget_against="Cost Center", cost_center="_Test Company - _TC")
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
@@ -241,25 +241,30 @@
def set_total_expense_zero(posting_date, budget_against_field=None, budget_against_CC=None):
- if budget_against_field == "Project":
+ if budget_against_field == "project":
budget_against = "_Test Project"
else:
budget_against = budget_against_CC or "_Test Cost Center - _TC"
- existing_expense = get_actual_expense(frappe._dict({
+
+ args = frappe._dict({
"account": "_Test Account Cost for Goods Sold - _TC",
"cost_center": "_Test Cost Center - _TC",
"monthly_end_date": posting_date,
"company": "_Test Company",
"fiscal_year": "_Test Fiscal Year 2013",
"budget_against_field": budget_against_field,
- "budget_against": budget_against
- }))
+ })
+
+ if not args.get(budget_against_field):
+ args[budget_against_field] = budget_against
+
+ existing_expense = get_actual_expense(args)
if existing_expense:
- if budget_against_field == "Cost Center":
+ if budget_against_field == "cost_center":
make_journal_entry("_Test Account Cost for Goods Sold - _TC",
"_Test Bank - _TC", -existing_expense, "_Test Cost Center - _TC", posting_date="2013-02-28", submit=True)
- elif budget_against_field == "Project":
+ elif budget_against_field == "project":
make_journal_entry("_Test Account Cost for Goods Sold - _TC",
"_Test Bank - _TC", -existing_expense, "_Test Cost Center - _TC", submit=True, project="_Test Project", posting_date="2013-02-28")
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index 2b21ee8..90ba8b3 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -46,6 +46,7 @@
set_default_income_account_for_item(self)
self.set_customer_address()
self.validate_for_duplicate_items()
+ self.validate_target_warehouse()
def set_missing_values(self, for_validate=False):
@@ -403,6 +404,14 @@
else:
chk_dupl_itm.append(f)
+ def validate_target_warehouse(self):
+ items = self.get("items") + (self.get("packed_items") or [])
+
+ for d in items:
+ if d.get("target_warehouse") and d.get("warehouse") == d.get("target_warehouse"):
+ warehouse = frappe.bold(d.get("target_warehouse"))
+ frappe.throw(_("Row {0}: Delivery Warehouse ({1}) and Customer Warehouse ({2}) can not be same")
+ .format(d.idx, warehouse, warehouse))
def validate_items(self):
# validate items to see if they have is_sales_item enabled
diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py
index 7083950..b4a5bd1 100644
--- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py
+++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py
@@ -67,11 +67,11 @@
frappe.throw(_("Please setup a default bank account for company {0}").format(company))
for account in response["accounts"]:
- acc_type = frappe.db.get_value("Account Type", account["type"])
+ acc_type = frappe.db.get_value("Bank Account Type", account["type"])
if not acc_type:
add_account_type(account["type"])
- acc_subtype = frappe.db.get_value("Account Subtype", account["subtype"])
+ acc_subtype = frappe.db.get_value("Bank Account Subtype", account["subtype"])
if not acc_subtype:
add_account_subtype(account["subtype"])
@@ -106,7 +106,7 @@
def add_account_type(account_type):
try:
frappe.get_doc({
- "doctype": "Account Type",
+ "doctype": "Bank Account Type",
"account_type": account_type
}).insert()
except Exception:
@@ -116,7 +116,7 @@
def add_account_subtype(account_subtype):
try:
frappe.get_doc({
- "doctype": "Account Subtype",
+ "doctype": "Bank Account Subtype",
"account_subtype": account_subtype
}).insert()
except Exception:
diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/test_plaid_settings.py b/erpnext/erpnext_integrations/doctype/plaid_settings/test_plaid_settings.py
index 29e8fa4..1a063d6 100644
--- a/erpnext/erpnext_integrations/doctype/plaid_settings/test_plaid_settings.py
+++ b/erpnext/erpnext_integrations/doctype/plaid_settings/test_plaid_settings.py
@@ -23,11 +23,11 @@
for ba in frappe.get_all("Bank Account"):
frappe.get_doc("Bank Account", ba.name).delete()
- for at in frappe.get_all("Account Type"):
- frappe.get_doc("Account Type", at.name).delete()
+ for at in frappe.get_all("Bank Account Type"):
+ frappe.get_doc("Bank Account Type", at.name).delete()
- for ast in frappe.get_all("Account Subtype"):
- frappe.get_doc("Account Subtype", ast.name).delete()
+ for ast in frappe.get_all("Bank Account Subtype"):
+ frappe.get_doc("Bank Account Subtype", ast.name).delete()
def test_plaid_disabled(self):
frappe.db.set_value("Plaid Settings", None, "enabled", 0)
@@ -35,11 +35,11 @@
def test_add_account_type(self):
add_account_type("brokerage")
- self.assertEqual(frappe.get_doc("Account Type", "brokerage").name, "brokerage")
+ self.assertEqual(frappe.get_doc("Bank Account Type", "brokerage").name, "brokerage")
def test_add_account_subtype(self):
add_account_subtype("loan")
- self.assertEqual(frappe.get_doc("Account Subtype", "loan").name, "loan")
+ self.assertEqual(frappe.get_doc("Bank Account Subtype", "loan").name, "loan")
def test_default_bank_account(self):
if not frappe.db.exists("Bank", "Citi"):
diff --git a/erpnext/loan_management/doctype/loan_application/loan_application.js b/erpnext/loan_management/doctype/loan_application/loan_application.js
index aba5f42..6cf47bf 100644
--- a/erpnext/loan_management/doctype/loan_application/loan_application.js
+++ b/erpnext/loan_management/doctype/loan_application/loan_application.js
@@ -31,7 +31,7 @@
add_toolbar_buttons: function(frm) {
if (frm.doc.status == "Approved") {
- if (frm.doc.is_secured) {
+ if (frm.doc.is_secured_loan) {
frappe.db.get_value("Loan Security Pledge", {"loan_application": frm.doc.name, "docstatus": 1}, "name", (r) => {
if (!r) {
frm.add_custom_button(__('Loan Security Pledge'), function() {
diff --git a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py
index b405cca..eb61358 100644
--- a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py
+++ b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py
@@ -30,7 +30,8 @@
if not pledge.qty and not pledge.amount:
frappe.throw(_("Qty or Amount is mandatroy for loan security"))
- pledge.loan_security_price = get_loan_security_price(pledge.loan_security)
+ if not (self.loan_application and pledge.loan_security_price):
+ pledge.loan_security_price = get_loan_security_price(pledge.loan_security)
if not pledge.qty:
pledge.qty = cint(pledge.amount/pledge.loan_security_price)
diff --git a/erpnext/loan_management/doctype/loan_security_price/loan_security_price.py b/erpnext/loan_management/doctype/loan_security_price/loan_security_price.py
index 2855b52..32d81af 100644
--- a/erpnext/loan_management/doctype/loan_security_price/loan_security_price.py
+++ b/erpnext/loan_management/doctype/loan_security_price/loan_security_price.py
@@ -37,7 +37,7 @@
}, 'loan_security_price')
if not loan_security_price:
- frappe.throw(_("No valid <b>Loan Security Price</b> found for {0}").format(frappe.bold(loan_security)))
+ frappe.throw(_("No valid Loan Security Price found for {0}").format(frappe.bold(loan_security)))
else:
return loan_security_price
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 6ccd12a..a83d193 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -246,12 +246,13 @@
if rate:
d.rate = rate
d.amount = flt(d.rate) * flt(d.qty)
+ d.db_update()
if self.docstatus == 1:
self.flags.ignore_validate_update_after_submit = True
self.calculate_cost()
if save:
- self.save()
+ self.db_update()
self.update_exploded_items()
# update parent BOMs
diff --git a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
index 2758a42..e6c10ad 100644
--- a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
+++ b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
@@ -82,7 +82,7 @@
@frappe.whitelist()
def enqueue_update_cost():
- frappe.enqueue("erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_cost")
+ frappe.enqueue("erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_cost", timeout=40000)
frappe.msgprint(_("Queued for updating latest price in all Bill of Materials. It may take a few minutes."))
def update_latest_price_in_all_boms():
@@ -98,6 +98,9 @@
doc.replace_bom()
def update_cost():
+ frappe.db.auto_commit_on_many_writes = 1
bom_list = get_boms_in_bottom_up_order()
for bom in bom_list:
- frappe.get_doc("BOM", bom).update_cost(update_parent=False, from_child_bom=True)
\ No newline at end of file
+ frappe.get_doc("BOM", bom).update_cost(update_parent=False, from_child_bom=True)
+
+ frappe.db.auto_commit_on_many_writes = 0
\ No newline at end of file
diff --git a/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py b/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py
index 154addf..ac9a409 100644
--- a/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py
+++ b/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py
@@ -5,6 +5,9 @@
from __future__ import unicode_literals
import unittest
import frappe
+from erpnext.stock.doctype.item.test_item import create_item
+from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
+from erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool import update_cost
test_records = frappe.get_test_records('BOM')
@@ -27,4 +30,31 @@
# reverse, as it affects other testcases
update_tool.current_bom = bom_doc.name
update_tool.new_bom = current_bom
- update_tool.replace_bom()
\ No newline at end of file
+ update_tool.replace_bom()
+
+ def test_bom_cost(self):
+ for item in ["BOM Cost Test Item 1", "BOM Cost Test Item 2", "BOM Cost Test Item 3"]:
+ item_doc = create_item(item, valuation_rate=100)
+ if item_doc.valuation_rate != 100.00:
+ frappe.db.set_value("Item", item_doc.name, "valuation_rate", 100)
+
+ bom_no = frappe.db.get_value('BOM', {'item': 'BOM Cost Test Item 1'}, "name")
+ if not bom_no:
+ doc = make_bom(item = 'BOM Cost Test Item 1',
+ raw_materials =['BOM Cost Test Item 2', 'BOM Cost Test Item 3'], currency="INR")
+ else:
+ doc = frappe.get_doc("BOM", bom_no)
+
+ self.assertEquals(doc.total_cost, 200)
+
+ frappe.db.set_value("Item", "BOM Cost Test Item 2", "valuation_rate", 200)
+ update_cost()
+
+ doc.load_from_db()
+ self.assertEquals(doc.total_cost, 300)
+
+ frappe.db.set_value("Item", "BOM Cost Test Item 2", "valuation_rate", 100)
+ update_cost()
+
+ doc.load_from_db()
+ self.assertEquals(doc.total_cost, 200)
diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
index f70c9cc..26f580d 100644
--- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
@@ -192,9 +192,10 @@
args = frappe._dict(args)
bom = frappe.get_doc({
- 'doctype': "BOM",
+ 'doctype': 'BOM',
'is_default': 1,
'item': args.item,
+ 'currency': args.currency or 'USD',
'quantity': args.quantity or 1,
'company': args.company or '_Test Company'
})
@@ -211,4 +212,5 @@
})
bom.insert(ignore_permissions=True)
- bom.submit()
\ No newline at end of file
+ bom.submit()
+ return bom
\ No newline at end of file
diff --git a/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.py b/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.py
index 65f4d08..75ebcbc 100644
--- a/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.py
+++ b/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.py
@@ -18,10 +18,10 @@
"""return columns"""
columns = [
_("Item") + ":Link/Item:150",
- _("Description") + "::500",
- _("Qty per BOM Line") + ":Float:100",
- _("Required Qty") + ":Float:100",
- _("In Stock Qty") + ":Float:100",
+ _("Description") + "::300",
+ _("BOM Qty") + ":Float:160",
+ _("Required Qty") + ":Float:120",
+ _("In Stock Qty") + ":Float:120",
_("Enough Parts to Build") + ":Float:200",
]
@@ -59,13 +59,14 @@
bom_item.item_code,
bom_item.description ,
bom_item.{qty_field},
- bom_item.{qty_field} * {qty_to_produce},
+ bom_item.{qty_field} * {qty_to_produce} / bom.quantity,
sum(ledger.actual_qty) as actual_qty,
- sum(FLOOR(ledger.actual_qty / (bom_item.{qty_field} * {qty_to_produce})))
+ sum(FLOOR(ledger.actual_qty / (bom_item.{qty_field} * {qty_to_produce} / bom.quantity)))
FROM
- {table} AS bom_item
+ `tabBOM` AS bom INNER JOIN {table} AS bom_item
+ ON bom.name = bom_item.parent
LEFT JOIN `tabBin` AS ledger
- ON bom_item.item_code = ledger.item_code
+ ON bom_item.item_code = ledger.item_code
{conditions}
WHERE
bom_item.parent = '{bom}' and bom_item.parenttype='BOM'
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 361c1d5..eb2b35c 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -662,9 +662,11 @@
erpnext.patches.v12_0.move_bank_account_swift_number_to_bank
erpnext.patches.v12_0.rename_bank_reconciliation_fields # 2020-01-22
erpnext.patches.v12_0.set_received_qty_in_material_request_as_per_stock_uom
+erpnext.patches.v12_0.rename_account_type_doctype
erpnext.patches.v12_0.recalculate_requested_qty_in_bin
erpnext.patches.v12_0.update_healthcare_refactored_changes
erpnext.patches.v12_0.set_total_batch_quantity
erpnext.patches.v12_0.rename_mws_settings_fields
erpnext.patches.v12_0.set_updated_purpose_in_pick_list
+erpnext.patches.v12_0.repost_stock_ledger_entries_for_target_warehouse
erpnext.patches.v12_0.update_end_date_and_status_in_email_campaign
\ No newline at end of file
diff --git a/erpnext/patches/v12_0/rename_account_type_doctype.py b/erpnext/patches/v12_0/rename_account_type_doctype.py
new file mode 100644
index 0000000..ffb4e93
--- /dev/null
+++ b/erpnext/patches/v12_0/rename_account_type_doctype.py
@@ -0,0 +1,7 @@
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+ frappe.rename_doc('DocType', 'Account Type', 'Bank Account Type', force=True)
+ frappe.rename_doc('DocType', 'Account Subtype', 'Bank Account Subtype', force=True)
+ frappe.reload_doc('accounts', 'doctype', 'bank_account')
\ No newline at end of file
diff --git a/erpnext/patches/v12_0/repost_stock_ledger_entries_for_target_warehouse.py b/erpnext/patches/v12_0/repost_stock_ledger_entries_for_target_warehouse.py
new file mode 100644
index 0000000..13e935b
--- /dev/null
+++ b/erpnext/patches/v12_0/repost_stock_ledger_entries_for_target_warehouse.py
@@ -0,0 +1,71 @@
+# Copyright (c) 2020, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+ warehouse_perm = frappe.get_all("User Permission",
+ fields=["count(*) as p_count", "is_default", "user"], filters={"allow": "Warehouse"}, group_by="user")
+
+ if not warehouse_perm:
+ return
+
+ execute_patch = False
+ for perm_data in warehouse_perm:
+ if perm_data.p_count == 1 or (perm_data.p_count > 1 and frappe.get_all("User Permission",
+ filters = {"user": perm_data.user, "allow": "warehouse", "is_default": 1}, limit=1)):
+ execute_patch = True
+ break
+
+ if not execute_patch: return
+
+ for doctype in ["Sales Invoice", "Delivery Note"]:
+ if not frappe.get_meta(doctype + ' Item').get_field("target_warehouse").hidden: continue
+
+ cond = ""
+ if doctype == "Sales Invoice":
+ cond = " AND parent_doc.update_stock = 1"
+
+ data = frappe.db.sql(""" SELECT parent_doc.name as name, child_doc.name as child_name
+ FROM
+ `tab{doctype}` parent_doc, `tab{doctype} Item` child_doc
+ WHERE
+ parent_doc.name = child_doc.parent AND parent_doc.docstatus < 2
+ AND child_doc.target_warehouse is not null AND child_doc.target_warehouse != ''
+ AND child_doc.creation > '2020-04-16' {cond}
+ """.format(doctype=doctype, cond=cond), as_dict=1)
+
+ if data:
+ names = [d.child_name for d in data]
+ frappe.db.sql(""" UPDATE `tab{0} Item` set target_warehouse = null
+ WHERE name in ({1}) """.format(doctype, ','.join(["%s"] * len(names) )), tuple(names))
+
+ frappe.db.sql(""" UPDATE `tabPacked Item` set target_warehouse = null
+ WHERE parenttype = '{0}' and parent_detail_docname in ({1})
+ """.format(doctype, ','.join(["%s"] * len(names) )), tuple(names))
+
+ parent_names = list(set([d.name for d in data]))
+
+ for d in parent_names:
+ doc = frappe.get_doc(doctype, d)
+ if doc.docstatus != 1: continue
+
+ doc.docstatus = 2
+ doc.update_stock_ledger()
+ doc.make_gl_entries_on_cancel(repost_future_gle=False)
+
+ # update stock & gl entries for submit state of PR
+ doc.docstatus = 1
+ doc.update_stock_ledger()
+ doc.make_gl_entries()
+
+ if frappe.get_meta('Sales Order Item').get_field("target_warehouse").hidden:
+ frappe.db.sql(""" UPDATE `tabSales Order Item` set target_warehouse = null
+ WHERE creation > '2020-04-16' and docstatus < 2 """)
+
+ frappe.db.sql(""" UPDATE `tabPacked Item` set target_warehouse = null
+ WHERE creation > '2020-04-16' and docstatus < 2 and parenttype = 'Sales Order' """)
+
+
+
diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py
index ff03381..ab87ee1 100644
--- a/erpnext/stock/report/stock_balance/stock_balance.py
+++ b/erpnext/stock/report/stock_balance/stock_balance.py
@@ -170,6 +170,8 @@
from_date = getdate(filters.get("from_date"))
to_date = getdate(filters.get("to_date"))
+ float_precision = cint(frappe.db.get_default("float_precision")) or 3
+
for d in sle:
key = (d.company, d.item_code, d.warehouse)
if key not in iwb_map:
@@ -184,7 +186,7 @@
qty_dict = iwb_map[(d.company, d.item_code, d.warehouse)]
if d.voucher_type == "Stock Reconciliation":
- qty_diff = flt(d.qty_after_transaction) - qty_dict.bal_qty
+ qty_diff = flt(d.qty_after_transaction) - flt(qty_dict.bal_qty)
else:
qty_diff = flt(d.actual_qty)
@@ -195,7 +197,7 @@
qty_dict.opening_val += value_diff
elif d.posting_date >= from_date and d.posting_date <= to_date:
- if qty_diff > 0:
+ if flt(qty_diff, float_precision) >= 0:
qty_dict.in_qty += qty_diff
qty_dict.in_val += value_diff
else:
@@ -206,16 +208,15 @@
qty_dict.bal_qty += qty_diff
qty_dict.bal_val += value_diff
- iwb_map = filter_items_with_no_transactions(iwb_map)
+ iwb_map = filter_items_with_no_transactions(iwb_map, float_precision)
return iwb_map
-def filter_items_with_no_transactions(iwb_map):
+def filter_items_with_no_transactions(iwb_map, float_precision):
for (company, item, warehouse) in sorted(iwb_map):
qty_dict = iwb_map[(company, item, warehouse)]
no_transactions = True
- float_precision = cint(frappe.db.get_default("float_precision")) or 3
for key, val in iteritems(qty_dict):
val = flt(val, float_precision)
qty_dict[key] = val