merged deprecate account balance

This commit is contained in:
Anand Doshi
2012-10-01 11:30:00 +05:30
52 changed files with 3540 additions and 2997 deletions

View File

@@ -25,14 +25,8 @@ from webnotes.model.doclist import getlist, copy_doclist
from webnotes.model.code import get_obj, get_server_obj, run_server_obj, updatedb, check_syntax
from webnotes import session, form, msgprint, errprint
set = webnotes.conn.set
sql = webnotes.conn.sql
get_value = webnotes.conn.get_value
in_transaction = webnotes.conn.in_transaction
convert_to_lists = webnotes.conn.convert_to_lists
# -----------------------------------------------------------------------------------------
class DocType:
def __init__(self,d,dl):
@@ -49,7 +43,6 @@ class DocType:
ret={'address':add[0][0]}
return ret
# check whether master name entered for supplier/customer
def validate_master_name(self):
if (self.doc.master_type == 'Customer' or self.doc.master_type == 'Supplier') and not self.doc.master_name:
@@ -86,7 +79,6 @@ class DocType:
if (self.doc.fields.get('__islocal') or (not self.doc.name)) and sql("select name from tabAccount where account_name=%s and company=%s", (self.doc.account_name, self.doc.company)):
msgprint("Account Name already exists, please rename", raise_exception=1)
# validate root details
def validate_root_details(self):
#does not exists parent
if self.doc.account_name in ['Income','Source of Funds', 'Expenses','Application of Funds'] and self.doc.parent_account:
@@ -104,7 +96,6 @@ class DocType:
elif self.doc.account_name in ['Source of Funds','Application of Funds']:
self.doc.is_pl_account = 'No'
# Convert group to ledger
def convert_group_to_ledger(self):
if self.check_if_child_exists():
msgprint("Account: %s has existing child. You can not convert this account to ledger" % (self.doc.name), raise_exception=1)
@@ -115,7 +106,6 @@ class DocType:
self.doc.save()
return 1
# Convert ledger to group
def convert_ledger_to_group(self):
if self.check_gle_exists():
msgprint("Account with existing transaction can not be converted to group.",
@@ -133,47 +123,15 @@ class DocType:
exists = sql("select name from `tabGL Entry` where account = '%s' and ifnull(is_cancelled, 'No') = 'No'" % (self.doc.name))
return exists and exists[0][0] or ''
# check if child exists
def check_if_child_exists(self):
return sql("select name from `tabAccount` where parent_account = %s and docstatus != 2", self.doc.name)
# Update balance
def update_balance(self, fy, period_det, flag = 1):
# update in all parents
for p in period_det:
sql("update `tabAccount Balance` t1, `tabAccount` t2 set t1.balance = t1.balance + (%s), t1.opening = t1.opening + (%s), t1.debit = t1.debit + (%s), t1.credit = t1.credit + (%s) where t1.period = %s and t1.account = t2.name and t2.lft<=%s and t2.rgt>=%s", (flt(flag)*flt(p[1]), flt(flag)*flt(p[2]), flt(flag)*flt(p[3]), flt(flag)*flt(p[4]), p[0], self.doc.lft, self.doc.rgt))
# change parent balance
def change_parent_bal(self):
period_det = []
fy = sql("select name from `tabFiscal Year` where if(ifnull(is_fiscal_year_closed, 'No'),ifnull(is_fiscal_year_closed, 'No'), 'No') = 'No'")
for f in fy:
# get my opening, balance
per = sql("select period, balance, opening, debit, credit from `tabAccount Balance` where account = %s and fiscal_year = %s", (self.doc.name, f[0]))
for p in per:
period_det.append([p[0], p[1], p[2], p[3], p[4]])
# deduct balance from old_parent
op = get_obj('Account',self.doc.old_parent)
op.update_balance(fy, period_det, -1)
# add to new parent_account
flag = 1
if op.doc.debit_or_credit != self.doc.debit_or_credit:
flag = -1
get_obj('Account', self.doc.parent_account).update_balance(fy, period_det, flag)
msgprint('Balances updated')
def validate_mandatory(self):
if not self.doc.debit_or_credit:
msgprint("Debit or Credit field is mandatory", raise_exception=1)
if not self.doc.is_pl_account:
msgprint("Is PL Account field is mandatory", raise_exception=1)
# VALIDATE
def validate(self):
self.validate_master_name()
self.validate_rate_for_tax()
@@ -185,27 +143,6 @@ class DocType:
# Defaults
if not self.doc.parent_account:
self.doc.parent_account = ''
# parent changed
if self.doc.old_parent and self.doc.parent_account and (self.doc.parent_account != self.doc.old_parent):
self.change_parent_bal()
# Add current fiscal year balance
def set_year_balance(self):
p = sql("select name, start_date, end_date, fiscal_year from `tabPeriod` where docstatus != 2 and period_type in ('Month', 'Year')")
for d in p:
if not sql("select name from `tabAccount Balance` where account=%s and period=%s", (self.doc.name, d[0])):
ac = Document('Account Balance')
ac.account = self.doc.name
ac.period = d[0]
ac.start_date = d[1].strftime('%Y-%m-%d')
ac.end_date = d[2].strftime('%Y-%m-%d')
ac.fiscal_year = d[3]
ac.opening = 0
ac.debit = 0
ac.credit = 0
ac.balance = 0
ac.save(1)
# Update Node Set Model
def update_nsm_model(self):
@@ -213,13 +150,9 @@ class DocType:
import webnotes.utils.nestedset
webnotes.utils.nestedset.update_nsm(self)
# ON UPDATE
def on_update(self):
# update nsm
self.update_nsm_model()
# Add curret year balance
self.set_year_balance()
# Check user role for approval process
def get_authorized_user(self):
@@ -243,49 +176,31 @@ class DocType:
msgprint("Total Outstanding amount (%s) for <b>%s</b> can not be greater than credit limit (%s). To change your credit limit settings, please update the <b>%s</b>" \
% (fmt_money(tot_outstanding), account, fmt_money(credit_limit), credit_limit_from), raise_exception=1)
# Account with balance cannot be inactive
def check_balance_before_trash(self):
def validate_trash(self):
"""checks gl entries and if child exists"""
if self.check_gle_exists():
msgprint("Account with existing transaction (Sales Invoice / Purchase Invoice / Journal Voucher) can not be trashed", raise_exception=1)
if self.check_if_child_exists():
msgprint("Child account exists for this account. You can not trash this account.", raise_exception=1)
# get current year balance
def get_curr_bal(self):
bal = sql("select balance from `tabAccount Balance` where period = '%s' and parent = '%s'" % (get_defaults()['fiscal_year'], self.doc.name),debug=0)
return bal and flt(bal[0][0]) or 0
# On Trash
def on_trash(self):
# Check balance before trash
self.check_balance_before_trash()
self.validate_trash()
# rebuild tree
from webnotes.utils.nestedset import update_remove_node
update_remove_node('Account', self.doc.name)
self.update_nsm_model()
# delete all cancelled gl entry of this account
sql("delete from `tabGL Entry` where account = %s and ifnull(is_cancelled, 'No') = 'Yes'", self.doc.name)
#delete Account Balance
sql("delete from `tabAccount Balance` where account = %s", self.doc.name)
# On restore
def on_restore(self):
# rebuild tree
self.update_nsm_model()
# intiate balances
self.set_year_balance()
# on rename
def on_rename(self,newdn,olddn):
company_abbr = sql("select tc.abbr from `tabAccount` ta, `tabCompany` tc where ta.company = tc.name and ta.name=%s", olddn)[0][0]
newdnchk = newdn.split(" - ")
if newdnchk[-1].lower() != company_abbr.lower():
if newdnchk[-1].lower() != company_abbr.lower():
msgprint("Please add company abbreviation <b>%s</b>" %(company_abbr), raise_exception=1)
else:
account_name = " - ".join(newdnchk[:-1])
sql("update `tabAccount` set account_name = '%s' where name = '%s'" %(account_name,olddn))
sql("update `tabAccount` set account_name = '%s' where name = '%s'" %(account_name,olddn))

View File

@@ -1 +0,0 @@
from __future__ import unicode_literals

View File

@@ -1,177 +0,0 @@
# DocType, Account Balance
[
# These values are common in all dictionaries
{
'creation': '2012-03-27 14:35:40',
'docstatus': 0,
'modified': '2012-03-27 14:35:40',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all DocType
{
'_last_update': u'1322549700',
'autoname': u'_ACB.######',
'colour': u'White:FFF',
'default_print_format': u'Standard',
'doctype': 'DocType',
'istable': 0,
'module': u'Accounts',
'name': '__common__',
'search_fields': u'account, period, fiscal_year, balance',
'section_style': u'Simple',
'server_code_error': u' ',
'show_in_menu': 0,
'version': 6
},
# These values are common for all DocField
{
'doctype': u'DocField',
'name': '__common__',
'parent': u'Account Balance',
'parentfield': u'fields',
'parenttype': u'DocType',
'permlevel': 0
},
# These values are common for all DocPerm
{
'amend': 0,
'cancel': 0,
'create': 0,
'doctype': u'DocPerm',
'name': '__common__',
'parent': u'Account Balance',
'parentfield': u'permissions',
'parenttype': u'DocType',
'permlevel': 0,
'read': 1,
'submit': 0,
'write': 0
},
# DocType, Account Balance
{
'doctype': 'DocType',
'name': u'Account Balance'
},
# DocPerm
{
'doctype': u'DocPerm',
'role': u'Accounts User'
},
# DocPerm
{
'doctype': u'DocPerm',
'role': u'Accounts Manager'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'account',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Account',
'options': u'Account',
'search_index': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'period',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Period',
'oldfieldname': u'period',
'oldfieldtype': u'Link',
'options': u'Period',
'search_index': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'opening',
'fieldtype': u'Currency',
'label': u'Opening',
'oldfieldname': u'opening',
'oldfieldtype': u'Currency'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'debit',
'fieldtype': u'Currency',
'label': u'Debit',
'oldfieldname': u'debit',
'oldfieldtype': u'Currency'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'credit',
'fieldtype': u'Currency',
'label': u'Credit',
'oldfieldname': u'credit',
'oldfieldtype': u'Currency'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'balance',
'fieldtype': u'Currency',
'label': u'Balance',
'oldfieldname': u'balance',
'oldfieldtype': u'Currency'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'fiscal_year',
'fieldtype': u'Link',
'hidden': 1,
'in_filter': 1,
'label': u'Fiscal Year',
'oldfieldname': u'fiscal_year',
'oldfieldtype': u'Link',
'options': u'Fiscal Year',
'search_index': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'start_date',
'fieldtype': u'Date',
'hidden': 1,
'in_filter': 1,
'label': u'Start Date',
'oldfieldname': u'start_date',
'oldfieldtype': u'Date',
'search_index': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'end_date',
'fieldtype': u'Date',
'hidden': 1,
'in_filter': 1,
'label': u'End Date',
'oldfieldname': u'end_date',
'oldfieldtype': u'Date',
'search_index': 1
}
]

View File

@@ -1,221 +0,0 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Please edit this list and import only required elements
from __future__ import unicode_literals
import webnotes
from webnotes.utils import add_days, add_months, add_years, cint, cstr, date_diff, default_fields, flt, fmt_money, formatdate, getTraceback, get_defaults, get_first_day, get_last_day, getdate, has_common, month_name, now, nowdate, replace_newlines, sendmail, set_default, str_esc_quote, user_format, validate_email_add
from webnotes.model import db_exists
from webnotes.model.doc import Document, addchild, getchildren, make_autoname
from webnotes.model.doclist import getlist, copy_doclist
from webnotes.model.code import get_obj, get_server_obj, run_server_obj, updatedb, check_syntax
from webnotes import session, form, msgprint, errprint
set = webnotes.conn.set
sql = webnotes.conn.sql
get_value = webnotes.conn.get_value
in_transaction = webnotes.conn.in_transaction
convert_to_lists = webnotes.conn.convert_to_lists
# -----------------------------------------------------------------------------------------
class DocType:
def __init__(self, d, dl):
self.doc, self.doclist = d,dl
def repost(self):
if not self.doc.company:
msgprint("Please select company", raise_exception=1)
if not in_transaction:
sql("start transaction")
self.rebuid_account_tree()
self.clear_account_balances()
self.create_account_balances()
self.update_opening(self.doc.company)
self.post_entries()
sql("commit")
msgprint("Account balance reposted for fiscal year: " + self.doc.name)
def rebuid_account_tree(self):
from webnotes.utils.nestedset import rebuild_tree
rebuild_tree('Account', 'parent_account')
def clear_account_balances(self):
# balances clear - `tabAccount Balance` for fiscal year
sql("update `tabAccount Balance` t1, tabAccount t2 set t1.opening=0, t1.balance=0, t1.debit=0, t1.credit=0 where t1.fiscal_year=%s and t2.company = %s and t1.account = t2.name", (self.doc.name, self.doc.company))
def create_account_balances(self):
# get periods
period_list = self.get_period_list()
cnt = 0
# get accounts
al = sql("select name from tabAccount")
for a in al:
# check
if sql("select count(*) from `tabAccount Balance` where fiscal_year=%s and account=%s", (self.doc.name, a[0]))[0][0] < 13:
for p in period_list:
# check if missing
if not sql("select name from `tabAccount Balance` where period=%s and account=%s and fiscal_year=%s", (p[0], a[0], self.doc.name)):
d = Document('Account Balance')
d.account = a[0]
d.period = p[0]
d.start_date = p[1].strftime('%Y-%m-%d')
d.end_date = p[2].strftime('%Y-%m-%d')
d.fiscal_year = p[3]
d.debit = 0
d.credit = 0
d.opening = 0
d.balance = 0
d.save(1)
cnt += 1
if cnt % 100 == 0:
sql("commit")
sql("start transaction")
return cnt
# Get periods(month and year)
#=================================
def get_period_list(self):
periods = []
pl = sql("SELECT name, start_date, end_date, fiscal_year FROM tabPeriod WHERE fiscal_year = '%s' and period_type in ('Month', 'Year') order by start_date ASC, end_date DESC" % self.doc.name)
for p in pl:
periods.append([p[0], p[1], p[2], p[3]])
return periods
# ====================================================================================
def update_opening(self, company):
"""
set opening from last year closing
"""
abl = sql("select t1.account, t1.balance from `tabAccount Balance` t1, tabAccount t2 where t1.period= '%s' and t2.company= '%s' and ifnull(t2.is_pl_account, 'No') = 'No' and t1.account = t2.name for update" % (self.doc.past_year, company))
cnt = 0
for ab in abl:
if cnt % 100 == 0:
sql("commit")
sql("start transaction")
sql("update `tabAccount Balance` set opening=%s where period=%s and account=%s", (ab[1], self.doc.name, ab[0]))
sql("update `tabAccount Balance` set balance=%s where fiscal_year=%s and account=%s", (ab[1], self.doc.name, ab[0]))
cnt += 1
return cnt
def get_account_details(self, account):
return sql("select debit_or_credit, lft, rgt, is_pl_account from tabAccount where name=%s", account)[0]
# ====================================================================================
def post_entries(self):
sql("LOCK TABLE `tabGL Entry` WRITE")
# post each gl entry (batch or complete)
gle = sql("select name, account, debit, credit, is_opening, posting_date from `tabGL Entry` where fiscal_year=%s and ifnull(is_cancelled,'No')='No' and company=%s", (self.doc.name, self.doc.company))
account_details = {}
cnt = 0
for entry in gle:
# commit in batches of 100
if cnt % 100 == 0:
sql("commit")
sql("start transaction")
cnt += 1
#print cnt
if not account_details.has_key(entry[1]):
account_details[entry[1]] = self.get_account_details(entry[1])
det = account_details[entry[1]]
diff = flt(entry[2])-flt(entry[3])
if det[0]=='Credit': diff = -diff
# build dict
p = {
'debit': entry[4]=='No' and flt(entry[2]) or 0
,'credit': entry[4]=='No' and flt(entry[3]) or 0
,'opening': entry[4]=='Yes' and diff or 0
# end date conditino only if it is not opening
,'end_date_condition':(entry[4]!='Yes' and ("and ab.end_date >= '"+entry[5].strftime('%Y-%m-%d')+"'") or '')
,'diff': diff
,'lft': det[1]
,'rgt': det[2]
,'posting_date': entry[5]
,'fiscal_year': self.doc.name
}
sql("""update `tabAccount Balance` ab, `tabAccount` a
set
ab.debit = ifnull(ab.debit,0) + %(debit)s
,ab.credit = ifnull(ab.credit,0) + %(credit)s
,ab.opening = ifnull(ab.opening,0) + %(opening)s
,ab.balance = ifnull(ab.balance,0) + %(diff)s
where
a.lft <= %(lft)s
and a.rgt >= %(rgt)s
and ab.account = a.name
%(end_date_condition)s
and ab.fiscal_year = '%(fiscal_year)s' """ % p)
sql("UNLOCK TABLES")
# Clear PV/RV outstanding
# ====================================================================================
def clear_outstanding(self):
# clear o/s of current year
sql("update `tabPurchase Invoice` set outstanding_amount = 0 where fiscal_year=%s and company=%s", (self.doc.name, self.doc.company))
sql("update `tabSales Invoice` set outstanding_amount = 0 where fiscal_year=%s and company=%s", (self.doc.name, self.doc.company))
# Update Voucher Outstanding
def update_voucher_outstanding(self):
# Clear outstanding
self.clear_outstanding()
against_voucher = sql("select against_voucher, against_voucher_type from `tabGL Entry` where fiscal_year=%s and ifnull(is_cancelled, 'No')='No' and company=%s and ifnull(against_voucher, '') != '' and ifnull(against_voucher_type, '') != '' group by against_voucher, against_voucher_type", (self.doc.name, self.doc.company))
for d in against_voucher:
# get voucher balance
bal = sql("select sum(debit)-sum(credit) from `tabGL Entry` where against_voucher=%s and against_voucher_type=%s and ifnull(is_cancelled, 'No') = 'No'", (d[0], d[1]))
bal = bal and flt(bal[0][0]) or 0.0
if d[1] == 'Purchase Invoice':
bal = -bal
# set voucher balance
sql("update `tab%s` set outstanding_amount=%s where name='%s'"% (d[1], bal, d[0]))
# ====================================================================================
# Generate periods
def create_periods(self):
get_obj('Period Control').generate_periods(self.doc.name)
def validate(self):
if sql("select name from `tabFiscal Year` where year_start_date < %s", self.doc.year_start_date) and not self.doc.past_year:
msgprint("Please enter Past Year", raise_exception=1)
# on update
def on_update(self):
self.create_periods()
self.create_account_balances()
if self.doc.fields.get('localname', '')[:15] == 'New Fiscal Year':
for d in sql("select name from tabCompany"):
self.update_opening(d[0])

View File

@@ -41,36 +41,6 @@ class DocType:
dcc = TransactionBase().get_company_currency(arg)
return dcc
# Get current balance
# --------------------
def get_bal(self,arg):
ac, fy = arg.split('~~~')
det = webnotes.conn.sql("select t1.balance, t2.debit_or_credit from `tabAccount Balance` t1, `tabAccount` t2 where t1.period = %s and t2.name=%s and t1.account = t2.name", (fy, ac))
bal = det and flt(det[0][0]) or 0
dr_or_cr = det and flt(det[0][1]) or ''
return fmt_money(bal) + ' ' + dr_or_cr
def get_period_balance(self,arg):
acc, f, t = arg.split('~~~')
c, fy = '', get_defaults()['fiscal_year']
det = webnotes.conn.sql("select debit_or_credit, lft, rgt, is_pl_account from tabAccount where name=%s", acc)
if f: c += (' and t1.posting_date >= "%s"' % f)
if t: c += (' and t1.posting_date <= "%s"' % t)
bal = webnotes.conn.sql("select sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) from `tabGL Entry` t1 where t1.account='%s' and ifnull(is_opening, 'No') = 'No' %s" % (acc, c))
bal = bal and flt(bal[0][0]) or 0
if det[0][0] != 'Debit':
bal = (-1) * bal
# add opening for balance sheet accounts
if det[0][3] == 'No':
opening = flt(webnotes.conn.sql("select opening from `tabAccount Balance` where account=%s and period=%s", (acc, fy))[0][0])
bal = bal + opening
return flt(bal)
def get_period_difference(self,arg, cost_center =''):
# used in General Ledger Page Report
# used for Budget where cost center passed as extra argument
@@ -89,32 +59,6 @@ class DocType:
return flt(bal)
# Get Children (for tree)
# -----------------------
def get_cl(self, arg):
fy = get_defaults()['fiscal_year']
parent, parent_acc_name, company, type = arg.split(',')
# get children account details
if type=='Account':
if parent=='Root Node':
cl = webnotes.conn.sql("select t1.name, t1.group_or_ledger, t1.debit_or_credit, t2.balance, t1.account_name from tabAccount t1, `tabAccount Balance` t2 where ifnull(t1.parent_account, '') = '' and t1.docstatus != 2 and t1.company=%s and t1.name = t2.account and t2.period = %s order by t1.name asc", (company, fy),as_dict=1)
else:
cl = webnotes.conn.sql("select t1.name, t1.group_or_ledger, t1.debit_or_credit, t2.balance, t1.account_name from tabAccount t1, `tabAccount Balance` t2 where ifnull(t1.parent_account, '')=%s and t1.docstatus != 2 and t1.company=%s and t1.name = t2.account and t2.period = %s order by t1.name asc",(parent, company, fy) ,as_dict=1)
# remove Decimals
for c in cl: c['balance'] = flt(c['balance'])
# get children cost center details
elif type=='Cost Center':
if parent=='Root Node':
cl = webnotes.conn.sql("select name,group_or_ledger, cost_center_name from `tabCost Center` where ifnull(parent_cost_center, '')='' and docstatus != 2 and company_name=%s order by name asc",(company),as_dict=1)
else:
cl = webnotes.conn.sql("select name,group_or_ledger,cost_center_name from `tabCost Center` where ifnull(parent_cost_center, '')=%s and docstatus != 2 and company_name=%s order by name asc",(parent,company),as_dict=1)
return {'parent':parent, 'parent_acc_name':parent_acc_name, 'cl':cl}
# Add a new account
# -----------------
@@ -254,39 +198,10 @@ class DocType:
# set as cancelled
if cancel:
vt, vn = self.get_val(le_map['voucher_type'], doc, doc), self.get_val(le_map['voucher_no'], doc, doc)
vt = self.get_val(le_map['voucher_type'], doc, doc)
vn = self.get_val(le_map['voucher_no'], doc, doc)
webnotes.conn.sql("update `tabGL Entry` set is_cancelled='Yes' where voucher_type=%s and voucher_no=%s", (vt, vn))
# Get account balance on any date
# -------------------------------
def get_as_on_balance(self, account_name, fiscal_year, as_on, credit_or_debit, lft, rgt):
# initialization
det = webnotes.conn.sql("select start_date, opening from `tabAccount Balance` where period = %s and account = %s", (fiscal_year, account_name))
from_date, opening, debit_bal, credit_bal, closing_bal = det and det[0][0] or getdate(nowdate()), det and flt(det[0][1]) or 0, 0, 0, det and flt(det[0][1]) or 0
# prev month closing
prev_month_det = webnotes.conn.sql("select end_date, debit, credit, balance from `tabAccount Balance` where account = %s and end_date <= %s and fiscal_year = %s order by end_date desc limit 1", (account_name, as_on, fiscal_year))
if prev_month_det:
from_date = getdate(add_days(prev_month_det[0][0].strftime('%Y-%m-%d'), 1))
opening = 0
debit_bal = flt(prev_month_det[0][1])
credit_bal = flt(prev_month_det[0][2])
closing_bal = flt(prev_month_det[0][3])
# curr month transaction
if getdate(as_on) >= from_date:
curr_month_bal = webnotes.conn.sql("select SUM(t1.debit), SUM(t1.credit) from `tabGL Entry` t1, `tabAccount` t2 WHERE t1.posting_date >= %s AND t1.posting_date <= %s and ifnull(t1.is_opening, 'No') = 'No' AND t1.account = t2.name AND t2.lft >= %s AND t2.rgt <= %s and ifnull(t1.is_cancelled, 'No') = 'No'", (from_date, as_on, lft, rgt))
curr_debit_amt, curr_credit_amt = flt(curr_month_bal[0][0]), flt(curr_month_bal[0][1])
debit_bal = curr_month_bal and debit_bal + curr_debit_amt or debit_bal
credit_bal = curr_month_bal and credit_bal + curr_credit_amt or credit_bal
if credit_or_debit == 'Credit':
curr_debit_amt, curr_credit_amt = -1*flt(curr_month_bal[0][0]), -1*flt(curr_month_bal[0][1])
closing_bal = closing_bal + curr_debit_amt - curr_credit_amt
return flt(debit_bal), flt(credit_bal), flt(closing_bal)
# ADVANCE ALLOCATION
#-------------------
def get_advances(self, obj, account_head, table_name,table_field_name, dr_or_cr):

View File

@@ -121,117 +121,8 @@ class DocType:
if getdate(self.doc.posting_date) <= getdate(acc_frozen_upto) and not bde_auth_role in webnotes.user.get_roles():
msgprint("You are not authorized to do/modify back dated accounting entries before %s." % getdate(acc_frozen_upto).strftime('%d-%m-%Y'), raise_exception=1)
# create new bal if not exists
#-----------------------------
def create_new_balances(self, det):
# check
if sql("select count(t1.name) from `tabAccount Balance` t1, tabAccount t2 where t1.fiscal_year=%s and t2.lft <= %s and t2.rgt >= %s and t2.name = t1.account", (self.doc.fiscal_year, det[0][0], det[0][1]))[0][0] < 13*(cint(det[0][1]) - cint(det[0][0]) +1)/2:
period_list = self.get_period_list()
accounts = sql("select name from tabAccount where lft <= %s and rgt >= %s" % (det[0][0], det[0][1]))
for p in period_list:
for a in accounts:
# check if missing
if not sql("select name from `tabAccount Balance` where period=%s and account=%s and fiscal_year=%s", (p[0], a[0], self.doc.fiscal_year)):
d = Document('Account Balance')
d.account = a[0]
d.period = p[0]
d.start_date = p[1].strftime('%Y-%m-%d')
d.end_date = p[2].strftime('%Y-%m-%d')
d.fiscal_year = self.doc.fiscal_year
d.debit = 0
d.credit = 0
d.opening = 0
d.balance = 0
d.save(1)
# Post Balance
# ------------
def post_balance(self, acc, cancel):
# get details
det = sql("select lft, rgt, debit_or_credit from `tabAccount` where name='%s'" % acc)
# amount to debit
amt = flt(self.doc.debit) - flt(self.doc.credit)
if det[0][2] == 'Credit': amt = -amt
if cancel:
debit = -1 * flt(self.doc.credit)
credit = -1 * flt(self.doc.debit)
else:
debit = flt(self.doc.debit)
credit = flt(self.doc.credit)
self.create_new_balances(det)
# build dict
p = {
'debit': self.doc.is_opening=='No' and flt(debit) or 0
,'credit':self.doc.is_opening=='No' and flt(credit) or 0
,'opening': self.doc.is_opening=='Yes' and amt or 0
# end date condition only if it is not opening
,'end_date_condition':(self.doc.is_opening!='Yes' and ("and ab.end_date >= '"+self.doc.posting_date+"'") or '')
,'diff': amt
,'lft': cint(det[0][0])
,'rgt': cint(det[0][1])
,'posting_date': self.doc.posting_date
,'fiscal_year': self.doc.fiscal_year
}
# Update account balance for current year
sql("""update `tabAccount Balance` ab, `tabAccount` a
set
ab.debit = ifnull(ab.debit,0) + %(debit)s
,ab.credit = ifnull(ab.credit,0) + %(credit)s
,ab.opening = ifnull(ab.opening,0) + %(opening)s
,ab.balance = ifnull(ab.balance,0) + %(diff)s
where
a.lft <= %(lft)s
and a.rgt >= %(rgt)s
and ab.account = a.name
%(end_date_condition)s
and ab.fiscal_year = '%(fiscal_year)s' """ % p)
# Future year balances
# Update opening only where period_type is Year
sql("""update `tabAccount Balance` ab, `tabAccount` a, `tabFiscal Year` fy
set
ab.opening = ifnull(ab.opening,0) + %(diff)s
where
a.lft <= %(lft)s
and a.rgt >= %(rgt)s
and ab.account = a.name
and ifnull(a.is_pl_account, 'No') = 'No'
and ab.period = ab.fiscal_year
and fy.name = ab.fiscal_year
and fy.year_start_date > '%(posting_date)s'""" % p)
# Update balance for all period for future years
sql("""update `tabAccount Balance` ab, `tabAccount` a, `tabFiscal Year` fy
set
ab.balance = ifnull(ab.balance,0) + %(diff)s
where
a.lft <= %(lft)s
and a.rgt >= %(rgt)s
and ab.account = a.name
and ifnull(a.is_pl_account, 'No') = 'No'
and fy.name = ab.fiscal_year
and fy.year_start_date > '%(posting_date)s'""" % p)
# Get periods(month and year)
#-----------------------------
def get_period_list(self):
pl = sql("SELECT name, start_date, end_date, fiscal_year FROM tabPeriod WHERE fiscal_year = '%s' and period_type in ('Month', 'Year')" % (self.doc.fiscal_year))
return pl
# Voucher Balance
# ---------------
def update_outstanding_amt(self):
# get final outstanding amt
bal = flt(sql("select sum(debit)-sum(credit) from `tabGL Entry` where against_voucher=%s and against_voucher_type=%s and ifnull(is_cancelled,'No') = 'No'", (self.doc.against_voucher, self.doc.against_voucher_type))[0][0] or 0.0)
tds = 0
@@ -291,10 +182,7 @@ class DocType:
# Posting date must be after freezing date
self.check_freezing_date(adv_adj)
# Update current account balance
self.post_balance(self.doc.account, cancel)
# Update outstanding amt on against voucher
if self.doc.against_voucher and self.doc.against_voucher_type not in ('Journal Voucher','POS') and update_outstanding == 'Yes':
self.update_outstanding_amt()

View File

@@ -145,7 +145,14 @@ cur_frm.cscript.get_balance = function(doc,dt,dn) {
cur_frm.cscript.account = function(doc,dt,dn) {
var d = locals[dt][dn];
$c_obj('GL Control','get_bal',d.account+'~~~'+doc.fiscal_year, function(r,rt) { d.balance = r.message; refresh_field('balance',d.name,'entries'); });
wn.call({
method: "accounts.utils.get_balance_on",
args: {account: d.account, date: doc.posting_date},
callback: function(r) {
d.balance = fmt_money(r.message);
refresh_field('balance',d.name,'entries');
}
});
}
cur_frm.cscript.validate = function(doc,cdt,cdn) {

View File

@@ -8,11 +8,11 @@
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Please edit this list and import only required elements
from __future__ import unicode_literals
@@ -35,431 +35,431 @@ convert_to_lists = webnotes.conn.convert_to_lists
from utilities.transaction_base import TransactionBase
class DocType:
def __init__(self,d,dl):
self.doc, self.doclist = d,dl
self.master_type = {}
self.credit_days_for = {}
self.credit_days_global = -1
self.is_approving_authority = -1
def __init__(self,d,dl):
self.doc, self.doclist = d,dl
self.master_type = {}
self.credit_days_for = {}
self.credit_days_global = -1
self.is_approving_authority = -1
#--------------------------------------------------------------------------------------------------------
# Autoname
#--------------------------------------------------------------------------------------------------------
def autoname(self):
self.doc.name = make_autoname(self.doc.naming_series+'.#####')
#--------------------------------------------------------------------------------------------------------
# Autoname
#--------------------------------------------------------------------------------------------------------
def autoname(self):
self.doc.name = make_autoname(self.doc.naming_series+'.#####')
#--------------------------------------------------------------------------------------------------------
# Fetch outstanding amount from RV/PV
#--------------------------------------------------------------------------------------------------------
def get_outstanding(self, args):
args = eval(args)
o_s = sql("select outstanding_amount from `tab%s` where name = '%s'" % (args['doctype'],args['docname']))
if args['doctype'] == 'Purchase Invoice':
return {'debit': o_s and flt(o_s[0][0]) or 0}
if args['doctype'] == 'Sales Invoice':
return {'credit': o_s and flt(o_s[0][0]) or 0}
#--------------------------------------------------------------------------------------------------------
# Fetch outstanding amount from RV/PV
#--------------------------------------------------------------------------------------------------------
def get_outstanding(self, args):
args = eval(args)
o_s = sql("select outstanding_amount from `tab%s` where name = '%s'" % (args['doctype'],args['docname']))
if args['doctype'] == 'Purchase Invoice':
return {'debit': o_s and flt(o_s[0][0]) or 0}
if args['doctype'] == 'Sales Invoice':
return {'credit': o_s and flt(o_s[0][0]) or 0}
#--------------------------------------------------------------------------------------------------------
# Create remarks
#--------------------------------------------------------------------------------------------------------
def create_remarks(self):
r = []
if self.doc.cheque_no :
if self.doc.cheque_date:
r.append('Via cheque #%s dated %s' % (self.doc.cheque_no, formatdate(self.doc.cheque_date)))
else :
msgprint("Please enter cheque date")
raise Exception
for d in getlist(self.doclist, 'entries'):
if d.against_invoice and d.credit:
currency = sql("select currency from `tabSales Invoice` where name = '%s'" % d.against_invoice)
currency = currency and currency[0][0] or ''
r.append('%s %s against Invoice: %s' % (cstr(currency), fmt_money(flt(d.credit)), d.against_invoice))
if d.against_voucher and d.debit:
bill_no = sql("select bill_no, bill_date, currency from `tabPurchase Invoice` where name=%s", d.against_voucher)
if bill_no and bill_no[0][0] and bill_no[0][0].lower().strip() not in ['na', 'not applicable', 'none']:
bill_no = bill_no and bill_no[0]
r.append('%s %s against Bill %s dated %s' % (bill_no[2] and cstr(bill_no[2]) or '', fmt_money(flt(d.debit)), bill_no[0], bill_no[1] and formatdate(bill_no[1].strftime('%Y-%m-%d')) or ''))
if self.doc.ded_amount:
r.append("TDS Amount: %s" % self.doc.ded_amount)
if self.doc.user_remark:
r.append("User Remark : %s"%self.doc.user_remark)
#--------------------------------------------------------------------------------------------------------
# Create remarks
#--------------------------------------------------------------------------------------------------------
def create_remarks(self):
r = []
if self.doc.cheque_no :
if self.doc.cheque_date:
r.append('Via cheque #%s dated %s' % (self.doc.cheque_no, formatdate(self.doc.cheque_date)))
else :
msgprint("Please enter cheque date")
raise Exception
for d in getlist(self.doclist, 'entries'):
if d.against_invoice and d.credit:
currency = sql("select currency from `tabSales Invoice` where name = '%s'" % d.against_invoice)
currency = currency and currency[0][0] or ''
r.append('%s %s against Invoice: %s' % (cstr(currency), fmt_money(flt(d.credit)), d.against_invoice))
if d.against_voucher and d.debit:
bill_no = sql("select bill_no, bill_date, currency from `tabPurchase Invoice` where name=%s", d.against_voucher)
if bill_no and bill_no[0][0] and bill_no[0][0].lower().strip() not in ['na', 'not applicable', 'none']:
bill_no = bill_no and bill_no[0]
r.append('%s %s against Bill %s dated %s' % (bill_no[2] and cstr(bill_no[2]) or '', fmt_money(flt(d.debit)), bill_no[0], bill_no[1] and formatdate(bill_no[1].strftime('%Y-%m-%d')) or ''))
if self.doc.ded_amount:
r.append("TDS Amount: %s" % self.doc.ded_amount)
if self.doc.user_remark:
r.append("User Remark : %s"%self.doc.user_remark)
if r:
self.doc.remark = ("\n").join(r)
# --------------------------------------------------------------------------------------------------------
# Check user role for approval process
# --------------------------------------------------------------------------------------------------------
def get_authorized_user(self):
if self.is_approving_authority==-1:
self.is_approving_authority = 0
if r:
self.doc.remark = ("\n").join(r)
# --------------------------------------------------------------------------------------------------------
# Check user role for approval process
# --------------------------------------------------------------------------------------------------------
def get_authorized_user(self):
if self.is_approving_authority==-1:
self.is_approving_authority = 0
# Fetch credit controller role
approving_authority = sql("select value from `tabSingles` where field='credit_controller' and doctype='Global Defaults'")
approving_authority = approving_authority and approving_authority[0][0] or ''
# Check logged-in user is authorized
if approving_authority in webnotes.user.get_roles():
self.is_approving_authority = 1
return self.is_approving_authority
# get master type
# ---------------
def get_master_type(self, ac):
if not self.master_type.get(ac):
self.master_type[ac] = sql("select master_type from `tabAccount` where name=%s", ac)[0][0] or 'None'
return self.master_type[ac]
# get credit days for
# -------------------
def get_credit_days_for(self, ac):
# Fetch credit controller role
approving_authority = sql("select value from `tabSingles` where field='credit_controller' and doctype='Global Defaults'")
approving_authority = approving_authority and approving_authority[0][0] or ''
# Check logged-in user is authorized
if approving_authority in webnotes.user.get_roles():
self.is_approving_authority = 1
return self.is_approving_authority
# get master type
# ---------------
def get_master_type(self, ac):
if not self.master_type.get(ac):
self.master_type[ac] = sql("select master_type from `tabAccount` where name=%s", ac)[0][0] or 'None'
return self.master_type[ac]
# get credit days for
# -------------------
def get_credit_days_for(self, ac):
if not self.credit_days_for.has_key(ac):
self.credit_days_for[ac] = sql("select credit_days from `tabAccount` where name='%s'" % ac)[0][0] or 0
if not self.credit_days_for.has_key(ac):
self.credit_days_for[ac] = sql("select credit_days from `tabAccount` where name='%s'" % ac)[0][0] or 0
if not self.credit_days_for[ac]:
if self.credit_days_global==-1:
self.credit_days_global = sql("select credit_days from `tabCompany` where name='%s'" % self.doc.company)[0][0] or 0
return self.credit_days_global
else:
return self.credit_days_for[ac]
# --------------------------------------------------------------------------------------------------------
# Check Credit Days - Cheque Date can not after (Posting date + Credit Days)
# --------------------------------------------------------------------------------------------------------
def check_credit_days(self):
date_diff = 0
if self.doc.cheque_date:
date_diff = (getdate(self.doc.cheque_date)-getdate(self.doc.posting_date)).days
if date_diff <= 0: return
# Get List of Customer Account
acc_list = filter(lambda d: self.get_master_type(d.account)=='Customer', getlist(self.doclist,'entries'))
for d in acc_list:
credit_days = self.get_credit_days_for(d.account)
# Check credit days
if credit_days > 0 and not self.get_authorized_user() and cint(date_diff) > credit_days:
msgprint("Credit Not Allowed: Cannot allow a check that is dated more than %s days after the posting date" % credit_days)
raise Exception
#--------------------------------------------------------------------------------------------------------
# validation of debit/credit account with Debit To Account(RV) or Credit To Account (PV)
#--------------------------------------------------------------------------------------------------------
def check_account_against_entries(self):
for d in getlist(self.doclist,'entries'):
if d.against_invoice:
acc=sql("select debit_to from `tabSales Invoice` where name='%s'"%d.against_invoice)
if acc and acc[0][0] != d.account:
msgprint("Debit account is not matching with receivable voucher")
raise Exception
if d.against_voucher:
acc=sql("select credit_to from `tabPurchase Invoice` where name='%s'"%d.against_voucher)
if acc and acc[0][0] != d.account:
msgprint("Credit account is not matching with payable voucher")
raise Exception
#--------------------------------------------------------------------------------------------------------
# Validate Cheque Info: Mandatory for Bank/Contra voucher
#--------------------------------------------------------------------------------------------------------
def validate_cheque_info(self):
if self.doc.voucher_type in ['Bank Voucher']:
if not self.doc.cheque_no or not self.doc.cheque_date:
msgprint("Cheque No & Cheque Date is required for " + cstr(self.doc.voucher_type))
raise Exception
if self.doc.cheque_date and not self.doc.cheque_no:
msgprint("Cheque No is mandatory if you entered Cheque Date")
raise Exception
#--------------------------------------------------------------------------------------------------------
# Gives reminder for making is_advance = 'Yes' in Advance Entry
#--------------------------------------------------------------------------------------------------------
def validate_entries_for_advance(self):
for d in getlist(self.doclist,'entries'):
if not d.is_advance and not d.against_voucher and not d.against_invoice and d.against_jv:
master_type = self.get_master_type(d.account)
if (master_type == 'Customer' and flt(d.credit) > 0) or (master_type == 'Supplier' and flt(d.debit) > 0):
msgprint("Message: Please check Is Advance as 'Yes' against Account %s if this is an advance entry." % d.account)
#--------------------------------------------------------------------------------------------------------
# TDS: Validate tds related fields
#--------------------------------------------------------------------------------------------------------
def get_tds_category_account(self):
for d in getlist(self.doclist,'entries'):
if flt(d.debit) > 0 and not d.against_voucher and d.is_advance == 'Yes':
acc = sql("select tds_applicable from `tabAccount` where name = '%s'" % d.account)
acc_tds_applicable = acc and acc[0][0] or 'No'
if acc_tds_applicable == 'Yes':
# TDS applicable field become mandatory for advance payment towards supplier or related party
if not self.doc.tds_applicable:
msgprint("Please select TDS Applicable or Not")
raise Exception
# If TDS applicable, category and supplier account bocome mandatory
elif self.doc.tds_applicable == 'Yes':
self.validate_category_account(d.account)
if self.doc.ded_amount and not self.doc.tax_code:
msgprint("Please enter Tax Code in TDS section")
raise Exception
if not self.credit_days_for[ac]:
if self.credit_days_global==-1:
self.credit_days_global = sql("select credit_days from `tabCompany` where name='%s'" % self.doc.company)[0][0] or 0
return self.credit_days_global
else:
return self.credit_days_for[ac]
# --------------------------------------------------------------------------------------------------------
# Check Credit Days - Cheque Date can not after (Posting date + Credit Days)
# --------------------------------------------------------------------------------------------------------
def check_credit_days(self):
date_diff = 0
if self.doc.cheque_date:
date_diff = (getdate(self.doc.cheque_date)-getdate(self.doc.posting_date)).days
if date_diff <= 0: return
# Get List of Customer Account
acc_list = filter(lambda d: self.get_master_type(d.account)=='Customer', getlist(self.doclist,'entries'))
for d in acc_list:
credit_days = self.get_credit_days_for(d.account)
# Check credit days
if credit_days > 0 and not self.get_authorized_user() and cint(date_diff) > credit_days:
msgprint("Credit Not Allowed: Cannot allow a check that is dated more than %s days after the posting date" % credit_days)
raise Exception
#--------------------------------------------------------------------------------------------------------
# validation of debit/credit account with Debit To Account(RV) or Credit To Account (PV)
#--------------------------------------------------------------------------------------------------------
def check_account_against_entries(self):
for d in getlist(self.doclist,'entries'):
if d.against_invoice:
acc=sql("select debit_to from `tabSales Invoice` where name='%s'"%d.against_invoice)
if acc and acc[0][0] != d.account:
msgprint("Debit account is not matching with receivable voucher")
raise Exception
if d.against_voucher:
acc=sql("select credit_to from `tabPurchase Invoice` where name='%s'"%d.against_voucher)
if acc and acc[0][0] != d.account:
msgprint("Credit account is not matching with payable voucher")
raise Exception
#--------------------------------------------------------------------------------------------------------
# Validate Cheque Info: Mandatory for Bank/Contra voucher
#--------------------------------------------------------------------------------------------------------
def validate_cheque_info(self):
if self.doc.voucher_type in ['Bank Voucher']:
if not self.doc.cheque_no or not self.doc.cheque_date:
msgprint("Cheque No & Cheque Date is required for " + cstr(self.doc.voucher_type))
raise Exception
if self.doc.cheque_date and not self.doc.cheque_no:
msgprint("Cheque No is mandatory if you entered Cheque Date")
raise Exception
#--------------------------------------------------------------------------------------------------------
# Gives reminder for making is_advance = 'Yes' in Advance Entry
#--------------------------------------------------------------------------------------------------------
def validate_entries_for_advance(self):
for d in getlist(self.doclist,'entries'):
if not d.is_advance and not d.against_voucher and not d.against_invoice and d.against_jv:
master_type = self.get_master_type(d.account)
if (master_type == 'Customer' and flt(d.credit) > 0) or (master_type == 'Supplier' and flt(d.debit) > 0):
msgprint("Message: Please check Is Advance as 'Yes' against Account %s if this is an advance entry." % d.account)
#--------------------------------------------------------------------------------------------------------
# TDS: Validate tds related fields
#--------------------------------------------------------------------------------------------------------
def get_tds_category_account(self):
for d in getlist(self.doclist,'entries'):
if flt(d.debit) > 0 and not d.against_voucher and d.is_advance == 'Yes':
acc = sql("select tds_applicable from `tabAccount` where name = '%s'" % d.account)
acc_tds_applicable = acc and acc[0][0] or 'No'
if acc_tds_applicable == 'Yes':
# TDS applicable field become mandatory for advance payment towards supplier or related party
if not self.doc.tds_applicable:
msgprint("Please select TDS Applicable or Not")
raise Exception
# If TDS applicable, category and supplier account bocome mandatory
elif self.doc.tds_applicable == 'Yes':
self.validate_category_account(d.account)
if self.doc.ded_amount and not self.doc.tax_code:
msgprint("Please enter Tax Code in TDS section")
raise Exception
#If TDS not applicable, all related fields should blank
else:
self.set_fields_null()
# If tds amount but tds applicability not mentioned in account master
elif self.doc.ded_amount:
msgprint("Please select TDS Applicable = 'Yes' in account head: '%s' if you want to deduct TDS." % self.doc.supplier_account)
raise Exception
#If TDS not applicable, all related fields should blank
else:
self.set_fields_null()
# If tds amount but tds applicability not mentioned in account master
elif self.doc.ded_amount:
msgprint("Please select TDS Applicable = 'Yes' in account head: '%s' if you want to deduct TDS." % self.doc.supplier_account)
raise Exception
#--------------------------------------------------------------------------------------------------------
# If TDS applicable , TDS category and supplier account should be mandatory
#--------------------------------------------------------------------------------------------------------
def validate_category_account(self, credit_account):
if not self.doc.tds_category:
msgprint("Please select TDS Category")
raise Exception
if not self.doc.supplier_account:
self.doc.supplier_account = credit_account
elif self.doc.supplier_account and self.doc.supplier_account != credit_account:
msgprint("Supplier Account is not matching with the account mentioned in the table. Please select proper Supplier Account and click on 'Get TDS' button.")
raise Exception
#--------------------------------------------------------------------------------------------------------
# If TDS applicable , TDS category and supplier account should be mandatory
#--------------------------------------------------------------------------------------------------------
def validate_category_account(self, credit_account):
if not self.doc.tds_category:
msgprint("Please select TDS Category")
raise Exception
if not self.doc.supplier_account:
self.doc.supplier_account = credit_account
elif self.doc.supplier_account and self.doc.supplier_account != credit_account:
msgprint("Supplier Account is not matching with the account mentioned in the table. Please select proper Supplier Account and click on 'Get TDS' button.")
raise Exception
#--------------------------------------------------------------------------------------------------------
# If TDS is not applicable , all related fields should blank
#--------------------------------------------------------------------------------------------------------
def set_fields_null(self):
self.doc.ded_amount = 0
self.doc.rate = 0
self.doc.tax_code = ''
self.doc.tds_category = ''
self.doc.supplier_account = ''
#--------------------------------------------------------------------------------------------------------
# Get TDS amount
#--------------------------------------------------------------------------------------------------------
def get_tds(self):
if cstr(self.doc.is_opening) != 'Yes':
if self.doc.total_debit > 0:
self.get_tds_category_account()
if self.doc.supplier_account and self.doc.tds_category:
get_obj('TDS Control').get_tds_amount(self)
#--------------------------------------------------------------------------------------------------------
# If TDS is not applicable , all related fields should blank
#--------------------------------------------------------------------------------------------------------
def set_fields_null(self):
self.doc.ded_amount = 0
self.doc.rate = 0
self.doc.tax_code = ''
self.doc.tds_category = ''
self.doc.supplier_account = ''
#--------------------------------------------------------------------------------------------------------
# Get TDS amount
#--------------------------------------------------------------------------------------------------------
def get_tds(self):
if cstr(self.doc.is_opening) != 'Yes':
if self.doc.total_debit > 0:
self.get_tds_category_account()
if self.doc.supplier_account and self.doc.tds_category:
get_obj('TDS Control').get_tds_amount(self)
#--------------------------------------------------------------------------------------------------------
# Insert new row to balance total debit and total credit
#--------------------------------------------------------------------------------------------------------
def get_balance(self):
if not getlist(self.doclist,'entries'):
msgprint("Please enter atleast 1 entry in 'GL Entries' table")
else:
flag, self.doc.total_debit, self.doc.total_credit = 0,0,0
diff = flt(self.doc.difference)
# If any row without amount, set the diff on that row
for d in getlist(self.doclist,'entries'):
if (d.credit==0 or d.credit is None) and (d.debit==0 or d.debit is None) and (flt(diff) != 0):
if diff>0:
d.credit = flt(diff)
elif diff<0:
d.debit = flt(diff)
flag = 1
# Set the diff in a new row
if flag == 0 and (flt(diff) != 0):
jd = addchild(self.doc, 'entries', 'Journal Voucher Detail', 1, self.doclist)
if diff>0:
jd.credit = flt(diff)
elif diff<0:
jd.debit = flt(diff)
# Set the total debit, total credit and difference
for d in getlist(self.doclist,'entries'):
self.doc.total_debit += flt(d.debit)
self.doc.total_credit += flt(d.credit)
#--------------------------------------------------------------------------------------------------------
# Insert new row to balance total debit and total credit
#--------------------------------------------------------------------------------------------------------
def get_balance(self):
if not getlist(self.doclist,'entries'):
msgprint("Please enter atleast 1 entry in 'GL Entries' table")
else:
flag, self.doc.total_debit, self.doc.total_credit = 0,0,0
diff = flt(self.doc.difference)
# If any row without amount, set the diff on that row
for d in getlist(self.doclist,'entries'):
if (d.credit==0 or d.credit is None) and (d.debit==0 or d.debit is None) and (flt(diff) != 0):
if diff>0:
d.credit = flt(diff)
elif diff<0:
d.debit = flt(diff)
flag = 1
# Set the diff in a new row
if flag == 0 and (flt(diff) != 0):
jd = addchild(self.doc, 'entries', 'Journal Voucher Detail', 1, self.doclist)
if diff>0:
jd.credit = flt(diff)
elif diff<0:
jd.debit = flt(diff)
# Set the total debit, total credit and difference
for d in getlist(self.doclist,'entries'):
self.doc.total_debit += flt(d.debit)
self.doc.total_credit += flt(d.credit)
if self.doc.tds_applicable == 'Yes':
self.doc.total_credit = flt(self.doc.total_credit) + flt(self.doc.ded_amount)
if self.doc.tds_applicable == 'Yes':
self.doc.total_credit = flt(self.doc.total_credit) + flt(self.doc.ded_amount)
self.doc.difference = flt(self.doc.total_debit) - flt(self.doc.total_credit)
#--------------------------------------------------------------------------------------------------------
# Set against account
#--------------------------------------------------------------------------------------------------------
def get_against_account(self):
# Debit = Credit
debit, credit = 0.0, 0.0
debit_list, credit_list = [], []
for d in getlist(self.doclist, 'entries'):
debit += flt(d.debit)
credit += flt(d.credit)
if flt(d.debit)>0 and (d.account not in debit_list): debit_list.append(d.account)
if flt(d.credit)>0 and (d.account not in credit_list): credit_list.append(d.account)
self.doc.difference = flt(self.doc.total_debit) - flt(self.doc.total_credit)
#--------------------------------------------------------------------------------------------------------
# Set against account
#--------------------------------------------------------------------------------------------------------
def get_against_account(self):
# Debit = Credit
debit, credit = 0.0, 0.0
debit_list, credit_list = [], []
for d in getlist(self.doclist, 'entries'):
debit += flt(d.debit)
credit += flt(d.credit)
if flt(d.debit)>0 and (d.account not in debit_list): debit_list.append(d.account)
if flt(d.credit)>0 and (d.account not in credit_list): credit_list.append(d.account)
self.doc.total_debit = debit
if self.doc.tds_applicable == 'Yes':
self.doc.total_credit = credit + flt(self.doc.ded_amount)
else:
self.doc.total_credit = credit
self.doc.total_debit = debit
if self.doc.tds_applicable == 'Yes':
self.doc.total_credit = credit + flt(self.doc.ded_amount)
else:
self.doc.total_credit = credit
if abs(self.doc.total_debit-self.doc.total_credit) > 0.001:
msgprint("Debit must be equal to Credit. The difference is %s" % (self.doc.total_debit-self.doc.total_credit))
raise Exception
# update against account
for d in getlist(self.doclist, 'entries'):
if flt(d.debit) > 0: d.against_account = ', '.join(credit_list)
if flt(d.credit) > 0: d.against_account = ', '.join(debit_list)
if abs(self.doc.total_debit-self.doc.total_credit) > 0.001:
msgprint("Debit must be equal to Credit. The difference is %s" % (self.doc.total_debit-self.doc.total_credit))
raise Exception
# update against account
for d in getlist(self.doclist, 'entries'):
if flt(d.debit) > 0: d.against_account = ', '.join(credit_list)
if flt(d.credit) > 0: d.against_account = ', '.join(debit_list)
# set aging date
#---------------
def set_aging_date(self):
if self.doc.is_opening != 'Yes':
self.doc.aging_date = self.doc.posting_date
else:
# check account type whether supplier or customer
exists = ''
for d in getlist(self.doclist, 'entries'):
exists = sql("select name from tabAccount where account_type in ('Supplier', 'Customer') and name = '%s'" % d.account)
if exists:
break
# set aging date
#---------------
def set_aging_date(self):
if self.doc.is_opening != 'Yes':
self.doc.aging_date = self.doc.posting_date
else:
# check account type whether supplier or customer
exists = ''
for d in getlist(self.doclist, 'entries'):
exists = sql("select name from tabAccount where account_type in ('Supplier', 'Customer') and name = '%s'" % d.account)
if exists:
break
# If cus/supp aging dt is mandatory
if exists and not self.doc.aging_date:
msgprint("Aging Date is mandatory for opening entry")
raise Exception
# otherwise aging dt = posting dt
else:
self.doc.aging_date = self.doc.posting_date
# If cus/supp aging dt is mandatory
if exists and not self.doc.aging_date:
msgprint("Aging Date is mandatory for opening entry")
raise Exception
# otherwise aging dt = posting dt
else:
self.doc.aging_date = self.doc.posting_date
# ------------------------
# set print format fields
# ------------------------
def set_print_format_fields(self):
for d in getlist(self.doclist, 'entries'):
#msgprint(self.doc.company)
chk_type = sql("select master_type, account_type from `tabAccount` where name='%s'" % d.account)
master_type, acc_type = chk_type and cstr(chk_type[0][0]) or '', chk_type and cstr(chk_type[0][1]) or ''
if master_type in ['Supplier', 'Customer']:
if not self.doc.pay_to_recd_from:
self.doc.pay_to_recd_from = get_value(master_type, ' - '.join(d.account.split(' - ')[:-1]), master_type == 'Customer' and 'customer_name' or 'supplier_name')
if acc_type == 'Bank or Cash':
dcc = TransactionBase().get_company_currency(self.doc.company)
amt = cint(d.debit) and d.debit or d.credit
self.doc.total_amount = dcc +' '+ cstr(amt)
self.doc.total_amount_in_words = get_obj('Sales Common').get_total_in_words(dcc, cstr(amt))
# ------------------------
# set print format fields
# ------------------------
def set_print_format_fields(self):
for d in getlist(self.doclist, 'entries'):
#msgprint(self.doc.company)
chk_type = sql("select master_type, account_type from `tabAccount` where name='%s'" % d.account)
master_type, acc_type = chk_type and cstr(chk_type[0][0]) or '', chk_type and cstr(chk_type[0][1]) or ''
if master_type in ['Supplier', 'Customer']:
if not self.doc.pay_to_recd_from:
self.doc.pay_to_recd_from = get_value(master_type, ' - '.join(d.account.split(' - ')[:-1]), master_type == 'Customer' and 'customer_name' or 'supplier_name')
if acc_type == 'Bank or Cash':
dcc = TransactionBase().get_company_currency(self.doc.company)
amt = cint(d.debit) and d.debit or d.credit
self.doc.total_amount = dcc +' '+ cstr(amt)
self.doc.total_amount_in_words = get_obj('Sales Common').get_total_in_words(dcc, cstr(amt))
# --------------------------------
# get outstanding invoices values
# --------------------------------
def get_values(self):
cond = (flt(self.doc.write_off_amount) > 0) and ' and outstanding_amount <= '+self.doc.write_off_amount or ''
if self.doc.write_off_based_on == 'Accounts Receivable':
return sql("select name, debit_to, outstanding_amount from `tabSales Invoice` where docstatus = 1 and company = '%s' and outstanding_amount > 0 %s" % (self.doc.company, cond))
elif self.doc.write_off_based_on == 'Accounts Payable':
return sql("select name, credit_to, outstanding_amount from `tabPurchase Invoice` where docstatus = 1 and company = '%s' and outstanding_amount > 0 %s" % (self.doc.company, cond))
# --------------------------------
# get outstanding invoices values
# --------------------------------
def get_values(self):
cond = (flt(self.doc.write_off_amount) > 0) and ' and outstanding_amount <= '+self.doc.write_off_amount or ''
if self.doc.write_off_based_on == 'Accounts Receivable':
return sql("select name, debit_to, outstanding_amount from `tabSales Invoice` where docstatus = 1 and company = '%s' and outstanding_amount > 0 %s" % (self.doc.company, cond))
elif self.doc.write_off_based_on == 'Accounts Payable':
return sql("select name, credit_to, outstanding_amount from `tabPurchase Invoice` where docstatus = 1 and company = '%s' and outstanding_amount > 0 %s" % (self.doc.company, cond))
# -------------------------
# get outstanding invoices
# -------------------------
def get_outstanding_invoices(self):
self.doclist = self.doc.clear_table(self.doclist, 'entries')
total = 0
for d in self.get_values():
total += flt(d[2])
jd = addchild(self.doc, 'entries', 'Journal Voucher Detail', 1, self.doclist)
jd.account = cstr(d[1])
if self.doc.write_off_based_on == 'Accounts Receivable':
jd.credit = flt(d[2])
jd.against_invoice = cstr(d[0])
elif self.doc.write_off_based_on == 'Accounts Payable':
jd.debit = flt(d[2])
jd.against_voucher = cstr(d[0])
jd.save(1)
jd = addchild(self.doc, 'entries', 'Journal Voucher Detail', 1, self.doclist)
if self.doc.write_off_based_on == 'Accounts Receivable':
jd.debit = total
elif self.doc.write_off_based_on == 'Accounts Payable':
jd.credit = total
jd.save(1)
# -------------------------
# get outstanding invoices
# -------------------------
def get_outstanding_invoices(self):
self.doclist = self.doc.clear_table(self.doclist, 'entries')
total = 0
for d in self.get_values():
total += flt(d[2])
jd = addchild(self.doc, 'entries', 'Journal Voucher Detail', 1, self.doclist)
jd.account = cstr(d[1])
if self.doc.write_off_based_on == 'Accounts Receivable':
jd.credit = flt(d[2])
jd.against_invoice = cstr(d[0])
elif self.doc.write_off_based_on == 'Accounts Payable':
jd.debit = flt(d[2])
jd.against_voucher = cstr(d[0])
jd.save(1)
jd = addchild(self.doc, 'entries', 'Journal Voucher Detail', 1, self.doclist)
if self.doc.write_off_based_on == 'Accounts Receivable':
jd.debit = total
elif self.doc.write_off_based_on == 'Accounts Payable':
jd.credit = total
jd.save(1)
#--------------------------------------------------------------------------------------------------------
# VALIDATE
#--------------------------------------------------------------------------------------------------------
def validate(self):
if not self.doc.is_opening:
self.doc.is_opening='No'
self.get_against_account()
self.validate_cheque_info()
self.create_remarks()
# tds
get_obj('TDS Control').validate_first_entry(self)
self.get_tds_category_account()
#--------------------------------------------------------------------------------------------------------
# VALIDATE
#--------------------------------------------------------------------------------------------------------
def validate(self):
if not self.doc.is_opening:
self.doc.is_opening='No'
self.get_against_account()
self.validate_cheque_info()
self.create_remarks()
# tds
get_obj('TDS Control').validate_first_entry(self)
self.get_tds_category_account()
self.validate_entries_for_advance()
self.set_aging_date()
self.validate_against_jv()
self.set_print_format_fields()
self.validate_entries_for_advance()
self.set_aging_date()
self.validate_against_jv()
self.set_print_format_fields()
#FY and Date validation
get_obj('Sales Common').validate_fiscal_year(self.doc.fiscal_year,self.doc.posting_date,'Posting Date')
#FY and Date validation
get_obj('Sales Common').validate_fiscal_year(self.doc.fiscal_year,self.doc.posting_date,'Posting Date')
#--------------------------------------------------------------------------------------------------------
# On Update - Update Feed
#--------------------------------------------------------------------------------------------------------
def on_update(self):
pass
#--------------------------------------------------------------------------------------------------------
# On submit
#--------------------------------------------------------------------------------------------------------
def on_submit(self):
if self.doc.voucher_type in ['Bank Voucher', 'Contra Voucher', 'Journal Entry']:
self.check_credit_days()
self.check_account_against_entries()
get_obj(dt='GL Control').make_gl_entries(self.doc, self.doclist)
#--------------------------------------------------------------------------------------------------------
# On Update - Update Feed
#--------------------------------------------------------------------------------------------------------
def on_update(self):
pass
#--------------------------------------------------------------------------------------------------------
# On submit
#--------------------------------------------------------------------------------------------------------
def on_submit(self):
if self.doc.voucher_type in ['Bank Voucher', 'Contra Voucher', 'Journal Entry']:
self.check_credit_days()
self.check_account_against_entries()
get_obj(dt='GL Control').make_gl_entries(self.doc, self.doclist)
# validate against jv no
def validate_against_jv(self):
for d in getlist(self.doclist, 'entries'):
if d.against_jv:
if d.against_jv == self.doc.name:
msgprint("You can not enter current voucher in 'Against JV' column")
raise Exception
elif not sql("select name from `tabJournal Voucher Detail` where account = '%s' and docstatus = 1 and parent = '%s'" % (d.account, d.against_jv)):
msgprint("Against JV: "+ d.against_jv + " is not valid. Please check")
raise Exception
#--------------------------------------------------------------------------------------------------------
# On cancel reverse gl entry
#--------------------------------------------------------------------------------------------------------
def on_cancel(self):
self.check_tds_payment_voucher()
get_obj(dt='GL Control').make_gl_entries(self.doc, self.doclist, cancel=1)
# validate against jv no
def validate_against_jv(self):
for d in getlist(self.doclist, 'entries'):
if d.against_jv:
if d.against_jv == self.doc.name:
msgprint("You can not enter current voucher in 'Against JV' column")
raise Exception
elif not sql("select name from `tabJournal Voucher Detail` where account = '%s' and docstatus = 1 and parent = '%s'" % (d.account, d.against_jv)):
msgprint("Against JV: "+ d.against_jv + " is not valid. Please check")
raise Exception
#--------------------------------------------------------------------------------------------------------
# On cancel reverse gl entry
#--------------------------------------------------------------------------------------------------------
def on_cancel(self):
self.check_tds_payment_voucher()
get_obj(dt='GL Control').make_gl_entries(self.doc, self.doclist, cancel=1)
# Check whether tds payment voucher has been created against this voucher
#---------------------------------------------------------------------------
def check_tds_payment_voucher(self):
tdsp = sql("select parent from `tabTDS Payment Detail` where voucher_no = '%s' and docstatus = 1 and parent not like 'old%'")
if tdsp:
msgprint("TDS Payment voucher '%s' has been made against this voucher. Please cancel the payment voucher to proceed." % (tdsp and tdsp[0][0] or ''))
raise Exception
# Check whether tds payment voucher has been created against this voucher
#---------------------------------------------------------------------------
def check_tds_payment_voucher(self):
tdsp = sql("select parent from `tabTDS Payment Detail` where voucher_no = '%s' and docstatus = 1 and parent not like 'old%'")
if tdsp:
msgprint("TDS Payment voucher '%s' has been made against this voucher. Please cancel the payment voucher to proceed." % (tdsp and tdsp[0][0] or ''))
raise Exception

View File

@@ -0,0 +1,118 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Please edit this list and import only required elements
import unittest
import webnotes
import webnotes.model
from webnotes.utils import nowdate, flt, add_days
from accounts.utils import get_fiscal_year, get_balance_on
company = webnotes.conn.get_default("company")
abbr = webnotes.conn.get_value("Company", company, "abbr")
data = {
"expense_account": {
"doctype": "Account",
"account_name": "Test Expense",
"parent_account": "Direct Expenses - %s" % abbr,
"company": company,
"debit_or_credit": "Debit",
"is_pl_account": "Yes",
"group_or_ledger": "Ledger"
},
"supplier_account": {
"doctype": "Account",
"account_name": "Test Supplier",
"parent_account": "Accounts Payable - %s" % abbr,
"company": company,
"debit_or_credit": "Credit",
"is_pl_account": "No",
"group_or_ledger": "Ledger"
},
"journal_voucher": [
{
"doctype": "Journal Voucher",
"voucher_type": "Journal Entry",
"naming_series": "JV",
"posting_date": nowdate(),
"remark": "Test Journal Voucher",
"fiscal_year": get_fiscal_year(nowdate())[0],
"company": company
},
{
"doctype": "Journal Voucher Detail",
"parentfield": "entries",
"account": "Test Expense - %s" % abbr,
"debit": 5000,
"cost_center": "Default CC Ledger - %s" % abbr,
},
{
"doctype": "Journal Voucher Detail",
"parentfield": "entries",
"account": "Test Supplier - %s" % abbr,
"credit": 5000,
},
]
}
def get_name(s):
return s + " - " + abbr
class TestJournalVoucher(unittest.TestCase):
def setUp(self):
webnotes.conn.begin()
# create a dummy account
webnotes.model.insert([data["expense_account"]])
webnotes.model.insert([data["supplier_account"]])
def tearDown(self):
webnotes.conn.rollback()
def test_save_journal_voucher(self):
expense_ac_balance = get_balance_on(get_name("Test Expense"), nowdate())
supplier_ac_balance = get_balance_on(get_name("Test Supplier"), nowdate())
dl = webnotes.model.insert(data["journal_voucher"])
dl.submit()
dl.load_from_db()
# test submitted jv
self.assertTrue(webnotes.conn.exists("Journal Voucher", dl.doclist[0].name))
for d in dl.doclist[1:]:
self.assertEquals(webnotes.conn.get_value("Journal Voucher Detail",
d.name, "parent"), dl.doclist[0].name)
# test gl entry
gle = webnotes.conn.sql("""select account, debit, credit
from `tabGL Entry` where voucher_no = %s order by account""",
dl.doclist[0].name)
self.assertEquals((gle[0][0], flt(gle[0][1]), flt(gle[0][2])),
('Test Expense - %s' % abbr, 5000.0, 0.0))
self.assertEquals((gle[1][0], flt(gle[1][1]), flt(gle[1][2])),
('Test Supplier - %s' % abbr, 0.0, 5000.0))
# check balance as on today
self.assertEqual(get_balance_on(get_name("Test Expense"), nowdate()),
expense_ac_balance + 5000)
self.assertEqual(get_balance_on(get_name("Test Supplier"), nowdate()),
supplier_ac_balance + 5000)
# check previous balance
self.assertEqual(get_balance_on(get_name("Test Expense"), add_days(nowdate(), -1)), 0)

View File

@@ -8,11 +8,11 @@
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Please edit this list and import only required elements
from __future__ import unicode_literals
@@ -30,390 +30,342 @@ sql = webnotes.conn.sql
get_value = webnotes.conn.get_value
in_transaction = webnotes.conn.in_transaction
convert_to_lists = webnotes.conn.convert_to_lists
# -----------------------------------------------------------------------------------------
from accounts.utils import get_balance_on, get_fiscal_year
class DocType:
def __init__(self, doc, doclist):
self.doc = doc
self.doclist = doclist
self.account_list = []
self.ac_details = {} # key: account id, values: debit_or_credit, lft, rgt
self.roles = webnotes.user.get_roles()
def __init__(self, doc, doclist):
self.doc = doc
self.doclist = doclist
self.account_list = []
self.ac_details = {} # key: account id, values: debit_or_credit, lft, rgt
self.roles = webnotes.user.get_roles()
self.period_list = []
self.period_start_date = {}
self.period_end_date = {}
self.period_list = []
self.period_start_date = {}
self.period_end_date = {}
self.fs_list = []
self.root_bal = []
self.flag = 0
self.fs_list = []
self.root_bal = []
self.flag = 0
# Get defaults on load of MIS, MIS - Comparison Report and Financial statements
# ----------------------------------------------------
def get_comp(self):
ret = {}
type = []
comp = []
# ------ get period -----------
ret['period'] = ['Annual','Half Yearly','Quarterly','Monthly']
# ---- get companies ---------
res = sql("select name from `tabCompany`")
for r in res:
comp.append(r[0])
#comp.append(r[0] for r in res)
ret['company'] = comp
# Get defaults on load of MIS, MIS - Comparison Report and Financial statements
# ----------------------------------------------------
def get_comp(self):
ret = {}
type = []
comp = []
# ------ get period -----------
ret['period'] = ['Annual','Half Yearly','Quarterly','Monthly']
# ---- get companies ---------
res = sql("select name from `tabCompany`")
for r in res:
comp.append(r[0])
#comp.append(r[0] for r in res)
ret['company'] = comp
#--- to get fiscal year and start_date of that fiscal year -----
res = sql("select name, year_start_date from `tabFiscal Year`")
ret['fiscal_year'] = [r[0] for r in res]
ret['start_dates'] = {}
for r in res:
ret['start_dates'][r[0]] = str(r[1])
#--- from month and to month (for MIS - Comparison Report) -------
month_list = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
fiscal_start_month = sql("select MONTH(year_start_date) from `tabFiscal Year` where name = %s",(get_defaults()['fiscal_year']))
fiscal_start_month = fiscal_start_month and fiscal_start_month[0][0] or 1
mon = ['']
for i in range(fiscal_start_month,13): mon.append(month_list[i-1])
for i in range(0,fiscal_start_month-1): mon.append(month_list[i])
ret['month'] = mon
#--- to get fiscal year and start_date of that fiscal year -----
res = sql("select name, year_start_date from `tabFiscal Year`")
ret['fiscal_year'] = [r[0] for r in res]
ret['start_dates'] = {}
for r in res:
ret['start_dates'][r[0]] = str(r[1])
#--- from month and to month (for MIS - Comparison Report) -------
month_list = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
fiscal_start_month = sql("select MONTH(year_start_date) from `tabFiscal Year` where name = %s",(get_defaults()['fiscal_year']))
fiscal_start_month = fiscal_start_month and fiscal_start_month[0][0] or 1
mon = ['']
for i in range(fiscal_start_month,13): mon.append(month_list[i-1])
for i in range(0,fiscal_start_month-1): mon.append(month_list[i])
ret['month'] = mon
# ------------------------ get MIS Type on basis of roles of session user ------------------------------------------
if has_common(self.roles, ['Sales Manager']):
type.append('Sales')
if has_common(self.roles, ['Purchase Manager']):
type.append('Purchase')
ret['type'] = type
return ret
# Gets Transactions type and Group By options based on module
#------------------------------------------------------------------
def get_trans_group(self,module):
ret = {}
st,group = [],[]
if module == 'Sales':
st = ['Quotation','Sales Order','Delivery Note','Sales Invoice']
group = ['Item','Item Group','Customer','Customer Group','Cost Center']
elif module == 'Purchase':
st = ['Purchase Order','Purchase Receipt','Purchase Invoice']
group = ['Item','Item Group','Supplier','Supplier Type']
ret['stmt_type'] = st
ret['group_by'] = group
return ret
# ------------------------ get MIS Type on basis of roles of session user ------------------------------------------
if has_common(self.roles, ['Sales Manager']):
type.append('Sales')
if has_common(self.roles, ['Purchase Manager']):
type.append('Purchase')
ret['type'] = type
return ret
# Gets Transactions type and Group By options based on module
#------------------------------------------------------------------
def get_trans_group(self,module):
ret = {}
st,group = [],[]
if module == 'Sales':
st = ['Quotation','Sales Order','Delivery Note','Sales Invoice']
group = ['Item','Item Group','Customer','Customer Group','Cost Center']
elif module == 'Purchase':
st = ['Purchase Order','Purchase Receipt','Purchase Invoice']
group = ['Item','Item Group','Supplier','Supplier Type']
ret['stmt_type'] = st
ret['group_by'] = group
return ret
# Get Days based on month (for MIS Comparison Report)
# --------------------------------------------------------
def get_days(self,month):
days = []
ret = {}
if month == 'Jan' or month == 'Mar' or month == 'May' or month == 'Jul' or month == 'Aug' or month == 'Oct' or month == 'Dec':
for i in range(1,32):
days.append(i)
elif month == 'Apr' or month == 'Jun' or month == 'Sep' or month == 'Nov':
for i in range(1,31):
days.append(i)
elif month == 'Feb':
for i in range(1,29):
days.append(i)
ret['days'] = days
return ret
# Get Days based on month (for MIS Comparison Report)
# --------------------------------------------------------
def get_days(self,month):
days = []
ret = {}
if month == 'Jan' or month == 'Mar' or month == 'May' or month == 'Jul' or month == 'Aug' or month == 'Oct' or month == 'Dec':
for i in range(1,32):
days.append(i)
elif month == 'Apr' or month == 'Jun' or month == 'Sep' or month == 'Nov':
for i in range(1,31):
days.append(i)
elif month == 'Feb':
for i in range(1,29):
days.append(i)
ret['days'] = days
return ret
# Get from date and to date based on fiscal year (for in summary - comparison report)
# -----------------------------------------------------------------------------------------------------
def dates(self,fiscal_year,from_date,to_date):
import datetime
ret = ''
start_date = cstr(sql("select year_start_date from `tabFiscal Year` where name = %s",fiscal_year)[0][0])
st_mon = cint(from_date.split('-')[1])
ed_mon = cint(to_date.split('-')[1])
st_day = cint(from_date.split('-')[2])
ed_day = cint(to_date.split('-')[2])
fiscal_start_month = cint(start_date.split('-')[1])
next_fiscal_year = cint(start_date.split('-')[0]) + 1
current_year = ''
next_year = ''
#CASE - 1 : Jan - Mar (Valid)
if st_mon < fiscal_start_month and ed_mon < fiscal_start_month:
current_year = cint(start_date.split('-')[0]) + 1
next_year = cint(start_date.split('-')[0]) + 1
# Case - 2 : Apr - Dec (Valid)
elif st_mon >= fiscal_start_month and ed_mon <= 12 and ed_mon >= fiscal_start_month:
current_year = cint(start_date.split('-')[0])
next_year = cint(start_date.split('-')[0])
# Get from date and to date based on fiscal year (for in summary - comparison report)
# -----------------------------------------------------------------------------------------------------
def dates(self,fiscal_year,from_date,to_date):
import datetime
ret = ''
start_date = cstr(sql("select year_start_date from `tabFiscal Year` where name = %s",fiscal_year)[0][0])
st_mon = cint(from_date.split('-')[1])
ed_mon = cint(to_date.split('-')[1])
st_day = cint(from_date.split('-')[2])
ed_day = cint(to_date.split('-')[2])
fiscal_start_month = cint(start_date.split('-')[1])
next_fiscal_year = cint(start_date.split('-')[0]) + 1
current_year = ''
next_year = ''
#CASE - 1 : Jan - Mar (Valid)
if st_mon < fiscal_start_month and ed_mon < fiscal_start_month:
current_year = cint(start_date.split('-')[0]) + 1
next_year = cint(start_date.split('-')[0]) + 1
# Case - 2 : Apr - Dec (Valid)
elif st_mon >= fiscal_start_month and ed_mon <= 12 and ed_mon >= fiscal_start_month:
current_year = cint(start_date.split('-')[0])
next_year = cint(start_date.split('-')[0])
# Case 3 : Jan - May (Invalid)
elif st_mon < fiscal_start_month and ed_mon >= fiscal_start_month:
current_year = cint(start_date.split('-')[0]) + 1
next_year = cint(start_date.split('-')[0]) + 2
# Case 3 : Jan - May (Invalid)
elif st_mon < fiscal_start_month and ed_mon >= fiscal_start_month:
current_year = cint(start_date.split('-')[0]) + 1
next_year = cint(start_date.split('-')[0]) + 2
# check whether from date is within fiscal year
if datetime.date(current_year, st_mon, st_day) >= datetime.date(cint(start_date.split('-')[0]), cint(start_date.split('-')[1]), cint(start_date.split('-')[2])) and datetime.date(cint(current_year), cint(st_mon), cint(st_day)) < datetime.date((cint(start_date.split('-')[0])+1), cint(start_date.split('-')[1]), cint(start_date.split('-')[2])):
begin_date = cstr(current_year)+"-"+cstr(st_mon)+"-"+cstr(st_day)
else:
msgprint("Please enter appropriate from date.")
raise Exception
# check whether to date is within fiscal year
if datetime.date(next_year, ed_mon, ed_day) >= datetime.date(cint(start_date.split('-')[0]), cint(start_date.split('-')[1]), cint(start_date.split('-')[2])) and datetime.date(cint(next_year), cint(ed_mon), cint(ed_day)) < datetime.date(cint(start_date.split('-')[0])+1, cint(start_date.split('-')[1]), cint(start_date.split('-')[2])):
end_date = cstr(next_year)+"-"+cstr(ed_mon)+"-"+cstr(ed_day)
else:
msgprint("Please enter appropriate to date.")
raise Exception
ret = begin_date+'~~~'+end_date
return ret
# check whether from date is within fiscal year
if datetime.date(current_year, st_mon, st_day) >= datetime.date(cint(start_date.split('-')[0]), cint(start_date.split('-')[1]), cint(start_date.split('-')[2])) and datetime.date(cint(current_year), cint(st_mon), cint(st_day)) < datetime.date((cint(start_date.split('-')[0])+1), cint(start_date.split('-')[1]), cint(start_date.split('-')[2])):
begin_date = cstr(current_year)+"-"+cstr(st_mon)+"-"+cstr(st_day)
else:
msgprint("Please enter appropriate from date.")
raise Exception
# check whether to date is within fiscal year
if datetime.date(next_year, ed_mon, ed_day) >= datetime.date(cint(start_date.split('-')[0]), cint(start_date.split('-')[1]), cint(start_date.split('-')[2])) and datetime.date(cint(next_year), cint(ed_mon), cint(ed_day)) < datetime.date(cint(start_date.split('-')[0])+1, cint(start_date.split('-')[1]), cint(start_date.split('-')[2])):
end_date = cstr(next_year)+"-"+cstr(ed_mon)+"-"+cstr(ed_day)
else:
msgprint("Please enter appropriate to date.")
raise Exception
ret = begin_date+'~~~'+end_date
return ret
# Get MIS Totals
# ---------------
def get_totals(self, args):
args = eval(args)
#msgprint(args)
totals = sql("SELECT %s FROM %s WHERE %s %s %s %s" %(cstr(args['query_val']), cstr(args['tables']), cstr(args['company']), cstr(args['cond']), cstr(args['add_cond']), cstr(args['fil_cond'])), as_dict = 1)[0]
#msgprint(totals)
tot_keys = totals.keys()
# return in flt because JSON doesn't accept Decimal
for d in tot_keys:
totals[d] = flt(totals[d])
return totals
# Get MIS Totals
# ---------------
def get_totals(self, args):
args = eval(args)
#msgprint(args)
totals = sql("SELECT %s FROM %s WHERE %s %s %s %s" %(cstr(args['query_val']), cstr(args['tables']), cstr(args['company']), cstr(args['cond']), cstr(args['add_cond']), cstr(args['fil_cond'])), as_dict = 1)[0]
#msgprint(totals)
tot_keys = totals.keys()
# return in flt because JSON doesn't accept Decimal
for d in tot_keys:
totals[d] = flt(totals[d])
return totals
# Get Statement
# -------------
def get_statement(self, arg):
self.return_data = []
# Get Statement
# -------------
def get_statement(self, arg):
self.return_data = []
# define periods
arg = eval(arg)
pl = ''
self.define_periods(arg['year'], arg['period']) # declares 1.period_list i.e. (['Jan','Feb','Mar'...] or ['Q1','Q2'...] or ['FY2009-2010']) based on period
# 2.period_start_date dict {'Jan':'01-01-2009'...}
# 3.period_start_date dict {'Jan':'31-01-2009'...}
self.return_data.append([4,'']+self.period_list)
# define periods
arg = eval(arg)
pl = ''
self.define_periods(arg['year'], arg['period']) # declares 1.period_list i.e. (['Jan','Feb','Mar'...] or ['Q1','Q2'...] or ['FY2009-2010']) based on period
# 2.period_start_date dict {'Jan':'01-01-2009'...}
# 3.period_start_date dict {'Jan':'31-01-2009'...}
self.return_data.append([4,'']+self.period_list)
if arg['statement'] == 'Balance Sheet': pl = 'No'
if arg['statement'] == 'Profit & Loss': pl = 'Yes'
self.get_children('',0,pl,arg['company'], arg['year'])
#self.balance_pl_statement(acct, arg['statement'])
#msgprint(self.return_data)
return self.return_data
# Get Children
# ------------
def get_children(self, parent_account, level, pl, company, fy):
cl = sql("select distinct account_name, name, debit_or_credit, lft, rgt from `tabAccount` where ifnull(parent_account, '') = %s and ifnull(is_pl_account, 'No')=%s and company=%s and docstatus != 2 order by name asc", (parent_account, pl, company))
level0_diff = [0 for p in self.period_list]
if pl=='Yes' and level==0: # switch for income & expenses
cl = [c for c in cl]
cl.reverse()
if cl:
for c in cl:
self.ac_details[c[1]] = [c[2], c[3], c[4]]
bal_list = self.get_period_balance(c[1], level, pl, company, fy)
if level==0: # top level - put balances as totals
self.return_data.append([level, c[0]] + ['' for b in bal_list])
totals = bal_list
for i in range(len(totals)): # make totals
if c[2]=='Credit':
level0_diff[i] += flt(totals[i])
else:
level0_diff[i] -= flt(totals[i])
else:
self.return_data.append([level, c[0]]+bal_list)
if level < 2:
self.get_children(c[1], level+1, pl, company, fy)
# make totals - for top level
# ---------------------------
if level==0:
# add rows for profit / loss in B/S
if pl=='No':
if c[2]=='Credit':
self.return_data.append([1, 'Total Liabilities'] + totals)
level0_diff = [-i for i in level0_diff] # convert to debit
self.return_data.append([5, 'Profit/Loss (Provisional)'] + level0_diff)
for i in range(len(totals)): # make totals
level0_diff[i] = flt(totals[i]) + level0_diff[i]
self.return_data.append([4, 'Total '+c[0]] + level0_diff)
else:
self.return_data.append([4, 'Total '+c[0]] + totals)
if arg['statement'] == 'Balance Sheet': pl = 'No'
if arg['statement'] == 'Profit & Loss': pl = 'Yes'
self.get_children('',0,pl,arg['company'], arg['year'])
#self.balance_pl_statement(acct, arg['statement'])
#msgprint(self.return_data)
return self.return_data
# Get Children
# ------------
def get_children(self, parent_account, level, pl, company, fy):
cl = sql("select distinct account_name, name, debit_or_credit, lft, rgt from `tabAccount` where ifnull(parent_account, '') = %s and ifnull(is_pl_account, 'No')=%s and company=%s and docstatus != 2 order by name asc", (parent_account, pl, company))
level0_diff = [0 for p in self.period_list]
if pl=='Yes' and level==0: # switch for income & expenses
cl = [c for c in cl]
cl.reverse()
if cl:
for c in cl:
self.ac_details[c[1]] = [c[2], c[3], c[4]]
bal_list = self.get_period_balance(c[1])
if level==0: # top level - put balances as totals
self.return_data.append([level, c[0]] + ['' for b in bal_list])
totals = bal_list
for i in range(len(totals)): # make totals
if c[2]=='Credit':
level0_diff[i] += flt(totals[i])
else:
level0_diff[i] -= flt(totals[i])
else:
self.return_data.append([level, c[0]]+bal_list)
if level < 2:
self.get_children(c[1], level+1, pl, company, fy)
# make totals - for top level
# ---------------------------
if level==0:
# add rows for profit / loss in B/S
if pl=='No':
if c[2]=='Credit':
self.return_data.append([1, 'Total Liabilities'] + totals)
level0_diff = [-i for i in level0_diff] # convert to debit
self.return_data.append([5, 'Profit/Loss (Provisional)'] + level0_diff)
for i in range(len(totals)): # make totals
level0_diff[i] = flt(totals[i]) + level0_diff[i]
self.return_data.append([4, 'Total '+c[0]] + level0_diff)
else:
self.return_data.append([4, 'Total '+c[0]] + totals)
# add rows for profit / loss in P/L
else:
if c[2]=='Debit':
self.return_data.append([1, 'Total Expenses (before Profit)'] + totals)
self.return_data.append([5, 'Profit/Loss (Provisional)'] + level0_diff)
for i in range(len(totals)): # make totals
level0_diff[i] = flt(totals[i]) + level0_diff[i]
self.return_data.append([4, 'Total '+c[0]] + level0_diff)
else:
self.return_data.append([4, 'Total '+c[0]] + totals)
# Define Periods
# --------------
def define_periods(self, year, period):
# get year start date
ysd = sql("select year_start_date from `tabFiscal Year` where name=%s", year)
ysd = ysd and ysd[0][0] or ''
# add rows for profit / loss in P/L
else:
if c[2]=='Debit':
self.return_data.append([1, 'Total Expenses (before Profit)'] + totals)
self.return_data.append([5, 'Profit/Loss (Provisional)'] + level0_diff)
for i in range(len(totals)): # make totals
level0_diff[i] = flt(totals[i]) + level0_diff[i]
self.return_data.append([4, 'Total '+c[0]] + level0_diff)
else:
self.return_data.append([4, 'Total '+c[0]] + totals)
# Define Periods
# --------------
def define_periods(self, year, period):
# get year start date
ysd = sql("select year_start_date from `tabFiscal Year` where name=%s", year)
ysd = ysd and ysd[0][0] or ''
self.ysd = ysd
self.ysd = ysd
# year
if period == 'Annual':
pn = 'FY'+year
self.period_list.append(pn)
self.period_start_date[pn] = ysd
self.period_end_date[pn] = get_last_day(get_first_day(ysd,0,11))
# year
if period == 'Annual':
pn = 'FY'+year
self.period_list.append(pn)
self.period_start_date[pn] = ysd
self.period_end_date[pn] = get_last_day(get_first_day(ysd,0,11))
# quarter
if period == 'Quarterly':
for i in range(4):
pn = 'Q'+str(i+1)
self.period_list.append(pn)
self.period_start_date[pn] = get_first_day(ysd,0,i*3)
self.period_end_date[pn] = get_last_day(get_first_day(ysd,0,((i+1)*3)-1))
# quarter
if period == 'Quarterly':
for i in range(4):
pn = 'Q'+str(i+1)
self.period_list.append(pn)
self.period_start_date[pn] = get_first_day(ysd,0,i*3)
self.period_end_date[pn] = get_last_day(get_first_day(ysd,0,((i+1)*3)-1))
# month
if period == 'Monthly':
mlist = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
for i in range(12):
fd = get_first_day(ysd,0,i)
pn = mlist[fd.month-1]
self.period_list.append(pn)
self.period_start_date[pn] = fd
self.period_end_date[pn] = get_last_day(fd)
# Get Balance For A Period
# ------------------------
def get_period_balance(self, acc, level, pl, company, fy):
debit_or_credit, lft, rgt = self.ac_details[acc]
ret = []
for p in self.period_list:
sd, ed = self.period_start_date[p].strftime('%Y-%m-%d'), self.period_end_date[p].strftime('%Y-%m-%d')
cond = "and t1.voucher_type != 'Period Closing Voucher'"
if pl=='No':
sd = self.ysd.strftime('%Y-%m-%d')
cond = ""
# month
if period == 'Monthly':
mlist = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
for i in range(12):
fd = get_first_day(ysd,0,i)
pn = mlist[fd.month-1]
self.period_list.append(pn)
self.period_start_date[pn] = fd
self.period_end_date[pn] = get_last_day(fd)
def get_period_balance(self, acc):
ret = []
for p in self.period_list:
period_end_date = self.period_end_date[p].strftime('%Y-%m-%d')
ret.append(get_balance_on(acc, period_end_date))
return ret
def get_top_5_cust(self, company):
rec_grp = sql("select receivables_group from tabCompany where name=%s", company)
if rec_grp:
pa_lft_rgt = sql("select lft, rgt from tabAccount where name=%s and company=%s", (rec_grp[0][0], company))[0]
return sql("select t1.account_name, SUM(t2.debit) from tabAccount t1, `tabGL Entry` t2 where t1.lft > %s and t1.rgt < %s and t2.account = t1.name and ifnull(t2.is_cancelled, 'No') = 'No' GROUP BY t1.name ORDER BY SUM(t2.debit) desc limit 5", (pa_lft_rgt[0], pa_lft_rgt[1]))
else:
return []
bal = sql("select SUM(t1.debit), SUM(t1.credit) from `tabGL Entry` t1, `tabAccount` t2 WHERE t1.posting_date >= '%s' AND t1.posting_date <= '%s' AND t1.company = '%s' AND t1.account = t2.name AND t2.lft >= %s AND t2.rgt <= %s and ifnull(t1.is_opening,'No') = 'No' and ifnull(t1.is_cancelled, 'No') = 'No' %s" % (sd,ed,company,lft,rgt, cond))
bal = bal and (flt(bal[0][0]) - flt(bal[0][1])) or 0
if debit_or_credit == 'Credit' and bal:
bal = -bal
if pl=='No':
op = sql("select opening from `tabAccount Balance` where account=%s and period=%s", (acc, fy))
op = op and op[0][0] or 0
bal += flt(op)
ret.append(bal)
return ret
# Get Dashboard Amounts
# ---------------------
def get_balance(self, acc, sd, ed, company, fy):
a = sql("select account_name, name, debit_or_credit, lft, rgt, is_pl_account from `tabAccount` where account_name=%s and company=%s", (acc, company), as_dict=1)
if a:
a = a[0]
bal = sql("select SUM(IFNULL(t1.debit,0)), SUM(IFNULL(t1.credit,0)) from `tabGL Entry` t1, `tabAccount` t2 WHERE t1.posting_date >= %s AND t1.posting_date <= %s AND t1.account = t2.name AND t2.lft >= %s AND t2.rgt <= %s and ifnull(is_opening, 'No') = 'No' and ifnull(t1.is_cancelled, 'No') = 'No'", (sd,ed,a['lft'],a['rgt']))
if a['debit_or_credit']=='Debit':
bal = flt(flt(bal[0][0]) - flt(bal[0][1]))
else:
bal = flt(flt(bal[0][1]) - flt(bal[0][0]))
def get_top_5_exp(self, company):
a = sql("select distinct account_name, name, debit_or_credit, lft, rgt from `tabAccount` where account_name=%s and company=%s", ('Expenses', company), as_dict=1)[0]
return sql("select t1.account_name, SUM(t2.debit) from tabAccount t1, `tabGL Entry` t2 where t1.lft>%s and t1.rgt<%s and t1.group_or_ledger = 'Ledger' and t2.account = t1.name and ifnull(t2.is_cancelled, 'No') = 'No' and t2.voucher_type != 'Period Closing Voucher' GROUP BY t1.name ORDER BY SUM(t2.debit) desc limit 5", (a['lft'],a['rgt']))
def bl(self, acc, company):
dt = getdate(nowdate())
if a['is_pl_account']=='No':
op = sql("select opening from `tabAccount Balance` where account=%s and period=%s", (acc, fy))
op = op and op[0][0] or 0
bal += flt(op)
r = []
# cur
r.append(get_balance_on(acc, get_fiscal_year(nowdate())))
# this month
r.append(get_balance_on(acc, get_last_day(dt)))
# last month
r.append(get_balance_on(acc, get_last_day(get_first_day(dt,0,-1))))
return r
return flt(bal)
def bl_bs(self, acc, company, sd):
dt = getdate(nowdate())
r = []
# cur
r.append(get_balance_on(acc, get_fiscal_year(nowdate())))
# last month
r.append(self.get_balance_on(acc, get_last_day(get_first_day(dt,0,-1))))
# opening
r.append(self.get_balance_on(acc, sd))
return r
else:
msgprint("Did not find %s for %s" % (acc, company))
return 0
def get_dashboard_values(self, arg=''):
d = get_defaults()
self.fiscal_year = d['fiscal_year']
if arg:
company = arg
else:
company = d['company']
def get_cur_balance(self, acc, company):
bal = sql("select IFNULL(t1.balance,0) from `tabAccount Balance` t1, `tabAccount` t2 where t1.account = %s and t1.period=%s and t1.account = t2.name and t2.company=%s", (acc, self.fiscal_year, company))
return bal and flt(bal[0][0]) or 0
def get_top_5_cust(self, company):
rec_grp = sql("select receivables_group from tabCompany where name=%s", company)
if rec_grp:
pa_lft_rgt = sql("select lft, rgt from tabAccount where name=%s and company=%s", (rec_grp[0][0], company))[0]
return sql("select t1.account_name, SUM(t2.debit) from tabAccount t1, `tabGL Entry` t2 where t1.lft > %s and t1.rgt < %s and t2.account = t1.name and ifnull(t2.is_cancelled, 'No') = 'No' GROUP BY t1.name ORDER BY SUM(t2.debit) desc limit 5", (pa_lft_rgt[0], pa_lft_rgt[1]))
else:
return []
r = {}
r['Income'] = self.bl('Income', company)
r['Expenses'] = self.bl('Expenses', company)
def get_top_5_exp(self, company):
a = sql("select distinct account_name, name, debit_or_credit, lft, rgt from `tabAccount` where account_name=%s and company=%s", ('Expenses', company), as_dict=1)[0]
return sql("select t1.account_name, SUM(t2.debit) from tabAccount t1, `tabGL Entry` t2 where t1.lft>%s and t1.rgt<%s and t1.group_or_ledger = 'Ledger' and t2.account = t1.name and ifnull(t2.is_cancelled, 'No') = 'No' and t2.voucher_type != 'Period Closing Voucher' GROUP BY t1.name ORDER BY SUM(t2.debit) desc limit 5", (a['lft'],a['rgt']))
def bl(self, acc, company):
dt = getdate(nowdate())
r['Profit'] = []
for i in range(3):
r['Profit'].append(r['Income'][i] - r['Expenses'][i])
r['Current Assets'] = self.bl_bs('Current Assets', company, getdate(d['year_start_date']))
r['Current Liabilities'] = self.bl_bs('Current Liabilities', company, getdate(d['year_start_date']))
r['Working Capital'] = []
for i in range(3):
r['Working Capital'].append(r['Current Assets'][i] - r['Current Liabilities'][i])
r = []
# cur
r.append(self.get_cur_balance(acc, company))
# this month
r.append(self.get_balance(acc, get_first_day(dt), get_last_day(dt), company, self.fiscal_year))
# last month
r.append(self.get_balance(acc, get_first_day(dt,0,-1), get_last_day(get_first_day(dt,0,-1)), company, self.fiscal_year))
return r
def bl_bs(self, acc, company, sd):
dt = getdate(nowdate())
r = []
# cur
r.append(self.get_cur_balance(acc, company))
# last month
r.append(self.get_balance(acc, sd, get_last_day(get_first_day(dt,0,-1)), company, self.fiscal_year))
# opening
r.append(self.get_balance(acc, sd, sd, company, self.fiscal_year))
return r
def get_dashboard_values(self, arg=''):
d = get_defaults()
self.fiscal_year = d['fiscal_year']
if arg:
company = arg
else:
company = d['company']
r = {}
r['Income'] = self.bl('Income', company)
r['Expenses'] = self.bl('Expenses', company)
r['Profit'] = []
for i in range(3):
r['Profit'].append(r['Income'][i] - r['Expenses'][i])
r['Current Assets'] = self.bl_bs('Current Assets', company, getdate(d['year_start_date']))
r['Current Liabilities'] = self.bl_bs('Current Liabilities', company, getdate(d['year_start_date']))
r['Working Capital'] = []
for i in range(3):
r['Working Capital'].append(r['Current Assets'][i] - r['Current Liabilities'][i])
r['Bank Accounts'] = self.bl_bs('Bank Accounts', company, getdate(d['year_start_date']))
r['Top Customers'] = convert_to_lists(self.get_top_5_cust(company))
r['Top Expenses'] = convert_to_lists(self.get_top_5_exp(company))
return r
r['Bank Accounts'] = self.bl_bs('Bank Accounts', company, getdate(d['year_start_date']))
r['Top Customers'] = convert_to_lists(self.get_top_5_cust(company))
r['Top Expenses'] = convert_to_lists(self.get_top_5_exp(company))
return r

View File

@@ -1 +0,0 @@
from __future__ import unicode_literals

View File

@@ -1,19 +0,0 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
cur_frm.cscript.export_report = function(doc, cdt, cdn) {
$c_obj_csv(make_doclist(cdt, cdn), 'get_report_data', '');
}

View File

@@ -1,150 +0,0 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
import webnotes
from webnotes.utils import add_days, cint, cstr, flt, getdate
from webnotes.model.doclist import getlist
from webnotes.model.code import get_obj
from webnotes import session, form, msgprint, errprint
sql = webnotes.conn.sql
get_value = webnotes.conn.get_value
#---------------------------------------------------------------------
class DocType:
def __init__(self, doc, doclist=[]):
self.doc = doc
self.doclist = doclist
# Get fiscal year based on date
def get_year(self, dt):
yr = sql("select name from `tabFiscal Year` where %s between year_start_date and date_sub(date_add(year_start_date,interval 1 year), interval 1 day)",dt)
return yr and yr[0][0] or ''
def validate_date(self):
"""check for from date and to date within same year"""
if not sql("select name from `tabFiscal Year` where %s between year_start_date and date_sub(date_add(year_start_date,interval 1 year), interval 1 day) and %s between year_start_date and date_sub(date_add(year_start_date,interval 1 year), interval 1 day)",(self.doc.from_date, self.doc.to_date)):
msgprint("From Date and To Date must be within same year")
raise Exception
if not self.doc.from_date or not self.doc.to_date:
msgprint("From Date and To Date is mandatory")
raise Exception
def add_header(self):
title = 'Ledger Balances Between ' + getdate(self.doc.from_date).strftime('%d-%m-%Y') + ' and ' + getdate(self.doc.to_date).strftime('%d-%m-%Y')
return [[title], ['Account', 'Posting Date', 'Voucher Type', 'Voucher No', 'Debit', 'Credit', 'Remarks']]
def get_account_subtree(self, acc):
return sql("""
SELECT
CONCAT(REPEAT(' ', COUNT(parent.name) - (sub_tree.depth + 1)), node.name) as account,
node.lft AS lft, node.rgt AS rgt,
node.debit_or_credit as dr_or_cr, node.group_or_ledger as group_or_ledger, node.is_pl_account as is_pl_account
FROM tabAccount AS node,
tabAccount AS parent,
tabAccount AS sub_parent,
(
SELECT node.name, (COUNT(parent.name) - 1) AS depth
FROM tabAccount AS node, tabAccount AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
AND node.name = %s
GROUP BY node.name
ORDER BY node.lft
)AS sub_tree
WHERE node.lft BETWEEN parent.lft AND parent.rgt
AND node.lft BETWEEN sub_parent.lft AND sub_parent.rgt
AND sub_parent.name = sub_tree.name
GROUP BY node.name
ORDER BY node.lft""", acc, as_dict = 1, as_utf8=1)
def get_acc_summary(self, glc, acc_det):
from_date_year = self.get_year(add_days(self.doc.from_date, -1))
to_date_year = self.get_year(self.doc.to_date)
acc = acc_det['account'].strip()
if from_date_year == to_date_year:
debit_on_fromdate, credit_on_fromdate, opening = glc.get_as_on_balance(acc, from_date_year, add_days(self.doc.from_date, -1), acc_det['dr_or_cr'], acc_det['lft'], acc_det['rgt']) # opening = closing of prev_date
elif acc_det['is_pl_account'] == 'No': # if there is no previous year in system and not pl account
opening = sql("select opening from `tabAccount Balance` where account = %s and period = %s", (acc, to_date_year))
debit_on_fromdate, credit_on_fromdate, opening = 0, 0, flt(opening[0][0])
else: # if pl account and there is no previous year in system
debit_on_fromdate, credit_on_fromdate, opening = 0,0,0
# closing balance
#--------------------------------
debit_on_todate, credit_on_todate, closing = glc.get_as_on_balance(acc, to_date_year, self.doc.to_date, acc_det['dr_or_cr'], acc_det['lft'], acc_det['rgt'])
# transaction betn the period
#----------------------------------------
debit = flt(debit_on_todate) - flt(debit_on_fromdate)
credit = flt(credit_on_todate) - flt(credit_on_fromdate)
# Debit / Credit
if acc_det['dr_or_cr'] == 'Credit':
opening, closing = -1*opening, -1*closing
return flt(opening>0 and opening or 0), flt(opening<0 and -opening or 0), \
debit, credit, flt(closing>0.01 and closing or 0), flt(closing<-0.01 and -closing or 0)
def show_gl_entries(self, acc):
"""Get gl entries for the period and account"""
gle = sql("select posting_date, voucher_type, voucher_no, debit, credit, remarks from `tabGL Entry` WHERE account = %s and posting_date >= %s AND posting_date <= %s and ifnull(is_opening, 'No') = 'No' and ifnull(is_cancelled, 'No') = 'No'", (acc, self.doc.from_date, self.doc.to_date), as_dict=1, as_utf8=1)
entries, dr, cr = [], 0, 0
for d in gle:
entries.append(['', d['posting_date'], d['voucher_type'], d['voucher_no'], d['debit'], d['credit'], d['remarks']])
return entries
# Get Report Data
def get_report_data(self):
self.validate_date()
res = []
res += self.add_header()
glc = get_obj('GL Control')
for d in getlist(self.doclist, 'ledger_details'):
# Fetch acc details
sub_tree = self.get_account_subtree(d.account)
for acc_det in sub_tree:
acc_summary = self.get_acc_summary(glc, acc_det)
if acc_summary[0] or acc_summary[1] or acc_summary[2] or acc_summary[3] or acc_summary[4] or acc_summary[5]:
res.append([acc_det['account']])
# Show gl entries if account is ledger
if acc_det['group_or_ledger'] == 'Ledger' and (acc_summary[2] or acc_summary[3]):
gle = self.show_gl_entries(acc_det['account'].strip())
res += gle
# Totals
res.append(['', '', '', 'Total Debit/Credit', acc_summary[2], acc_summary[3]])
res.append(['', '', '', 'Opening Balance', acc_summary[0], acc_summary[1]])
res.append(['', '', '', 'Closing Balance', acc_summary[4], acc_summary[5]])
return res

View File

@@ -1,124 +0,0 @@
# DocType, Multi Ledger Report
[
# These values are common in all dictionaries
{
'creation': '2012-03-27 14:35:44',
'docstatus': 0,
'modified': '2012-03-27 14:35:44',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all DocType
{
'_last_update': u'1306229235',
'allow_copy': 1,
'allow_email': 1,
'allow_print': 1,
'colour': u'White:FFF',
'doctype': 'DocType',
'document_type': u'Other',
'hide_heading': 0,
'issingle': 1,
'module': u'Accounts',
'name': '__common__',
'section_style': u'Simple',
'show_in_menu': 0,
'version': 9
},
# These values are common for all DocField
{
'doctype': u'DocField',
'name': '__common__',
'parent': u'Multi Ledger Report',
'parentfield': u'fields',
'parenttype': u'DocType',
'permlevel': 0
},
# These values are common for all DocPerm
{
'create': 1,
'doctype': u'DocPerm',
'name': '__common__',
'parent': u'Multi Ledger Report',
'parentfield': u'permissions',
'parenttype': u'DocType',
'permlevel': 0,
'read': 1,
'write': 1
},
# DocType, Multi Ledger Report
{
'doctype': 'DocType',
'name': u'Multi Ledger Report'
},
# DocPerm
{
'doctype': u'DocPerm',
'role': u'Accounts Manager'
},
# DocPerm
{
'doctype': u'DocPerm',
'role': u'Accounts User'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'select_date_range',
'fieldtype': u'Column Break',
'label': u'Select Date Range'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'from_date',
'fieldtype': u'Date',
'label': u'From Date',
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'to_date',
'fieldtype': u'Date',
'label': u'To Date',
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'select_ledgers',
'fieldtype': u'Column Break',
'label': u'Select ledgers'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'ledger_details',
'fieldtype': u'Table',
'label': u'Multi Ledger Report Details',
'options': u'Multi Ledger Report Detail'
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'export_report',
'fieldtype': u'Button',
'label': u'Export Report',
'trigger': u'Client'
}
]

View File

@@ -63,7 +63,8 @@ class DocType:
def validate_posting_date(self):
yr = sql("select start_date, end_date from `tabPeriod` where fiscal_year = '%s' and period_type = 'Year'" % (self.doc.fiscal_year))
yr = sql("""select year_start_date, adddate(year_start_date, interval 1 year)
from `tabFiscal Year` where name=%s""", (self.doc.fiscal_year, ))
self.year_start_date = yr and yr[0][0] or ''
self.year_end_date = yr and yr[0][1] or ''