It is answer to the questions like
a- how to verify address of partner in openerp
b- how to correct address entered by user
We need to verify and valid address in several cases like for - shipping address.
Here I am going to tell you how to verify your address with Ava Tax (https://development.avalara.net/). It is a short integration.
Follow these simple steps:-
for this you have to install a python package "suds" -
can use command - pip install suds
then import suds into your code -
import suds
then get instance of client -
client = suds.client.Client(wsdl)
put this wsdl address into your code -
wsdl = "https://avatax.avalara.net/%s/%ssvc.wsdl"
now create a usps id -
go to address - **http://avatax.avalara.com/services**
register your self . You will get USPS user id. put that into variable usps_id into your code
**usps_id = "269SHIVACXXXX"** // example
now you can use "VerifyAddress" method of client class , to validate and correct address .
Here is sample code =>
import suds
import socket
import urllib2
import string
import os
import datetime
import base64
from tools.translate import _
from osv import osv
class AvaTaxService:
def enable_log(self):
import logging, tempfile
logger = logging.getLogger('suds.client')
logger.setLevel(logging.DEBUG)
handler = logging.FileHandler(os.path.join(tempfile.gettempdir(), "soap-messages.log"))
logger.propagate = False
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
def __init__(self, username, password, url, timeout, enable_log=False):
self.username = username #This is the company's Development/Production Account number
self.password = password #Put in the License Key received from AvaTax
self.url = url
self.timeout = timeout
enable_log and self.enable_log()
def create_tax_service(self):
self.taxSvc = self.service('tax')
return self
def create_address_service(self):
self.addressSvc = self.service('address')
return self
def create_account_service(self):
self.accountSvc = self.service('account')
return self
def service(self, name):
nameCap = string.capitalize(name) # So this will be 'Tax' or 'Address'
# The Python SUDS library can fetch the WSDL down from the server
# or use a local file URL. We'll use a local file URL.
# wsdl_url = 'file:///' + os.getcwd().replace('\\', '/') + '/%ssvc.wsdl.xml' % name
# If you want to fetch the WSDL from the server, use this instead:
wsdl_url = 'https://avatax.avalara.net/%s/%ssvc.wsdl' % (nameCap, nameCap)
try:
svc = suds.client.Client(url=wsdl_url)
except urllib2.URLError, details:
raise osv.except_osv(_('Avatax: Server Failed to Response'), _(details))
else:
svc.set_options(service='%sSvc' % nameCap)
svc.set_options(port='%sSvcSoap' % nameCap)
svc.set_options(location='%s/%s/%sSvc.asmx' % (self.url, nameCap, nameCap))
svc.set_options(wsse=self.my_security(self.username, self.password))
svc.set_options(soapheaders=self.my_profile())
svc.set_options(timeout=self.timeout)
return svc
def my_security(self, username, password):
"""Using username and password as key to verify user account to access avalara API's"""
token = suds.wsse.UsernameToken(username, password)
token.setnonce()
token.setcreated()
security = suds.wsse.Security()
security.tokens.append(token)
return security
def my_profile(self):
# Set elements adapter defaults
ADAPTER = 'Pragmatic'
# Profile Client.
CLIENT = 'Pragmatic'
#Build the Profile element
profileNameSpace = ('ns1', 'http://avatax.avalara.com/services')
profile = suds.sax.element.Element('Profile', ns=profileNameSpace)
profile.append(suds.sax.element.Element('Client', ns=profileNameSpace).setText(CLIENT))
profile.append(suds.sax.element.Element('Adapter', ns=profileNameSpace).setText(ADAPTER))
hostname = socket.gethostname()
profile.append(suds.sax.element.Element('Machine', ns=profileNameSpace).setText(hostname))
return profile
def get_result(self, svc, operation, request):
try:
result = operation(request)
except suds.WebFault, e:
raise osv.except_osv(_('Avatax: Error'), _(e.fault.faultstring))
except urllib2.HTTPError, e:
raise osv.except_osv(_('Avatax: Server Failed to Response'), _(e.code))
except urllib2.URLError, details:
# We could also print the SOAP request here:
raise osv.except_osv(_('Failed to reach the server'), _(details.reason))
else:
if (result.ResultCode != 'Success'):
for w_message in result.Messages.Message:
if (w_message._Name == 'AddressRangeError' or w_message._Name == 'AddressUnknownStreetError' or w_message._Name == 'AddressNotGeocodedError' or w_message._Name == 'NonDeliverableAddressError' ):
raise osv.except_osv(_('Avatax: Warning \n Avatax could not validate the street address.'), _('Avatax will make an attempt to compute taxes based on the zip code if not corrected.'))
raise osv.except_osv(('Avatax: Error'), _(AvaTaxError(result.ResultCode, result.Messages)))
else:
return result
def ping(self):
return self.get_result(self.taxSvc, self.taxSvc.service.Ping, '')
def is_authorized(self):
return self.get_result(self.taxSvc, self.taxSvc.service.IsAuthorized, 'GetTax,PostTax')
def validate_address(self, baseaddress, textcase='Default'):
request = self.addressSvc.factory.create('ValidateRequest')
textCase = self.addressSvc.factory.create('TextCase')
request.TextCase = textcase
request.Coordinates = True
request.Taxability = False
request.Date = '2013-08-09'
request.Address = baseaddress
result = self.get_result(self.addressSvc, self.addressSvc.service.Validate, request)
return result
def get_tax(self, company_code, doc_date, doc_type, partner_code, doc_code, origin, destination,
received_lines, exemption_no=None, customer_usage_type=None, salesman_code=None, commit=False, invoice_date=None, reference_code=None,
location_code=None, currency_code='USD', vat_id=None):
""" Create tax request and get tax amount by customer address
@currency_code : 'USD' is the default currency code for avalara, if user not specify in the own company
@request.DetailLevel = 'Document': Document (GetTaxResult) level details; TaxLines will not be returned.
@request.DetailLevel = 'Diagnostic': In addition to Tax level details, indicates that the server should
return information about how the tax was calculated. Intended for use only while the SDK is in a development environment.
"""
lineslist = []
request = self.taxSvc.factory.create('GetTaxRequest')
request.Commit = commit
request.DetailLevel = 'Diagnostic'
# request.DetailLevel = 'Document'
request.Discount = 0.0
request.ServiceMode = 'Automatic' ##service mode = Automatic/Local/Remote
request.PaymentDate = doc_date
request.ExchangeRate = 45
request.ExchangeRateEffDate = '2011-07-07'
request.HashCode = 0
request.LocationCode = location_code
request.ReferenceCode = reference_code
if invoice_date:
taxoverride = self.taxSvc.factory.create('TaxOverride')
taxoverride.TaxOverrideType = 'TaxDate'
taxoverride.TaxDate = invoice_date
taxoverride.TaxAmount = 0
taxoverride.Reason = 'Return Items'
request.TaxOverride = taxoverride
request.CompanyCode = company_code
request.DocDate = doc_date
request.DocType = doc_type
request.DocCode = doc_code
request.CustomerCode = partner_code
request.ExemptionNo = exemption_no
request.CustomerUsageType = customer_usage_type
request.SalespersonCode = salesman_code
request.CurrencyCode = currency_code
request.BusinessIdentificationNo = vat_id
addresses = self.taxSvc.factory.create('ArrayOfBaseAddress')
addresses.BaseAddress = [origin, destination]
request.Addresses = addresses
request.OriginCode = '0' # Referencing an address above
request.DestinationCode = '1' # Referencing an address above
for line in range(0, len(received_lines)):
line1 = self.taxSvc.factory.create('Line')
line1.Qty = received_lines[line].get('qty', 1)
line1.Discounted = False
line1.No = '%d' %line
line1.ItemCode = received_lines[line].get('itemcode', None)
line1.Description = received_lines[line].get('description', None)
line1.Amount = received_lines[line].get('amount', 0.0)
line1.TaxCode = received_lines[line].get('tax_code', None)
lineslist.append(line1)
# So now we build request.Lines
lines = self.taxSvc.factory.create('ArrayOfLine')
lines.Line = lineslist
request.Lines = lines
# And we're ready to make the call
result = self.get_result(self.taxSvc, self.taxSvc.service.GetTax, request)
return result
def get_tax_history(self, company_code, doc_code, doc_type):
request = self.taxSvc.factory.create('GetTaxHistoryRequest')
request.DetailLevel = 'Document'
request.CompanyCode = company_code
request.DocCode = doc_code
request.DocType = doc_type
# request.CancelCode = cancel_code
result = self.get_result(self.taxSvc, self.taxSvc.service.GetTaxHistory, request)
return result
def cancel_tax(self, company_code, doc_code, doc_type, cancel_code):
request = self.taxSvc.factory.create('CancelTaxRequest')
request.CompanyCode = company_code
request.DocCode = doc_code
request.DocType = doc_type
request.CancelCode = cancel_code
result = self.get_result(self.taxSvc, self.taxSvc.service.CancelTax, request)
return result
class Error(Exception):
"""Base class for exceptions in this module."""
pass
class AvaTaxError(Error):
"""Exception raised for errors calling AvaTax.
Attributes:
resultCode -- result.ResultCode
messages -- result.Messages
"""
def __init__(self, resultCode, messages):
self.resultCode = resultCode
self.messages = messages
def __str__(self):
str = ''
for item in self.messages:
message = item[1][0] # SUDS gives us the message in a list, in a tuple
str = "Severity: %s\n\nDetails: %s\n\n RefersTo: %s\n\n Summary: %s" \
% (message.Severity, message.Details, message.RefersTo, message.Summary)
return str
class BaseAddress:
def __init__(self, addSvc, Line1=None, Line2=None, City=None, PostalCode=None, Region=None, Country=None, AddressCode=None):
self.data = addSvc.factory.create('BaseAddress')
self.data.TaxRegionId = 0
self.data.Line1 = Line1
self.data.Line2 = Line2
self.data.City = City
self.data.PostalCode = PostalCode
self.data.Region = Region
self.data.Country = Country
self.data.AddressCode = AddressCode
class Line:
def __init__(self, taxSvc, ItemCode, Amount, Qty, Description=None, TaxCode=None):
self.taxSvc = taxSvc
# We're not setting No here
self.data = self.defaultLine()
self.data.ItemCode = ItemCode
self.data.Amount = Amount
self.data.Qty = Qty
self.data.Description = Description
self.data.TaxCode = TaxCode
def defaultLine(self):
line = self.taxSvc.factory.create('Line')
line.Qty = 1
line.Discounted = False
return line
Note - It requires a working internet connection
0 Comment(s)