2015-03-03 14:55:30 +05:30
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
2013-08-05 14:59:54 +05:30
# License: GNU General Public License v3. See license.txt
2013-01-29 11:34:39 +05:30
from __future__ import unicode_literals
2014-02-14 15:47:51 +05:30
import frappe
from frappe import _ , throw
2015-07-24 13:26:36 +05:30
from frappe . utils import today , flt , cint
2014-07-01 17:45:15 +05:30
from erpnext . setup . utils import get_company_currency , get_exchange_rate
2015-09-28 13:31:17 +05:30
from erpnext . accounts . utils import get_fiscal_year , validate_fiscal_year , get_account_currency
2014-02-10 14:47:54 +05:30
from erpnext . utilities . transaction_base import TransactionBase
2014-09-21 19:45:49 +05:30
from erpnext . controllers . recurring_document import convert_to_recurring , validate_recurring_document
2015-07-24 13:26:36 +05:30
from erpnext . controllers . sales_and_purchase_return import validate_return
2015-10-22 17:54:50 +05:30
from erpnext . accounts . party import get_party_account_currency
2015-09-30 16:41:15 +05:30
from erpnext . exceptions import CustomerFrozen , InvalidCurrency
2015-07-17 15:19:02 +05:30
2015-08-10 19:18:39 +05:30
force_item_fields = ( " item_group " , " barcode " , " brand " , " stock_uom " )
2015-08-03 16:13:33 +05:30
2013-01-30 12:49:08 +05:30
class AccountsController ( TransactionBase ) :
2015-08-19 13:49:10 +05:30
def __init__ ( self , arg1 , arg2 = None ) :
super ( AccountsController , self ) . __init__ ( arg1 , arg2 )
2015-09-11 16:22:37 +05:30
2015-08-27 12:28:36 +05:30
@property
def company_currency ( self ) :
if not hasattr ( self , " __company_currency " ) :
self . __company_currency = get_company_currency ( self . company )
2015-09-11 16:22:37 +05:30
2015-08-27 12:28:36 +05:30
return self . __company_currency
2015-09-11 16:22:37 +05:30
2013-03-20 12:55:28 +05:30
def validate ( self ) :
2014-07-03 12:25:06 +05:30
if self . get ( " _action " ) and self . _action != " update_after_submit " :
2014-06-05 16:55:31 +05:30
self . set_missing_values ( for_validate = True )
2013-07-11 17:49:18 +05:30
self . validate_date_with_fiscal_year ( )
2015-08-03 16:13:33 +05:30
2013-05-24 19:25:01 +05:30
if self . meta . get_field ( " currency " ) :
2013-05-28 17:23:36 +05:30
self . calculate_taxes_and_totals ( )
2015-07-17 15:19:02 +05:30
if not self . meta . get_field ( " is_return " ) or not self . is_return :
self . validate_value ( " base_grand_total " , " >= " , 0 )
2015-08-03 16:13:33 +05:30
2015-07-24 13:26:36 +05:30
validate_return ( self )
2013-05-24 19:25:01 +05:30
self . set_total_in_words ( )
2014-04-08 20:10:03 +05:30
2015-07-17 16:54:25 +05:30
if self . doctype in ( " Sales Invoice " , " Purchase Invoice " ) and not self . is_return :
2015-07-17 15:19:02 +05:30
self . validate_due_date ( )
2014-04-08 20:10:03 +05:30
2014-09-21 19:45:49 +05:30
if self . meta . get_field ( " is_recurring " ) :
validate_recurring_document ( self )
2014-10-06 13:20:53 +05:30
if self . meta . get_field ( " taxes_and_charges " ) :
self . validate_enabled_taxes_and_charges ( )
2015-08-03 16:13:33 +05:30
2015-07-17 12:10:12 +05:30
self . validate_party ( )
2015-08-20 14:55:39 +05:30
self . validate_currency ( )
2014-10-06 13:20:53 +05:30
2014-09-21 19:45:49 +05:30
def on_submit ( self ) :
if self . meta . get_field ( " is_recurring " ) :
convert_to_recurring ( self , self . get ( " posting_date " ) or self . get ( " transaction_date " ) )
def on_update_after_submit ( self ) :
if self . meta . get_field ( " is_recurring " ) :
validate_recurring_document ( self )
convert_to_recurring ( self , self . get ( " posting_date " ) or self . get ( " transaction_date " ) )
def before_recurring ( self ) :
2015-06-08 12:10:43 +05:30
if self . meta . get_field ( " fiscal_year " ) :
self . fiscal_year = None
2015-04-27 18:08:51 +05:30
if self . meta . get_field ( " due_date " ) :
self . due_date = None
2014-09-21 19:45:49 +05:30
2013-06-14 17:44:03 +05:30
def set_missing_values ( self , for_validate = False ) :
for fieldname in [ " posting_date " , " transaction_date " ] :
2014-03-28 13:55:00 +05:30
if not self . get ( fieldname ) and self . meta . get_field ( fieldname ) :
self . set ( fieldname , today ( ) )
2015-06-08 12:06:33 +05:30
if self . meta . get_field ( " fiscal_year " ) and not self . fiscal_year :
2014-03-31 23:37:40 +05:30
self . fiscal_year = get_fiscal_year ( self . get ( fieldname ) ) [ 0 ]
2014-04-18 01:30:14 +05:30
break
2014-04-08 20:10:03 +05:30
2015-02-17 11:11:11 +05:30
def calculate_taxes_and_totals ( self ) :
2015-02-18 12:23:18 +05:30
from erpnext . controllers . taxes_and_totals import calculate_taxes_and_totals
calculate_taxes_and_totals ( self )
2015-02-17 11:11:11 +05:30
if self . doctype in [ " Quotation " , " Sales Order " , " Delivery Note " , " Sales Invoice " ] :
self . calculate_commission ( )
self . calculate_contribution ( )
2013-07-11 17:49:18 +05:30
def validate_date_with_fiscal_year ( self ) :
if self . meta . get_field ( " fiscal_year " ) :
date_field = " "
if self . meta . get_field ( " posting_date " ) :
date_field = " posting_date "
elif self . meta . get_field ( " transaction_date " ) :
date_field = " transaction_date "
2014-04-08 20:10:03 +05:30
2014-03-31 23:37:40 +05:30
if date_field and self . get ( date_field ) :
2014-04-08 20:10:03 +05:30
validate_fiscal_year ( self . get ( date_field ) , self . fiscal_year ,
2015-02-19 14:51:58 +05:30
self . meta . get_label ( date_field ) , self )
2014-04-08 20:10:03 +05:30
2014-08-27 16:46:33 +05:30
def validate_due_date ( self ) :
from erpnext . accounts . party import validate_due_date
if self . doctype == " Sales Invoice " :
2015-07-22 17:47:49 +05:30
if not self . due_date :
frappe . throw ( _ ( " Due Date is mandatory " ) )
2015-08-03 16:13:33 +05:30
2014-08-27 16:46:33 +05:30
validate_due_date ( self . posting_date , self . due_date , " Customer " , self . customer , self . company )
elif self . doctype == " Purchase Invoice " :
validate_due_date ( self . posting_date , self . due_date , " Supplier " , self . supplier , self . company )
2013-10-17 17:01:14 +05:30
def set_price_list_currency ( self , buying_or_selling ) :
2013-08-09 18:11:35 +05:30
if self . meta . get_field ( " currency " ) :
2013-09-17 10:21:20 +05:30
# price list part
fieldname = " selling_price_list " if buying_or_selling . lower ( ) == " selling " \
else " buying_price_list "
2014-03-28 13:55:00 +05:30
if self . meta . get_field ( fieldname ) and self . get ( fieldname ) :
self . price_list_currency = frappe . db . get_value ( " Price List " ,
self . get ( fieldname ) , " currency " )
2014-04-08 20:10:03 +05:30
2015-08-28 19:24:22 +05:30
if self . price_list_currency == self . company_currency :
2014-03-28 13:55:00 +05:30
self . plc_conversion_rate = 1.0
2013-09-24 14:36:55 +05:30
2014-03-28 13:55:00 +05:30
elif not self . plc_conversion_rate :
2014-07-01 17:45:15 +05:30
self . plc_conversion_rate = get_exchange_rate (
2015-08-28 19:24:22 +05:30
self . price_list_currency , self . company_currency )
2014-04-08 20:10:03 +05:30
2013-09-17 10:21:20 +05:30
# currency
2014-03-28 13:55:00 +05:30
if not self . currency :
self . currency = self . price_list_currency
self . conversion_rate = self . plc_conversion_rate
2015-08-28 19:24:22 +05:30
elif self . currency == self . company_currency :
2014-03-28 13:55:00 +05:30
self . conversion_rate = 1.0
elif not self . conversion_rate :
2014-07-01 17:45:15 +05:30
self . conversion_rate = get_exchange_rate ( self . currency ,
2015-08-28 19:24:22 +05:30
self . company_currency )
2013-09-17 10:21:20 +05:30
2014-02-11 16:14:52 +05:30
def set_missing_item_details ( self ) :
2013-05-24 19:25:01 +05:30
""" set missing item values """
2014-02-11 16:14:52 +05:30
from erpnext . stock . get_item_details import get_item_details
2015-11-30 18:40:06 +05:30
if self . doctype == " Purchase Invoice " :
auto_accounting_for_stock = cint ( frappe . defaults . get_global_default ( " auto_accounting_for_stock " ) )
if auto_accounting_for_stock :
stock_not_billed_account = self . get_company_default ( " stock_received_but_not_billed " )
stock_items = self . get_stock_items ( )
2015-02-24 16:50:47 +05:30
2014-12-26 13:15:21 +05:30
if hasattr ( self , " items " ) :
2014-06-20 15:59:49 +05:30
parent_dict = { }
2014-04-10 17:53:30 +05:30
for fieldname in self . meta . get_valid_columns ( ) :
parent_dict [ fieldname ] = self . get ( fieldname )
2014-12-26 13:15:21 +05:30
for item in self . get ( " items " ) :
2014-04-03 14:30:42 +05:30
if item . get ( " item_code " ) :
2014-06-20 15:59:49 +05:30
args = parent_dict . copy ( )
args . update ( item . as_dict ( ) )
2015-03-09 14:54:37 +05:30
if not args . get ( " transaction_date " ) :
args [ " transaction_date " ] = args . get ( " posting_date " )
2015-03-20 14:18:09 +05:30
if self . get ( " is_subcontracted " ) :
args [ " is_subcontracted " ] = self . is_subcontracted
2014-04-03 14:30:42 +05:30
ret = get_item_details ( args )
2014-05-28 12:49:20 +05:30
2014-04-03 14:30:42 +05:30
for fieldname , value in ret . items ( ) :
2015-11-16 19:05:46 +05:30
if item . meta . get_field ( fieldname ) and value is not None :
if ( item . get ( fieldname ) is None or fieldname in force_item_fields ) :
2014-04-03 14:30:42 +05:30
item . set ( fieldname , value )
2014-04-08 20:10:03 +05:30
2015-11-16 19:05:46 +05:30
elif fieldname == " cost_center " and not item . get ( " cost_center " ) :
item . set ( fieldname , value )
elif fieldname == " conversion_factor " and not item . get ( " conversion_factor " ) :
2014-12-30 18:33:52 +05:30
item . set ( fieldname , value )
2014-05-28 12:49:20 +05:30
if ret . get ( " pricing_rule " ) :
2015-08-13 13:25:43 +05:30
item . set ( " discount_percentage " , ret . get ( " discount_percentage " ) )
if ret . get ( " pricing_rule_for " ) == " Price " :
item . set ( " pricing_list_rate " , ret . get ( " pricing_list_rate " ) )
2015-09-11 16:22:37 +05:30
2015-09-22 15:26:15 +05:30
if item . price_list_rate :
item . rate = flt ( item . price_list_rate *
2015-09-28 17:27:02 +05:30
( 1.0 - ( flt ( item . discount_percentage ) / 100.0 ) ) , item . precision ( " rate " ) )
2015-11-30 18:40:06 +05:30
if self . doctype == " Purchase Invoice " :
if auto_accounting_for_stock and item . item_code in stock_items \
and self . is_opening == ' No ' \
and ( not item . po_detail or not frappe . db . get_value ( " Purchase Order Item " ,
item . po_detail , " delivered_by_supplier " ) ) :
item . expense_account = stock_not_billed_account
item . cost_center = None
2014-05-28 12:49:20 +05:30
2015-05-12 15:07:02 +05:30
def set_taxes ( self ) :
if not self . meta . get_field ( " taxes " ) :
2013-05-24 19:25:01 +05:30
return
2014-04-08 20:10:03 +05:30
2015-05-12 15:07:02 +05:30
tax_master_doctype = self . meta . get_field ( " taxes_and_charges " ) . options
2014-04-08 20:10:03 +05:30
2015-05-12 15:07:02 +05:30
if not self . get ( " taxes " ) :
if not self . get ( " taxes_and_charges " ) :
2013-05-24 19:25:01 +05:30
# get the default tax master
2015-05-12 15:07:02 +05:30
self . set ( " taxes_and_charges " , frappe . db . get_value ( tax_master_doctype , { " is_default " : 1 } ) )
2014-04-08 20:10:03 +05:30
2015-05-12 15:07:02 +05:30
self . append_taxes_from_master ( tax_master_doctype )
2014-04-08 20:10:03 +05:30
2015-05-12 15:07:02 +05:30
def append_taxes_from_master ( self , tax_master_doctype = None ) :
if self . get ( " taxes_and_charges " ) :
2013-07-04 17:13:53 +05:30
if not tax_master_doctype :
2015-05-12 15:07:02 +05:30
tax_master_doctype = self . meta . get_field ( " taxes_and_charges " ) . options
2014-04-08 20:10:03 +05:30
2015-05-12 15:07:02 +05:30
self . extend ( " taxes " , get_taxes_and_charges ( tax_master_doctype , self . get ( " taxes_and_charges " ) ) )
2014-01-30 13:56:57 +05:30
2014-04-18 01:30:14 +05:30
def set_other_charges ( self ) :
2014-12-25 16:01:55 +05:30
self . set ( " taxes " , [ ] )
2015-05-12 15:07:02 +05:30
self . set_taxes ( )
2014-04-08 20:10:03 +05:30
2014-10-06 13:20:53 +05:30
def validate_enabled_taxes_and_charges ( self ) :
taxes_and_charges_doctype = self . meta . get_options ( " taxes_and_charges " )
if frappe . db . get_value ( taxes_and_charges_doctype , self . taxes_and_charges , " disabled " ) :
frappe . throw ( _ ( " {0} ' {1} ' is disabled " ) . format ( taxes_and_charges_doctype , self . taxes_and_charges ) )
2015-08-19 13:49:10 +05:30
def get_gl_dict ( self , args , account_currency = None ) :
2013-01-29 11:34:39 +05:30
""" this method populates the common properties of a gl entry record """
2014-02-14 15:47:51 +05:30
gl_dict = frappe . _dict ( {
2014-04-08 20:10:03 +05:30
' company ' : self . company ,
2014-03-28 13:55:00 +05:30
' posting_date ' : self . posting_date ,
' voucher_type ' : self . doctype ,
' voucher_no ' : self . name ,
2014-04-07 12:02:57 +05:30
' remarks ' : self . get ( " remarks " ) ,
2014-03-28 13:55:00 +05:30
' fiscal_year ' : self . fiscal_year ,
2013-01-29 11:34:39 +05:30
' debit ' : 0 ,
' credit ' : 0 ,
2015-08-19 13:49:10 +05:30
' debit_in_account_currency ' : 0 ,
' credit_in_account_currency ' : 0 ,
2014-03-28 13:55:00 +05:30
' is_opening ' : self . get ( " is_opening " ) or " No " ,
2014-08-29 11:18:32 +05:30
' party_type ' : None ,
' party ' : None
2013-08-28 18:53:11 +05:30
} )
2013-01-29 11:34:39 +05:30
gl_dict . update ( args )
2015-09-11 16:22:37 +05:30
2015-08-20 14:55:39 +05:30
if not account_currency :
2015-09-28 13:31:17 +05:30
account_currency = get_account_currency ( gl_dict . account )
2015-09-11 16:22:37 +05:30
2015-10-21 13:22:40 +05:30
if self . doctype not in [ " Journal Entry " , " Period Closing Voucher " ] :
2015-09-17 21:07:04 +05:30
self . validate_account_currency ( gl_dict . account , account_currency )
self . set_balance_in_account_currency ( gl_dict , account_currency )
2015-09-11 16:22:37 +05:30
2015-08-19 19:22:34 +05:30
return gl_dict
2015-09-11 16:22:37 +05:30
2015-08-20 14:55:39 +05:30
def validate_account_currency ( self , account , account_currency = None ) :
2015-08-28 19:24:22 +05:30
valid_currency = [ self . company_currency ]
if self . get ( " currency " ) and self . currency != self . company_currency :
valid_currency . append ( self . currency )
2015-08-20 14:55:39 +05:30
if account_currency not in valid_currency :
2015-08-27 12:28:36 +05:30
frappe . throw ( _ ( " Account {0} is invalid. Account Currency must be {1} " )
2015-09-11 16:22:37 +05:30
. format ( account , _ ( " or " ) . join ( valid_currency ) ) )
def set_balance_in_account_currency ( self , gl_dict , account_currency = None ) :
2015-09-17 21:07:04 +05:30
if ( not self . get ( " conversion_rate " ) and account_currency != self . company_currency ) :
2015-08-28 19:24:22 +05:30
frappe . throw ( _ ( " Account: {0} with currency: {1} can not be selected " )
. format ( gl_dict . account , account_currency ) )
2015-09-11 16:22:37 +05:30
2015-08-28 19:24:22 +05:30
gl_dict [ " account_currency " ] = self . company_currency if account_currency == self . company_currency \
2015-08-19 19:22:34 +05:30
else account_currency
2015-09-11 16:22:37 +05:30
2015-08-19 13:49:10 +05:30
# set debit/credit in account currency if not provided
if flt ( gl_dict . debit ) and not flt ( gl_dict . debit_in_account_currency ) :
gl_dict . debit_in_account_currency = gl_dict . debit if account_currency == self . company_currency \
2015-08-19 19:22:34 +05:30
else flt ( gl_dict . debit / ( self . get ( " conversion_rate " ) ) , 2 )
2015-09-11 16:22:37 +05:30
2015-08-19 13:49:10 +05:30
if flt ( gl_dict . credit ) and not flt ( gl_dict . credit_in_account_currency ) :
gl_dict . credit_in_account_currency = gl_dict . credit if account_currency == self . company_currency \
2015-08-19 19:22:34 +05:30
else flt ( gl_dict . credit / ( self . get ( " conversion_rate " ) ) , 2 )
2015-09-11 16:22:37 +05:30
2013-02-06 17:33:46 +05:30
def clear_unallocated_advances ( self , childtype , parentfield ) :
2014-04-02 18:09:34 +05:30
self . set ( parentfield , self . get ( parentfield , { " allocated_amount " : [ " not in " , [ 0 , None , " " ] ] } ) )
2014-04-08 20:10:03 +05:30
frappe . db . sql ( """ delete from `tab %s ` where parentfield= %s and parent = %s
2015-11-16 19:05:46 +05:30
and allocated_amount = 0 """ % (childtype, ' %s ' , ' %s ' ), (parentfield, self.name))
2014-04-08 20:10:03 +05:30
2014-08-29 11:18:32 +05:30
def get_advances ( self , account_head , party_type , party , child_doctype , parentfield , dr_or_cr , against_order_field ) :
2015-08-10 17:04:07 +05:30
""" Returns list of advances against Account, Party, Reference """
order_list = list ( set ( [ d . get ( against_order_field ) for d in self . get ( " items " ) if d . get ( against_order_field ) ] ) )
# conver sales_order to "Sales Order"
reference_type = against_order_field . replace ( " _ " , " " ) . title ( )
2015-09-11 16:22:37 +05:30
2015-08-21 12:34:41 +05:30
condition = " "
if order_list :
in_placeholder = ' , ' . join ( [ ' %s ' ] * len ( order_list ) )
condition = " or (t2.reference_type = ' {0} ' and ifnull(t2.reference_name, ' ' ) in ( {1} )) " \
. format ( reference_type , in_placeholder )
2015-09-11 16:22:37 +05:30
2014-05-01 15:43:22 +05:30
res = frappe . db . sql ( """
select
2015-08-10 17:04:07 +05:30
t1 . name as jv_no , t1 . remark , t2 . { 0 } as amount , t2 . name as jv_detail_no ,
reference_name as against_order
2014-05-01 15:43:22 +05:30
from
2014-12-25 17:14:18 +05:30
` tabJournal Entry ` t1 , ` tabJournal Entry Account ` t2
2014-05-01 15:43:22 +05:30
where
2014-08-29 11:18:32 +05:30
t1 . name = t2 . parent and t2 . account = % s
2015-08-10 17:04:07 +05:30
and t2 . party_type = % s and t2 . party = % s
2014-08-29 11:18:32 +05:30
and t2 . is_advance = ' Yes ' and t1 . docstatus = 1
2015-08-21 12:34:41 +05:30
and ( ifnull ( t2 . reference_type , ' ' ) = ' ' { 1 } )
order by t1 . posting_date """ .format(dr_or_cr, condition),
[ account_head , party_type , party ] + order_list , as_dict = 1 )
2014-09-16 11:08:08 +05:30
2014-03-27 16:12:56 +05:30
self . set ( parentfield , [ ] )
2013-01-30 19:16:13 +05:30
for d in res :
2014-09-18 15:03:54 +05:30
self . append ( parentfield , {
" doctype " : child_doctype ,
2014-12-25 17:14:18 +05:30
" journal_entry " : d . jv_no ,
2014-09-18 15:03:54 +05:30
" jv_detail_no " : d . jv_detail_no ,
" remarks " : d . remark ,
" advance_amount " : flt ( d . amount ) ,
2014-10-13 10:47:14 +05:30
" allocated_amount " : flt ( d . amount ) if d . against_order else 0
2014-09-18 15:03:54 +05:30
} )
2015-08-10 17:04:07 +05:30
def validate_advance_jv ( self , reference_type ) :
against_order_field = frappe . scrub ( reference_type )
2014-12-25 18:19:39 +05:30
order_list = list ( set ( [ d . get ( against_order_field ) for d in self . get ( " items " ) if d . get ( against_order_field ) ] ) )
2014-09-18 15:03:54 +05:30
if order_list :
account = self . get ( " debit_to " if self . doctype == " Sales Invoice " else " credit_to " )
2015-08-10 17:04:07 +05:30
jv_against_order = frappe . db . sql ( """ select parent, reference_name as against_order
2014-12-25 16:01:55 +05:30
from ` tabJournal Entry Account `
2014-09-18 15:03:54 +05:30
where docstatus = 1 and account = % s and ifnull ( is_advance , ' No ' ) = ' Yes '
2015-08-10 17:04:07 +05:30
and reference_type = % s
and ifnull ( reference_name , ' ' ) in ( { 0 } )
group by parent , reference_name """ .format( ' , ' .join([ ' %s ' ]*len(order_list))),
tuple ( [ account , reference_type ] + order_list ) , as_dict = 1 )
2014-09-18 15:03:54 +05:30
if jv_against_order :
order_jv_map = { }
for d in jv_against_order :
order_jv_map . setdefault ( d . against_order , [ ] ) . append ( d . parent )
2015-08-10 17:04:07 +05:30
advance_jv_against_si = [ d . journal_entry for d in self . get ( " advances " ) ]
2014-09-18 15:03:54 +05:30
for order , jv_list in order_jv_map . items ( ) :
for jv in jv_list :
if not advance_jv_against_si or jv not in advance_jv_against_si :
2014-12-31 13:24:36 +05:30
frappe . msgprint ( _ ( " Journal Entry {0} is linked against Order {1} , check if it should be pulled as advance in this invoice. " )
2014-09-18 15:03:54 +05:30
. format ( jv , order ) )
2014-04-08 20:10:03 +05:30
2013-07-29 18:35:39 +05:30
def validate_multiple_billing ( self , ref_dt , item_ref_dn , based_on , parentfield ) :
2014-01-23 15:33:30 +05:30
from erpnext . controllers . status_updater import get_tolerance_for
2014-01-03 17:43:19 +05:30
item_tolerance = { }
global_tolerance = None
2014-04-08 20:10:03 +05:30
2014-12-25 18:19:39 +05:30
for item in self . get ( " items " ) :
2014-03-28 13:55:00 +05:30
if item . get ( item_ref_dn ) :
2014-04-08 20:10:03 +05:30
ref_amt = flt ( frappe . db . get_value ( ref_dt + " Item " ,
2014-03-31 23:37:40 +05:30
item . get ( item_ref_dn ) , based_on ) , self . precision ( based_on , item ) )
2014-01-07 12:41:09 +05:30
if not ref_amt :
2014-04-14 19:20:45 +05:30
frappe . msgprint ( _ ( " Warning: System will not check overbilling since amount for Item {0} in {1} is zero " ) . format ( item . item_code , ref_dt ) )
2014-01-07 12:41:09 +05:30
else :
2014-04-08 20:10:03 +05:30
already_billed = frappe . db . sql ( """ select sum( %s ) from `tab %s `
where % s = % s and docstatus = 1 and parent != % s """ %
2014-12-26 13:15:21 +05:30
( based_on , self . doctype + " Item " , item_ref_dn , ' %s ' , ' %s ' ) ,
2014-03-31 23:37:40 +05:30
( item . get ( item_ref_dn ) , self . name ) ) [ 0 ] [ 0 ]
2014-04-08 20:10:03 +05:30
total_billed_amt = flt ( flt ( already_billed ) + flt ( item . get ( based_on ) ) ,
2014-01-07 12:41:09 +05:30
self . precision ( based_on , item ) )
2014-04-08 20:10:03 +05:30
tolerance , item_tolerance , global_tolerance = get_tolerance_for ( item . item_code ,
2014-01-07 12:41:09 +05:30
item_tolerance , global_tolerance )
2014-04-08 20:10:03 +05:30
2014-01-07 12:41:09 +05:30
max_allowed_amt = flt ( ref_amt * ( 100 + tolerance ) / 100 )
2014-04-08 20:10:03 +05:30
2014-01-07 12:41:09 +05:30
if total_billed_amt - max_allowed_amt > 0.01 :
2015-01-06 12:56:37 +05:30
frappe . throw ( _ ( " Cannot overbill for Item {0} in row {1} more than {2} . To allow overbilling, please set in Stock Settings " ) . format ( item . item_code , item . idx , max_allowed_amt ) )
2014-04-08 20:10:03 +05:30
2013-03-25 11:06:00 +05:30
def get_company_default ( self , fieldname ) :
2013-12-12 19:12:19 +05:30
from erpnext . accounts . utils import get_company_default
2014-03-28 13:55:00 +05:30
return get_company_default ( self . company , fieldname )
2014-04-08 20:10:03 +05:30
2013-08-02 14:50:12 +05:30
def get_stock_items ( self ) :
stock_items = [ ]
2014-12-26 13:15:21 +05:30
item_codes = list ( set ( item . item_code for item in self . get ( " items " ) ) )
2013-08-02 14:50:12 +05:30
if item_codes :
2014-02-26 12:35:33 +05:30
stock_items = [ r [ 0 ] for r in frappe . db . sql ( """ select name
2015-07-24 15:16:25 +05:30
from ` tabItem ` where name in ( % s ) and is_stock_item = 1 """ % \
2013-08-02 14:50:12 +05:30
( " , " . join ( ( [ " %s " ] * len ( item_codes ) ) ) , ) , item_codes ) ]
2014-04-08 20:10:03 +05:30
2013-08-02 14:50:12 +05:30
return stock_items
2014-04-08 20:10:03 +05:30
2014-09-12 15:18:53 +05:30
def set_total_advance_paid ( self ) :
if self . doctype == " Sales Order " :
2015-08-28 19:24:22 +05:30
dr_or_cr = " credit_in_account_currency "
2014-09-12 15:18:53 +05:30
else :
2015-08-28 19:24:22 +05:30
dr_or_cr = " debit_in_account_currency "
2014-09-12 15:18:53 +05:30
advance_paid = frappe . db . sql ( """
select
2015-11-16 19:05:46 +05:30
sum ( { dr_or_cr } )
2014-09-12 15:18:53 +05:30
from
2014-12-25 16:01:55 +05:30
` tabJournal Entry Account `
2014-09-12 15:18:53 +05:30
where
2015-09-11 16:22:37 +05:30
reference_type = % s and reference_name = % s
2015-08-28 19:24:22 +05:30
and docstatus = 1 and is_advance = " Yes "
""" .format(dr_or_cr=dr_or_cr), (self.doctype, self.name))
2014-09-12 15:18:53 +05:30
if advance_paid :
advance_paid = flt ( advance_paid [ 0 ] [ 0 ] , self . precision ( " advance_paid " ) )
2015-02-12 16:09:11 +05:30
if flt ( self . base_grand_total ) > = advance_paid :
2014-09-12 15:18:53 +05:30
frappe . db . set_value ( self . doctype , self . name , " advance_paid " , advance_paid )
else :
frappe . throw ( _ ( " Total advance ( {0} ) against Order {1} cannot be greater \
than the Grand Total ( { 2 } ) " )
2015-02-12 16:09:11 +05:30
. format ( advance_paid , self . name , self . base_grand_total ) )
2014-09-12 15:18:53 +05:30
2014-08-26 14:29:06 +05:30
@property
def company_abbr ( self ) :
if not hasattr ( self , " _abbr " ) :
self . _abbr = frappe . db . get_value ( " Company " , self . company , " abbr " )
return self . _abbr
2015-07-17 12:10:12 +05:30
def validate_party ( self ) :
2015-07-24 13:10:50 +05:30
frozen_accounts_modifier = frappe . db . get_value ( ' Accounts Settings ' , None , ' frozen_accounts_modifier ' )
if frozen_accounts_modifier in frappe . get_roles ( ) :
return
2015-08-03 16:13:33 +05:30
2015-08-27 12:28:36 +05:30
party_type , party = self . get_party ( )
if party_type :
2015-09-11 16:22:37 +05:30
if frappe . db . get_value ( party_type , party , " is_frozen " ) :
2015-08-27 12:28:36 +05:30
frappe . throw ( " {0} {1} is frozen " . format ( party_type , party ) , CustomerFrozen )
2015-09-11 16:22:37 +05:30
2015-08-27 12:28:36 +05:30
def get_party ( self ) :
2015-07-20 13:03:48 +05:30
party_type = None
2015-07-17 12:10:12 +05:30
if self . meta . get_field ( " customer " ) :
2015-07-20 13:03:48 +05:30
party_type = ' Customer '
2015-07-17 12:10:12 +05:30
2015-07-20 13:03:48 +05:30
elif self . meta . get_field ( " supplier " ) :
party_type = ' Supplier '
2015-09-11 16:22:37 +05:30
2015-08-27 12:28:36 +05:30
party = self . get ( party_type . lower ( ) ) if party_type else None
2015-09-11 16:22:37 +05:30
2015-08-27 12:28:36 +05:30
return party_type , party
2015-09-11 16:22:37 +05:30
2015-08-27 12:28:36 +05:30
def validate_currency ( self ) :
2015-08-28 19:24:22 +05:30
if self . get ( " currency " ) :
2015-08-27 12:28:36 +05:30
party_type , party = self . get_party ( )
2015-08-28 19:24:22 +05:30
if party_type and party :
2015-09-25 16:17:50 +05:30
party_account_currency = get_party_account_currency ( party_type , party , self . company )
2015-09-11 16:22:37 +05:30
2015-10-01 18:55:25 +05:30
if ( party_account_currency
and party_account_currency != self . company_currency
and self . currency != party_account_currency ) :
2015-09-03 10:28:08 +05:30
frappe . throw ( _ ( " Accounting Entry for {0} : {1} can only be made in currency: {2} " )
. format ( party_type , party , party_account_currency ) , InvalidCurrency )
2015-09-11 16:22:37 +05:30
2015-10-22 17:54:50 +05:30
# Note: not validating with gle account because we don't have the account at quotation / sales order level and we shouldn't stop someone from creating a sales invoice if sales order is already created
2014-02-14 15:47:51 +05:30
@frappe.whitelist ( )
2013-10-10 16:35:09 +05:30
def get_tax_rate ( account_head ) :
2014-04-08 20:10:03 +05:30
return frappe . db . get_value ( " Account " , account_head , " tax_rate " )
2015-06-01 17:15:42 +05:30
2015-05-12 15:07:02 +05:30
@frappe.whitelist ( )
def get_default_taxes_and_charges ( master_doctype ) :
default_tax = frappe . db . get_value ( master_doctype , { " is_default " : 1 } )
return get_taxes_and_charges ( master_doctype , default_tax )
2014-05-02 15:45:10 +05:30
@frappe.whitelist ( )
2015-05-12 15:07:02 +05:30
def get_taxes_and_charges ( master_doctype , master_name ) :
2015-05-16 12:14:39 +05:30
if not master_name :
return
2014-05-02 15:45:10 +05:30
from frappe . model import default_fields
tax_master = frappe . get_doc ( master_doctype , master_name )
taxes_and_charges = [ ]
2015-05-12 15:07:02 +05:30
for i , tax in enumerate ( tax_master . get ( " taxes " ) ) :
2014-05-02 15:45:10 +05:30
tax = tax . as_dict ( )
for fieldname in default_fields :
if fieldname in tax :
del tax [ fieldname ]
taxes_and_charges . append ( tax )
return taxes_and_charges
2014-09-29 12:17:03 +05:30
def validate_conversion_rate ( currency , conversion_rate , conversion_rate_label , company ) :
""" common validation for currency and price list currency """
2015-04-27 13:13:38 +05:30
company_currency = frappe . db . get_value ( " Company " , company , " default_currency " , cache = True )
2014-09-29 12:17:03 +05:30
if not conversion_rate :
throw ( _ ( " {0} is mandatory. Maybe Currency Exchange record is not created for {1} to {2} . " ) . format (
conversion_rate_label , currency , company_currency ) )
2015-02-23 11:58:15 +05:30
def validate_taxes_and_charges ( tax ) :
2015-02-23 16:01:33 +05:30
if tax . charge_type in [ ' Actual ' , ' On Net Total ' ] and tax . row_id :
2015-02-23 11:58:15 +05:30
frappe . throw ( _ ( " Can refer row only if the charge type is ' On Previous Row Amount ' or ' Previous Row Total ' " ) )
2015-02-23 16:01:33 +05:30
elif tax . charge_type in [ ' On Previous Row Amount ' , ' On Previous Row Total ' ] :
2015-02-23 11:58:15 +05:30
if cint ( tax . idx ) == 1 :
frappe . throw ( _ ( " Cannot select charge type as ' On Previous Row Amount ' or ' On Previous Row Total ' for first row " ) )
elif not tax . row_id :
frappe . throw ( _ ( " Please specify a valid Row ID for row {0} in table {1} " . format ( tax . idx , _ ( tax . doctype ) ) ) )
elif tax . row_id and cint ( tax . row_id ) > = cint ( tax . idx ) :
frappe . throw ( _ ( " Cannot refer row number greater than or equal to current row number for this Charge type " ) )
2015-02-25 15:08:42 +05:30
if tax . charge_type == " Actual " :
2015-02-27 23:40:56 +05:30
tax . rate = None
2015-02-25 15:08:42 +05:30
2015-02-23 11:58:15 +05:30
def validate_inclusive_tax ( tax , doc ) :
def _on_previous_row_error ( row_range ) :
throw ( _ ( " To include tax in row {0} in Item rate, taxes in rows {1} must also be included " ) . format ( tax . idx ,
row_range ) )
if cint ( getattr ( tax , " included_in_print_rate " , None ) ) :
if tax . charge_type == " Actual " :
# inclusive tax cannot be of type Actual
throw ( _ ( " Charge of type ' Actual ' in row {0} cannot be included in Item Rate " ) . format ( tax . idx ) )
elif tax . charge_type == " On Previous Row Amount " and \
not cint ( doc . get ( " taxes " ) [ cint ( tax . row_id ) - 1 ] . included_in_print_rate ) :
# referred row should also be inclusive
_on_previous_row_error ( tax . row_id )
elif tax . charge_type == " On Previous Row Total " and \
not all ( [ cint ( t . included_in_print_rate ) for t in doc . get ( " taxes " ) [ : cint ( tax . row_id ) - 1 ] ] ) :
# all rows about the reffered tax should be inclusive
_on_previous_row_error ( " 1 - %d " % ( tax . row_id , ) )
2015-02-24 17:08:34 +05:30
elif tax . get ( " category " ) == " Valuation " :
2015-02-24 16:05:19 +05:30
frappe . throw ( _ ( " Valuation type charges can not marked as Inclusive " ) )