Merge pull request #21401 from rohitwaghchaure/fixed-taget-warehouse-mandatory-issue
fix: make target warehouse field mandatory while saving the work order
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/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index b7c97a7..05f0147 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -106,6 +106,21 @@
};
});
+ frm.set_query('payment_term', 'references', function(frm, cdt, cdn) {
+ const child = locals[cdt][cdn];
+ if (in_list(['Purchase Invoice', 'Sales Invoice'], child.reference_doctype) && child.reference_name) {
+ let payment_term_list = frappe.get_list('Payment Schedule', {'parent': child.reference_name});
+
+ payment_term_list = payment_term_list.map(pt => pt.payment_term);
+
+ return {
+ filters: {
+ 'name': ['in', payment_term_list]
+ }
+ }
+ }
+ });
+
frm.set_query("reference_name", "references", function(doc, cdt, cdn) {
const child = locals[cdt][cdn];
const filters = {"docstatus": 1, "company": doc.company};
@@ -1033,4 +1048,4 @@
});
}
},
-})
+})
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index a453e95..b53e68f 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -71,9 +71,9 @@
self.update_outstanding_amounts()
self.update_advance_paid()
self.update_expense_claim()
+ self.update_payment_schedule()
self.set_status()
-
def on_cancel(self):
self.setup_party_account_field()
self.make_gl_entries(cancel=1)
@@ -81,6 +81,7 @@
self.update_advance_paid()
self.update_expense_claim()
self.delink_advance_entry_references()
+ self.update_payment_schedule(cancel=1)
self.set_payment_req_status()
self.set_status()
@@ -94,10 +95,10 @@
def validate_duplicate_entry(self):
reference_names = []
for d in self.get("references"):
- if (d.reference_doctype, d.reference_name) in reference_names:
+ if (d.reference_doctype, d.reference_name, d.payment_term) in reference_names:
frappe.throw(_("Row #{0}: Duplicate entry in References {1} {2}")
.format(d.idx, d.reference_doctype, d.reference_name))
- reference_names.append((d.reference_doctype, d.reference_name))
+ reference_names.append((d.reference_doctype, d.reference_name, d.payment_term))
def set_bank_account_data(self):
if self.bank_account:
@@ -285,6 +286,36 @@
frappe.throw(_("Against Journal Entry {0} does not have any unmatched {1} entry")
.format(d.reference_name, dr_or_cr))
+ def update_payment_schedule(self, cancel=0):
+ invoice_payment_amount_map = {}
+ invoice_paid_amount_map = {}
+
+ for reference in self.get('references'):
+ if reference.payment_term and reference.reference_name:
+ key = (reference.payment_term, reference.reference_name)
+ invoice_payment_amount_map.setdefault(key, 0.0)
+ invoice_payment_amount_map[key] += reference.allocated_amount
+
+ if not invoice_paid_amount_map.get(reference.reference_name):
+ payment_schedule = frappe.get_all('Payment Schedule', filters={'parent': reference.reference_name},
+ fields=['paid_amount', 'payment_amount', 'payment_term'])
+ for term in payment_schedule:
+ invoice_key = (term.payment_term, reference.reference_name)
+ invoice_paid_amount_map.setdefault(invoice_key, {})
+ invoice_paid_amount_map[invoice_key]['outstanding'] = term.payment_amount - term.paid_amount
+
+ for key, amount in iteritems(invoice_payment_amount_map):
+ if cancel:
+ frappe.db.sql(""" UPDATE `tabPayment Schedule` SET paid_amount = `paid_amount` - %s
+ WHERE parent = %s and payment_term = %s""", (amount, key[1], key[0]))
+ else:
+ outstanding = invoice_paid_amount_map.get(key)['outstanding']
+ if amount > outstanding:
+ frappe.throw(_('Cannot allocate more than {0} against payment term {1}').format(outstanding, key[0]))
+
+ frappe.db.sql(""" UPDATE `tabPayment Schedule` SET paid_amount = `paid_amount` + %s
+ WHERE parent = %s and payment_term = %s""", (amount, key[1], key[0]))
+
def set_status(self):
if self.docstatus == 2:
self.status = 'Cancelled'
@@ -1012,15 +1043,22 @@
if doc.doctype == "Purchase Invoice" and doc.invoice_is_blocked():
frappe.msgprint(_('{0} is on hold till {1}').format(doc.name, doc.release_date))
else:
- pe.append("references", {
- 'reference_doctype': dt,
- 'reference_name': dn,
- "bill_no": doc.get("bill_no"),
- "due_date": doc.get("due_date"),
- 'total_amount': grand_total,
- 'outstanding_amount': outstanding_amount,
- 'allocated_amount': outstanding_amount
- })
+ if (doc.doctype in ('Sales Invoice', 'Purchase Invoice')
+ and frappe.get_value('Payment Terms Template',
+ {'name': doc.payment_terms_template}, 'allocate_payment_based_on_payment_terms')):
+
+ for reference in get_reference_as_per_payment_terms(doc.payment_schedule, dt, dn, doc, grand_total, outstanding_amount):
+ pe.append('references', reference)
+ else:
+ pe.append("references", {
+ 'reference_doctype': dt,
+ 'reference_name': dn,
+ "bill_no": doc.get("bill_no"),
+ "due_date": doc.get("due_date"),
+ 'total_amount': grand_total,
+ 'outstanding_amount': outstanding_amount,
+ 'allocated_amount': outstanding_amount
+ })
pe.setup_party_account_field()
pe.set_missing_values()
@@ -1029,6 +1067,22 @@
pe.set_amounts()
return pe
+def get_reference_as_per_payment_terms(payment_schedule, dt, dn, doc, grand_total, outstanding_amount):
+ references = []
+ for payment_term in payment_schedule:
+ references.append({
+ 'reference_doctype': dt,
+ 'reference_name': dn,
+ 'bill_no': doc.get('bill_no'),
+ 'due_date': doc.get('due_date'),
+ 'total_amount': grand_total,
+ 'outstanding_amount': outstanding_amount,
+ 'payment_term': payment_term.payment_term,
+ 'allocated_amount': flt(payment_term.payment_amount - payment_term.paid_amount,
+ payment_term.precision('payment_amount'))
+ })
+
+ return references
def get_paid_amount(dt, dn, party_type, party, account, due_date):
if party_type=="Customer":
diff --git a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py
index a25e0e3..4c7d933 100644
--- a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py
@@ -171,6 +171,32 @@
self.assertEqual(flt(outstanding_amount), 100)
self.assertEqual(status, 'Unpaid')
+ def test_payment_entry_against_payment_terms(self):
+ si = create_sales_invoice(do_not_save=1, qty=1, rate=200)
+ create_payment_terms_template()
+ si.payment_terms_template = 'Test Receivable Template'
+
+ si.append('taxes', {
+ "charge_type": "On Net Total",
+ "account_head": "_Test Account Service Tax - _TC",
+ "cost_center": "_Test Cost Center - _TC",
+ "description": "Service Tax",
+ "rate": 18
+ })
+ si.save()
+
+ si.submit()
+
+ pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Cash - _TC")
+ pe.submit()
+ si.load_from_db()
+
+ self.assertEqual(pe.references[0].payment_term, 'Basic Amount Receivable')
+ self.assertEqual(pe.references[1].payment_term, 'Tax Receivable')
+ self.assertEqual(si.payment_schedule[0].paid_amount, 200.0)
+ self.assertEqual(si.payment_schedule[1].paid_amount, 36.0)
+
+
def test_payment_against_purchase_invoice_to_check_status(self):
pi = make_purchase_invoice(supplier="_Test Supplier USD", debit_to="_Test Payable USD - _TC",
currency="USD", conversion_rate=50)
@@ -609,4 +635,38 @@
self.assertEqual(expected_party_account_balance, party_account_balance)
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
- accounts_settings.save()
\ No newline at end of file
+ accounts_settings.save()
+
+def create_payment_terms_template():
+
+ create_payment_term('Basic Amount Receivable')
+ create_payment_term('Tax Receivable')
+
+ if not frappe.db.exists('Payment Terms Template', 'Test Receivable Template'):
+ payment_term_template = frappe.get_doc({
+ 'doctype': 'Payment Terms Template',
+ 'template_name': 'Test Receivable Template',
+ 'allocate_payment_based_on_payment_terms': 1,
+ 'terms': [{
+ 'doctype': 'Payment Terms Template Detail',
+ 'payment_term': 'Basic Amount Receivable',
+ 'invoice_portion': 84.746,
+ 'credit_days_based_on': 'Day(s) after invoice date',
+ 'credit_days': 1
+ },
+ {
+ 'doctype': 'Payment Terms Template Detail',
+ 'payment_term': 'Tax Receivable',
+ 'invoice_portion': 15.254,
+ 'credit_days_based_on': 'Day(s) after invoice date',
+ 'credit_days': 2
+ }]
+ }).insert()
+
+
+def create_payment_term(name):
+ if not frappe.db.exists('Payment Term', name):
+ frappe.get_doc({
+ 'doctype': 'Payment Term',
+ 'payment_term_name': name
+ }).insert()
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_entry_reference/payment_entry_reference.json b/erpnext/accounts/doctype/payment_entry_reference/payment_entry_reference.json
index b6a6643..8f5e9fb 100644
--- a/erpnext/accounts/doctype/payment_entry_reference/payment_entry_reference.json
+++ b/erpnext/accounts/doctype/payment_entry_reference/payment_entry_reference.json
@@ -1,343 +1,107 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
+ "actions": [],
"creation": "2016-06-01 16:55:32.196722",
- "custom": 0,
- "docstatus": 0,
"doctype": "DocType",
- "document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
+ "field_order": [
+ "reference_doctype",
+ "reference_name",
+ "due_date",
+ "bill_no",
+ "payment_term",
+ "column_break_4",
+ "total_amount",
+ "outstanding_amount",
+ "allocated_amount",
+ "exchange_rate"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
"columns": 2,
- "fetch_if_empty": 0,
"fieldname": "reference_doctype",
"fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
"label": "Type",
- "length": 0,
- "no_copy": 0,
"options": "DocType",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
"columns": 2,
- "fetch_if_empty": 0,
"fieldname": "reference_name",
"fieldtype": "Dynamic Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
"in_global_search": 1,
"in_list_view": 1,
- "in_standard_filter": 0,
"label": "Name",
- "length": 0,
- "no_copy": 0,
"options": "reference_doctype",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "due_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": "Due Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fetch_if_empty": 0,
"fieldname": "bill_no",
"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": "Supplier Invoice No",
- "length": 0,
"no_copy": 1,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "column_break_4",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldtype": "Column Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
"columns": 2,
- "fetch_if_empty": 0,
"fieldname": "total_amount",
"fieldtype": "Float",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
"label": "Total Amount",
- "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,
- "translatable": 0,
- "unique": 0
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
"columns": 2,
- "fetch_if_empty": 0,
"fieldname": "outstanding_amount",
"fieldtype": "Float",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
"label": "Outstanding",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
"columns": 2,
- "fetch_if_empty": 0,
"fieldname": "allocated_amount",
"fieldtype": "Float",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Allocated",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "label": "Allocated"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"depends_on": "eval:(doc.reference_doctype=='Purchase Invoice')",
- "fetch_if_empty": 0,
"fieldname": "exchange_rate",
"fieldtype": "Float",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Exchange Rate",
- "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,
- "translatable": 0,
- "unique": 0
+ "read_only": 1
+ },
+ {
+ "fieldname": "payment_term",
+ "fieldtype": "Link",
+ "label": "Payment Term",
+ "options": "Payment Term"
}
],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
"istable": 1,
- "max_attachments": 0,
- "modified": "2019-05-01 13:24:56.586677",
+ "links": [],
+ "modified": "2020-03-13 12:07:19.362539",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry Reference",
- "name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_schedule/payment_schedule.json b/erpnext/accounts/doctype/payment_schedule/payment_schedule.json
index 1b38904..d363cf1 100644
--- a/erpnext/accounts/doctype/payment_schedule/payment_schedule.json
+++ b/erpnext/accounts/doctype/payment_schedule/payment_schedule.json
@@ -1,243 +1,82 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "",
- "beta": 0,
- "creation": "2017-08-10 15:38:00.080575",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "creation": "2017-08-10 15:38:00.080575",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "payment_term",
+ "description",
+ "due_date",
+ "invoice_portion",
+ "payment_amount",
+ "mode_of_payment",
+ "paid_amount"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 2,
- "fieldname": "payment_term",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Payment Term",
- "length": 0,
- "no_copy": 0,
- "options": "Payment Term",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "columns": 2,
+ "fieldname": "payment_term",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Payment Term",
+ "options": "Payment Term",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 2,
- "fetch_from": "",
- "fieldname": "description",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Description",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "columns": 2,
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "in_list_view": 1,
+ "label": "Description"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 2,
- "fieldname": "due_date",
- "fieldtype": "Date",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Due Date",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "columns": 2,
+ "fieldname": "due_date",
+ "fieldtype": "Date",
+ "in_list_view": 1,
+ "label": "Due Date",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 2,
- "fetch_from": "",
- "fieldname": "invoice_portion",
- "fieldtype": "Percent",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Invoice Portion",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "columns": 2,
+ "fieldname": "invoice_portion",
+ "fieldtype": "Percent",
+ "in_list_view": 1,
+ "label": "Invoice Portion",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 2,
- "fieldname": "payment_amount",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Payment Amount",
- "length": 0,
- "no_copy": 0,
- "options": "currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "columns": 2,
+ "fieldname": "payment_amount",
+ "fieldtype": "Currency",
+ "in_list_view": 1,
+ "label": "Payment Amount",
+ "options": "currency",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "mode_of_payment",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Mode of Payment",
- "length": 0,
- "no_copy": 0,
- "options": "Mode of Payment",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldname": "mode_of_payment",
+ "fieldtype": "Link",
+ "label": "Mode of Payment",
+ "options": "Mode of Payment"
+ },
+ {
+ "fieldname": "paid_amount",
+ "fieldtype": "Currency",
+ "label": "Paid Amount"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2018-09-06 17:35:44.580209",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "Payment Schedule",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-03-13 17:58:24.729526",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Payment Schedule",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.json b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.json
index 7a3483d..c4a2a88 100644
--- a/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.json
+++ b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.json
@@ -1,164 +1,84 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "field:template_name",
- "beta": 0,
- "creation": "2017-08-10 15:34:28.058054",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:template_name",
+ "creation": "2017-08-10 15:34:28.058054",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "template_name",
+ "allocate_payment_based_on_payment_terms",
+ "terms"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "template_name",
- "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": "Template 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": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "template_name",
+ "fieldtype": "Data",
+ "label": "Template Name",
+ "unique": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "terms",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Payment Terms",
- "length": 0,
- "no_copy": 0,
- "options": "Payment Terms Template Detail",
- "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
+ "fieldname": "terms",
+ "fieldtype": "Table",
+ "label": "Payment Terms",
+ "options": "Payment Terms Template Detail",
+ "reqd": 1
+ },
+ {
+ "default": "0",
+ "description": "If this checkbox is checked, paid amount will be splitted and allocated as per the amounts in payment schedule against each payment term",
+ "fieldname": "allocate_payment_based_on_payment_terms",
+ "fieldtype": "Check",
+ "label": "Allocate Payment Based On Payment Terms"
}
- ],
- "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-01-24 11:13:31.158613",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "Payment Terms Template",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "links": [],
+ "modified": "2020-04-01 15:35:18.112619",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Payment Terms Template",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "apply_user_permissions": 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,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "apply_user_permissions": 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,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts User",
+ "share": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "apply_user_permissions": 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,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts Manager",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
index e13fcb9..19f571f 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
@@ -237,6 +237,7 @@
if pricing_rule.mixed_conditions or pricing_rule.apply_rule_on_other:
item_details.update({
'apply_rule_on_other_items': json.dumps(pricing_rule.apply_rule_on_other_items),
+ 'price_or_product_discount': pricing_rule.price_or_product_discount,
'apply_rule_on': (frappe.scrub(pricing_rule.apply_rule_on_other)
if pricing_rule.apply_rule_on_other else frappe.scrub(pricing_rule.get('apply_on')))
})
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 6f78db2..a6113cd 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -32,6 +32,7 @@
me.frm.script_manager.trigger("is_pos");
me.frm.refresh_fields();
}
+ erpnext.queries.setup_warehouse_query(this.frm);
},
refresh: function(doc, dt, dn) {
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index 240b0d8..e9c286f 100755
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -344,26 +344,28 @@
def allocate_outstanding_based_on_payment_terms(self, row):
self.get_payment_terms(row)
for term in row.payment_terms:
- term.outstanding = term.invoiced
# update "paid" and "oustanding" for this term
- self.allocate_closing_to_term(row, term, 'paid')
+ if not term.paid:
+ self.allocate_closing_to_term(row, term, 'paid')
# update "credit_note" and "oustanding" for this term
if term.outstanding:
self.allocate_closing_to_term(row, term, 'credit_note')
+ row.payment_terms = sorted(row.payment_terms, key=lambda x: x['due_date'])
+
def get_payment_terms(self, row):
# build payment_terms for row
payment_terms_details = frappe.db.sql("""
select
si.name, si.party_account_currency, si.currency, si.conversion_rate,
- ps.due_date, ps.payment_amount, ps.description
+ ps.due_date, ps.payment_amount, ps.description, ps.paid_amount
from `tab{0}` si, `tabPayment Schedule` ps
where
si.name = ps.parent and
si.name = %s
- order by ps.due_date
+ order by ps.paid_amount desc, due_date
""".format(row.voucher_type), row.voucher_no, as_dict = 1)
@@ -389,11 +391,14 @@
"invoiced": invoiced,
"invoice_grand_total": row.invoiced,
"payment_term": d.description,
- "paid": 0.0,
+ "paid": d.paid_amount,
"credit_note": 0.0,
- "outstanding": 0.0
+ "outstanding": invoiced - d.paid_amount
}))
+ if d.paid_amount:
+ row['paid'] -= d.paid_amount
+
def allocate_closing_to_term(self, row, term, key):
if row[key]:
if row[key] > term.outstanding:
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 4045250..3e97f76 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -819,7 +819,7 @@
else:
for d in self.get("payment_schedule"):
if d.invoice_portion:
- d.payment_amount = grand_total * flt(d.invoice_portion) / 100
+ d.payment_amount = flt(grand_total * flt(d.invoice_portion) / 100, d.precision('payment_amount'))
def set_due_date(self):
due_dates = [d.due_date for d in self.get("payment_schedule") if d.due_date]
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/crm/doctype/email_campaign/email_campaign.py b/erpnext/crm/doctype/email_campaign/email_campaign.py
index 00a4bd1..8f60ecf 100644
--- a/erpnext/crm/doctype/email_campaign/email_campaign.py
+++ b/erpnext/crm/doctype/email_campaign/email_campaign.py
@@ -27,7 +27,7 @@
for entry in campaign.get("campaign_schedules"):
send_after_days.append(entry.send_after_days)
try:
- end_date = add_days(getdate(self.start_date), max(send_after_days))
+ self.end_date = add_days(getdate(self.start_date), max(send_after_days))
except ValueError:
frappe.throw(_("Please set up the Campaign Schedule in the Campaign {0}").format(self.campaign_name))
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/hr/doctype/upload_attendance/upload_attendance.py b/erpnext/hr/doctype/upload_attendance/upload_attendance.py
index 1707e35..f75bb41 100644
--- a/erpnext/hr/doctype/upload_attendance/upload_attendance.py
+++ b/erpnext/hr/doctype/upload_attendance/upload_attendance.py
@@ -9,6 +9,8 @@
from frappe import _
from frappe.utils.csvutils import UnicodeWriter
from frappe.model.document import Document
+from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee
+from erpnext.hr.utils import get_holidays_for_employee
class UploadAttendance(Document):
pass
@@ -48,6 +50,7 @@
def get_data(args):
dates = get_dates(args)
employees = get_active_employees()
+ holidays = get_holidays_for_employees([employee.name for employee in employees], args["from_date"], args["to_date"])
existing_attendance_records = get_existing_attendance_records(args)
data = []
for date in dates:
@@ -63,6 +66,9 @@
and getdate(employee.date_of_joining) <= getdate(date) \
and getdate(employee.relieving_date) >= getdate(date):
existing_attendance = existing_attendance_records[tuple([getdate(date), employee.name])]
+
+ employee_holiday_list = get_holiday_list_for_employee(employee.name)
+
row = [
existing_attendance and existing_attendance.name or "",
employee.name, employee.employee_name, date,
@@ -70,9 +76,22 @@
existing_attendance and existing_attendance.leave_type or "", employee.company,
existing_attendance and existing_attendance.naming_series or get_naming_series(),
]
+ if date in holidays[employee_holiday_list]:
+ row[4] = "Holiday"
data.append(row)
+
return data
+def get_holidays_for_employees(employees, from_date, to_date):
+ holidays = {}
+ for employee in employees:
+ holiday_list = get_holiday_list_for_employee(employee)
+ holiday = get_holidays_for_employee(employee, getdate(from_date), getdate(to_date))
+ if holiday_list not in holidays:
+ holidays[holiday_list] = holiday
+
+ return holidays
+
def writedata(w, data):
for row in data:
w.writerow(row)
@@ -123,6 +142,11 @@
frappe.enqueue(import_attendances, rows=rows, now=True if len(rows) < 200 else False)
def import_attendances(rows):
+
+ def remove_holidays(rows):
+ rows = [ row for row in rows if row[4] != "Holiday"]
+ return
+
from frappe.modules import scrub
rows = list(filter(lambda x: x and any(x), rows))
@@ -133,6 +157,8 @@
ret = []
error = False
+ rows = remove_holidays(rows)
+
from frappe.utils.csvutils import check_record, import_doc
for i, row in enumerate(rows):
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 9ef0b8d..eb2b35c 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -662,8 +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/patches/v12_0/update_end_date_and_status_in_email_campaign.py b/erpnext/patches/v12_0/update_end_date_and_status_in_email_campaign.py
new file mode 100644
index 0000000..db71a73
--- /dev/null
+++ b/erpnext/patches/v12_0/update_end_date_and_status_in_email_campaign.py
@@ -0,0 +1,24 @@
+from __future__ import unicode_literals
+import frappe
+from frappe.utils import add_days, getdate, today
+
+def execute():
+ if frappe.db.exists('DocType', 'Email Campaign'):
+ email_campaign = frappe.get_all('Email Campaign')
+ for campaign in email_campaign:
+ doc = frappe.get_doc("Email Campaign",campaign["name"])
+ send_after_days = []
+
+ camp = frappe.get_doc("Campaign", doc.campaign_name)
+ for entry in camp.get("campaign_schedules"):
+ send_after_days.append(entry.send_after_days)
+ if send_after_days:
+ end_date = add_days(getdate(doc.start_date), max(send_after_days))
+ doc.db_set("end_date", end_date)
+ today_date = getdate(today())
+ if doc.start_date > today_date:
+ doc.db_set("status", "Scheduled")
+ elif end_date >= today_date:
+ doc.db_set("status", "In Progress")
+ elif end_date < today_date:
+ doc.db_set("status", "Completed")
\ No newline at end of file
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 3443abc..4296447 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -1412,7 +1412,7 @@
me.frm.doc.items.forEach(d => {
if (in_list(data.apply_rule_on_other_items, d[data.apply_rule_on])) {
for(var k in data) {
- if (in_list(fields, k) && data[k]) {
+ if (in_list(fields, k) && data[k] && (data.price_or_product_discount === 'price' || k === 'pricing_rules')) {
frappe.model.set_value(d.doctype, d.name, k, data[k]);
}
}
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