Giter VIP home page Giter VIP logo

avatax-rest-v2-python-sdk's Introduction

Avalara AvaTax Python SDK

Build Status PyPI

This GitHub repository is the Python SDK for Avalara's world-class tax service, AvaTax. It uses the AvaTax REST v2 API, which is a fully REST implementation and provides a single client for all AvaTax functionality. For more information about AvaTax REST v2, please visit Avalara's Developer Network or view the online Swagger documentation.

Installation:

Install simply with pip. pip install Avalara

OR

  1. Clone this repository to your local machine.
$ git clone https://github.com/avadev/AvaTax-REST-V2-Python-SDK.git
  1. Once downloaded, cd into the AvaTax-REST-V2-Python-SDK directory.
$ cd AvaTax-REST-V2-Python-SDK
  1. Begin a new virtual environment with Python 3 and activate it.
AvaTax-REST-V2-Python-SDK $ python3 -m venv ENV
AvaTax-REST-V2-Python-SDK $ source ENV/bin/activate
  1. pip install this package as well as the testing set of extras into your virtual enviroment.
(ENV) AvaTax-REST-V2-Python-SDK $ pip install -e .
(ENV) AvaTax-REST-V2-Python-SDK $ pip install -e .[testing]

Usage:

Create a transaction

Import the AvataxClient from the avalara module

First thing to do is to import the AvataxClient constructor module to your name space, or your python script.

from avalara import AvataxClient

Now we are ready to construct a client object

Create a new AvaTaxClient object:

    client = AvataxClient('my test app',
                          'ver 0.0',
                          'my test machine',
                          'sandbox')

The client constructor takes four string parameters, in squence they are app_name(required), app_version(required), machine_name(optional), and environment(required). The app_name, app_version, machine_name will be used to construct the Client Header associated with each call made by this client. It will be returned within the response object to help you keep track of the API calls. The environment variable can be either "sandbox" or production, they correspond to the two different environments for AvaTax service. If you are a regular or free trial customer please use "production". If you don't have an account, you can sign up for a free trail account on our developer site, this will be a production account as well. If you wish to obtain a Sandbox account, please contact your Customer Account Manager

Ping the service

Now we have a client object, we can ping the AvaTax REST V2 server to ensure connectivity.

  response = client.ping()

  # to view respnse text
  print(response.text())

  # to view json version of the response
  print(response.json())

  # to view the status code
  print(response.status_code())

  # to view the raw response
  print(response.raw())

Note that the response from all REST calls made using this SDK will be Request object, which contains status code, response text, raw josn, and more information on the respnse.

Add credentials to your client object

Unlike ping, most methods in our REST V2 API requires you to be authenticated in order to associate those information provided by you with your account. To find out if a method requires authentication, visit our API Reference page. To add credential on the current client object:

  client = client.add_credentials('USERNAME/ACCOUNT_ID', 'PASSWORD/LICENSE_KEY')

The add_credential method will hash your username/password, or account_id/license_key pair and attach to every call made by your client object, meaning you only have to add credential once to each client you prepare to use.

To verify that you have added a valid credential, simply call the ping method again, this time in the response text you should see "authenticated": true.

To create a transaction using your client object

Now our client object is authenticated, we can call the create_transaction method which calls the CreateTransaction API

  transaction_response = client.create_transaction(tax_document)
  print(transaction_response.text())

  tax_document = {
      'addresses': {'SingleLocation': {'city': 'Irvine',
                                       'country': 'US',
                                       'line1': '123 Main Street',
                                       'postalCode': '92615',
                                       'region': 'CA'}},
      'commit': False,
      'companyCode': 'DEFAULT',
      'currencyCode': 'USD',
      'customerCode': 'ABC',
      'date': '2017-04-12',
      'description': 'Yarn',
      'lines': [{'amount': 100,
                'description': 'Yarn',
                 'itemCode': 'Y0001',
                 'number': '1',
                 'quantity': 1,
                 'taxCode': 'PS081282'}],
      'purchaseOrderNo': '2017-04-12-001',
      'type': 'SalesInvoice'}

The create_transaction method takes in a model, in python it's a dictionary type object. Which you will fill out to include all of your transaction information. In this case, we are using the TransactionModel For information on other models use by AvaTax APIs, visit our information page here

Use other methods

Like our SDKs in other languages, the Python SDK includes all methods offered by the AvaTax REST V2 API. To find a mehtod corresponding to a specific API endpoint, simply visit this code page To learn more about integrating our REST API into your system, visit our developer guide that contains information on using the powerful features offered by our API.

Use transaction builder

We realize that having to format the TransactionModel can be complicated and time consuming, thus we created a tool called Transaction Builder to help you put together a transaction model, and create it! First import the transaction builder constructor into your name space: from avalara.transaction_builder import TransactionBuilder

Then, let's create a transaction builder object:

  tb = TransactionBuilder(client, "DEFAULT", "SalesInvoice", "ABC")

The builder takes four required parameters, in sequence they are

  • The client object
  • Company name(created through AvaTax portal or by calling CreateCompany API)
  • The type of transaction, a full list of options.
  • The customer code, an unique code identifying the customer that requested this transaction.

Now you are free to add transaction details to this object, by using methods like with_address, with_line, with_parameter. For a fulll list of transaction builder methods available and the parameters they take in, visit the code page In the end, you may call the create method on your builder object, which will call the CreateTransaction API with the transaction model you have build so far, and return back the response.

Setup Test Credentials

If you wish to run the integration and unit testings, you must store a pair of credentials in the current enviroment. Add the following to the activate file in your environment, and restart bash. OR simply export them directly:

export SANDBOX_USERNAME='your_sandbox_username'
export SANDBOX_PASSWORD='your_sandbox_password'

# OR
SANDBOX_ACCOUNTID='your_sandbox_account_id'
SANDBOX_LICENSEKEY='your_sandbox_license_key'

Note: Only Sandbox credentials should be used for testing, as the test case will commit/adjust/void dummy transactions on the account to verify functionalities.

Logging

Logging is implemented using standard Python logging framework.

  1. All relevant methods from AvataxClient class are decorated with ava_log decorator.(This is achieved using another decorator at class level, decorate_all_methods)
  2. ava_log decorator collects relevant request data, response data useful for instrumentation and logs error data in case of exception.
  3. AvataxClient constructor is modified with optional parameter, is_log_req_resp_allowed (defaulted to False), to control if log entry should contain request and response objects.
  4. SDK Consumer code can also set logger property of AvataxClient to use already configured logger instance. e.g.
from logging import config 

# configure logging using file config or dictConfig 
# or by setting basicConfig (this is default in case no logger is set)
config.fileConfig("logger_config.conf")

logger = logging.getLogger()

# set logger property
client.logger = logger

Issue or suggestion

User feedbacks are highly valued here at Avalara, we want to ensure the best experience for every customer using our services. If you have any concern with this SDK or AvaTax in general, please post your queston/suggestion on our Developer Relation Forum as we will reply to you in a timely manner. If you wish to contribute to this SDK, please fork the repository and submit your pull request from the forked version. We are happy to review your contribution, and merge them if all checks has passed!

Original Contributors

Han Bao

Philip Werner

Robert Bronson

Adrienne Karnoski

avatax-rest-v2-python-sdk's People

Contributors

abhishekavalara avatar adriennekarnoski avatar avalara-chriswalker avatar avalara-tela avatar avasachinbaijal avatar contygm avatar fisher6 avatar han8909227 avatar p4rk avatar philipwerner avatar qjavalara avatar rjb888 avatar robertbronsonavalara avatar shilpa-khanal avatar snakeclown avatar svc-developer avatar taion avatar ted-spence-avalara avatar ztaylor2 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

avatax-rest-v2-python-sdk's Issues

Support TaxIncluded in AvaTax Line Items

Happy to move this elsewhere if there's a formal process for submitting issues.

Problem statement

The TransactionBuilder doesn't support the taxIncluded attribute which is required
on a per-line item basis if used. See full docs here: https://developer.avalara.com/avatax/dev-guide/customizing-transaction/using-tax-included/

Desired Behavior

As a user of the transaction builder I would like to be able to use something like the following

builder.with_line(amount=100, quantity=1, tax_code=MY_TAX_CODE, tax_included=True)

or (less ideal)

(
  builder
    .with_line(amount=100, quantity=1, tax_code=MY_TAX_CODE)
    .with_tax_included()
)

Workaround

One can work around this by abandoning the TransactionBuilder or by breaking into the model a bit.
This could be done with conditions for item info, but a simple pass for all items is:

for item in builder.create_model["items"]:
  item["taxIncluded"] = True

Notes

It's worth noting two items related to this:

  1. the builder currently requires tax_code which is also not a true requirement.
  2. with_exempt_line is currently a single quantity, but almost entirely the same as add item

Suggestion for improving might be to do three, backwards-compatible steps to align all three:

  • move tax_code to be optional (non-breaking) so that it is only added to the request if not-none
  • with_exempt_line calls with_line with minimal alteration (quantity=1 for backwards compatibility, tax_code=None)
  • add tax_included to with_line

I'd be happy to PR if you would be amenable.

update docs for new package name

Installed this package via pip yesterday and got an import error using from client import AvataxClient. from avalara import AvataxClient works.

TransactionBuilder.with_line() breaks with string line_number

I'm trying to use line number shipping-1. Why? Not sure. That seems to be what the 1st party Avalara Shopify app does. And I need to mirror that.

ac = AvataxClient('Tax App 123', 'ver 2022.09')        
tb = TransactionBuilder(ac, 'COMANY_CODE_ABC', 'SalesOrder', 'CUSTOMER_XYZ')
tb.with_line(amount=10, quantity=2, item_code='FREIGHT', tax_code='FR020800', line_number='shipping-1')
 File "/usr/local/lib/python3.8/site-packages/avalara/transaction_builder_methods.py", line 153, in with_line
    self.line_num += 1
TypeError: can only concatenate str (not "int") to str

Python2

Hey does this work on Python2.7.14?

Error when trying to Ping

Hello, I'm using Python, and trying to use the API.

I've got a Sandbox account, and I used pip to install Avalara.

However, the following code does not work: TypeError: 'str' object is not callable - it's looking at print(response.text())

Any suggestions?

from avalara import AvataxClient

client = AvataxClient('my test app',
'ver 0.0',
'my test machine',
'sandbox')

response = client.ping()

to view respnse text

print(response.text())

to view json version of the response

print(response.json())

to view the status code

print(response.status_code())

to view the raw response

print(response.raw())

Ava Logger raises KeyError on ConnectionError

When a ConnectionError is raised using the AvataxClient (at least during an adjust_transaction) the following code errors because the ava_log_entry only contains an error key and no execution_time key...

>           if ava_log_entry["execution_time"] is None:
E           KeyError: 'execution_time'

From my reading, if running the wrapped func at line 39 raises an Exception the ava_log_entry will have no "execution_time" key.

Forgive me if I've missing something here, this is showing up in our unit tests and I'm no pythonista/pythoneer

Apache License Implementation

I don't believe the Apache license is implemented correctly on this SDK. It is also missing from some of the distributed source files.

For people to be able to use and redistribute the SDK in their own code it needs to implement the Apache license correctly. I have open a pull request to address this. #67

Feature request: Changelog

Would like to know what changed from version to version. Important to know whether updating will break my application.
Just having a commit history isn't very friendly for humans.

Rename package from "client"

It's a little confusing that the package is just client. This seems potentially prone to causing name collisions, and also hurts readability of code using this library.

It seems like it would be better if the import instead looked like e.g.:

from avalara import AvataxClient

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.