-
Notifications
You must be signed in to change notification settings - Fork 42
Shipstation API Integration
ShipStation is a web-based software designed to help eCommerce retailers process, fulfill, and ship their orders from all the most popular marketplaces and shopping carts using all the top carriers.
The Cenit.io platform provides a collection that allows you to integrate with Shipstation's API with ease.
The only data you need to successfully install the Shipstation Integration
addon for Odoo are the API Key
and API Secret
related to your
Shipstation account. You can follow the steps described in the addon
description if you are unsure on how to get those.
Once installed, the addon features will allow you to send any data you want as Shipstation Schemas. To do so, all you need is add Data types describing how to transform your Odoo models into the Shipstation ones.
Let's see some examples, go and create a new Data type.
The most popular choice to map as Shipstation Orders are Odoo's
stock.picking
(also known as Picking List).
This model actually refers to product movements on your warehouses (both in and
out), so you will need to restrict them to those with picking_type_code
set
as outgoing
. This is accomplished on the Conditions tab of the Data type
form. You may also consider to restrict to those which state
is different
than draft
, as those are not yet confirmed.
But lets not get ahead of ourselves. For the Name we recommend using something
that'll let you know quickly what's the Data type about, something like
"Picking List as Shipstation Order". Make sure to select Picking List
for
the model, Shipstation
for the library and Order.json
for the schema.
Now we are all for the mapping. Let's examine the Order.json
schema
properties.
-
orderId: this is an internal property used by Shipstation and we won't be using it.
-
orderNumber: string - A user-defined order number used to identify an order.
-
Schema property:
orderNumber
-
Model value:
id
-
Type:
Field
-
Schema property:
-
orderKey: string - A user-provided key that should be unique to each order.
-
Schema property:
orderKey
-
Model value:
name
-
Type:
Field
-
Schema property:
-
orderDate: string - The date the order was placed.
-
Schema property:
orderDate
-
Model value:
date
-
Type:
Field
-
Schema property:
-
orderDate: string - The date the order was placed.
-
Schema property:
orderDate
-
Model value:
date
-
Type:
Field
-
Schema property:
-
createDate: also an internal property set by Shipstation.
-
modifyDate: as above.
-
paymentDate: at present this value is not obtainable, due to the internal structure of the
Picking List
. A good thing is not mandatory. -
orderStatus: string - The order's status. Possible values: "awaiting_payment", "awaiting_shipment", "shipped", "on_hold", "cancelled".
Since the Picking
state
values are different from the Shipstation ones, we will use a Python code to translate them-
Schema property:
orderStatus
-
Model value:
{"cancel": "cancelled", "waiting": "awaiting_payment", "confirmed": "on_hold", "partially_available": "on_hold", "assigned": "awaiting_shipment", "done": "shipped"}.get(obj.state, "on_hold")
-
Type:
Python code
Note that we haven't mapped the "draft"
state
, since we assume those will be restricted as stated at the beginning.Also note the use of the special variable obj, which refers to the actual object being serialized.
-
Schema property:
-
customerId: internal property set by Shipstation.
-
customerUsername: string - Identifier for the customer in the originating system. This is typically a username or email address.
-
Schema property:
customerUsername
-
Model value:
{partner_id.user_id.login}
-
Type:
Default
-
Schema property:
-
customerEmail: string - The customer's email address.
-
Schema property:
customerEmail
-
Model value:
{partner_id.email}
-
Type:
Default
-
Schema property:
-
carrierCode: string - The code for the carrier that is to be used (or was used) when this order is shipped(was shipped).
-
Schema property:
carrierCode
-
Model value:
{carrier_id.name}
-
Type:
Default
Notice that this would require the additional
delivery
addon to be installed on your system, otherwise, you might as well omit this from the mapping.Also, it is likely that the
name
field won't do the trick, so, if you can do so, maybe a more specific mapping can be made, check the next alternative example:-
Schema property:
carrierCode
-
Model value:
{"UPS": "ups", "FedEx": "fedex"}.get(obj.carrier_id.name, "ups")
-
Type:
Python code
or even something more generic:
-
Schema property:
carrierCode
-
Model value:
obj.carrier_id.name.lower().replace(" ", "_").replace(".", "_")
-
Type:
Python code
just make sure all your carriers will be correctly processed in order to avoid crashes further down the road.
-
Schema property:
These are some of the possible mappings for value fields, but there are some others that won't be mapped as easily.
For instance, the billTo and shipTo properties are complex object
types, for these we create their own Data type. So, for now, uncheck the
Enabled
tick, click the Save button and go and create a new Data type.
This new Data type will be representing a Partner's address, so set the
model to res.partner
(will most likely look like Partner
), the library
to Shipstation
and the schema to address.json
. For the name choose
something like "Partner as Shipstation address" or anything you like.
We won't be restricting this Data type with Conditions
since it is not
intended to trigger events on its own. On to the mappings:
-
name: string - Name of person.
-
Schema property:
name
-
Model value:
name
-
Type:
Field
-
Schema property:
-
street1: string - First line of address.
-
Schema property:
street1
-
Model value:
street
-
Type:
Field
-
Schema property:
-
street2: string - Second line of address.
-
Schema property:
street2
-
Model value:
street2
-
Type:
Field
-
Schema property:
-
city: string - City.
-
Schema property:
city
-
Model value:
city
-
Type:
Field
-
Schema property:
-
state: string - State.
-
Schema property:
state
-
Model value:
{state_id.name}
-
Type:
Default
Note that most Odoo installations don't hold records for any State not in the US, so if it doesn't apply: don't use it.
-
Schema property:
-
country: string - Country Code. The two-character ISO country code is required.
-
Schema property:
country
-
Model value:
{country_id.code}
-
Type:
Default
-
Schema property:
-
phone: string - Telephone number.
-
Schema property:
phone
-
Model value:
phone
-
Type:
Field
-
Schema property:
That should do it for the moment. Save the Data type and head back to the one for the Order.
-
billTo: Address - The recipients billing address.
-
Schema property:
billTo
-
Model value:
partner_id
-
Type:
Model
- Reference: set this to the newly created Data type for the Partner's address.
-
Cardinality:
2one
-
Schema property:
-
shipTo: Address - The recipients shipping address.
-
Schema property:
shipTo
-
Model value:
partner_id
-
Type:
Model
- Reference: set this to the newly created Data type for the Partner's address.
-
Cardinality:
2one
-
Schema property:
Another important complex property of the Order model refers to the list of items to be shipped with the order (check out the items property). For that one, we will need to do something similar to what we did for the billing and shipping addresses.
So save the Data type again (leave the Enabled
tick unchecked) and let us
create a new one that maps Odoo's stock.move
(you should see it as
Stock Move
) items as Shipstation's order_item
.
As usual name your Data type, something like "StockMove as Shipstation
OrderItem" should be enough, for the model choose Stock Move
, set the
library to Shipstation
and the schema to order_item.json
.
As with the partner's address above, this Data type should trigger no events, so we won't set any conditions or triggers on it.
- orderItemId: this is an internal property used by Shipstation and we won't be using it.
-
lineItemKey: string - An identifier for the OrderItem in the originating
system.
-
Schema property:
lineItemKey
-
Model value:
id
-
Type:
Field
-
Schema property:
-
sku: string - The SKU (stock keeping unit) identifier for the product
associated with this line item.
-
Schema property:
sku
-
Model value:
{product_id.code}
-
Type:
Default
-
Schema property:
-
name: string - The name of the product associated with this line item.
-
Schema property:
name
-
Model value:
{product_id.name_template}
-
Type:
Default
-
Schema property:
-
quantity: number - The quantity of product ordered.
-
Schema property:
quantity
-
Model value:
product_qty
-
Type:
Field
-
Schema property:
-
unitPrice: number - The selling price of a single item specified by the
order source.
-
Schema property:
unitPrice
-
Model value:
price_unit
-
Type:
Field
-
Schema property:
That should be enough for the now. Save the Data type and let us return to the Order one.
As you can see, the items property refers not to a single object, but rather
a list (expressed as an array), so we will be using a 2many
cardinality for
this one.
-
items: OrderItem - Array of purchased items.
-
Schema property:
items
-
Model value:
move_lines
-
Type:
Model
- Reference: set this to the newly created Data type for the Stock Move.
-
Cardinality:
2many
-
Schema property:
With this, you should have a fairly functional mapping of your Picking List
to Shipstation's Order
, all that is left is to determine when to trigger the
sending of your data to Shipstation.
Go to the Triggers tab and add a new one. Select the On creation or update option and that's all folks!
Check back the Enabled
tick and save the Data type.
In order to test the mappings go to the Warehouse tab on the top panel, and under All Operations choose any Delivery order.
Edit it, modify something (probably adding a note would be right so not to disturb the actual content on the delivery) and Save it. If it does match the Conditions for the Data type, you should able to see in Cenit.io's data integrator, a record for that specific Picking List.