2012-02-23 07:05:32 +00:00
# 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/>.
2012-07-19 08:10:31 +00:00
from __future__ import unicode_literals
2011-06-08 09:07:15 +00:00
import webnotes
2013-05-15 15:45:57 +00:00
from webnotes import msgprint , _
2013-03-13 07:28:54 +00:00
from webnotes . utils import load_json , cstr , flt , now_datetime
2012-11-30 11:08:04 +00:00
from webnotes . model . doc import addchild
2011-06-08 09:07:15 +00:00
2013-06-03 11:15:38 +00:00
from controllers . status_updater import StatusUpdater
2013-01-15 13:09:21 +00:00
2013-06-03 11:15:38 +00:00
class TransactionBase ( StatusUpdater ) :
2013-04-26 11:51:49 +00:00
def get_default_address_and_contact ( self , party_type ) :
""" get a dict of default field values of address and contact for a given party type
party_type can be one of : customer , supplier """
ret = { }
# {customer: self.doc.fields.get("customer")}
args = { party_type : self . doc . fields . get ( party_type ) }
address_text , address_name = self . get_address_text ( * * args )
ret . update ( {
# customer_address
( party_type + " _address " ) : address_name ,
" address_display " : address_text
} )
ret . update ( self . get_contact_text ( * * args ) )
return ret
2011-06-08 09:07:15 +00:00
# Get Customer Default Primary Address - first load
def get_default_customer_address ( self , args = ' ' ) :
address_text , address_name = self . get_address_text ( customer = self . doc . customer )
self . doc . customer_address = address_name or ' '
self . doc . address_display = address_text or ' '
2012-10-26 09:31:22 +00:00
self . doc . fields . update ( self . get_contact_text ( customer = self . doc . customer ) )
2012-04-20 04:55:03 +00:00
2012-02-14 09:43:21 +00:00
if args != ' onload ' :
2012-04-20 04:55:03 +00:00
self . get_customer_details ( self . doc . customer )
2012-02-14 09:43:21 +00:00
self . get_sales_person ( self . doc . customer )
2011-06-08 09:07:15 +00:00
# Get Customer Default Shipping Address - first load
# -----------------------
def get_default_customer_shipping_address ( self , args = ' ' ) :
address_text , address_name = self . get_address_text ( customer = self . doc . customer , is_shipping_address = 1 )
self . doc . customer_address = address_name or ' '
self . doc . address_display = address_text or ' '
2012-10-26 09:31:22 +00:00
self . doc . fields . update ( self . get_contact_text ( customer = self . doc . customer ) )
2011-06-08 09:07:15 +00:00
2012-02-14 09:43:21 +00:00
if self . doc . doctype != ' Quotation ' and args != ' onload ' :
2012-04-20 04:55:03 +00:00
self . get_customer_details ( self . doc . customer )
2012-02-14 09:43:21 +00:00
self . get_sales_person ( self . doc . customer )
2011-06-08 09:07:15 +00:00
# Get Customer Address
# -----------------------
def get_customer_address ( self , args ) :
args = load_json ( args )
address_text , address_name = self . get_address_text ( address_name = args [ ' address ' ] )
ret = {
' customer_address ' : address_name ,
' address_display ' : address_text ,
}
2012-10-26 09:31:22 +00:00
ret . update ( self . get_contact_text ( contact_name = args [ ' contact ' ] ) )
2011-08-16 11:08:11 +00:00
return ret
2011-06-08 09:07:15 +00:00
# Get Address Text
# -----------------------
def get_address_text ( self , customer = None , address_name = None , supplier = None , is_shipping_address = None ) :
if customer :
cond = customer and ' customer= " %s " ' % customer or ' name= " %s " ' % address_name
elif supplier :
cond = supplier and ' supplier= " %s " ' % supplier or ' name= " %s " ' % address_name
else :
cond = ' name= " %s " ' % address_name
if is_shipping_address :
2012-09-26 07:40:37 +00:00
details = webnotes . conn . sql ( " select name, address_line1, address_line2, city, country, pincode, state, phone, fax from `tabAddress` where %s and docstatus != 2 order by is_shipping_address desc, is_primary_address desc limit 1 " % cond , as_dict = 1 )
2011-06-08 09:07:15 +00:00
else :
2012-03-21 11:37:42 +00:00
details = webnotes . conn . sql ( " select name, address_line1, address_line2, city, country, pincode, state, phone, fax from `tabAddress` where %s and docstatus != 2 order by is_primary_address desc limit 1 " % cond , as_dict = 1 )
2013-04-26 11:51:49 +00:00
2011-06-08 09:07:15 +00:00
extract = lambda x : details and details [ 0 ] and details [ 0 ] . get ( x , ' ' ) or ' '
2013-03-01 12:25:37 +00:00
address_fields = [ ( ' ' , ' address_line1 ' ) , ( ' \n ' , ' address_line2 ' ) , ( ' \n ' , ' city ' ) , ( ' \n ' , ' state ' ) , ( ' ' , ' pincode ' ) , ( ' \n ' , ' country ' ) , ( ' \n Phone: ' , ' phone ' ) , ( ' \n Fax: ' , ' fax ' ) ]
2011-06-08 09:07:15 +00:00
address_display = ' ' . join ( [ a [ 0 ] + extract ( a [ 1 ] ) for a in address_fields if extract ( a [ 1 ] ) ] )
if address_display . startswith ( ' \n ' ) : address_display = address_display [ 1 : ]
address_name = details and details [ 0 ] [ ' name ' ] or ' '
return address_display , address_name
# Get Contact Text
# -----------------------
def get_contact_text ( self , customer = None , contact_name = None , supplier = None ) :
if customer :
cond = customer and ' customer= " %s " ' % customer or ' name= " %s " ' % contact_name
elif supplier :
cond = supplier and ' supplier= " %s " ' % supplier or ' name= " %s " ' % contact_name
else :
cond = ' name= " %s " ' % contact_name
2012-01-27 06:55:09 +00:00
details = webnotes . conn . sql ( " select name, first_name, last_name, email_id, phone, mobile_no, department, designation from `tabContact` where %s and docstatus != 2 order by is_primary_contact desc limit 1 " % cond , as_dict = 1 )
2011-06-08 09:07:15 +00:00
extract = lambda x : details and details [ 0 ] and details [ 0 ] . get ( x , ' ' ) or ' '
2012-01-17 08:52:09 +00:00
contact_fields = [ ( ' ' , ' first_name ' ) , ( ' ' , ' last_name ' ) ]
contact_display = ' ' . join ( [ a [ 0 ] + cstr ( extract ( a [ 1 ] ) ) for a in contact_fields if extract ( a [ 1 ] ) ] )
2011-06-08 09:07:15 +00:00
if contact_display . startswith ( ' \n ' ) : contact_display = contact_display [ 1 : ]
2012-10-26 09:31:22 +00:00
return {
" contact_display " : contact_display ,
" contact_person " : details and details [ 0 ] [ " name " ] or " " ,
" contact_email " : details and details [ 0 ] [ " email_id " ] or " " ,
" contact_mobile " : details and details [ 0 ] [ " mobile_no " ] or " " ,
" contact_designation " : details and details [ 0 ] [ " designation " ] or " " ,
" contact_department " : details and details [ 0 ] [ " department " ] or " " ,
}
2012-07-18 14:43:52 +00:00
def get_customer_details ( self , name ) :
"""
Get customer details like name , group , territory
and other such defaults
"""
customer_details = webnotes . conn . sql ( """ \
select
customer_name , customer_group , territory ,
default_sales_partner , default_commission_rate , default_currency ,
default_price_list
from ` tabCustomer `
where name = % s and docstatus < 2 """ , name, as_dict=1)
2011-06-08 09:07:15 +00:00
if customer_details :
2012-07-18 14:43:52 +00:00
for f in [ ' customer_name ' , ' customer_group ' , ' territory ' ] :
self . doc . fields [ f ] = customer_details [ 0 ] [ f ] or self . doc . fields . get ( f )
# fields prepended with default in Customer doctype
for f in [ ' sales_partner ' , ' commission_rate ' , ' currency ' ] :
self . doc . fields [ f ] = customer_details [ 0 ] [ " default_ %s " % f ] or self . doc . fields . get ( f )
2011-06-08 09:07:15 +00:00
2012-07-18 14:43:52 +00:00
# optionally fetch default price list from Customer Group
self . doc . price_list_name = ( customer_details [ 0 ] [ ' default_price_list ' ]
or webnotes . conn . get_value ( ' Customer Group ' , self . doc . customer_group ,
' default_price_list ' )
or self . doc . fields . get ( ' price_list_name ' ) )
2011-06-08 09:07:15 +00:00
# Get Customer Shipping Address
# -----------------------
def get_shipping_address ( self , name ) :
2012-09-26 07:40:37 +00:00
details = webnotes . conn . sql ( " select name, address_line1, address_line2, city, country, pincode, state, phone from `tabAddress` where customer = ' %s ' and docstatus != 2 order by is_shipping_address desc, is_primary_address desc limit 1 " % ( name ) , as_dict = 1 )
2011-06-08 09:07:15 +00:00
extract = lambda x : details and details [ 0 ] and details [ 0 ] . get ( x , ' ' ) or ' '
address_fields = [ ( ' ' , ' address_line1 ' ) , ( ' \n ' , ' address_line2 ' ) , ( ' \n ' , ' city ' ) , ( ' ' , ' pincode ' ) , ( ' \n ' , ' state ' ) , ( ' \n ' , ' country ' ) , ( ' \n Phone: ' , ' phone ' ) ]
address_display = ' ' . join ( [ a [ 0 ] + extract ( a [ 1 ] ) for a in address_fields if extract ( a [ 1 ] ) ] )
if address_display . startswith ( ' \n ' ) : address_display = address_display [ 1 : ]
ret = {
' shipping_address_name ' : details and details [ 0 ] [ ' name ' ] or ' ' ,
' shipping_address ' : address_display
}
2011-08-16 11:08:11 +00:00
return ret
2011-06-08 09:07:15 +00:00
# Get Lead Details
# -----------------------
2013-06-28 13:48:33 +00:00
def get_lead_details ( self , name ) :
details = webnotes . conn . sql ( """ select name, lead_name, address_line1, address_line2, city, country, state, pincode
from ` tabAddress ` where lead = % s """ , name, as_dict=True)
lead = webnotes . conn . get_value ( " Lead " , name ,
[ " territory " , " phone " , " mobile_no " , " email_id " , " company_name " , " lead_name " ] , as_dict = True ) or { }
address_display = " "
if details :
details = details [ 0 ]
for separator , fieldname in ( ( ' ' , ' address_line1 ' ) , ( ' \n ' , ' address_line2 ' ) , ( ' \n ' , ' city ' ) ,
( ' ' , ' pincode ' ) , ( ' \n ' , ' state ' ) , ( ' \n ' , ' country ' ) , ( ' \n Phone: ' , ' phone ' ) ) :
if details . get ( fieldname ) :
address_display + = separator + details . get ( fieldname )
if address_display . startswith ( ' \n ' ) :
address_display = address_display [ 1 : ]
2011-06-08 09:07:15 +00:00
ret = {
2013-06-28 13:48:33 +00:00
' contact_display ' : lead . get ( ' lead_name ' ) ,
2011-06-08 09:07:15 +00:00
' address_display ' : address_display ,
2013-06-28 13:48:33 +00:00
' territory ' : lead . get ( ' territory ' ) ,
' contact_mobile ' : lead . get ( ' mobile_no ' ) ,
' contact_email ' : lead . get ( ' email_id ' ) ,
' customer_name ' : lead . get ( ' company_name ' ) or lead . get ( ' lead_name ' )
2011-06-08 09:07:15 +00:00
}
2011-08-16 11:08:11 +00:00
return ret
2011-06-08 09:07:15 +00:00
# Get Supplier Default Primary Address - first load
# -----------------------
def get_default_supplier_address ( self , args ) :
2013-05-28 11:53:36 +00:00
if isinstance ( args , basestring ) :
args = load_json ( args )
2011-06-08 09:07:15 +00:00
address_text , address_name = self . get_address_text ( supplier = args [ ' supplier ' ] )
ret = {
' supplier_address ' : address_name ,
' address_display ' : address_text ,
}
2012-10-26 09:31:22 +00:00
ret . update ( self . get_contact_text ( supplier = args [ ' supplier ' ] ) )
2011-06-08 09:07:15 +00:00
ret . update ( self . get_supplier_details ( args [ ' supplier ' ] ) )
2011-08-16 11:08:11 +00:00
return ret
2011-06-08 09:07:15 +00:00
# Get Supplier Address
# -----------------------
def get_supplier_address ( self , args ) :
args = load_json ( args )
address_text , address_name = self . get_address_text ( address_name = args [ ' address ' ] )
ret = {
' supplier_address ' : address_name ,
2012-07-18 14:43:52 +00:00
' address_display ' : address_text ,
2011-06-08 09:07:15 +00:00
}
2012-10-26 09:31:22 +00:00
ret . update ( self . get_contact_text ( contact_name = args [ ' contact ' ] ) )
2011-08-16 11:08:11 +00:00
return ret
2011-06-08 09:07:15 +00:00
# Get Supplier Details
# -----------------------
2012-07-18 14:43:52 +00:00
def get_supplier_details ( self , name ) :
supplier_details = webnotes . conn . sql ( """ \
select supplier_name , default_currency
from ` tabSupplier `
where name = % s and docstatus < 2 """ , name, as_dict=1)
if supplier_details :
return {
' supplier_name ' : ( supplier_details [ 0 ] [ ' supplier_name ' ]
or self . doc . fields . get ( ' supplier_name ' ) ) ,
' currency ' : ( supplier_details [ 0 ] [ ' default_currency ' ]
or self . doc . fields . get ( ' currency ' ) ) ,
}
else :
return { }
2011-06-08 09:07:15 +00:00
# Get Sales Person Details of Customer
# ------------------------------------
def get_sales_person ( self , name ) :
2012-06-25 14:35:35 +00:00
self . doclist = self . doc . clear_table ( self . doclist , ' sales_team ' )
2011-06-08 09:07:15 +00:00
idx = 0
2012-01-27 06:55:09 +00:00
for d in webnotes . conn . sql ( " select sales_person, allocated_percentage, allocated_amount, incentives from `tabSales Team` where parent = ' %s ' " % name ) :
2012-12-24 11:32:38 +00:00
ch = addchild ( self . doc , ' sales_team ' , ' Sales Team ' , self . doclist )
2011-06-08 09:07:15 +00:00
ch . sales_person = d and cstr ( d [ 0 ] ) or ' '
ch . allocated_percentage = d and flt ( d [ 1 ] ) or 0
ch . allocated_amount = d and flt ( d [ 2 ] ) or 0
ch . incentives = d and flt ( d [ 3 ] ) or 0
ch . idx = idx
idx + = 1
2012-04-30 09:06:18 +00:00
2012-11-30 05:27:28 +00:00
def load_notification_message ( self ) :
dt = self . doc . doctype . lower ( ) . replace ( " " , " _ " )
if int ( webnotes . conn . get_value ( " Notification Control " , None , dt ) or 0 ) :
self . doc . fields [ " __notification_message " ] = \
webnotes . conn . get_value ( " Notification Control " , None , dt + " _message " )
2012-11-26 12:48:10 +00:00
def add_communication_list ( self ) :
# remove communications if present
self . doclist = webnotes . doclist ( self . doclist ) . get ( {
" doctype " : [ " != " , " Communcation " ] } )
comm_list = webnotes . conn . sql ( """ select * from tabCommunication
where % s = % s order by modified desc limit 20 """ \
% ( self . doc . doctype . replace ( " " , " _ " ) . lower ( ) , " %s " ) ,
2013-06-12 12:10:36 +00:00
self . doc . name , as_dict = 1 , update = { " doctype " : " Communication " } )
2012-11-26 12:48:10 +00:00
self . doclist . extend ( webnotes . doclist ( [ webnotes . doc ( fielddata = d ) \
2013-03-13 07:28:54 +00:00
for d in comm_list ] ) )
def validate_posting_time ( self ) :
if not self . doc . posting_time :
2013-03-26 07:03:43 +00:00
self . doc . posting_time = now_datetime ( ) . strftime ( ' % H: % M: % S ' )
2013-06-10 09:45:40 +00:00
2013-06-10 10:08:01 +00:00
def add_calendar_event ( self , opts , force = False ) :
2013-06-10 09:45:40 +00:00
if self . doc . contact_by != cstr ( self . _prev . contact_by ) or \
2013-06-10 10:08:01 +00:00
self . doc . contact_date != cstr ( self . _prev . contact_date ) or force :
2013-06-10 09:45:40 +00:00
self . delete_events ( )
self . _add_calendar_event ( opts )
def delete_events ( self ) :
webnotes . delete_doc ( " Event " , webnotes . conn . sql_list ( """ select name from `tabEvent`
where ref_type = % s and ref_name = % s """ , (self.doc.doctype, self.doc.name)))
def _add_calendar_event ( self , opts ) :
opts = webnotes . _dict ( opts )
if self . doc . contact_date :
event_doclist = [ {
" doctype " : " Event " ,
" owner " : opts . owner or self . doc . owner ,
" subject " : opts . subject ,
" description " : opts . description ,
" starts_on " : self . doc . contact_date + " 10:00:00 " ,
" event_type " : " Private " ,
" ref_type " : self . doc . doctype ,
" ref_name " : self . doc . name
} ]
if webnotes . conn . exists ( " Profile " , self . doc . contact_by ) :
event_doclist . append ( {
" doctype " : " Event User " ,
" parentfield " : " event_individuals " ,
" person " : self . doc . contact_by
} )
webnotes . bean ( event_doclist ) . insert ( )
2013-07-02 06:10:16 +00:00
def get_address_display ( address_dict ) :
meta = webnotes . get_doctype ( " Address " )
address_sequence = ( ( " " , " address_line1 " ) , ( " \n " , " address_line2 " ) , ( " \n " , " city " ) ,
( " \n " , " state " ) , ( " \n " + meta . get_label ( " pincode " ) + " : " , " pincode " ) , ( " \n " , " country " ) ,
( " \n " + meta . get_label ( " phone " ) + " : " , " phone " ) , ( " \n " + meta . get_label ( " fax " ) + " : " , " fax " ) )
address_display = " "
for separator , fieldname in address_sequence :
if address_dict . get ( fieldname ) :
address_display + = separator + address_dict . get ( fieldname )
return address_display
2013-05-15 15:45:57 +00:00
def validate_conversion_rate ( currency , conversion_rate , conversion_rate_label , company ) :
""" common validation for currency and price list currency """
if conversion_rate == 0 :
msgprint ( conversion_rate_label + _ ( ' cannot be 0 ' ) , raise_exception = True )
company_currency = webnotes . conn . get_value ( " Company " , company , " default_currency " )
# parenthesis for 'OR' are necessary as we want it to evaluate as
# mandatory valid condition and (1st optional valid condition
# or 2nd optional valid condition)
valid_conversion_rate = ( conversion_rate and
( ( currency == company_currency and conversion_rate == 1.00 )
or ( currency != company_currency and conversion_rate != 1.00 ) ) )
if not valid_conversion_rate :
msgprint ( _ ( ' Please enter valid ' ) + conversion_rate_label + ( ' : ' )
+ ( " 1 %s = [?] %s " % ( currency , company_currency ) ) ,
raise_exception = True )
def validate_item_fetch ( args , item ) :
from stock . utils import validate_end_of_life
validate_end_of_life ( item . name , item . end_of_life )
# validate company
if not args . company :
msgprint ( _ ( " Please specify Company " ) , raise_exception = True )
2013-05-21 14:05:06 +00:00
def validate_currency ( args , item , meta = None ) :
2013-05-27 13:59:07 +00:00
from webnotes . model . meta import get_field_precision
2013-05-21 14:05:06 +00:00
if not meta :
meta = webnotes . get_doctype ( args . doctype )
2013-05-27 13:59:07 +00:00
2013-05-21 14:05:06 +00:00
# validate conversion rate
2013-05-15 15:45:57 +00:00
if meta . get_field ( " currency " ) :
validate_conversion_rate ( args . currency , args . conversion_rate ,
meta . get_label ( " conversion_rate " ) , args . company )
2013-05-27 13:59:07 +00:00
# round it
args . conversion_rate = flt ( args . conversion_rate ,
2013-05-31 09:00:46 +00:00
get_field_precision ( meta . get_field ( " conversion_rate " ) ,
webnotes . _dict ( { " fields " : args } ) ) )
2013-05-15 15:45:57 +00:00
2013-05-21 14:05:06 +00:00
# validate price list conversion rate
if meta . get_field ( " price_list_currency " ) and args . price_list_name and \
args . price_list_currency :
validate_conversion_rate ( args . price_list_currency , args . plc_conversion_rate ,
2013-05-27 13:59:07 +00:00
meta . get_label ( " plc_conversion_rate " ) , args . company )
# round it
args . plc_conversion_rate = flt ( args . plc_conversion_rate ,
2013-05-31 09:00:46 +00:00
get_field_precision ( meta . get_field ( " plc_conversion_rate " ) ,
webnotes . _dict ( { " fields " : args } ) ) )
2013-06-10 10:08:31 +00:00
2013-06-17 07:21:36 +00:00
def delete_events ( ref_type , ref_name ) :
webnotes . delete_doc ( " Event " , webnotes . conn . sql_list ( """ select name from `tabEvent`
2013-06-17 07:25:05 +00:00
where ref_type = % s and ref_name = % s """ , (ref_type, ref_name)), for_reload=True)