Skip to content

Repository files navigation

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

Documentation Status

Fulfil REST API Client in Python

Features

  • Ability to call models

Installation

pip install fulfil_client

Quickstart

fromfulfil_clientimportClientclient=Client('<subdomain>', '<api_key>')
Product=client.model('product.product')
# find productssome_products=Product.find()
# find products that have a name similar to iphoneiphones=Product.find(['name', 'ilike', 'iphone'])

Contacts

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

fromfulfil_clientimportClientclient=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 mechanismscontact, =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'
}])]
}])
printcontact# Searching for a contactcontact, =Contact.find([('name', '=', 'Jon Doe')])
printcontact# Get a contact by IDcontact=Contact.get(contact['id'])
printcontact

Products

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

fromdecimalimportDecimal# Creating a Product TemplateTemplate=client.model('product.template')
iphone, =Template.create([{
'name': 'iPhone',
'account_category': True,
}])
# Creating productsProduct=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 variationiphone6s, =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 SaleSale=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

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

Using Bearer Auth

fromfulfil_clientimportClient, BearerAuthclient=Client('subdomain')
client.set_auth(BearerAuth(bearer_token))

Using OAuth Session

Flask example

fromfulfil_client.oauthimportSessionfromfulfil_clientimportClient, BearerAuthSession.setup(CLIENT_ID, CLIENT_SECRET)
fulfil_session=Session('localhost') # Provide subdomain@app.route('/')defindex():
callback_url=url_for('authorized')
if'oauth_token'notinsession:
authorization_url, state=fulfil_session.create_authorization_url(
redirect_uri=callback_url, scope=['user_session']
)
session['oauth_state'] =statereturnredirect(authorization_url)
client=Client('subdomain')
client.set_auth(BearerAuth(session['oauth_token']['access_token']))
Party=client.model('party.party')
returnjsonify(Party.find())
@app.route('/authorized')defauthorized():
"""Callback route to fetch access token from grant code """token=fulfil_session.get_token(code=request.args.get('code'))
session['oauth_token'] =tokenreturnjsonify(oauth_token=token)

Verify Webhooks

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

fromfulfil_clientimportverify_webhook@app.route('/webhook', methods=['POST'])defwebhook():
data=flask.request.get_data()
verified=verify_webhook(
data,
secret, # This should be saved somewhereflask.request.headers.get('X-Fulfil-Hmac-SHA256')
)
ifnotverified:
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

defapi_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'] forpinproducts],
{'active': False}
)
returnclient

Then the test case can mock the API call

deftest_mock_1():
withMockFulfil('fulfil_client.Client') asmocked_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 functionapi_calling_method()
# Now assertProduct.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.

About

Fulfil.IO Python API Client

Resources

Contributing

Stars

9 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages