2015-03-03 09:25:30 +00:00
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
2013-08-05 09:29:54 +00:00
# License: GNU General Public License v3. See license.txt
2013-01-29 06:02:38 +00:00
from __future__ import unicode_literals
2014-02-14 10:17:51 +00:00
import frappe
2016-05-16 09:08:47 +00:00
from frappe . utils import nowdate , cstr , flt , cint , now , getdate
2014-04-14 13:50:45 +00:00
from frappe import throw , _
2014-02-14 10:17:51 +00:00
from frappe . utils import formatdate
2013-01-29 06:02:38 +00:00
2015-09-28 08:01:17 +00:00
# imported to enable erpnext.accounts.utils.get_account_currency
2016-06-23 07:14:06 +00:00
from erpnext . accounts . doctype . account . account import get_account_currency
2016-06-21 07:03:12 +00:00
import frappe . defaults
from erpnext . accounts . report . financial_statements import sort_root_accounts
2015-09-28 08:01:17 +00:00
2014-02-14 10:17:51 +00:00
class FiscalYearError ( frappe . ValidationError ) : pass
2013-08-22 12:55:43 +00:00
2014-10-03 12:13:02 +00:00
@frappe.whitelist ( )
2016-03-11 09:26:19 +00:00
def get_fiscal_year ( date = None , fiscal_year = None , label = " Date " , verbose = 1 , company = None , as_dict = False ) :
return get_fiscal_years ( date , fiscal_year , label , verbose , company , as_dict = as_dict ) [ 0 ]
2013-01-29 06:02:38 +00:00
2016-03-11 09:26:19 +00:00
def get_fiscal_years ( transaction_date = None , fiscal_year = None , label = " Date " , verbose = 1 , company = None , as_dict = False ) :
2013-01-29 06:02:38 +00:00
# if year start date is 2012-04-01, year end date should be 2013-03-31 (hence subdate)
2015-11-16 13:35:46 +00:00
cond = " disabled = 0 "
2013-06-20 11:05:09 +00:00
if fiscal_year :
2015-05-20 07:23:04 +00:00
cond + = " and fy.name = %(fiscal_year)s "
2013-06-20 11:05:09 +00:00
else :
2015-05-20 07:23:04 +00:00
cond + = " and %(transaction_date)s >= fy.year_start_date and %(transaction_date)s <= fy.year_end_date "
2015-01-14 10:57:13 +00:00
2015-01-12 11:11:46 +00:00
if company :
cond + = """ and (not exists(select name from `tabFiscal Year Company` fyc where fyc.parent = fy.name)
or exists ( select company from ` tabFiscal Year Company ` fyc where fyc . parent = fy . name and fyc . company = % ( company ) s ) ) """
2015-01-14 10:57:13 +00:00
fy = frappe . db . sql ( """ select fy.name, fy.year_start_date, fy.year_end_date from `tabFiscal Year` fy
2015-05-20 06:56:07 +00:00
where % s order by fy . year_start_date desc """ % c ond, {
2015-01-12 11:11:46 +00:00
" fiscal_year " : fiscal_year ,
" transaction_date " : transaction_date ,
" company " : company
2016-03-11 09:26:19 +00:00
} , as_dict = as_dict )
2014-04-08 08:23:35 +00:00
2013-01-29 06:02:38 +00:00
if not fy :
2016-03-11 09:26:19 +00:00
error_msg = _ ( """ {0} {1} not in any active Fiscal Year. For more details check {2} . """ ) . format ( label , formatdate ( transaction_date ) , " https://frappe.github.io/erpnext/user/manual/en/accounts/articles/fiscal-year-error " )
2014-10-03 12:13:02 +00:00
if verbose == 1 : frappe . msgprint ( error_msg )
2013-01-29 06:02:38 +00:00
raise FiscalYearError , error_msg
2013-02-05 17:55:37 +00:00
return fy
2014-04-08 08:23:35 +00:00
2015-02-19 09:21:58 +00:00
def validate_fiscal_year ( date , fiscal_year , label = _ ( " Date " ) , doc = None ) :
2013-07-11 12:19:18 +00:00
years = [ f [ 0 ] for f in get_fiscal_years ( date , label = label ) ]
2013-02-05 17:55:37 +00:00
if fiscal_year not in years :
2015-02-19 09:21:58 +00:00
if doc :
doc . fiscal_year = years [ 0 ]
else :
throw ( _ ( " {0} ' {1} ' not in Fiscal Year {2} " ) . format ( label , formatdate ( date ) , fiscal_year ) )
2013-01-29 06:02:38 +00:00
2014-02-14 10:17:51 +00:00
@frappe.whitelist ( )
2016-07-20 05:56:45 +00:00
def get_balance_on ( account = None , date = None , party_type = None , party = None , company = None , in_account_currency = True ) :
2014-02-14 10:17:51 +00:00
if not account and frappe . form_dict . get ( " account " ) :
account = frappe . form_dict . get ( " account " )
2014-09-17 08:41:22 +00:00
if not date and frappe . form_dict . get ( " date " ) :
2014-02-14 10:17:51 +00:00
date = frappe . form_dict . get ( " date " )
2014-09-17 08:41:22 +00:00
if not party_type and frappe . form_dict . get ( " party_type " ) :
party_type = frappe . form_dict . get ( " party_type " )
if not party and frappe . form_dict . get ( " party " ) :
party = frappe . form_dict . get ( " party " )
2014-04-21 07:12:21 +00:00
2013-01-29 06:02:38 +00:00
cond = [ ]
if date :
2015-11-19 08:54:39 +00:00
cond . append ( " posting_date <= ' %s ' " % frappe . db . escape ( cstr ( date ) ) )
2013-01-29 06:02:38 +00:00
else :
# get balance of all entries that exist
date = nowdate ( )
2014-04-08 08:23:35 +00:00
2013-01-29 06:02:38 +00:00
try :
year_start_date = get_fiscal_year ( date , verbose = 0 ) [ 1 ]
2014-04-14 13:50:45 +00:00
except FiscalYearError :
2013-01-29 06:02:38 +00:00
if getdate ( date ) > getdate ( nowdate ( ) ) :
# if fiscal year not found and the date is greater than today
# get fiscal year for today's date and its corresponding year start date
year_start_date = get_fiscal_year ( nowdate ( ) , verbose = 1 ) [ 1 ]
else :
# this indicates that it is a date older than any existing fiscal year.
# hence, assuming balance as 0.0
return 0.0
2014-04-08 08:23:35 +00:00
2014-09-17 08:41:22 +00:00
if account :
acc = frappe . get_doc ( " Account " , account )
2015-10-15 11:01:16 +00:00
if not frappe . flags . ignore_account_permission :
acc . check_permission ( " read " )
2014-09-17 08:41:22 +00:00
# for pl accounts, get balance within a fiscal year
if acc . report_type == ' Profit and Loss ' :
cond . append ( " posting_date >= ' %s ' and voucher_type != ' Period Closing Voucher ' " \
% year_start_date )
# different filter for group and ledger - improved performance
2015-04-23 07:44:17 +00:00
if acc . is_group :
2014-09-17 08:41:22 +00:00
cond . append ( """ exists (
2015-06-14 12:19:29 +00:00
select name from ` tabAccount ` ac where ac . name = gle . account
2014-09-17 08:41:22 +00:00
and ac . lft > = % s and ac . rgt < = % s
) """ % (acc.lft, acc.rgt))
2015-09-28 08:01:17 +00:00
# If group and currency same as company,
2015-09-17 08:27:42 +00:00
# always return balance based on debit and credit in company currency
if acc . account_currency == frappe . db . get_value ( " Company " , acc . company , " default_currency " ) :
in_account_currency = False
2014-09-17 08:41:22 +00:00
else :
2016-02-19 07:15:57 +00:00
cond . append ( """ gle.account = " %s " """ % ( frappe . db . escape ( account , percent = False ) , ) )
2016-03-11 09:26:19 +00:00
2014-09-17 08:41:22 +00:00
if party_type and party :
cond . append ( """ gle.party_type = " %s " and gle.party = " %s " """ %
2016-02-19 07:15:57 +00:00
( frappe . db . escape ( party_type ) , frappe . db . escape ( party , percent = False ) ) )
2016-12-15 05:57:35 +00:00
2016-07-20 05:56:45 +00:00
if company :
cond . append ( """ gle.company = " %s " """ % ( frappe . db . escape ( company , percent = False ) ) )
2015-09-16 07:16:54 +00:00
2015-08-17 05:57:00 +00:00
if account or ( party_type and party ) :
2015-09-04 07:56:23 +00:00
if in_account_currency :
2015-11-16 13:35:46 +00:00
select_field = " sum(debit_in_account_currency) - sum(credit_in_account_currency) "
2015-09-04 07:56:23 +00:00
else :
2015-11-16 13:35:46 +00:00
select_field = " sum(debit) - sum(credit) "
2015-08-17 05:57:00 +00:00
bal = frappe . db . sql ( """
2015-09-04 07:56:23 +00:00
SELECT { 0 }
2015-08-17 05:57:00 +00:00
FROM ` tabGL Entry ` gle
2015-09-04 07:56:23 +00:00
WHERE { 1 } """ .format(select_field, " and " .join(cond)))[0][0]
2015-08-17 05:57:00 +00:00
# if bal is None, return 0
return flt ( bal )
2013-01-30 13:46:13 +00:00
2016-09-20 05:41:39 +00:00
def get_count_on ( account , fieldname , date ) :
cond = [ ]
if date :
cond . append ( " posting_date <= ' %s ' " % frappe . db . escape ( cstr ( date ) ) )
else :
# get balance of all entries that exist
date = nowdate ( )
try :
year_start_date = get_fiscal_year ( date , verbose = 0 ) [ 1 ]
except FiscalYearError :
if getdate ( date ) > getdate ( nowdate ( ) ) :
# if fiscal year not found and the date is greater than today
# get fiscal year for today's date and its corresponding year start date
year_start_date = get_fiscal_year ( nowdate ( ) , verbose = 1 ) [ 1 ]
else :
# this indicates that it is a date older than any existing fiscal year.
# hence, assuming balance as 0.0
return 0.0
if account :
acc = frappe . get_doc ( " Account " , account )
if not frappe . flags . ignore_account_permission :
acc . check_permission ( " read " )
# for pl accounts, get balance within a fiscal year
if acc . report_type == ' Profit and Loss ' :
cond . append ( " posting_date >= ' %s ' and voucher_type != ' Period Closing Voucher ' " \
% year_start_date )
# different filter for group and ledger - improved performance
if acc . is_group :
cond . append ( """ exists (
select name from ` tabAccount ` ac where ac . name = gle . account
and ac . lft > = % s and ac . rgt < = % s
) """ % (acc.lft, acc.rgt))
# If group and currency same as company,
# always return balance based on debit and credit in company currency
if acc . account_currency == frappe . db . get_value ( " Company " , acc . company , " default_currency " ) :
in_account_currency = False
else :
cond . append ( """ gle.account = " %s " """ % ( frappe . db . escape ( account , percent = False ) , ) )
entries = frappe . db . sql ( """
SELECT name , posting_date , account , party_type , party , debit , credit ,
voucher_type , voucher_no , against_voucher_type , against_voucher
FROM ` tabGL Entry ` gle
WHERE { 0 } """ .format( " and " .join(cond)), as_dict=True)
2016-12-15 05:57:35 +00:00
2016-09-20 05:41:39 +00:00
count = 0
for gle in entries :
if fieldname not in ( ' invoiced_amount ' , ' payables ' ) :
count + = 1
else :
dr_or_cr = " debit " if fieldname == " invoiced_amount " else " credit "
cr_or_dr = " credit " if fieldname == " invoiced_amount " else " debit "
select_fields = " ifnull(sum(credit-debit),0) " if fieldname == " invoiced_amount " else " ifnull(sum(debit-credit),0) "
if ( ( not gle . against_voucher ) or ( gle . against_voucher_type in [ " Sales Order " , " Purchase Order " ] ) or
( gle . against_voucher == gle . voucher_no and gle . get ( dr_or_cr ) > 0 ) ) :
payment_amount = frappe . db . sql ( """
SELECT { 0 }
FROM ` tabGL Entry ` gle
WHERE docstatus < 2 and posting_date < = % ( date ) s and against_voucher = % ( voucher_no ) s
and party = % ( party ) s and name != % ( name ) s """ .format(select_fields),
{ " date " : date , " voucher_no " : gle . voucher_no , " party " : gle . party , " name " : gle . name } ) [ 0 ] [ 0 ]
2016-12-15 05:57:35 +00:00
2016-09-20 05:41:39 +00:00
outstanding_amount = flt ( gle . get ( dr_or_cr ) ) - flt ( gle . get ( cr_or_dr ) ) - payment_amount
currency_precision = get_currency_precision ( ) or 2
if abs ( flt ( outstanding_amount ) ) > 0.1 / 10 * * currency_precision :
count + = 1
2016-12-15 05:57:35 +00:00
2016-09-20 05:41:39 +00:00
return count
2014-02-14 10:17:51 +00:00
@frappe.whitelist ( )
2013-01-30 13:46:13 +00:00
def add_ac ( args = None ) :
2017-01-11 07:11:01 +00:00
from frappe . desk . treeview import make_tree_args
2013-01-30 13:46:13 +00:00
if not args :
2014-02-14 10:17:51 +00:00
args = frappe . local . form_dict
2017-01-11 07:11:01 +00:00
args = make_tree_args ( * * args )
2016-12-15 05:57:35 +00:00
2014-04-22 13:24:54 +00:00
ac = frappe . new_doc ( " Account " )
2016-05-31 01:52:37 +00:00
2016-05-13 10:26:00 +00:00
if args . get ( " ignore_permissions " ) :
ac . flags . ignore_permissions = True
args . pop ( " ignore_permissions " )
2016-05-31 01:52:37 +00:00
2014-04-22 13:24:54 +00:00
ac . update ( args )
2016-05-30 12:24:16 +00:00
if not ac . parent_account :
ac . parent_account = args . get ( " parent " )
2016-12-15 05:57:35 +00:00
2014-03-28 08:25:00 +00:00
ac . old_parent = " "
ac . freeze_account = " No "
2016-05-11 07:07:22 +00:00
if cint ( ac . get ( " is_root " ) ) :
ac . parent_account = None
2016-05-31 01:52:37 +00:00
ac . flags . ignore_mandatory = True
2013-01-30 13:46:13 +00:00
ac . insert ( )
2014-04-22 13:24:54 +00:00
2014-03-28 08:25:00 +00:00
return ac . name
2013-01-30 13:46:13 +00:00
2014-02-14 10:17:51 +00:00
@frappe.whitelist ( )
2013-01-30 13:46:13 +00:00
def add_cc ( args = None ) :
2017-01-11 07:11:01 +00:00
from frappe . desk . treeview import make_tree_args
2013-01-30 13:46:13 +00:00
if not args :
2014-02-14 10:17:51 +00:00
args = frappe . local . form_dict
2017-01-11 07:11:01 +00:00
args = make_tree_args ( * * args )
2014-04-08 08:23:35 +00:00
2014-04-22 13:24:54 +00:00
cc = frappe . new_doc ( " Cost Center " )
cc . update ( args )
2016-05-30 12:24:16 +00:00
if not cc . parent_cost_center :
cc . parent_cost_center = args . get ( " parent " )
2014-03-28 08:25:00 +00:00
cc . old_parent = " "
2013-01-30 13:46:13 +00:00
cc . insert ( )
2014-03-28 08:25:00 +00:00
return cc . name
2013-01-30 13:46:13 +00:00
def reconcile_against_document ( args ) :
"""
Cancel JV , Update aginst document , split if required and resubmit jv
"""
for d in args :
2016-12-15 05:57:35 +00:00
check_if_advance_entry_modified ( d )
2014-04-30 14:00:50 +00:00
validate_allocated_amount ( d )
2016-12-15 05:57:35 +00:00
2016-06-27 12:11:39 +00:00
# cancel advance entry
doc = frappe . get_doc ( d . voucher_type , d . voucher_no )
2013-01-30 13:46:13 +00:00
2016-06-27 12:11:39 +00:00
doc . make_gl_entries ( cancel = 1 , adv_adj = 1 )
2013-01-30 13:46:13 +00:00
2016-06-27 12:11:39 +00:00
# update ref in advance entry
if d . voucher_type == " Journal Entry " :
update_reference_in_journal_entry ( d , doc )
else :
update_reference_in_payment_entry ( d , doc )
2013-01-30 13:46:13 +00:00
2016-06-27 12:11:39 +00:00
# re-submit advance entry
doc = frappe . get_doc ( d . voucher_type , d . voucher_no )
doc . make_gl_entries ( cancel = 0 , adv_adj = 1 )
2013-01-30 13:46:13 +00:00
2016-06-27 12:11:39 +00:00
def check_if_advance_entry_modified ( args ) :
2013-01-30 13:46:13 +00:00
"""
check if there is already a voucher reference
check if amount is same
check if jv is submitted
"""
2016-06-27 12:11:39 +00:00
ret = None
if args . voucher_type == " Journal Entry " :
ret = frappe . db . sql ( """
select t2 . { dr_or_cr } from ` tabJournal Entry ` t1 , ` tabJournal Entry Account ` t2
where t1 . name = t2 . parent and t2 . account = % ( account ) s
and t2 . party_type = % ( party_type ) s and t2 . party = % ( party ) s
and ( t2 . reference_type is null or t2 . reference_type in ( " " , " Sales Order " , " Purchase Order " ) )
and t1 . name = % ( voucher_no ) s and t2 . name = % ( voucher_detail_no ) s
and t1 . docstatus = 1 """ .format(dr_or_cr = args.get( " dr_or_cr " )), args)
else :
party_account_field = " paid_from " if args . party_type == " Customer " else " paid_to "
if args . voucher_detail_no :
2016-12-15 05:57:35 +00:00
ret = frappe . db . sql ( """ select t1.name
from ` tabPayment Entry ` t1 , ` tabPayment Entry Reference ` t2
2016-06-27 12:11:39 +00:00
where
2016-12-15 05:57:35 +00:00
t1 . name = t2 . parent and t1 . docstatus = 1
2016-06-27 12:11:39 +00:00
and t1 . name = % ( voucher_no ) s and t2 . name = % ( voucher_detail_no ) s
and t1 . party_type = % ( party_type ) s and t1 . party = % ( party ) s and t1 . { 0 } = % ( account ) s
2016-12-15 05:57:35 +00:00
and t2 . reference_doctype in ( " " , " Sales Order " , " Purchase Order " )
2016-06-27 12:11:39 +00:00
and t2 . allocated_amount = % ( unadjusted_amount ) s
""" .format(party_account_field), args)
else :
ret = frappe . db . sql ( """ select name from `tabPayment Entry`
where
name = % ( voucher_no ) s and docstatus = 1
and party_type = % ( party_type ) s and party = % ( party ) s and { 0 } = % ( account ) s
and unallocated_amount = % ( unadjusted_amount ) s
""" .format(party_account_field), args)
2014-04-08 08:23:35 +00:00
2013-01-30 13:46:13 +00:00
if not ret :
2014-01-29 11:01:38 +00:00
throw ( _ ( """ Payment Entry has been modified after you pulled it. Please pull it again. """ ) )
2013-01-30 13:46:13 +00:00
2014-04-30 14:00:50 +00:00
def validate_allocated_amount ( args ) :
2016-06-27 12:11:39 +00:00
if args . get ( " allocated_amount " ) < 0 :
2014-04-30 14:00:50 +00:00
throw ( _ ( " Allocated amount can not be negative " ) )
2016-06-27 12:11:39 +00:00
elif args . get ( " allocated_amount " ) > args . get ( " unadjusted_amount " ) :
throw ( _ ( " Allocated amount can not greater than unadjusted amount " ) )
2014-04-30 14:00:50 +00:00
2016-06-27 12:11:39 +00:00
def update_reference_in_journal_entry ( d , jv_obj ) :
2013-01-30 13:46:13 +00:00
"""
Updates against document , if partial amount splits into rows
"""
2014-12-25 12:49:39 +00:00
jv_detail = jv_obj . get ( " accounts " , { " name " : d [ " voucher_detail_no " ] } ) [ 0 ]
2016-06-27 12:11:39 +00:00
jv_detail . set ( d [ " dr_or_cr " ] , d [ " allocated_amount " ] )
2015-10-15 11:01:16 +00:00
jv_detail . set ( ' debit ' if d [ ' dr_or_cr ' ] == ' debit_in_account_currency ' else ' credit ' ,
2016-06-27 12:11:39 +00:00
d [ " allocated_amount " ] * flt ( jv_detail . exchange_rate ) )
2015-08-10 11:34:07 +00:00
original_reference_type = jv_detail . reference_type
original_reference_name = jv_detail . reference_name
jv_detail . set ( " reference_type " , d [ " against_voucher_type " ] )
jv_detail . set ( " reference_name " , d [ " against_voucher " ] )
2013-01-30 13:46:13 +00:00
2016-06-27 12:11:39 +00:00
if d [ ' allocated_amount ' ] < d [ ' unadjusted_amount ' ] :
2015-09-09 13:13:12 +00:00
jvd = frappe . db . sql ( """
2015-11-12 11:35:29 +00:00
select cost_center , balance , against_account , is_advance ,
2015-10-16 07:38:33 +00:00
account_type , exchange_rate , account_currency
2015-09-09 13:13:12 +00:00
from ` tabJournal Entry Account ` where name = % s
""" , d[ ' voucher_detail_no ' ], as_dict=True)
2015-10-15 11:01:16 +00:00
2016-06-27 12:11:39 +00:00
amount_in_account_currency = flt ( d [ ' unadjusted_amount ' ] ) - flt ( d [ ' allocated_amount ' ] )
2015-10-02 06:35:55 +00:00
amount_in_company_currency = amount_in_account_currency * flt ( jvd [ 0 ] [ ' exchange_rate ' ] )
2015-09-16 07:16:54 +00:00
2013-01-30 13:46:13 +00:00
# new entry with balance amount
2014-12-25 12:49:39 +00:00
ch = jv_obj . append ( " accounts " )
2013-01-30 13:46:13 +00:00
ch . account = d [ ' account ' ]
2015-09-09 13:13:12 +00:00
ch . account_type = jvd [ 0 ] [ ' account_type ' ]
2015-10-16 07:38:33 +00:00
ch . account_currency = jvd [ 0 ] [ ' account_currency ' ]
2015-09-09 13:13:12 +00:00
ch . exchange_rate = jvd [ 0 ] [ ' exchange_rate ' ]
2014-08-29 05:48:32 +00:00
ch . party_type = d [ " party_type " ]
ch . party = d [ " party " ]
2015-09-09 13:13:12 +00:00
ch . cost_center = cstr ( jvd [ 0 ] [ " cost_center " ] )
ch . balance = flt ( jvd [ 0 ] [ " balance " ] )
2015-10-15 11:01:16 +00:00
2015-10-02 06:35:55 +00:00
ch . set ( d [ ' dr_or_cr ' ] , amount_in_account_currency )
ch . set ( ' debit ' if d [ ' dr_or_cr ' ] == ' debit_in_account_currency ' else ' credit ' , amount_in_company_currency )
2015-10-15 11:01:16 +00:00
ch . set ( ' credit_in_account_currency ' if d [ ' dr_or_cr ' ] == ' debit_in_account_currency '
2015-10-02 06:35:55 +00:00
else ' debit_in_account_currency ' , 0 )
ch . set ( ' credit ' if d [ ' dr_or_cr ' ] == ' debit_in_account_currency ' else ' debit ' , 0 )
2015-10-15 11:01:16 +00:00
2015-09-09 13:13:12 +00:00
ch . against_account = cstr ( jvd [ 0 ] [ " against_account " ] )
2015-08-10 11:34:07 +00:00
ch . reference_type = original_reference_type
ch . reference_name = original_reference_name
2015-09-09 13:13:12 +00:00
ch . is_advance = cstr ( jvd [ 0 ] [ " is_advance " ] )
2013-01-30 13:46:13 +00:00
ch . docstatus = 1
2014-04-08 08:23:35 +00:00
# will work as update after submit
2015-02-10 09:11:27 +00:00
jv_obj . flags . ignore_validate_update_after_submit = True
2015-12-31 07:56:36 +00:00
jv_obj . save ( ignore_permissions = True )
2016-12-15 05:57:35 +00:00
2016-06-27 12:11:39 +00:00
def update_reference_in_payment_entry ( d , payment_entry ) :
reference_details = {
" reference_doctype " : d . against_voucher_type ,
" reference_name " : d . against_voucher ,
" total_amount " : d . grand_total ,
" outstanding_amount " : d . outstanding_amount ,
" allocated_amount " : d . allocated_amount ,
" exchange_rate " : d . exchange_rate
}
2016-12-15 05:57:35 +00:00
2016-06-27 12:11:39 +00:00
if d . voucher_detail_no :
existing_row = payment_entry . get ( " references " , { " name " : d [ " voucher_detail_no " ] } ) [ 0 ]
original_row = existing_row . as_dict ( ) . copy ( )
existing_row . update ( reference_details )
2016-12-15 05:57:35 +00:00
2016-06-27 12:11:39 +00:00
if d . allocated_amount < original_row . allocated_amount :
new_row = payment_entry . append ( " references " )
new_row . docstatus = 1
for field in reference_details . keys ( ) :
new_row . set ( field , original_row [ field ] )
2016-12-15 05:57:35 +00:00
2016-06-27 12:11:39 +00:00
new_row . allocated_amount = original_row . allocated_amount - d . allocated_amount
else :
new_row = payment_entry . append ( " references " )
new_row . docstatus = 1
new_row . update ( reference_details )
2016-12-15 05:57:35 +00:00
2016-06-27 12:11:39 +00:00
payment_entry . flags . ignore_validate_update_after_submit = True
2016-06-28 14:12:19 +00:00
payment_entry . setup_party_account_field ( )
2016-06-27 14:39:05 +00:00
payment_entry . set_missing_values ( )
2016-06-27 12:11:39 +00:00
payment_entry . set_amounts ( )
payment_entry . save ( ignore_permissions = True )
2016-12-15 05:57:35 +00:00
2016-11-23 10:28:51 +00:00
def unlink_ref_doc_from_payment_entries ( ref_doc ) :
remove_ref_doc_link_from_jv ( ref_doc . doctype , ref_doc . name )
remove_ref_doc_link_from_pe ( ref_doc . doctype , ref_doc . name )
2016-12-15 05:57:35 +00:00
2016-07-21 13:00:03 +00:00
frappe . db . sql ( """ update `tabGL Entry`
set against_voucher_type = null , against_voucher = null ,
modified = % s , modified_by = % s
where against_voucher_type = % s and against_voucher = % s
and voucher_no != ifnull ( against_voucher , ' ' ) """ ,
2016-11-23 10:28:51 +00:00
( now ( ) , frappe . session . user , ref_doc . doctype , ref_doc . name ) )
2016-12-15 05:57:35 +00:00
2016-11-23 10:28:51 +00:00
if ref_doc . doctype in ( " Sales Invoice " , " Purchase Invoice " ) :
ref_doc . set ( " advances " , [ ] )
2016-12-15 05:57:35 +00:00
2016-11-23 10:28:51 +00:00
frappe . db . sql ( """ delete from `tab {0} Advance` where parent = %s """
. format ( ref_doc . doctype ) , ref_doc . name )
2016-07-21 13:00:03 +00:00
def remove_ref_doc_link_from_jv ( ref_type , ref_no ) :
2014-12-25 10:31:55 +00:00
linked_jv = frappe . db . sql_list ( """ select parent from `tabJournal Entry Account`
2015-08-10 11:34:07 +00:00
where reference_type = % s and reference_name = % s and docstatus < 2 """ , (ref_type, ref_no))
2014-04-08 08:23:35 +00:00
if linked_jv :
2015-08-10 11:34:07 +00:00
frappe . db . sql ( """ update `tabJournal Entry Account`
set reference_type = null , reference_name = null ,
2014-01-03 09:42:16 +00:00
modified = % s , modified_by = % s
2015-08-10 11:34:07 +00:00
where reference_type = % s and reference_name = % s
and docstatus < 2 """ , (now(), frappe.session.user, ref_type, ref_no))
2014-04-08 08:23:35 +00:00
2014-12-25 11:44:18 +00:00
frappe . msgprint ( _ ( " Journal Entries {0} are un-linked " . format ( " \n " . join ( linked_jv ) ) ) )
2016-12-15 05:57:35 +00:00
2016-07-21 13:00:03 +00:00
def remove_ref_doc_link_from_pe ( ref_type , ref_no ) :
linked_pe = frappe . db . sql_list ( """ select parent from `tabPayment Entry Reference`
where reference_doctype = % s and reference_name = % s and docstatus < 2 """ , (ref_type, ref_no))
if linked_pe :
frappe . db . sql ( """ update `tabPayment Entry Reference`
set allocated_amount = 0 , modified = % s , modified_by = % s
where reference_doctype = % s and reference_name = % s
and docstatus < 2 """ , (now(), frappe.session.user, ref_type, ref_no))
2016-12-15 05:57:35 +00:00
2016-07-21 13:00:03 +00:00
for pe in linked_pe :
pe_doc = frappe . get_doc ( " Payment Entry " , pe )
pe_doc . set_total_allocated_amount ( )
pe_doc . set_unallocated_amount ( )
pe_doc . clear_unallocated_reference_document_rows ( )
2016-12-15 05:57:35 +00:00
frappe . db . sql ( """ update `tabPayment Entry` set total_allocated_amount= %s ,
base_total_allocated_amount = % s , unallocated_amount = % s , modified = % s , modified_by = % s
where name = % s """ , (pe_doc.total_allocated_amount, pe_doc.base_total_allocated_amount,
2016-07-21 13:00:03 +00:00
pe_doc . unallocated_amount , now ( ) , frappe . session . user , pe ) )
2016-12-15 05:57:35 +00:00
2016-07-21 13:00:03 +00:00
frappe . msgprint ( _ ( " Payment Entries {0} are un-linked " . format ( " \n " . join ( linked_pe ) ) ) )
2013-03-25 05:36:00 +00:00
2014-02-14 10:17:51 +00:00
@frappe.whitelist ( )
2013-03-25 05:36:00 +00:00
def get_company_default ( company , fieldname ) :
2014-02-26 07:05:33 +00:00
value = frappe . db . get_value ( " Company " , company , fieldname )
2014-04-08 08:23:35 +00:00
2013-03-25 05:36:00 +00:00
if not value :
2016-06-26 12:18:07 +00:00
throw ( _ ( " Please set default {0} in Company {1} " ) . format ( frappe . get_meta ( " Company " ) . get_label ( fieldname ) , company ) )
2014-04-08 08:23:35 +00:00
2013-03-25 05:36:00 +00:00
return value
2013-05-28 11:22:30 +00:00
def fix_total_debit_credit ( ) :
2014-04-08 08:23:35 +00:00
vouchers = frappe . db . sql ( """ select voucher_type, voucher_no,
sum ( debit ) - sum ( credit ) as diff
from ` tabGL Entry `
2013-05-28 11:22:30 +00:00
group by voucher_type , voucher_no
2015-11-16 13:35:46 +00:00
having sum ( debit ) != sum ( credit ) """ , as_dict=1)
2014-04-08 08:23:35 +00:00
2013-05-28 11:22:30 +00:00
for d in vouchers :
if abs ( d . diff ) > 0 :
dr_or_cr = d . voucher_type == " Sales Invoice " and " credit " or " debit "
2014-04-08 08:23:35 +00:00
2014-02-26 07:05:33 +00:00
frappe . db . sql ( """ update `tabGL Entry` set %s = %s + %s
2013-05-28 11:22:30 +00:00
where voucher_type = % s and voucher_no = % s and % s > 0 limit 1 """ %
2014-04-08 08:23:35 +00:00
( dr_or_cr , dr_or_cr , ' %s ' , ' %s ' , ' %s ' , dr_or_cr ) ,
2013-08-02 06:14:29 +00:00
( d . diff , d . voucher_type , d . voucher_no ) )
2014-04-08 08:23:35 +00:00
2013-08-26 11:23:30 +00:00
def get_stock_and_account_difference ( account_list = None , posting_date = None ) :
2014-10-08 06:49:55 +00:00
from erpnext . stock . utils import get_stock_value_on
2014-04-08 08:23:35 +00:00
2013-08-26 11:23:30 +00:00
if not posting_date : posting_date = nowdate ( )
2014-04-08 08:23:35 +00:00
2013-08-02 06:14:29 +00:00
difference = { }
2014-04-08 08:23:35 +00:00
2014-08-27 06:35:48 +00:00
account_warehouse = dict ( frappe . db . sql ( """ select name, warehouse from tabAccount
2016-06-25 08:48:28 +00:00
where account_type = ' Stock ' and ( warehouse is not null and warehouse != ' ' ) and is_group = 0
2013-09-25 05:02:51 +00:00
and name in ( % s ) """ % ' , ' .join([ ' %s ' ]*len(account_list)), account_list))
2014-04-08 08:23:35 +00:00
2013-09-25 05:02:51 +00:00
for account , warehouse in account_warehouse . items ( ) :
2015-09-04 07:56:23 +00:00
account_balance = get_balance_on ( account , posting_date , in_account_currency = False )
2014-10-08 06:49:55 +00:00
stock_value = get_stock_value_on ( warehouse , posting_date )
2013-08-07 08:51:04 +00:00
if abs ( flt ( stock_value ) - flt ( account_balance ) ) > 0.005 :
2013-08-07 07:03:37 +00:00
difference . setdefault ( account , flt ( stock_value ) - flt ( account_balance ) )
2013-08-07 08:51:04 +00:00
2013-08-06 10:49:18 +00:00
return difference
2013-08-22 09:08:46 +00:00
2014-01-22 10:06:44 +00:00
def get_currency_precision ( currency = None ) :
if not currency :
2014-04-08 08:23:35 +00:00
currency = frappe . db . get_value ( " Company " ,
2015-12-23 11:07:00 +00:00
frappe . db . get_default ( " Company " ) , " default_currency " , cache = True )
2015-04-27 07:43:38 +00:00
currency_format = frappe . db . get_value ( " Currency " , currency , " number_format " , cache = True )
2014-04-08 08:23:35 +00:00
2014-02-14 10:17:51 +00:00
from frappe . utils import get_number_format_info
2014-01-24 16:14:36 +00:00
return get_number_format_info ( currency_format ) [ 2 ]
2014-08-07 09:40:05 +00:00
def get_stock_rbnb_difference ( posting_date , company ) :
stock_items = frappe . db . sql_list ( """ select distinct item_code
2014-08-07 09:43:52 +00:00
from ` tabStock Ledger Entry ` where company = % s """ , company)
2014-08-07 09:40:05 +00:00
pr_valuation_amount = frappe . db . sql ( """
2015-11-16 13:35:46 +00:00
select sum ( pr_item . valuation_rate * pr_item . qty * pr_item . conversion_factor )
2014-08-07 09:40:05 +00:00
from ` tabPurchase Receipt Item ` pr_item , ` tabPurchase Receipt ` pr
where pr . name = pr_item . parent and pr . docstatus = 1 and pr . company = % s
and pr . posting_date < = % s and pr_item . item_code in ( % s ) """ %
( ' %s ' , ' %s ' , ' , ' . join ( [ ' %s ' ] * len ( stock_items ) ) ) , tuple ( [ company , posting_date ] + stock_items ) ) [ 0 ] [ 0 ]
pi_valuation_amount = frappe . db . sql ( """
2015-11-16 13:35:46 +00:00
select sum ( pi_item . valuation_rate * pi_item . qty * pi_item . conversion_factor )
2014-08-07 09:40:05 +00:00
from ` tabPurchase Invoice Item ` pi_item , ` tabPurchase Invoice ` pi
where pi . name = pi_item . parent and pi . docstatus = 1 and pi . company = % s
and pi . posting_date < = % s and pi_item . item_code in ( % s ) """ %
( ' %s ' , ' %s ' , ' , ' . join ( [ ' %s ' ] * len ( stock_items ) ) ) , tuple ( [ company , posting_date ] + stock_items ) ) [ 0 ] [ 0 ]
# Balance should be
stock_rbnb = flt ( pr_valuation_amount , 2 ) - flt ( pi_valuation_amount , 2 )
# Balance as per system
2014-08-07 09:43:52 +00:00
stock_rbnb_account = " Stock Received But Not Billed - " + frappe . db . get_value ( " Company " , company , " abbr " )
2015-09-04 07:56:23 +00:00
sys_bal = get_balance_on ( stock_rbnb_account , posting_date , in_account_currency = False )
2014-08-07 09:40:05 +00:00
# Amount should be credited
return flt ( stock_rbnb ) + flt ( sys_bal )
2014-09-12 09:48:53 +00:00
2015-11-12 11:35:29 +00:00
def get_outstanding_invoices ( party_type , party , account , condition = None ) :
outstanding_invoices = [ ]
precision = frappe . get_precision ( " Sales Invoice " , " outstanding_amount " )
if party_type == " Customer " :
2015-11-16 13:35:46 +00:00
dr_or_cr = " debit_in_account_currency - credit_in_account_currency "
payment_dr_or_cr = " payment_gl_entry.credit_in_account_currency - payment_gl_entry.debit_in_account_currency "
2015-11-12 11:35:29 +00:00
else :
2015-11-16 13:35:46 +00:00
dr_or_cr = " credit_in_account_currency - debit_in_account_currency "
payment_dr_or_cr = " payment_gl_entry.debit_in_account_currency - payment_gl_entry.credit_in_account_currency "
2015-11-12 11:35:29 +00:00
2016-07-04 10:46:24 +00:00
invoice_list = frappe . db . sql ( """
select
voucher_no , voucher_type , posting_date , ifnull ( sum ( { dr_or_cr } ) , 0 ) as invoice_amount ,
2015-11-12 11:35:29 +00:00
(
2016-07-04 10:46:24 +00:00
select ifnull ( sum ( { payment_dr_or_cr } ) , 0 )
2015-11-12 11:35:29 +00:00
from ` tabGL Entry ` payment_gl_entry
2016-07-04 10:46:24 +00:00
where payment_gl_entry . against_voucher_type = invoice_gl_entry . voucher_type
2015-11-12 11:35:29 +00:00
and payment_gl_entry . against_voucher = invoice_gl_entry . voucher_no
and payment_gl_entry . party_type = invoice_gl_entry . party_type
and payment_gl_entry . party = invoice_gl_entry . party
and payment_gl_entry . account = invoice_gl_entry . account
and { payment_dr_or_cr } > 0
) as payment_amount
2014-09-12 09:48:53 +00:00
from
2015-11-12 11:35:29 +00:00
` tabGL Entry ` invoice_gl_entry
2014-09-12 09:48:53 +00:00
where
2016-12-15 05:57:35 +00:00
party_type = % ( party_type ) s and party = % ( party ) s
2016-07-04 10:46:24 +00:00
and account = % ( account ) s and { dr_or_cr } > 0
2015-11-12 11:35:29 +00:00
{ condition }
and ( ( voucher_type = ' Journal Entry '
2016-07-01 10:28:39 +00:00
and ( against_voucher = ' ' or against_voucher is null ) )
or ( voucher_type not in ( ' Journal Entry ' , ' Payment Entry ' ) ) )
2014-09-12 09:48:53 +00:00
group by voucher_type , voucher_no
2016-06-25 20:07:21 +00:00
having ( invoice_amount - payment_amount ) > 0.005
order by posting_date , name """ .format(
2015-11-12 11:35:29 +00:00
dr_or_cr = dr_or_cr ,
payment_dr_or_cr = payment_dr_or_cr ,
condition = condition or " "
) , {
" party_type " : party_type ,
" party " : party ,
" account " : account ,
2016-07-01 10:28:39 +00:00
} , as_dict = True )
2015-11-12 11:35:29 +00:00
for d in invoice_list :
2016-06-28 10:45:58 +00:00
outstanding_invoices . append ( frappe . _dict ( {
2015-11-12 11:35:29 +00:00
' voucher_no ' : d . voucher_no ,
' voucher_type ' : d . voucher_type ,
' posting_date ' : d . posting_date ,
' invoice_amount ' : flt ( d . invoice_amount ) ,
' payment_amount ' : flt ( d . payment_amount ) ,
2016-05-05 10:26:48 +00:00
' outstanding_amount ' : flt ( d . invoice_amount - d . payment_amount , precision ) ,
2016-06-25 20:07:21 +00:00
' due_date ' : frappe . db . get_value ( d . voucher_type , d . voucher_no , " due_date " ) ,
2016-06-28 10:45:58 +00:00
} ) )
2016-12-15 05:57:35 +00:00
2016-06-27 12:11:39 +00:00
outstanding_invoices = sorted ( outstanding_invoices , key = lambda k : k [ ' due_date ' ] or getdate ( nowdate ( ) ) )
2016-12-15 05:57:35 +00:00
2015-11-12 11:35:29 +00:00
return outstanding_invoices
2016-02-22 09:48:40 +00:00
2016-03-18 09:35:50 +00:00
def get_account_name ( account_type = None , root_type = None , is_group = None , account_currency = None , company = None ) :
2016-02-22 09:48:40 +00:00
""" return account based on matching conditions """
2016-02-23 14:31:04 +00:00
return frappe . db . get_value ( " Account " , {
" account_type " : account_type or ' ' ,
" root_type " : root_type or ' ' ,
" is_group " : is_group or 0 ,
" account_currency " : account_currency or frappe . defaults . get_defaults ( ) . currency ,
" company " : company or frappe . defaults . get_defaults ( ) . company
} , " name " )
2016-06-21 07:03:12 +00:00
@frappe.whitelist ( )
def get_companies ( ) :
""" get a list of companies based on permission """
return [ d . name for d in frappe . get_list ( " Company " , fields = [ " name " ] ,
order_by = " name " ) ]
@frappe.whitelist ( )
def get_children ( ) :
args = frappe . local . form_dict
2016-06-24 06:06:31 +00:00
doctype , company = args [ ' doctype ' ] , args [ ' company ' ]
fieldname = frappe . db . escape ( doctype . lower ( ) . replace ( ' ' , ' _ ' ) )
doctype = frappe . db . escape ( doctype )
2016-06-21 07:03:12 +00:00
# root
if args [ ' parent ' ] in ( " Accounts " , " Cost Centers " ) :
2016-06-24 06:06:31 +00:00
fields = " , root_type, report_type, account_currency " if doctype == " Account " else " "
2016-06-21 07:03:12 +00:00
acc = frappe . db . sql ( """ select
name as value , is_group as expandable { fields }
from ` tab { doctype } `
where ifnull ( ` parent_ { fieldname } ` , ' ' ) = ' '
and ` company ` = % s and docstatus < 2
order by name """ .format(fields=fields, fieldname = fieldname, doctype=doctype),
company , as_dict = 1 )
if args [ " parent " ] == " Accounts " :
sort_root_accounts ( acc )
else :
# other
2016-06-24 06:06:31 +00:00
fields = " , account_currency " if doctype == " Account " else " "
2016-06-21 07:03:12 +00:00
acc = frappe . db . sql ( """ select
name as value , is_group as expandable , parent_ { fieldname } as parent { fields }
from ` tab { doctype } `
where ifnull ( ` parent_ { fieldname } ` , ' ' ) = % s
and docstatus < 2
order by name """ .format(fields=fields, fieldname=fieldname, doctype=doctype),
args [ ' parent ' ] , as_dict = 1 )
2016-06-24 06:06:31 +00:00
if doctype == ' Account ' :
2016-06-21 07:03:12 +00:00
company_currency = frappe . db . get_value ( " Company " , company , " default_currency " )
for each in acc :
each [ " company_currency " ] = company_currency
each [ " balance " ] = flt ( get_balance_on ( each . get ( " value " ) , in_account_currency = False ) )
if each . account_currency != company_currency :
each [ " balance_in_account_currency " ] = flt ( get_balance_on ( each . get ( " value " ) ) )
return acc
2016-09-09 05:49:22 +00:00
def create_payment_gateway_and_account ( gateway ) :
create_payment_gateway ( gateway )
create_payment_gateway_account ( gateway )
def create_payment_gateway ( gateway ) :
# NOTE: we don't translate Payment Gateway name because it is an internal doctype
if not frappe . db . exists ( " Payment Gateway " , gateway ) :
payment_gateway = frappe . get_doc ( {
" doctype " : " Payment Gateway " ,
" gateway " : gateway
} )
payment_gateway . insert ( ignore_permissions = True )
def create_payment_gateway_account ( gateway ) :
from erpnext . setup . setup_wizard . setup_wizard import create_bank_account
company = frappe . db . get_value ( " Global Defaults " , None , " default_company " )
if not company :
return
# NOTE: we translate Payment Gateway account name because that is going to be used by the end user
bank_account = frappe . db . get_value ( " Account " , { " account_name " : _ ( gateway ) , " company " : company } ,
[ " name " , ' account_currency ' ] , as_dict = 1 )
if not bank_account :
# check for untranslated one
bank_account = frappe . db . get_value ( " Account " , { " account_name " : gateway , " company " : company } ,
[ " name " , ' account_currency ' ] , as_dict = 1 )
if not bank_account :
# try creating one
bank_account = create_bank_account ( { " company_name " : company , " bank_account " : _ ( gateway ) } )
if not bank_account :
frappe . msgprint ( _ ( " Payment Gateway Account not created, please create one manually. " ) )
return
# if payment gateway account exists, return
if frappe . db . exists ( " Payment Gateway Account " ,
{ " payment_gateway " : gateway , " currency " : bank_account . account_currency } ) :
return
try :
frappe . get_doc ( {
" doctype " : " Payment Gateway Account " ,
" is_default " : 1 ,
" payment_gateway " : gateway ,
" payment_account " : bank_account . name ,
" currency " : bank_account . account_currency
} ) . insert ( ignore_permissions = True )
except frappe . DuplicateEntryError :
# already exists, due to a reinstall?
2016-08-26 05:41:17 +00:00
pass