[cleanup] [minor] period closing voucher inherited from accounts_controller with testcases
This commit is contained in:
parent
9653f60e89
commit
4af17a88b0
@ -3,179 +3,102 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import webnotes
|
import webnotes
|
||||||
|
|
||||||
from webnotes.utils import cstr, flt, getdate
|
from webnotes.utils import cstr, flt, getdate
|
||||||
from webnotes.model import db_exists
|
from webnotes import msgprint, _
|
||||||
from webnotes.model.doc import Document
|
from controllers.accounts_controller import AccountsController
|
||||||
from webnotes.model.bean import copy_doclist
|
|
||||||
from webnotes.model.code import get_obj
|
|
||||||
from webnotes import msgprint
|
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
class DocType(AccountsController):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class DocType:
|
|
||||||
def __init__(self,d,dl):
|
def __init__(self,d,dl):
|
||||||
self.doc, self.doclist = d, dl
|
self.doc, self.doclist = d, dl
|
||||||
self.td, self.tc = 0, 0
|
|
||||||
self.year_start_date = ''
|
self.year_start_date = ''
|
||||||
self.year_end_date = ''
|
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
self.validate_account_head()
|
||||||
|
self.validate_posting_date()
|
||||||
|
self.validate_pl_balances()
|
||||||
|
|
||||||
|
def on_submit(self):
|
||||||
|
self.make_gl_entries()
|
||||||
|
|
||||||
|
def on_cancel(self):
|
||||||
|
webnotes.conn.sql("""delete from `tabGL Entry`
|
||||||
|
where voucher_type = 'Period Closing Voucher' and voucher_no=%s""", self.doc.name)
|
||||||
|
|
||||||
def validate_account_head(self):
|
def validate_account_head(self):
|
||||||
acc_det = sql("select debit_or_credit, is_pl_account, group_or_ledger, company \
|
debit_or_credit, is_pl_account = webnotes.conn.get_value("Account",
|
||||||
from `tabAccount` where name = '%s'" % (self.doc.closing_account_head))
|
self.doc.closing_account_head, ["debit_or_credit", "is_pl_account"])
|
||||||
|
|
||||||
# Account should be under liability
|
|
||||||
if cstr(acc_det[0][0]) != 'Credit' or cstr(acc_det[0][1]) != 'No':
|
|
||||||
msgprint("Account: %s must be created under 'Source of Funds'" % self.doc.closing_account_head)
|
|
||||||
raise Exception
|
|
||||||
|
|
||||||
# Account must be a ledger
|
|
||||||
if cstr(acc_det[0][2]) != 'Ledger':
|
|
||||||
msgprint("Account %s must be a ledger" % self.doc.closing_account_head)
|
|
||||||
raise Exception
|
|
||||||
|
|
||||||
# Account should belong to company selected
|
|
||||||
if cstr(acc_det[0][3]) != self.doc.company:
|
|
||||||
msgprint("Account %s does not belong to Company %s ." % (self.doc.closing_account_head, self.doc.company))
|
|
||||||
raise Exception
|
|
||||||
|
|
||||||
|
if debit_or_credit != 'Credit' or is_pl_account != 'No':
|
||||||
|
webnotes.throw(_("Account") + ": " + self.doc.closing_account_head +
|
||||||
|
_("must be a Liability account"))
|
||||||
|
|
||||||
def validate_posting_date(self):
|
def validate_posting_date(self):
|
||||||
yr = sql("""select year_start_date, adddate(year_start_date, interval 1 year)
|
from accounts.utils import get_fiscal_year
|
||||||
from `tabFiscal Year` where name=%s""", (self.doc.fiscal_year, ))
|
self.year_start_date = get_fiscal_year(self.doc.posting_date)[1]
|
||||||
self.year_start_date = yr and yr[0][0] or ''
|
|
||||||
self.year_end_date = yr and yr[0][1] or ''
|
|
||||||
|
|
||||||
# Posting Date should be within closing year
|
pce = webnotes.conn.sql("""select name from `tabPeriod Closing Voucher`
|
||||||
if getdate(self.doc.posting_date) < getdate(self.year_start_date) or getdate(self.doc.posting_date) > getdate(self.year_end_date):
|
where posting_date > %s and fiscal_year = %s and docstatus = 1""",
|
||||||
msgprint("Posting Date should be within Closing Fiscal Year")
|
(self.doc.posting_date, self.doc.fiscal_year))
|
||||||
raise Exception
|
|
||||||
|
|
||||||
# Period Closing Entry
|
|
||||||
pce = sql("select name from `tabPeriod Closing Voucher` \
|
|
||||||
where posting_date > '%s' and fiscal_year = '%s' and docstatus = 1" \
|
|
||||||
% (self.doc.posting_date, self.doc.fiscal_year))
|
|
||||||
if pce and pce[0][0]:
|
if pce and pce[0][0]:
|
||||||
msgprint("Another Period Closing Entry: %s has been made after posting date: %s"\
|
webnotes.throw(_("Another Period Closing Entry") + ": " + cstr(pce[0][0]) +
|
||||||
% (cstr(pce[0][0]), self.doc.posting_date))
|
_("has been made after posting date") + ": " + self.doc.posting_date)
|
||||||
raise Exception
|
|
||||||
|
|
||||||
|
|
||||||
def validate_pl_balances(self):
|
def validate_pl_balances(self):
|
||||||
income_bal = sql("select sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) \
|
income_bal = webnotes.conn.sql("""
|
||||||
from `tabGL Entry` t1, tabAccount t2 where t1.account = t2.name \
|
select sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0))
|
||||||
and t1.posting_date between '%s' and '%s' and t2.debit_or_credit = 'Credit' \
|
from `tabGL Entry` t1, tabAccount t2
|
||||||
and t2.group_or_ledger = 'Ledger' and t2.is_pl_account = 'Yes' and t2.docstatus < 2 \
|
where t1.account = t2.name and t1.posting_date between %s and %s
|
||||||
and t2.company = '%s'" % (self.year_start_date, self.doc.posting_date, self.doc.company))
|
and t2.debit_or_credit = 'Credit' and t2.is_pl_account = 'Yes'
|
||||||
|
and t2.docstatus < 2 and t2.company = %s""",
|
||||||
|
(self.year_start_date, self.doc.posting_date, self.doc.company))
|
||||||
|
|
||||||
expense_bal = sql("select sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) \
|
expense_bal = webnotes.conn.sql("""
|
||||||
from `tabGL Entry` t1, tabAccount t2 where t1.account = t2.name \
|
select sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0))
|
||||||
and t1.posting_date between '%s' and '%s' and t2.debit_or_credit = 'Debit' \
|
from `tabGL Entry` t1, tabAccount t2
|
||||||
and t2.group_or_ledger = 'Ledger' and t2.is_pl_account = 'Yes' and t2.docstatus < 2 \
|
where t1.account = t2.name and t1.posting_date between %s and %s
|
||||||
and t2.company = '%s'" % (self.year_start_date, self.doc.posting_date, self.doc.company))
|
and t2.debit_or_credit = 'Debit' and t2.is_pl_account = 'Yes'
|
||||||
|
and t2.docstatus < 2 and t2.company=%s""",
|
||||||
|
(self.year_start_date, self.doc.posting_date, self.doc.company))
|
||||||
|
|
||||||
income_bal = income_bal and income_bal[0][0] or 0
|
income_bal = income_bal and income_bal[0][0] or 0
|
||||||
expense_bal = expense_bal and expense_bal[0][0] or 0
|
expense_bal = expense_bal and expense_bal[0][0] or 0
|
||||||
|
|
||||||
if not income_bal and not expense_bal:
|
if not income_bal and not expense_bal:
|
||||||
msgprint("Both Income and Expense balances are zero. No Need to make Period Closing Entry.")
|
webnotes.throw(_("Both Income and Expense balances are zero. \
|
||||||
raise Exception
|
No Need to make Period Closing Entry."))
|
||||||
|
|
||||||
|
def get_pl_balances(self):
|
||||||
|
"""Get balance for pl accounts"""
|
||||||
|
|
||||||
def get_pl_balances(self, d_or_c):
|
return webnotes.conn.sql("""
|
||||||
"""Get account (pl) specific balance"""
|
select t1.account, sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) as balance
|
||||||
acc_bal = sql("select t1.account, sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) \
|
from `tabGL Entry` t1, `tabAccount` t2
|
||||||
from `tabGL Entry` t1, `tabAccount` t2 where t1.account = t2.name and t2.group_or_ledger = 'Ledger' \
|
where t1.account = t2.name and ifnull(t2.is_pl_account, 'No') = 'Yes'
|
||||||
and ifnull(t2.is_pl_account, 'No') = 'Yes' and ifnull(is_cancelled, 'No') = 'No' \
|
and t2.docstatus < 2 and t2.company = %s
|
||||||
and t2.debit_or_credit = '%s' and t2.docstatus < 2 and t2.company = '%s' \
|
and t1.posting_date between %s and %s
|
||||||
and t1.posting_date between '%s' and '%s' group by t1.account " \
|
group by t1.account
|
||||||
% (d_or_c, self.doc.company, self.year_start_date, self.doc.posting_date))
|
""", (self.doc.company, self.year_start_date, self.doc.posting_date), as_dict=1)
|
||||||
return acc_bal
|
|
||||||
|
|
||||||
|
def make_gl_entries(self):
|
||||||
|
gl_entries = []
|
||||||
|
net_pl_balance = 0
|
||||||
|
pl_accounts = self.get_pl_balances()
|
||||||
|
for acc in pl_accounts:
|
||||||
|
if flt(acc.balance):
|
||||||
|
gl_entries.append(self.get_gl_dict({
|
||||||
|
"account": acc.account,
|
||||||
|
"debit": abs(flt(acc.balance)) if flt(acc.balance) < 0 else 0,
|
||||||
|
"credit": abs(flt(acc.balance)) if flt(acc.balance) > 0 else 0,
|
||||||
|
}))
|
||||||
|
|
||||||
def make_gl_entries(self, acc_det):
|
net_pl_balance += flt(acc.balance)
|
||||||
for a in acc_det:
|
|
||||||
if flt(a[1]):
|
|
||||||
fdict = {
|
|
||||||
'account': a[0],
|
|
||||||
'cost_center': '',
|
|
||||||
'against': '',
|
|
||||||
'debit': flt(a[1]) < 0 and -1*flt(a[1]) or 0,
|
|
||||||
'credit': flt(a[1]) > 0 and flt(a[1]) or 0,
|
|
||||||
'remarks': self.doc.remarks,
|
|
||||||
'voucher_type': self.doc.doctype,
|
|
||||||
'voucher_no': self.doc.name,
|
|
||||||
'transaction_date': self.doc.transaction_date,
|
|
||||||
'posting_date': self.doc.posting_date,
|
|
||||||
'fiscal_year': self.doc.fiscal_year,
|
|
||||||
'against_voucher': '',
|
|
||||||
'against_voucher_type': '',
|
|
||||||
'company': self.doc.company,
|
|
||||||
'is_opening': 'No',
|
|
||||||
'aging_date': self.doc.posting_date
|
|
||||||
}
|
|
||||||
|
|
||||||
self.save_entry(fdict)
|
if net_pl_balance:
|
||||||
|
gl_entries.append(self.get_gl_dict({
|
||||||
|
"account": self.doc.closing_account_head,
|
||||||
|
"debit": abs(net_pl_balance) if net_pl_balance > 0 else 0,
|
||||||
|
"credit": abs(net_pl_balance) if net_pl_balance < 0 else 0
|
||||||
|
}))
|
||||||
|
|
||||||
|
from accounts.general_ledger import make_gl_entries
|
||||||
def save_entry(self, fdict, is_cancel = 'No'):
|
make_gl_entries(gl_entries)
|
||||||
# Create new GL entry object and map values
|
|
||||||
le = Document('GL Entry')
|
|
||||||
for k in fdict:
|
|
||||||
le.fields[k] = fdict[k]
|
|
||||||
|
|
||||||
le_obj = get_obj(doc=le)
|
|
||||||
# validate except on_cancel
|
|
||||||
if is_cancel == 'No':
|
|
||||||
le_obj.validate()
|
|
||||||
|
|
||||||
# update total debit / credit except on_cancel
|
|
||||||
self.td += flt(le.credit)
|
|
||||||
self.tc += flt(le.debit)
|
|
||||||
|
|
||||||
# save
|
|
||||||
le.save(1)
|
|
||||||
le_obj.on_update(adv_adj = '', cancel = '')
|
|
||||||
|
|
||||||
|
|
||||||
def validate(self):
|
|
||||||
# validate account head
|
|
||||||
self.validate_account_head()
|
|
||||||
|
|
||||||
# validate posting date
|
|
||||||
self.validate_posting_date()
|
|
||||||
|
|
||||||
# check if pl balance:
|
|
||||||
self.validate_pl_balances()
|
|
||||||
|
|
||||||
|
|
||||||
def on_submit(self):
|
|
||||||
|
|
||||||
# Makes closing entries for Expense Account
|
|
||||||
in_acc_det = self.get_pl_balances('Credit')
|
|
||||||
self.make_gl_entries(in_acc_det)
|
|
||||||
|
|
||||||
# Makes closing entries for Expense Account
|
|
||||||
ex_acc_det = self.get_pl_balances('Debit')
|
|
||||||
self.make_gl_entries(ex_acc_det)
|
|
||||||
|
|
||||||
|
|
||||||
# Makes Closing entry for Closing Account Head
|
|
||||||
bal = self.tc - self.td
|
|
||||||
self.make_gl_entries([[self.doc.closing_account_head, flt(bal)]])
|
|
||||||
|
|
||||||
|
|
||||||
def on_cancel(self):
|
|
||||||
# get all submit entries of current closing entry voucher
|
|
||||||
gl_entries = sql("select account, debit, credit from `tabGL Entry` where voucher_type = 'Period Closing Voucher' and voucher_no = '%s' and ifnull(is_cancelled, 'No') = 'No'" % (self.doc.name))
|
|
||||||
|
|
||||||
# Swap Debit & Credit Column and make gl entry
|
|
||||||
for gl in gl_entries:
|
|
||||||
fdict = {'account': gl[0], 'cost_center': '', 'against': '', 'debit': flt(gl[2]), 'credit' : flt(gl[1]), 'remarks': "cancelled", 'voucher_type': self.doc.doctype, 'voucher_no': self.doc.name, 'transaction_date': self.doc.transaction_date, 'posting_date': self.doc.posting_date, 'fiscal_year': self.doc.fiscal_year, 'against_voucher': '', 'against_voucher_type': '', 'company': self.doc.company, 'is_opening': 'No', 'aging_date': 'self.doc.posting_date'}
|
|
||||||
self.save_entry(fdict, is_cancel = 'Yes')
|
|
||||||
|
|
||||||
# Update is_cancelled = 'Yes' to all gl entries for current voucher
|
|
||||||
sql("update `tabGL Entry` set is_cancelled = 'Yes' where voucher_type = '%s' and voucher_no = '%s'" % (self.doc.doctype, self.doc.name))
|
|
@ -0,0 +1,53 @@
|
|||||||
|
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import unittest
|
||||||
|
import webnotes
|
||||||
|
|
||||||
|
class TestPeriodClosingVoucher(unittest.TestCase):
|
||||||
|
def test_closing_entry(self):
|
||||||
|
from accounts.doctype.journal_voucher.test_journal_voucher import test_records as jv_records
|
||||||
|
jv = webnotes.bean(copy=jv_records[2])
|
||||||
|
jv.insert()
|
||||||
|
jv.submit()
|
||||||
|
|
||||||
|
jv1 = webnotes.bean(copy=jv_records[0])
|
||||||
|
jv1.doclist[2].account = "_Test Account Cost for Goods Sold - _TC"
|
||||||
|
jv1.doclist[2].debit = 600.0
|
||||||
|
jv1.doclist[1].credit = 600.0
|
||||||
|
jv1.insert()
|
||||||
|
jv1.submit()
|
||||||
|
|
||||||
|
pcv = webnotes.bean(copy=test_record)
|
||||||
|
pcv.insert()
|
||||||
|
pcv.submit()
|
||||||
|
|
||||||
|
gl_entries = webnotes.conn.sql("""select account, debit, credit
|
||||||
|
from `tabGL Entry` where voucher_type='Period Closing Voucher' and voucher_no=%s
|
||||||
|
order by account asc, debit asc""", pcv.doc.name, as_dict=1)
|
||||||
|
|
||||||
|
self.assertTrue(gl_entries)
|
||||||
|
|
||||||
|
expected_gl_entries = sorted([
|
||||||
|
["_Test Account Reserves and Surplus - _TC", 200.0, 0.0],
|
||||||
|
["_Test Account Cost for Goods Sold - _TC", 0.0, 600.0],
|
||||||
|
["Sales - _TC", 400.0, 0.0]
|
||||||
|
])
|
||||||
|
for i, gle in enumerate(gl_entries):
|
||||||
|
self.assertEquals(expected_gl_entries[i][0], gle.account)
|
||||||
|
self.assertEquals(expected_gl_entries[i][1], gle.debit)
|
||||||
|
self.assertEquals(expected_gl_entries[i][2], gle.credit)
|
||||||
|
|
||||||
|
|
||||||
|
test_dependencies = ["Customer", "Cost Center"]
|
||||||
|
|
||||||
|
test_record = [{
|
||||||
|
"doctype": "Period Closing Voucher",
|
||||||
|
"closing_account_head": "_Test Account Reserves and Surplus - _TC",
|
||||||
|
"company": "_Test Company",
|
||||||
|
"fiscal_year": "_Test Fiscal Year 2013",
|
||||||
|
"posting_date": "2013-03-31",
|
||||||
|
"remarks": "test"
|
||||||
|
}]
|
Loading…
x
Reference in New Issue
Block a user