Allow cost center in entry of balance sheet accounts (#14972)

* Allow Cost Center In Entry of Balance Sheet Account

* Add parent cost center in get payment entry

* Add Tests for Allow Cost Center In Entry of Balance Sheet Account

* Add tests for cost center wise account and party balance

* set parent cost center in taxes

* 1. Remove copy parent cost_center to child
2. Improve update party and account balance functionality on cost_center change
3. Add cost_center filter to get_outstanding_documents

* fix Codacy and Travis issue
This commit is contained in:
Sanjay Kumar 2018-09-06 13:09:35 +04:00 committed by Nabin Hait
parent b94008dab3
commit 1b49f3a4e7
28 changed files with 998 additions and 88 deletions

View File

@ -296,6 +296,37 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "allow_cost_center_in_entry_of_bs_account",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Allow Cost Center In Entry of Balance Sheet Account",
"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
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
@ -543,6 +574,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -575,6 +607,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
@ -589,7 +622,7 @@
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2018-02-21 16:47:38.043115",
"modified": "2018-05-14 15:58:27.638576",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",
@ -597,7 +630,6 @@
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 0,
@ -617,7 +649,6 @@
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
@ -637,7 +668,6 @@
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,

View File

@ -17,6 +17,7 @@ class AccountsSettings(Document):
def validate(self):
self.validate_stale_days()
self.enable_payment_schedule_in_print()
self.enable_fields_for_cost_center_settings()
def validate_stale_days(self):
if not self.allow_stale and cint(self.stale_days) <= 0:
@ -28,4 +29,9 @@ class AccountsSettings(Document):
show_in_print = cint(self.show_payment_schedule_in_print)
for doctype in ("Sales Order", "Sales Invoice", "Purchase Order", "Purchase Invoice"):
make_property_setter(doctype, "due_date", "print_hide", show_in_print, "Check")
make_property_setter(doctype, "payment_schedule", "print_hide", 0 if show_in_print else 1, "Check")
make_property_setter(doctype, "payment_schedule", "print_hide", 0 if show_in_print else 1, "Check")
def enable_fields_for_cost_center_settings(self):
show_field = 0 if cint(self.allow_cost_center_in_entry_of_bs_account) else 1
for doctype in ("Sales Invoice", "Purchase Invoice", "Payment Entry"):
make_property_setter(doctype, "cost_center", "hidden", show_field, "Check")

View File

@ -4,4 +4,23 @@ from __future__ import unicode_literals
import frappe
test_records = frappe.get_test_records('Cost Center')
test_records = frappe.get_test_records('Cost Center')
def create_cost_center(**args):
args = frappe._dict(args)
if args.cost_center_name:
company = args.company or "_Test Company"
company_abbr = frappe.db.get_value("Company", company, "abbr")
cc_name = args.cost_center_name + " - " + company_abbr
if not frappe.db.exists("Cost Center", cc_name):
cc = frappe.new_doc("Cost Center")
cc.company = args.company or "_Test Company"
cc.cost_center_name = args.cost_center_name
cc.is_group = args.is_group or 0
cc.parent_cost_center = args.parent_cost_center or "_Test Company - _TC"
cc.insert()

View File

@ -67,7 +67,8 @@ class GLEntry(Document):
frappe.throw(_("{0} {1}: Cost Center is required for 'Profit and Loss' account {2}. Please set up a default Cost Center for the Company.")
.format(self.voucher_type, self.voucher_no, self.account))
else:
if self.cost_center:
from erpnext.accounts.utils import get_allow_cost_center_in_entry_of_bs_account
if not get_allow_cost_center_in_entry_of_bs_account() and self.cost_center:
self.cost_center = None
if self.project:
self.project = None

View File

@ -414,37 +414,18 @@ frappe.ui.form.on("Journal Entry Account", {
args: {
company: frm.doc.company,
party_type: d.party_type,
party: d.party
party: d.party,
cost_center: d.cost_center
}
});
}
},
cost_center: function(frm, dt, dn) {
erpnext.journal_entry.set_account_balance(frm, dt, dn);
},
account: function(frm, dt, dn) {
var d = locals[dt][dn];
if(d.account) {
if(!frm.doc.company) frappe.throw(__("Please select Company first"));
if(!frm.doc.posting_date) frappe.throw(__("Please select Posting Date first"));
return frappe.call({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_account_balance_and_party_type",
args: {
account: d.account,
date: frm.doc.posting_date,
company: frm.doc.company,
debit: flt(d.debit_in_account_currency),
credit: flt(d.credit_in_account_currency),
exchange_rate: d.exchange_rate
},
callback: function(r) {
if(r.message) {
$.extend(d, r.message);
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, dt, dn);
refresh_field('accounts');
}
}
});
}
erpnext.journal_entry.set_account_balance(frm, dt, dn);
},
debit_in_account_currency: function(frm, cdt, cdn) {
@ -637,3 +618,33 @@ $.extend(erpnext.journal_entry, {
cur_frm.reload_doc();
}
});
$.extend(erpnext.journal_entry, {
set_account_balance: function(frm, dt, dn) {
var d = locals[dt][dn];
if(d.account) {
if(!frm.doc.company) frappe.throw(__("Please select Company first"));
if(!frm.doc.posting_date) frappe.throw(__("Please select Posting Date first"));
return frappe.call({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_account_balance_and_party_type",
args: {
account: d.account,
date: frm.doc.posting_date,
company: frm.doc.company,
debit: flt(d.debit_in_account_currency),
credit: flt(d.credit_in_account_currency),
exchange_rate: d.exchange_rate,
cost_center: d.cost_center
},
callback: function(r) {
if(r.message) {
$.extend(d, r.message);
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, dt, dn);
refresh_field('accounts');
}
}
});
}
},
});

View File

@ -716,7 +716,7 @@ def get_payment_entry_against_invoice(dt, dn, amount=None, debit_in_account_cur
def get_payment_entry(ref_doc, args):
cost_center = frappe.get_cached_value('Company', ref_doc.company, "cost_center")
cost_center = ref_doc.get("cost_center") or frappe.get_cached_value('Company', ref_doc.company, "cost_center")
exchange_rate = 1
if args.get("party_account"):
# Modified to include the posting date for which the exchange rate is required.
@ -849,14 +849,14 @@ def get_outstanding(args):
}
@frappe.whitelist()
def get_party_account_and_balance(company, party_type, party):
def get_party_account_and_balance(company, party_type, party, cost_center=None):
if not frappe.has_permission("Account"):
frappe.msgprint(_("No Permission"), raise_exception=1)
account = get_party_account(party_type, party, company)
account_balance = get_balance_on(account=account)
party_balance = get_balance_on(party_type=party_type, party=party, company=company)
account_balance = get_balance_on(account=account, cost_center=cost_center)
party_balance = get_balance_on(party_type=party_type, party=party, company=company, cost_center=cost_center)
return {
"account": account,
@ -867,7 +867,7 @@ def get_party_account_and_balance(company, party_type, party):
@frappe.whitelist()
def get_account_balance_and_party_type(account, date, company, debit=None, credit=None, exchange_rate=None):
def get_account_balance_and_party_type(account, date, company, debit=None, credit=None, exchange_rate=None, cost_center=None):
"""Returns dict of account balance and party type to be set in Journal Entry on selection of account."""
if not frappe.has_permission("Account"):
frappe.msgprint(_("No Permission"), raise_exception=1)
@ -886,7 +886,7 @@ def get_account_balance_and_party_type(account, date, company, debit=None, credi
party_type = ""
grid_values = {
"balance": get_balance_on(account, date),
"balance": get_balance_on(account, date, cost_center=cost_center),
"party_type": party_type,
"account_type": account_details.account_type,
"account_currency": account_details.account_currency or company_currency,

View File

@ -204,12 +204,72 @@ class TestJournalEntry(unittest.TestCase):
self.assertEqual(jv.inter_company_journal_entry_reference, "")
self.assertEqual(jv1.inter_company_journal_entry_reference, "")
def test_jv_for_enable_allow_cost_center_in_entry_of_bs_account(self):
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
accounts_settings.save()
cost_center = "_Test Cost Center for BS Account - _TC"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
jv = make_journal_entry("_Test Cash - _TC", "_Test Bank - _TC", 100, cost_center = cost_center, save=False)
jv.voucher_type = "Bank Entry"
jv.multi_currency = 0
jv.cheque_no = "112233"
jv.cheque_date = nowdate()
jv.insert()
jv.submit()
expected_values = {
"_Test Cash - _TC": {
"cost_center": cost_center
},
"_Test Bank - _TC": {
"cost_center": cost_center
}
}
gl_entries = frappe.db.sql("""select account, cost_center, debit, credit
from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s
order by account asc""", jv.name, as_dict=1)
self.assertTrue(gl_entries)
for gle in gl_entries:
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
def test_jv_account_and_party_balance_for_enable_allow_cost_center_in_entry_of_bs_account(self):
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
from erpnext.accounts.utils import get_balance_on
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
accounts_settings.save()
cost_center = "_Test Cost Center for BS Account - _TC"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
jv = make_journal_entry("_Test Cash - _TC", "_Test Bank - _TC", 100, cost_center = cost_center, save=False)
account_balance = get_balance_on(account="_Test Bank - _TC", cost_center=cost_center)
jv.voucher_type = "Bank Entry"
jv.multi_currency = 0
jv.cheque_no = "112233"
jv.cheque_date = nowdate()
jv.insert()
jv.submit()
expected_account_balance = account_balance - 100
account_balance = get_balance_on(account="_Test Bank - _TC", cost_center=cost_center)
self.assertEqual(expected_account_balance, account_balance)
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
def make_journal_entry(account1, account2, amount, cost_center=None, posting_date=None, exchange_rate=1, save=True, submit=False, project=None):
if not cost_center:
cost_center = "_Test Cost Center - _TC"
jv = frappe.new_doc("Journal Entry")
jv.posting_date = posting_date or "2013-02-14"
jv.posting_date = posting_date or nowdate()
jv.company = "_Test Company"
jv.user_remark = "test"
jv.multi_currency = 1

View File

@ -245,7 +245,8 @@ frappe.ui.form.on('Payment Entry', {
company: frm.doc.company,
party_type: frm.doc.party_type,
party: frm.doc.party,
date: frm.doc.posting_date
date: frm.doc.posting_date,
cost_center: frm.doc.cost_center
},
callback: function(r, rt) {
if(r.message) {
@ -317,7 +318,8 @@ frappe.ui.form.on('Payment Entry', {
method: "erpnext.accounts.doctype.payment_entry.payment_entry.get_account_details",
args: {
"account": account,
"date": frm.doc.posting_date
"date": frm.doc.posting_date,
"cost_center": frm.doc.cost_center
},
callback: function(r, rt) {
if(r.message) {
@ -505,7 +507,8 @@ frappe.ui.form.on('Payment Entry', {
"party_type": frm.doc.party_type,
"payment_type": frm.doc.payment_type,
"party": frm.doc.party,
"party_account": frm.doc.payment_type=="Receive" ? frm.doc.paid_from : frm.doc.paid_to
"party_account": frm.doc.payment_type=="Receive" ? frm.doc.paid_from : frm.doc.paid_to,
"cost_center": frm.doc.cost_center
}
},
callback: function(r, rt) {
@ -859,3 +862,38 @@ frappe.ui.form.on('Payment Entry Deduction', {
frm.events.set_unallocated_amount(frm);
}
})
frappe.ui.form.on('Payment Entry', {
cost_center: function(frm){
if (frm.doc.posting_date && (frm.doc.paid_from||frm.doc.paid_to)) {
return frappe.call({
method: "erpnext.accounts.doctype.payment_entry.payment_entry.get_party_and_account_balance",
args: {
company: frm.doc.company,
date: frm.doc.posting_date,
paid_from: frm.doc.paid_from,
paid_to: frm.doc.paid_to,
ptype: frm.doc.party_type,
pty: frm.doc.party,
cost_center: frm.doc.cost_center
},
callback: function(r, rt) {
if(r.message) {
frappe.run_serially([
() => {
frm.set_value("paid_from_account_balance", r.message.paid_from_account_balance);
frm.set_value("paid_to_account_balance", r.message.paid_to_account_balance);
frm.set_value("party_balance", r.message.party_balance);
},
() => {
if(frm.doc.payment_type != "Internal") {
frm.events.get_outstanding_documents(frm);
}
}
]);
}
}
});
}
},
})

View File

@ -208,6 +208,39 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "cost_center",
"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": "Cost Center",
"length": 0,
"no_copy": 0,
"options": "Cost Center",
"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
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@ -1962,4 +1995,4 @@
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}
}

View File

@ -127,12 +127,12 @@ class PaymentEntry(AccountsController):
self.party_account = party_account
if self.paid_from and not (self.paid_from_account_currency or self.paid_from_account_balance):
acc = get_account_details(self.paid_from, self.posting_date)
acc = get_account_details(self.paid_from, self.posting_date, self.cost_center)
self.paid_from_account_currency = acc.account_currency
self.paid_from_account_balance = acc.account_balance
if self.paid_to and not (self.paid_to_account_currency or self.paid_to_account_balance):
acc = get_account_details(self.paid_to, self.posting_date)
acc = get_account_details(self.paid_to, self.posting_date, self.cost_center)
self.paid_to_account_currency = acc.account_currency
self.paid_to_account_balance = acc.account_balance
@ -419,7 +419,8 @@ class PaymentEntry(AccountsController):
"party_type": self.party_type,
"party": self.party,
"against": against_account,
"account_currency": self.party_account_currency
"account_currency": self.party_account_currency,
"cost_center": self.cost_center
})
dr_or_cr = "credit" if erpnext.get_party_account_type(self.party_type) == 'Receivable' else "debit"
@ -462,7 +463,8 @@ class PaymentEntry(AccountsController):
"account_currency": self.paid_from_account_currency,
"against": self.party if self.payment_type=="Pay" else self.paid_to,
"credit_in_account_currency": self.paid_amount,
"credit": self.base_paid_amount
"credit": self.base_paid_amount,
"cost_center": self.cost_center
})
)
if self.payment_type in ("Receive", "Internal Transfer"):
@ -472,7 +474,8 @@ class PaymentEntry(AccountsController):
"account_currency": self.paid_to_account_currency,
"against": self.party if self.payment_type=="Receive" else self.paid_from,
"debit_in_account_currency": self.received_amount,
"debit": self.base_received_amount
"debit": self.base_received_amount,
"cost_center": self.cost_center
})
)
@ -549,6 +552,10 @@ def get_outstanding_reference_documents(args):
condition = " and voucher_type='{0}' and voucher_no='{1}'"\
.format(frappe.db.escape(args["voucher_type"]), frappe.db.escape(args["voucher_no"]))
# Add cost center condition
if args.get("cost_center"):
condition += " and cost_center='%s'" % args.get("cost_center")
outstanding_invoices = get_outstanding_invoices(args.get("party_type"), args.get("party"),
args.get("party_account"), condition=condition)
@ -573,7 +580,7 @@ def get_outstanding_reference_documents(args):
return negative_outstanding_invoices + outstanding_invoices + orders_to_be_billed
def get_orders_to_be_billed(posting_date, party_type, party, party_account_currency, company_currency):
def get_orders_to_be_billed(posting_date, party_type, party, party_account_currency, company_currency, cost_center=None):
if party_type == "Customer":
voucher_type = 'Sales Order'
elif party_type == "Supplier":
@ -581,6 +588,12 @@ def get_orders_to_be_billed(posting_date, party_type, party, party_account_curre
elif party_type == "Employee":
voucher_type = None
# Add cost center condition
doc = frappe.get_doc({"doctype": voucher_type})
condition = ""
if doc and hasattr(doc, 'cost_center'):
condition = " and cost_center='%s'" % cost_center
orders = []
if voucher_type:
ref_field = "base_grand_total" if party_account_currency == company_currency else "grand_total"
@ -599,12 +612,14 @@ def get_orders_to_be_billed(posting_date, party_type, party, party_account_curre
and ifnull(status, "") != "Closed"
and {ref_field} > advance_paid
and abs(100 - per_billed) > 0.01
{condition}
order by
transaction_date, name
""".format(**{
"ref_field": ref_field,
"voucher_type": voucher_type,
"party_type": scrub(party_type)
"party_type": scrub(party_type),
"condition": condition
}), party, as_dict=True)
order_list = []
@ -616,7 +631,7 @@ def get_orders_to_be_billed(posting_date, party_type, party, party_account_curre
return order_list
def get_negative_outstanding_invoices(party_type, party, party_account, party_account_currency, company_currency):
def get_negative_outstanding_invoices(party_type, party, party_account, party_account_currency, company_currency, cost_center=None):
voucher_type = "Sales Invoice" if party_type == "Customer" else "Purchase Invoice"
supplier_condition = ""
if voucher_type == "Purchase Invoice":
@ -647,22 +662,23 @@ def get_negative_outstanding_invoices(party_type, party, party_account, party_ac
"grand_total_field": grand_total_field,
"voucher_type": voucher_type,
"party_type": scrub(party_type),
"party_account": "debit_to" if party_type == "Customer" else "credit_to"
"party_account": "debit_to" if party_type == "Customer" else "credit_to",
"cost_center": cost_center
}), (party, party_account), as_dict=True)
@frappe.whitelist()
def get_party_details(company, party_type, party, date):
def get_party_details(company, party_type, party, date, cost_center=None):
if not frappe.db.exists(party_type, party):
frappe.throw(_("Invalid {0}: {1}").format(party_type, party))
party_account = get_party_account(party_type, party, company)
account_currency = get_account_currency(party_account)
account_balance = get_balance_on(party_account, date)
account_balance = get_balance_on(party_account, date, cost_center=cost_center)
_party_name = "title" if party_type == "Student" else party_type.lower() + "_name"
party_name = frappe.db.get_value(party_type, party, _party_name)
party_balance = get_balance_on(party_type=party_type, party=party)
party_balance = get_balance_on(party_type=party_type, party=party, cost_center=cost_center)
return {
"party_account": party_account,
@ -674,11 +690,11 @@ def get_party_details(company, party_type, party, date):
@frappe.whitelist()
def get_account_details(account, date):
def get_account_details(account, date, cost_center=None):
frappe.has_permission('Payment Entry', throw=True)
return frappe._dict({
"account_currency": get_account_currency(account),
"account_balance": get_balance_on(account, date),
"account_balance": get_balance_on(account, date, cost_center=cost_center),
"account_type": frappe.db.get_value("Account", account, "account_type")
})
@ -855,6 +871,7 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
pe = frappe.new_doc("Payment Entry")
pe.payment_type = payment_type
pe.company = doc.company
pe.cost_center = doc.get("cost_center")
pe.posting_date = nowdate()
pe.mode_of_payment = doc.get("mode_of_payment")
pe.party_type = party_type
@ -912,4 +929,12 @@ def get_paid_amount(dt, dn, party_type, party, account, due_date):
and {dr_or_cr} > 0
""".format(dr_or_cr=dr_or_cr), (dt, dn, party_type, party, account, due_date))
return paid_amount[0][0] if paid_amount else 0
return paid_amount[0][0] if paid_amount else 0
@frappe.whitelist()
def get_party_and_account_balance(company, date, paid_from, paid_to=None, ptype=None, pty=None, cost_center=None):
return frappe._dict({
"party_balance": get_balance_on(party_type=ptype, party=pty, cost_center=cost_center),
"paid_from_account_balance": get_balance_on(paid_from, date, cost_center=cost_center),
"paid_to_account_balance": get_balance_on(paid_to, date=date, cost_center=cost_center)
})

View File

@ -8,8 +8,8 @@ import unittest
from frappe.utils import flt, nowdate
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry, InvalidPaymentEntry
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice, create_sales_invoice_against_cost_center
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice, make_purchase_invoice_against_cost_center
from erpnext.hr.doctype.expense_claim.test_expense_claim import make_expense_claim
test_dependencies = ["Item"]
@ -322,7 +322,7 @@ class TestPaymentEntry(unittest.TestCase):
self.assertTrue(gl_entries)
for i, gle in enumerate(gl_entries):
for gle in gl_entries:
self.assertEqual(expected_gle[gle.account][0], gle.account)
self.assertEqual(expected_gle[gle.account][1], gle.debit)
self.assertEqual(expected_gle[gle.account][2], gle.credit)
@ -394,3 +394,176 @@ class TestPaymentEntry(unittest.TestCase):
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
self.assertEqual(outstanding_amount, 0)
def test_payment_entry_against_sales_invoice_for_enable_allow_cost_center_in_entry_of_bs_account(self):
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
accounts_settings.save()
cost_center = "_Test Cost Center for BS Account - _TC"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
si = create_sales_invoice_against_cost_center(cost_center=cost_center, debit_to="Debtors - _TC")
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank - _TC")
self.assertEqual(pe.cost_center, si.cost_center)
pe.reference_no = "112211-1"
pe.reference_date = nowdate()
pe.paid_to = "_Test Bank - _TC"
pe.paid_amount = si.grand_total
pe.insert()
pe.submit()
expected_values = {
"_Test Bank - _TC": {
"cost_center": cost_center
},
"Debtors - _TC": {
"cost_center": cost_center
}
}
gl_entries = frappe.db.sql("""select account, cost_center, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
from `tabGL Entry` where voucher_type='Payment Entry' and voucher_no=%s
order by account asc""", pe.name, as_dict=1)
self.assertTrue(gl_entries)
for gle in gl_entries:
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
def test_payment_entry_against_sales_invoice_for_disable_allow_cost_center_in_entry_of_bs_account(self):
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
si = create_sales_invoice(debit_to="Debtors - _TC")
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank - _TC")
pe.reference_no = "112211-2"
pe.reference_date = nowdate()
pe.paid_to = "_Test Bank - _TC"
pe.paid_amount = si.grand_total
pe.insert()
pe.submit()
gl_entries = frappe.db.sql("""select account, cost_center, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
from `tabGL Entry` where voucher_type='Payment Entry' and voucher_no=%s
order by account asc""", pe.name, as_dict=1)
self.assertTrue(gl_entries)
for gle in gl_entries:
self.assertEqual(gle.cost_center, None)
def test_payment_entry_against_purchase_invoice_for_enable_allow_cost_center_in_entry_of_bs_account(self):
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
accounts_settings.save()
cost_center = "_Test Cost Center for BS Account - _TC"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
pi = make_purchase_invoice_against_cost_center(cost_center=cost_center, credit_to="Creditors - _TC")
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
self.assertEqual(pe.cost_center, pi.cost_center)
pe.reference_no = "112222-1"
pe.reference_date = nowdate()
pe.paid_from = "_Test Bank - _TC"
pe.paid_amount = pi.grand_total
pe.insert()
pe.submit()
expected_values = {
"_Test Bank - _TC": {
"cost_center": cost_center
},
"Creditors - _TC": {
"cost_center": cost_center
}
}
gl_entries = frappe.db.sql("""select account, cost_center, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
from `tabGL Entry` where voucher_type='Payment Entry' and voucher_no=%s
order by account asc""", pe.name, as_dict=1)
self.assertTrue(gl_entries)
for gle in gl_entries:
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
def test_payment_entry_against_purchase_invoice_for_disable_allow_cost_center_in_entry_of_bs_account(self):
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
pi = make_purchase_invoice(credit_to="Creditors - _TC")
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
pe.reference_no = "112222-2"
pe.reference_date = nowdate()
pe.paid_from = "_Test Bank - _TC"
pe.paid_amount = pi.grand_total
pe.insert()
pe.submit()
gl_entries = frappe.db.sql("""select account, cost_center, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
from `tabGL Entry` where voucher_type='Payment Entry' and voucher_no=%s
order by account asc""", pe.name, as_dict=1)
self.assertTrue(gl_entries)
for gle in gl_entries:
self.assertEqual(gle.cost_center, None)
def test_payment_entry_account_and_party_balance_for_enable_allow_cost_center_in_entry_of_bs_account(self):
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
from erpnext.accounts.utils import get_balance_on
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
accounts_settings.save()
cost_center = "_Test Cost Center for BS Account - _TC"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
si = create_sales_invoice_against_cost_center(cost_center=cost_center, debit_to="Debtors - _TC")
account_balance = get_balance_on(account="_Test Bank - _TC", cost_center=si.cost_center)
party_balance = get_balance_on(party_type="Customer", party=si.customer, cost_center=si.cost_center)
party_account_balance = get_balance_on(si.debit_to, cost_center=si.cost_center)
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank - _TC")
pe.reference_no = "112211-1"
pe.reference_date = nowdate()
pe.paid_to = "_Test Bank - _TC"
pe.paid_amount = si.grand_total
pe.insert()
pe.submit()
expected_account_balance = account_balance + si.grand_total
expected_party_balance = party_balance - si.grand_total
expected_party_account_balance = party_account_balance - si.grand_total
account_balance = get_balance_on(account=pe.paid_to, cost_center=pe.cost_center)
party_balance = get_balance_on(party_type="Customer", party=pe.party, cost_center=pe.cost_center)
party_account_balance = get_balance_on(account=pe.paid_from, cost_center=pe.cost_center)
self.assertEqual(pe.cost_center, si.cost_center)
self.assertEqual(expected_account_balance, account_balance)
self.assertEqual(expected_party_balance, party_balance)
self.assertEqual(expected_party_account_balance, party_account_balance)
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()

View File

@ -525,4 +525,4 @@ frappe.ui.form.on("Purchase Invoice", {
}
frm.toggle_reqd("supplier_warehouse", frm.doc.is_subcontracted==="Yes");
}
})
})

View File

@ -379,6 +379,39 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "cost_center",
"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": "Cost Center",
"length": 0,
"no_copy": 0,
"options": "Cost Center",
"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
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,

View File

@ -389,6 +389,7 @@ class PurchaseInvoice(BuyingController):
if self.party_account_currency==self.company_currency else grand_total,
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
"against_voucher_type": self.doctype,
"cost_center": self.cost_center
}, self.party_account_currency)
)
@ -472,7 +473,8 @@ class PurchaseInvoice(BuyingController):
"account": self.stock_received_but_not_billed,
"against": self.supplier,
"debit": flt(item.item_tax_amount, item.precision("item_tax_amount")),
"remarks": self.remarks or "Accounting Entry for Stock"
"remarks": self.remarks or "Accounting Entry for Stock",
"cost_center": self.cost_center
})
)
@ -500,7 +502,8 @@ class PurchaseInvoice(BuyingController):
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
"debit": base_asset_amount,
"debit_in_account_currency": (base_asset_amount
if asset_rbnb_currency == self.company_currency else asset_amount)
if asset_rbnb_currency == self.company_currency else asset_amount),
"cost_center": item.cost_center
}))
if item.item_tax_amount:
@ -526,7 +529,8 @@ class PurchaseInvoice(BuyingController):
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
"debit": base_asset_amount,
"debit_in_account_currency": (base_asset_amount
if cwip_account_currency == self.company_currency else asset_amount)
if cwip_account_currency == self.company_currency else asset_amount),
"cost_center": self.cost_center
}))
if item.item_tax_amount and not cint(erpnext.is_perpetual_inventory_enabled(self.company)):
@ -626,6 +630,7 @@ class PurchaseInvoice(BuyingController):
if self.party_account_currency==self.company_currency else self.paid_amount,
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
"against_voucher_type": self.doctype,
"cost_center": self.cost_center
}, self.party_account_currency)
)
@ -635,7 +640,8 @@ class PurchaseInvoice(BuyingController):
"against": self.supplier,
"credit": self.base_paid_amount,
"credit_in_account_currency": self.base_paid_amount \
if bank_account_currency==self.company_currency else self.paid_amount
if bank_account_currency==self.company_currency else self.paid_amount,
"cost_center": self.cost_center
}, bank_account_currency)
)
@ -656,6 +662,7 @@ class PurchaseInvoice(BuyingController):
if self.party_account_currency==self.company_currency else self.write_off_amount,
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
"against_voucher_type": self.doctype,
"cost_center": self.cost_center
}, self.party_account_currency)
)
gl_entries.append(
@ -665,7 +672,7 @@ class PurchaseInvoice(BuyingController):
"credit": flt(self.base_write_off_amount),
"credit_in_account_currency": self.base_write_off_amount \
if write_off_account_currency==self.company_currency else self.write_off_amount,
"cost_center": self.write_off_cost_center
"cost_center": self.cost_center or self.write_off_cost_center
})
)
@ -680,7 +687,7 @@ class PurchaseInvoice(BuyingController):
"against": self.supplier,
"debit_in_account_currency": self.rounding_adjustment,
"debit": self.base_rounding_adjustment,
"cost_center": round_off_cost_center,
"cost_center": self.cost_center or round_off_cost_center,
}
))

View File

@ -790,6 +790,66 @@ class TestPurchaseInvoice(unittest.TestCase):
pi_doc = frappe.get_doc('Purchase Invoice', pi.name)
self.assertEqual(pi_doc.outstanding_amount, 0)
def test_purchase_invoice_for_enable_allow_cost_center_in_entry_of_bs_account(self):
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
accounts_settings.save()
cost_center = "_Test Cost Center for BS Account - _TC"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
pi = make_purchase_invoice_against_cost_center(cost_center=cost_center, credit_to="Creditors - _TC")
self.assertEqual(pi.cost_center, cost_center)
expected_values = {
"Creditors - _TC": {
"cost_center": cost_center
},
"_Test Account Cost for Goods Sold - _TC": {
"cost_center": cost_center
}
}
gl_entries = frappe.db.sql("""select account, cost_center, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
order by account asc""", pi.name, as_dict=1)
self.assertTrue(gl_entries)
for gle in gl_entries:
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
def test_purchase_invoice_for_disable_allow_cost_center_in_entry_of_bs_account(self):
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
cost_center = "_Test Cost Center - _TC"
pi = make_purchase_invoice(credit_to="Creditors - _TC")
expected_values = {
"Creditors - _TC": {
"cost_center": None
},
"_Test Account Cost for Goods Sold - _TC": {
"cost_center": cost_center
}
}
gl_entries = frappe.db.sql("""select account, cost_center, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
order by account asc""", pi.name, as_dict=1)
self.assertTrue(gl_entries)
for gle in gl_entries:
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
def unlink_payment_on_cancel_of_invoice(enable=1):
accounts_settings = frappe.get_doc("Accounts Settings")
accounts_settings.unlink_payment_on_cancellation_of_invoice = enable
@ -839,4 +899,50 @@ def make_purchase_invoice(**args):
pi.submit()
return pi
test_records = frappe.get_test_records('Purchase Invoice')
def make_purchase_invoice_against_cost_center(**args):
pi = frappe.new_doc("Purchase Invoice")
args = frappe._dict(args)
pi.posting_date = args.posting_date or today()
if args.posting_time:
pi.posting_time = args.posting_time
if args.update_stock:
pi.update_stock = 1
if args.is_paid:
pi.is_paid = 1
if args.cash_bank_account:
pi.cash_bank_account=args.cash_bank_account
pi.company = args.company or "_Test Company"
pi.cost_center = args.cost_center or "_Test Cost Center - _TC"
pi.supplier = args.supplier or "_Test Supplier"
pi.currency = args.currency or "INR"
pi.conversion_rate = args.conversion_rate or 1
pi.is_return = args.is_return
pi.is_return = args.is_return
pi.credit_to = args.return_against or "Creditors - _TC"
pi.is_subcontracted = args.is_subcontracted or "No"
pi.supplier_warehouse = "_Test Warehouse 1 - _TC"
pi.append("items", {
"item_code": args.item or args.item_code or "_Test Item",
"warehouse": args.warehouse or "_Test Warehouse - _TC",
"qty": args.qty or 5,
"received_qty": args.received_qty or 0,
"rejected_qty": args.rejected_qty or 0,
"rate": args.rate or 50,
"conversion_factor": 1.0,
"serial_no": args.serial_no,
"stock_uom": "_Test UOM",
"cost_center": args.cost_center or "_Test Cost Center - _TC",
"project": args.project,
"rejected_warehouse": args.rejected_warehouse or "",
"rejected_serial_no": args.rejected_serial_no or ""
})
if not args.do_not_save:
pi.insert()
if not args.do_not_submit:
pi.submit()
return pi
test_records = frappe.get_test_records('Purchase Invoice')

View File

@ -447,6 +447,39 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "cost_center",
"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": "Cost Center",
"length": 0,
"no_copy": 0,
"options": "Cost Center",
"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
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,

View File

@ -735,7 +735,8 @@ class SalesInvoice(SellingController):
"debit_in_account_currency": grand_total_in_company_currency \
if self.party_account_currency==self.company_currency else grand_total,
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
"against_voucher_type": self.doctype
"against_voucher_type": self.doctype,
"cost_center": self.cost_center
}, self.party_account_currency)
)
@ -796,13 +797,14 @@ class SalesInvoice(SellingController):
"against": "Expense account - " + cstr(self.loyalty_redemption_account) + " for the Loyalty Program",
"credit": self.loyalty_amount,
"against_voucher": self.return_against if cint(self.is_return) else self.name,
"against_voucher_type": self.doctype
"against_voucher_type": self.doctype,
"cost_center": self.cost_center
})
)
gl_entries.append(
self.get_gl_dict({
"account": self.loyalty_redemption_account,
"cost_center": self.loyalty_redemption_cost_center,
"cost_center": self.cost_center or self.loyalty_redemption_cost_center,
"against": self.customer,
"debit": self.loyalty_amount,
"remark": "Loyalty Points redeemed by the customer"
@ -826,6 +828,7 @@ class SalesInvoice(SellingController):
else payment_mode.amount,
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
"against_voucher_type": self.doctype,
"cost_center": self.cost_center
}, self.party_account_currency)
)
@ -837,7 +840,8 @@ class SalesInvoice(SellingController):
"debit": payment_mode.base_amount,
"debit_in_account_currency": payment_mode.base_amount \
if payment_mode_account_currency==self.company_currency \
else payment_mode.amount
else payment_mode.amount,
"cost_center": self.cost_center
}, payment_mode_account_currency)
)
@ -854,7 +858,8 @@ class SalesInvoice(SellingController):
"debit_in_account_currency": flt(self.base_change_amount) \
if self.party_account_currency==self.company_currency else flt(self.change_amount),
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
"against_voucher_type": self.doctype
"against_voucher_type": self.doctype,
"cost_center": self.cost_center
}, self.party_account_currency)
)
@ -862,7 +867,8 @@ class SalesInvoice(SellingController):
self.get_gl_dict({
"account": self.account_for_change_amount,
"against": self.customer,
"credit": self.base_change_amount
"credit": self.base_change_amount,
"cost_center": self.cost_center
})
)
else:
@ -884,7 +890,8 @@ class SalesInvoice(SellingController):
"credit_in_account_currency": self.base_write_off_amount \
if self.party_account_currency==self.company_currency else self.write_off_amount,
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
"against_voucher_type": self.doctype
"against_voucher_type": self.doctype,
"cost_center": self.cost_center
}, self.party_account_currency)
)
gl_entries.append(
@ -894,7 +901,7 @@ class SalesInvoice(SellingController):
"debit": self.base_write_off_amount,
"debit_in_account_currency": self.base_write_off_amount \
if write_off_account_currency==self.company_currency else self.write_off_amount,
"cost_center": self.write_off_cost_center or default_cost_center
"cost_center": self.cost_center or self.write_off_cost_center or default_cost_center
}, write_off_account_currency)
)
@ -909,7 +916,7 @@ class SalesInvoice(SellingController):
"against": self.customer,
"credit_in_account_currency": self.base_rounding_adjustment,
"credit": self.base_rounding_adjustment,
"cost_center": round_off_cost_center,
"cost_center": self.cost_center or round_off_cost_center,
}
))

View File

@ -1438,6 +1438,66 @@ class TestSalesInvoice(unittest.TestCase):
si_doc = frappe.get_doc('Sales Invoice', si.name)
self.assertEqual(si_doc.outstanding_amount, 0)
def test_sales_invoice_for_enable_allow_cost_center_in_entry_of_bs_account(self):
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
accounts_settings.save()
cost_center = "_Test Cost Center for BS Account - _TC"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
si = create_sales_invoice_against_cost_center(cost_center=cost_center, debit_to="Debtors - _TC")
self.assertEqual(si.cost_center, cost_center)
expected_values = {
"Debtors - _TC": {
"cost_center": cost_center
},
"Sales - _TC": {
"cost_center": cost_center
}
}
gl_entries = frappe.db.sql("""select account, cost_center, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
order by account asc""", si.name, as_dict=1)
self.assertTrue(gl_entries)
for gle in gl_entries:
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
def test_sales_invoice_for_disable_allow_cost_center_in_entry_of_bs_account(self):
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
accounts_settings.save()
cost_center = "_Test Cost Center - _TC"
si = create_sales_invoice(debit_to="Debtors - _TC")
expected_values = {
"Debtors - _TC": {
"cost_center": None
},
"Sales - _TC": {
"cost_center": cost_center
}
}
gl_entries = frappe.db.sql("""select account, cost_center, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
order by account asc""", si.name, as_dict=1)
self.assertTrue(gl_entries)
for gle in gl_entries:
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
def create_sales_invoice(**args):
si = frappe.new_doc("Sales Invoice")
args = frappe._dict(args)
@ -1478,6 +1538,48 @@ def create_sales_invoice(**args):
return si
def create_sales_invoice_against_cost_center(**args):
si = frappe.new_doc("Sales Invoice")
args = frappe._dict(args)
if args.posting_date:
si.set_posting_time = 1
si.posting_date = args.posting_date or nowdate()
si.company = args.company or "_Test Company"
si.cost_center = args.cost_center or "_Test Cost Center - _TC"
si.customer = args.customer or "_Test Customer"
si.debit_to = args.debit_to or "Debtors - _TC"
si.update_stock = args.update_stock
si.is_pos = args.is_pos
si.is_return = args.is_return
si.return_against = args.return_against
si.currency=args.currency or "INR"
si.conversion_rate = args.conversion_rate or 1
si.append("items", {
"item_code": args.item or args.item_code or "_Test Item",
"gst_hsn_code": "999800",
"warehouse": args.warehouse or "_Test Warehouse - _TC",
"qty": args.qty or 1,
"rate": args.rate or 100,
"income_account": "Sales - _TC",
"expense_account": "Cost of Goods Sold - _TC",
"cost_center": args.cost_center or "_Test Cost Center - _TC",
"serial_no": args.serial_no
})
if not args.do_not_save:
si.insert()
if not args.do_not_submit:
si.submit()
else:
si.payment_schedule = []
else:
si.payment_schedule = []
return si
test_dependencies = ["Journal Entry", "Contact", "Address"]
test_records = frappe.get_test_records('Sales Invoice')

View File

@ -17,6 +17,21 @@ frappe.query_reports["General Ledger"] = {
"fieldtype": "Link",
"options": "Finance Book"
},
{
"fieldname":"cost_center",
"label": __("Cost Center"),
"fieldtype": "Link",
"options": "Cost Center",
"get_query": function() {
var company = frappe.query_report.get_filter_value('company');
return {
"doctype": "Cost Center",
"filters": {
"company": company,
}
}
}
},
{
"fieldname":"from_date",
"label": __("From Date"),

View File

@ -154,6 +154,11 @@ def get_conditions(filters):
conditions.append("""account in (select name from tabAccount
where lft>=%s and rgt<=%s and docstatus<2)""" % (lft, rgt))
if filters.get("cost_center"):
lft, rgt = frappe.db.get_value("Cost Center", filters["cost_center"], ["lft", "rgt"])
conditions.append("""cost_center in (select name from `tabCost Center`
where lft>=%s and rgt<=%s and docstatus<2)""" % (lft, rgt))
if filters.get("voucher_no"):
conditions.append("voucher_no=%(voucher_no)s")

View File

@ -12,6 +12,21 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
"default": frappe.defaults.get_user_default("Company"),
"reqd": 1
},
{
"fieldname":"cost_center",
"label": __("Cost Center"),
"fieldtype": "Link",
"options": "Cost Center",
"get_query": function() {
var company = frappe.query_report.get_filter_value('company');
return {
"doctype": "Cost Center",
"filters": {
"company": company,
}
}
}
},
{
"fieldname": "fiscal_year",
"label": __("Fiscal Year"),

View File

@ -84,7 +84,7 @@ def validate_fiscal_year(date, fiscal_year, company, label="Date", doc=None):
throw(_("{0} '{1}' not in Fiscal Year {2}").format(label, formatdate(date), fiscal_year))
@frappe.whitelist()
def get_balance_on(account=None, date=None, party_type=None, party=None, company=None, in_account_currency=True):
def get_balance_on(account=None, date=None, party_type=None, party=None, company=None, in_account_currency=True, cost_center=None):
if not account and frappe.form_dict.get("account"):
account = frappe.form_dict.get("account")
if not date and frappe.form_dict.get("date"):
@ -93,6 +93,9 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, company
party_type = frappe.form_dict.get("party_type")
if not party and frappe.form_dict.get("party"):
party = frappe.form_dict.get("party")
if not cost_center and frappe.form_dict.get("cost_center"):
cost_center = frappe.form_dict.get("cost_center")
cond = []
if date:
@ -113,17 +116,36 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, company
# hence, assuming balance as 0.0
return 0.0
allow_cost_center_in_entry_of_bs_account = get_allow_cost_center_in_entry_of_bs_account()
if cost_center and allow_cost_center_in_entry_of_bs_account:
cc = frappe.get_doc("Cost Center", cost_center)
if cc.is_group:
cond.append(""" exists (
select 1 from `tabCost Center` cc where cc.name = gle.cost_center
and cc.lft >= %s and cc.rgt <= %s
)""" % (cc.lft, cc.rgt))
else:
cond.append("""gle.cost_center = "%s" """ % (frappe.db.escape(cost_center, percent=False), ))
if account:
acc = frappe.get_doc("Account", account)
if not frappe.flags.ignore_account_permission:
acc.check_permission("read")
# for pl accounts, get balance within a fiscal year
if acc.report_type == 'Profit and Loss':
if not allow_cost_center_in_entry_of_bs_account and acc.report_type == 'Profit and Loss':
# for pl accounts, get balance within a fiscal year
cond.append("posting_date >= '%s' and voucher_type != 'Period Closing Voucher'" \
% year_start_date)
elif allow_cost_center_in_entry_of_bs_account:
# for all accounts, get balance within a fiscal year if maintain cost center in balance account is checked
cond.append("posting_date >= '%s' and voucher_type != 'Period Closing Voucher'" \
% year_start_date)
# different filter for group and ledger - improved performance
if acc.is_group:
cond.append("""exists (
@ -830,3 +852,10 @@ def get_coa(doctype, parent, is_root, chart=None):
accounts = [d for d in accounts if d['parent_account']==parent]
return accounts
def get_allow_cost_center_in_entry_of_bs_account():
def generator():
return cint(frappe.db.get_value('Accounts Settings', None, 'allow_cost_center_in_entry_of_bs_account'))
return frappe.local_cache("get_allow_cost_center_in_entry_of_bs_account", (), generator, regenerate_if_none=True)

View File

@ -343,7 +343,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
weight_per_unit: item.weight_per_unit,
weight_uom: item.weight_uom,
uom : item.uom,
pos_profile: me.frm.doc.doctype == 'Sales Invoice' ? me.frm.doc.pos_profile : ''
pos_profile: me.frm.doc.doctype == 'Sales Invoice' ? me.frm.doc.pos_profile : '',
cost_center: item.cost_center
}
},

View File

@ -78,6 +78,21 @@ function get_filters(){
"fieldtype": "Link",
"options": "Finance Book"
},
{
"fieldname":"cost_center",
"label": __("Cost Center"),
"fieldtype": "Link",
"options": "Cost Center",
"get_query": function() {
var company = frappe.query_report.get_filter_value('company');
return {
"doctype": "Cost Center",
"filters": {
"company": company,
}
};
}
},
{
"fieldname":"from_fiscal_year",
"label": __("Start Year"),

View File

@ -201,7 +201,18 @@ $.extend(erpnext.utils, {
} else {
return options[0];
}
}
},
copy_parent_value_in_all_row: function(doc, dt, dn, table_fieldname, fieldname, parent_fieldname) {
var d = locals[dt][dn];
if(d[fieldname]){
var cl = doc[table_fieldname] || [];
for(var i = 0; i < cl.length; i++) {
cl[i][fieldname] = doc[parent_fieldname];
}
}
refresh_field(table_fieldname);
},
});
erpnext.utils.select_alternate_items = function(opts) {

View File

@ -569,6 +569,74 @@ class TestDeliveryNote(unittest.TestCase):
dt = make_delivery_trip(dn.name)
self.assertEqual(dn.name, dt.delivery_stops[0].delivery_note)
def test_delivery_note_for_enable_allow_cost_center_in_entry_of_bs_account(self):
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
accounts_settings.save()
cost_center = "_Test Cost Center for BS Account - _TC"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company')
set_perpetual_inventory(1, company)
set_valuation_method("_Test Item", "FIFO")
make_stock_entry(target="_Test Warehouse - _TC", qty=5, basic_rate=100)
stock_in_hand_account = get_inventory_account('_Test Company')
dn = create_delivery_note(cost_center=cost_center)
gl_entries = get_gl_entries("Delivery Note", dn.name)
self.assertTrue(gl_entries)
expected_values = {
"Cost of Goods Sold - _TC": {
"cost_center": cost_center
},
stock_in_hand_account: {
"cost_center": cost_center
}
}
for i, gle in enumerate(gl_entries):
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
set_perpetual_inventory(0, company)
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
def test_delivery_note_for_disable_allow_cost_center_in_entry_of_bs_account(self):
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
cost_center = "_Test Cost Center - _TC"
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company')
set_perpetual_inventory(1, company)
set_valuation_method("_Test Item", "FIFO")
make_stock_entry(target="_Test Warehouse - _TC", qty=5, basic_rate=100)
stock_in_hand_account = get_inventory_account('_Test Company')
dn = create_delivery_note()
gl_entries = get_gl_entries("Delivery Note", dn.name)
self.assertTrue(gl_entries)
expected_values = {
"Cost of Goods Sold - _TC": {
"cost_center": cost_center
},
stock_in_hand_account: {
"cost_center": None
}
}
for i, gle in enumerate(gl_entries):
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
set_perpetual_inventory(0, company)
def create_delivery_note(**args):
dn = frappe.new_doc("Delivery Note")
args = frappe._dict(args)
@ -589,7 +657,7 @@ def create_delivery_note(**args):
"rate": args.rate or 100,
"conversion_factor": 1.0,
"expense_account": "Cost of Goods Sold - _TC",
"cost_center": "_Test Cost Center - _TC",
"cost_center": args.cost_center or "_Test Cost Center - _TC",
"serial_no": args.serial_no,
"target_warehouse": args.target_warehouse
})

View File

@ -470,4 +470,4 @@ def make_purchase_return(source_name, target_doc=None):
@frappe.whitelist()
def update_purchase_receipt_status(docname, status):
pr = frappe.get_doc("Purchase Receipt", docname)
pr.update_status(status)
pr.update_status(status)

View File

@ -333,11 +333,78 @@ class TestPurchaseReceipt(unittest.TestCase):
pr.cancel()
serial_nos = frappe.get_all('Serial No', {'asset': asset}, 'name') or []
self.assertEquals(len(serial_nos), 0)
frappe.db.sql("delete from `tabLocation")
#frappe.db.sql("delete from `tabLocation")
frappe.db.sql("delete from `tabAsset`")
def test_purchase_receipt_for_enable_allow_cost_center_in_entry_of_bs_account(self):
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
accounts_settings.save()
cost_center = "_Test Cost Center for BS Account - _TC"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
if not frappe.db.exists('Location', 'Test Location'):
frappe.get_doc({
'doctype': 'Location',
'location_name': 'Test Location'
}).insert()
pr = make_purchase_receipt(cost_center=cost_center)
set_perpetual_inventory(1, pr.company)
stock_in_hand_account = get_inventory_account(pr.company, pr.get("items")[0].warehouse)
gl_entries = get_gl_entries("Purchase Receipt", pr.name)
self.assertTrue(gl_entries)
expected_values = {
"Stock Received But Not Billed - _TC": {
"cost_center": cost_center
},
stock_in_hand_account: {
"cost_center": cost_center
}
}
for i, gle in enumerate(gl_entries):
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
set_perpetual_inventory(0, pr.company)
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
def test_purchase_receipt_for_disable_allow_cost_center_in_entry_of_bs_account(self):
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
if not frappe.db.exists('Location', 'Test Location'):
frappe.get_doc({
'doctype': 'Location',
'location_name': 'Test Location'
}).insert()
pr = make_purchase_receipt()
set_perpetual_inventory(1, pr.company)
stock_in_hand_account = get_inventory_account(pr.company, pr.get("items")[0].warehouse)
gl_entries = get_gl_entries("Purchase Receipt", pr.name)
self.assertTrue(gl_entries)
expected_values = {
"Stock Received But Not Billed - _TC": {
"cost_center": None
},
stock_in_hand_account: {
"cost_center": None
}
}
for i, gle in enumerate(gl_entries):
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
set_perpetual_inventory(0, pr.company)
def get_gl_entries(voucher_type, voucher_no):
return frappe.db.sql("""select account, debit, credit
return frappe.db.sql("""select account, debit, credit, cost_center
from `tabGL Entry` where voucher_type=%s and voucher_no=%s
order by account desc""", (voucher_type, voucher_no), as_dict=1)