Skip to main content

Fulfil REST API Client in Python

Project description

The V1 API is officially deprecated as of March 31, 2020.

As of Sep 2020, if you are still using API V1, you are in-fact accessing V2. The V2 API is mostly backwards compatible with the V1 API.

Fulfil IO Python Client

https://img.shields.io/pypi/v/fulfil_client.svg https://img.shields.io/travis/fulfilio/fulfil_client.svg Documentation Status

Fulfil REST API Client in Python

Features

  • Ability to call models

Installation

pip install fulfil_client

Quickstart

from fulfil_client import Client

client = Client('<subdomain>', '<api_key>')

Product = client.model('product.product')

# find products
some_products = Product.find()

# find products that have a name similar to iphone
iphones = Product.find(['name', 'ilike', 'iphone'])

Contacts

Contact can have multiple addresses and contact mechanisms i.e. phone, email.

from fulfil_client import Client
client = Client('<subdomain>', '<api_key>')

Contact = client.model('party.party')
Country = client.model('country.country')
Subdivision = client.model('country.subdivision')

country_usa, = Country.find([('code', '=', 'US')])
state_california, = Subdivision.find([('code', '=', 'US-CA')])

# Creating a contact with address and contact mechanisms
contact, = Contact.create([{
    'name': 'Jon Doe',
    'addresses': [('create', [{
        'name': 'Jone Doe Apartment',
        'street': '9805 Kaiden Grove',
        'city': 'New Leland',
        'zip': '57726',
        'country': country_usa['id'],
        'subdivision': state_california['id']
    }])],
    'contact_mechanisms': [('create', [{
        'type': 'phone',
        'value': '243243234'
    }, {
        'email': 'email',
        'value': 'hello@jondoe.com'
    }])]
}])
print contact

# Searching for a contact
contact, = Contact.find([('name', '=', 'Jon Doe')])
print contact

# Get a contact by ID
contact = Contact.get(contact['id'])
print contact

Products

Products are grouped by templates, which have common information shared by products a.k.a. variants.

from decimal import Decimal

# Creating a Product Template
Template = client.model('product.template')

iphone, = Template.create([{
    'name': 'iPhone',
    'account_category': True,
}])

# Creating products
Product = client.model('product.product')
iphone6, = Product.create([{
    'template': iphone['id'],
    'variant_name': 'iPhone 6',
    'code': 'IPHONE-6',
    'list_price': Decimal('699'),
    'cost_price': Decimal('599'),
}])

# Another variation
iphone6s, = Product.create([{
    'template': iphone['id'],
    'variant_name': 'iPhone 6S',
    'code': 'IPHONE-6S',
    'list_price': Decimal('899'),
    'cost_price': Decimal('699'),
}])

Sale

contact = Contact.get(contact['id'])
iphone6 = Product.get(iphone6['id'])
iphone6s = Product.get(iphone6s['id'])

# Creating a Sale
Sale = client.model('sale.sale')
sale, = Sale.create([{
    'party': contact['id'],
    'shipment_address': contact['addresses'][0],
    'invoice_address': contact['addresses'][0],
    'lines': [('create', [{
        'product': iphone6['id'],
        'description': iphone6['rec_name'],
        'unit': iphone6['default_uom'],
        'unit_price': iphone6['list_price'],
        'quantity': 3
    }, {
        'product': iphone6s['id'],
        'description': iphone6s['rec_name'],
        'unit': iphone6['default_uom'],
        'unit_price': iphone6s['list_price'],
        'quantity': 1
    }])]
}])

Fetching an interactive report (sales by month)

The report data (including rendering) information can be fetched over the API.

Below is the example code to fetch sales by month report.

report = client.interactive_report('sales_by_month.ireport')
data = report.execute(start_date=date(2017,1,1), end_date=date(2017, 12,1))

Using Session Auth

from fulfil_client import Client, SessionAuth

client = Client('subdomain')
user_id, session = client.login('username', 'password')
client.set_auth(SessionAuth(user_id, session))

Using Bearer Auth

from fulfil_client import Client, BearerAuth

client = Client('subdomain')
client.set_auth(BearerAuth(bearer_token))

Using OAuth Session

Flask example

from fulfil_client.oauth import Session
from fulfil_client import Client, BearerAuth

Session.setup(CLIENT_ID, CLIENT_SECRET)
fulfil_session = Session('localhost')  # Provide subdomain

@app.route('/')
def index():
    callback_url = url_for('authorized')
    if 'oauth_token' not in session:
        authorization_url, state = fulfil_session.create_authorization_url(
            redirect_uri=callback_url, scope=['user_session']
        )
        session['oauth_state'] = state
        return redirect(authorization_url)
    client = Client('subdomain')
    client.set_auth(BearerAuth(session['oauth_token']['access_token']))
    Party = client.model('party.party')
    return jsonify(Party.find())

@app.route('/authorized')
def authorized():
    """Callback route to fetch access token from grant code
    """
    token = fulfil_session.get_token(code=request.args.get('code'))
    session['oauth_token'] = token
    return jsonify(oauth_token=token)

Verify Webhooks

There is a convenience function that can verify the webhooks originating from Fulfil for you.

from fulfil_client import verify_webhook


@app.route('/webhook', methods=['POST'])
def webhook():
   data = flask.request.get_data()
   verified = verify_webhook(
      data,
      secret,     # This should be saved somewhere
      flask.request.headers.get('X-Fulfil-Hmac-SHA256')
   )

   if not verified:
      abort(401)

Testing

The libary also provides a mocking function powered by the mock library of python.

For example, if you want to test the function below

def api_calling_method():
    client = fulfil_client.Client('apple', 'apples-api-key')
    Product = client.model('product.product')
    products = Product.search_read_all([], None, ['id'])
    Product.write(
        [p['id'] for p in products],
        {'active': False}
    )
    return client

Then the test case can mock the API call

def test_mock_1():
    with MockFulfil('fulfil_client.Client') as mocked_fulfil:
        Product = mocked_fulfil.model('product.product')
        # Set the return value of the search call without
        # hitting the server.
        Product.search_read_all.return_value = [
            {'id': 1},
            {'id': 2},
            {'id': 3},
        ]

        # Call the function
        api_calling_method()

        # Now assert
        Product.search_read_all.assert_called()
        Product.search_read_all.assert_called_with([], None, ['id'])
        Product.write.assert_called_with(
            [1, 2, 3], {'active': False}
        )

The Product object returned is a mock.Mock object and supports all of the assertions supported by python Mock objects.

Credits

Fulfil.IO Inc.

History

0.2.0 (2016-6-22)

  • Change the behavior of search method.

    The method now reflects the fulfil search API which returns a list of ids. The previous behavior which returned an object with id and rec_name (record name) is now called find.

0.1.1 (2016-3-3)

  • Add method to create resource.

  • Add examples on how to create contacts, products and sales.

0.1.0 (2016-1-22)

  • First release on PyPI.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fulfil_client-3.0.0.tar.gz (29.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fulfil_client-3.0.0-py2.py3-none-any.whl (23.4 kB view details)

Uploaded Python 2Python 3

File details

Details for the file fulfil_client-3.0.0.tar.gz.

File metadata

  • Download URL: fulfil_client-3.0.0.tar.gz
  • Upload date:
  • Size: 29.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.6

File hashes

Hashes for fulfil_client-3.0.0.tar.gz
Algorithm Hash digest
SHA256 9defb07eaed007e6f75df6fb4885e5fc52516514708fc858c0507261cb3688df
MD5 49cd7a8150a1489f38ecb6608c358456
BLAKE2b-256 12fe9c21f63abe4c789df74bebde2ae8f02a07274efa269b64b83d0b9e6f6276

See more details on using hashes here.

File details

Details for the file fulfil_client-3.0.0-py2.py3-none-any.whl.

File metadata

  • Download URL: fulfil_client-3.0.0-py2.py3-none-any.whl
  • Upload date:
  • Size: 23.4 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.6

File hashes

Hashes for fulfil_client-3.0.0-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 d400e1e05ebe76c6d784f1a78afb5e8e7c438a1423e56d5e637dee00102344a0
MD5 e10f247135c2f735ab075e4405440336
BLAKE2b-256 ce25d1ff04071418ab04724da12f3c169dbf19025aadb3a3172409cb6713bcdf

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page