Merge branch 'develop' into email-camp-end-date
This commit is contained in:
commit
78d7ed521f
@ -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
|
||||
}
|
@ -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 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', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
@ -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() {
|
||||
|
||||
}
|
||||
});
|
@ -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
|
||||
}
|
@ -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
|
@ -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",
|
||||
|
@ -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() {
|
||||
|
||||
}
|
@ -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
|
||||
}
|
@ -5,5 +5,5 @@
|
||||
from __future__ import unicode_literals
|
||||
from frappe.model.document import Document
|
||||
|
||||
class AccountType(Document):
|
||||
class BankAccountSubtype(Document):
|
||||
pass
|
@ -2,15 +2,15 @@
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Account Type", 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 Type
|
||||
() => frappe.tests.make('Account Type', [
|
||||
// insert a new Bank Account Subtype
|
||||
() => frappe.tests.make('Bank Account Subtype', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
@ -5,5 +5,5 @@ from __future__ import unicode_literals
|
||||
|
||||
import unittest
|
||||
|
||||
class TestAccountSubtype(unittest.TestCase):
|
||||
class TestBankAccountSubtype(unittest.TestCase):
|
||||
pass
|
@ -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) {
|
||||
|
||||
// }
|
||||
});
|
@ -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"
|
||||
}
|
@ -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 AccountSubtype(Document):
|
||||
class BankAccountType(Document):
|
||||
pass
|
@ -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
|
@ -9,6 +9,7 @@ from frappe.utils import flt, getdate, add_months, get_last_day, fmt_money, nowd
|
||||
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 @@ def validate_expense_against_budget(args):
|
||||
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 @@ def validate_expense_against_budget(args):
|
||||
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_ordered_amount(args, budget):
|
||||
|
||||
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 @@ def get_other_condition(args, budget, for_doc):
|
||||
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 @@ def get_actual_expense(args):
|
||||
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 = {}
|
||||
|
@ -13,7 +13,7 @@ from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journ
|
||||
|
||||
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 @@ class TestBudget(unittest.TestCase):
|
||||
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 @@ class TestBudget(unittest.TestCase):
|
||||
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 @@ class TestBudget(unittest.TestCase):
|
||||
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 @@ class TestBudget(unittest.TestCase):
|
||||
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 @@ class TestBudget(unittest.TestCase):
|
||||
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 @@ class TestBudget(unittest.TestCase):
|
||||
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 @@ class TestBudget(unittest.TestCase):
|
||||
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 @@ class TestBudget(unittest.TestCase):
|
||||
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 @@ class TestBudget(unittest.TestCase):
|
||||
|
||||
|
||||
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")
|
||||
|
||||
|
@ -46,6 +46,7 @@ class SellingController(StockController):
|
||||
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 @@ class SellingController(StockController):
|
||||
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
|
||||
|
@ -67,11 +67,11 @@ def add_bank_accounts(response, bank, company):
|
||||
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_bank_accounts(response, bank, company):
|
||||
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_type(account_type):
|
||||
def add_account_subtype(account_subtype):
|
||||
try:
|
||||
frappe.get_doc({
|
||||
"doctype": "Account Subtype",
|
||||
"doctype": "Bank Account Subtype",
|
||||
"account_subtype": account_subtype
|
||||
}).insert()
|
||||
except Exception:
|
||||
|
@ -23,11 +23,11 @@ class TestPlaidSettings(unittest.TestCase):
|
||||
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 @@ class TestPlaidSettings(unittest.TestCase):
|
||||
|
||||
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"):
|
||||
|
@ -31,7 +31,7 @@ frappe.ui.form.on('Loan Application', {
|
||||
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() {
|
||||
|
@ -30,7 +30,8 @@ class LoanSecurityPledge(Document):
|
||||
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)
|
||||
|
@ -37,7 +37,7 @@ def get_loan_security_price(loan_security, valid_time=None):
|
||||
}, '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
|
||||
|
||||
|
@ -246,12 +246,13 @@ class BOM(WebsiteGenerator):
|
||||
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
|
||||
|
@ -82,7 +82,7 @@ def enqueue_replace_bom(args):
|
||||
|
||||
@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 @@ def replace_bom(args):
|
||||
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)
|
||||
frappe.get_doc("BOM", bom).update_cost(update_parent=False, from_child_bom=True)
|
||||
|
||||
frappe.db.auto_commit_on_many_writes = 0
|
@ -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 @@ class TestBOMUpdateTool(unittest.TestCase):
|
||||
# reverse, as it affects other testcases
|
||||
update_tool.current_bom = bom_doc.name
|
||||
update_tool.new_bom = current_bom
|
||||
update_tool.replace_bom()
|
||||
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)
|
||||
|
@ -192,9 +192,10 @@ def make_bom(**args):
|
||||
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 @@ def make_bom(**args):
|
||||
})
|
||||
|
||||
bom.insert(ignore_permissions=True)
|
||||
bom.submit()
|
||||
bom.submit()
|
||||
return bom
|
@ -18,10 +18,10 @@ def get_columns():
|
||||
"""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 @@ def get_bom_stock(filters):
|
||||
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'
|
||||
|
@ -662,9 +662,11 @@ erpnext.patches.v12_0.create_irs_1099_field_united_states
|
||||
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
|
7
erpnext/patches/v12_0/rename_account_type_doctype.py
Normal file
7
erpnext/patches/v12_0/rename_account_type_doctype.py
Normal file
@ -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')
|
@ -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' """)
|
||||
|
||||
|
||||
|
@ -170,6 +170,8 @@ def get_item_warehouse_map(filters, sle):
|
||||
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 @@ def get_item_warehouse_map(filters, sle):
|
||||
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 @@ def get_item_warehouse_map(filters, sle):
|
||||
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 @@ def get_item_warehouse_map(filters, sle):
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user