[perpetual accounting] gl entries based on stock_value difference in sl entries

This commit is contained in:
Nabin Hait
2013-08-26 16:53:30 +05:30
parent aeba24ee81
commit 27994c216a
20 changed files with 399 additions and 352 deletions

View File

@@ -9,40 +9,38 @@ def make_test_records(verbose):
accounts = [
# [account_name, parent_account, group_or_ledger]
["_Test Account Bank Account", "Bank Accounts - _TC", "Ledger"],
["_Test Account Bank Account", "Bank Accounts", "Ledger"],
["_Test Account Stock Expenses", "Direct Expenses - _TC", "Group"],
["_Test Account Shipping Charges", "_Test Account Stock Expenses - _TC", "Ledger"],
["_Test Account Customs Duty", "_Test Account Stock Expenses - _TC", "Ledger"],
["_Test Account Stock Expenses", "Direct Expenses", "Group"],
["_Test Account Shipping Charges", "_Test Account Stock Expenses", "Ledger"],
["_Test Account Customs Duty", "_Test Account Stock Expenses", "Ledger"],
["_Test Account Tax Assets", "Current Assets - _TC", "Group"],
["_Test Account VAT", "_Test Account Tax Assets - _TC", "Ledger"],
["_Test Account Service Tax", "_Test Account Tax Assets - _TC", "Ledger"],
["_Test Account Tax Assets", "Current Assets", "Group"],
["_Test Account VAT", "_Test Account Tax Assets", "Ledger"],
["_Test Account Service Tax", "_Test Account Tax Assets", "Ledger"],
["_Test Account Reserves and Surplus", "Current Liabilities - _TC", "Ledger"],
["_Test Account Reserves and Surplus", "Current Liabilities", "Ledger"],
["_Test Account Cost for Goods Sold", "Expenses - _TC", "Ledger"],
["_Test Account Excise Duty", "_Test Account Tax Assets - _TC", "Ledger"],
["_Test Account Education Cess", "_Test Account Tax Assets - _TC", "Ledger"],
["_Test Account S&H Education Cess", "_Test Account Tax Assets - _TC", "Ledger"],
["_Test Account CST", "Direct Expenses - _TC", "Ledger"],
["_Test Account Discount", "Direct Expenses - _TC", "Ledger"],
["_Test Account Cost for Goods Sold", "Expenses", "Ledger"],
["_Test Account Excise Duty", "_Test Account Tax Assets", "Ledger"],
["_Test Account Education Cess", "_Test Account Tax Assets", "Ledger"],
["_Test Account S&H Education Cess", "_Test Account Tax Assets", "Ledger"],
["_Test Account CST", "Direct Expenses", "Ledger"],
["_Test Account Discount", "Direct Expenses", "Ledger"],
# related to Account Inventory Integration
["_Test Account Stock In Hand", "Current Assets - _TC", "Ledger"],
["_Test Account Fixed Assets", "Current Assets - _TC", "Ledger"],
["_Test Account Stock In Hand", "Current Assets", "Ledger"],
["_Test Account Fixed Assets", "Current Assets", "Ledger"],
]
test_objects = make_test_objects("Account", [[{
"doctype": "Account",
"account_name": account_name,
"parent_account": parent_account,
"company": "_Test Company",
"group_or_ledger": group_or_ledger
}] for account_name, parent_account, group_or_ledger in accounts])
webnotes.conn.set_value("Company", "_Test Company", "stock_in_hand_account",
"_Test Account Stock In Hand - _TC")
for company, abbr in [["_Test Company", "_TC"], ["_Test Company 1", "_TC1"]]:
test_objects = make_test_objects("Account", [[{
"doctype": "Account",
"account_name": account_name,
"parent_account": parent_account + " - " + abbr,
"company": company,
"group_or_ledger": group_or_ledger
}] for account_name, parent_account, group_or_ledger in accounts])
return test_objects

View File

@@ -396,7 +396,7 @@ class DocType(BuyingController):
gl_entries.append(
self.get_gl_dict({
"account": self.get_company_default("expenses_included_in_valuation"),
"cost_center": self.get_company_default("stock_adjustment_cost_center"),
"cost_center": self.get_company_default("cost_center"),
"against": self.doc.credit_to,
"credit": valuation_tax,
"remarks": self.doc.remarks or "Accounting Entry for Stock"

View File

@@ -41,7 +41,7 @@ class TestPurchaseInvoice(unittest.TestCase):
for d in gl_entries:
self.assertEqual([d.debit, d.credit], expected_gl_entries.get(d.account))
def atest_gl_entries_with_perpetual_accounting(self):
def test_gl_entries_with_perpetual_accounting(self):
webnotes.defaults.set_global_default("perpetual_accounting", 1)
self.assertEqual(cint(webnotes.defaults.get_global_default("perpetual_accounting")), 1)
@@ -70,7 +70,7 @@ class TestPurchaseInvoice(unittest.TestCase):
webnotes.defaults.set_global_default("perpetual_accounting", 0)
def atest_gl_entries_with_aia_for_non_stock_items(self):
def test_gl_entries_with_aia_for_non_stock_items(self):
webnotes.defaults.set_global_default("perpetual_accounting", 1)
self.assertEqual(cint(webnotes.defaults.get_global_default("perpetual_accounting")), 1)

View File

@@ -557,10 +557,8 @@ class DocType(SellingController):
if gl_entries:
make_gl_entries(gl_entries, cancel=(self.doc.docstatus == 2),
update_outstanding=update_outstanding, merge_entries=False)
warehouse_list = list(set([d.warehouse for d in
self.doclist.get({"parentfield": "entries"})]))
self.sync_stock_account_balance(warehouse_list)
self.update_gl_entries_after()
def make_customer_gl_entry(self, gl_entries):
if self.doc.grand_total:
@@ -605,13 +603,7 @@ class DocType(SellingController):
# expense account gl entries
if cint(webnotes.defaults.get_global_default("perpetual_accounting")) \
and cint(self.doc.update_stock):
for item in self.doclist.get({"parentfield": "entries"}):
self.check_expense_account(item)
if item.buying_amount:
gl_entries += self.get_gl_entries_for_stock(item.expense_account,
-1*item.buying_amount, item.warehouse, cost_center=item.cost_center)
gl_entries += self.get_gl_entries_for_stock()
def make_pos_gl_entries(self, gl_entries):
if cint(self.doc.is_pos) and self.doc.cash_bank_account and self.doc.paid_amount:

View File

@@ -10,13 +10,25 @@ from accounts.utils import validate_expense_against_budget
def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True,
update_outstanding='Yes'):
if not cancel:
if merge_entries:
gl_map = merge_similar_entries(gl_map)
gl_map = process_gl_map(gl_map, merge_entries)
save_entries(gl_map, adv_adj, update_outstanding)
else:
delete_gl_entries(gl_map, adv_adj, update_outstanding)
def process_gl_map(gl_map, merge_entries=True):
if merge_entries:
gl_map = merge_similar_entries(gl_map)
for entry in gl_map:
# round off upto 2 decimal
entry["debit"] = flt(entry["debit"], 2)
entry["credit"] = flt(entry["credit"], 2)
# toggle debit, credit if negative entry
if flt(entry["debit"]) < 0 or flt(entry["credit"]) < 0:
entry["debit"], entry["credit"] = abs(flt(entry["credit"])), abs(flt(entry["debit"]))
return gl_map
def merge_similar_entries(gl_map):
merged_gl_map = []
for entry in gl_map:
@@ -31,7 +43,6 @@ def merge_similar_entries(gl_map):
# filter zero debit and credit entries
merged_gl_map = filter(lambda x: flt(x["debit"])!=0 or flt(x["credit"])!=0, merged_gl_map)
return merged_gl_map
def check_if_in_list(gle, gl_mqp):
@@ -43,31 +54,11 @@ def check_if_in_list(gle, gl_mqp):
and cstr(e.get('cost_center')) == cstr(gle.get('cost_center')):
return e
def check_budget(gl_map, cancel):
for gle in gl_map:
if gle.get('cost_center'):
#check budget only if account is expense account
acc_details = webnotes.conn.get_value("Account", gle['account'],
['is_pl_account', 'debit_or_credit'])
if acc_details[0]=="Yes" and acc_details[1]=="Debit":
webnotes.get_obj('Budget Control').check_budget(gle, cancel)
def save_entries(gl_map, adv_adj, update_outstanding):
total_debit = total_credit = 0.0
def _swap(entry):
entry["debit"], entry["credit"] = abs(flt(entry["credit"])), abs(flt(entry["debit"]))
for entry in gl_map:
# round off upto 2 decimal
entry["debit"] = flt(entry["debit"], 2)
entry["credit"] = flt(entry["credit"], 2)
# toggle debit, credit if negative entry
if flt(entry["debit"]) < 0 or flt(entry["credit"]) < 0:
_swap(entry)
make_entry(entry, adv_adj, update_outstanding)
# check against budget
validate_expense_against_budget(entry)
# update total debit / credit
@@ -86,14 +77,14 @@ def make_entry(args, adv_adj, update_outstanding):
def validate_total_debit_credit(total_debit, total_credit):
if abs(total_debit - total_credit) > 0.005:
webnotes.throw(_("Debit and Credit not equal for this voucher: Diff (Debit) is ") +
webnotes.throw(webnotes._("Debit and Credit not equal for this voucher: Diff (Debit) is ") +
cstr(total_debit - total_credit))
def delete_gl_entries(gl_entries, adv_adj, update_outstanding):
def delete_gl_entries(gl_entries=None, adv_adj=False, update_outstanding="Yes"):
from accounts.doctype.gl_entry.gl_entry import check_negative_balance, \
check_freezing_date, update_outstanding_amt, validate_freezed_account
check_freezing_date(gl_entries[0]["posting_date"], adv_adj)
if gl_entries:
check_freezing_date(gl_entries[0]["posting_date"], adv_adj)
webnotes.conn.sql("""delete from `tabGL Entry` where voucher_type=%s and voucher_no=%s""",
(gl_entries[0]["voucher_type"], gl_entries[0]["voucher_no"]))

View File

@@ -343,33 +343,24 @@ def validate_stock_and_account_balance():
to enable perpetual accounting." +
_(" Following accounts are not synced with stock balance") + ": \n" +
"\n".join(difference.keys())), raise_exception=1)
def get_stock_and_account_difference(warehouse_list=None):
from stock.utils import get_latest_stock_balance
if not warehouse_list:
warehouse_list = webnotes.conn.sql_list("""select name from tabWarehouse
where docstatus<2""")
def get_stock_and_account_difference(account_list=None, posting_date=None):
from stock.utils import get_stock_balance_on
if not posting_date: posting_date = nowdate()
account_warehouse_map = {}
warehouse_with_no_account = []
difference = {}
warehouse_account = webnotes.conn.sql("""select name, account from tabWarehouse
where name in (%s)""" % ', '.join(['%s']*len(warehouse_list)), warehouse_list, as_dict=1)
where account in (%s)""" % ', '.join(['%s']*len(account_list)), account_list, as_dict=1)
for wh in warehouse_account:
if not wh.account: warehouse_with_no_account.append(wh.name)
account_warehouse_map.setdefault(wh.account, []).append(wh.name)
if warehouse_with_no_account:
msgprint(_("Please mention Perpetual Account in warehouse master for following warehouses")
+ ": " + '\n'.join(warehouse_with_no_account), raise_exception=1)
bin_map = get_latest_stock_balance()
for account, warehouse_list in account_warehouse_map.items():
account_balance = get_balance_on(account)
stock_value = sum([sum(bin_map.get(warehouse, {}).values())
for warehouse in warehouse_list])
account_balance = get_balance_on(account, posting_date)
stock_value = get_stock_balance_on(warehouse_list, posting_date)
if abs(flt(stock_value) - flt(account_balance)) > 0.005:
difference.setdefault(account, flt(stock_value) - flt(account_balance))