Skip to content

Commit d4e680b

Browse files
committed
added fulfillment_inbound endpoints
fixes #71
1 parent a182ebd commit d4e680b

5 files changed

Lines changed: 237 additions & 15 deletions

File tree

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
setup(
44
name='python-amazon-sp-api',
5-
version='0.2.5',
5+
version='0.3.0',
66
install_requires=[
77
"requests",
88
"six~=1.15.0",

sp_api/api/catalog/catalog.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import urllib.parse
12

23
from sp_api.base import Client, sp_endpoint, fill_query_params, ApiResponse
34

@@ -64,5 +65,6 @@ def list_items(self, **kwargs) -> ApiResponse:
6465
Returns:
6566
ListCatalogItemsResponse:
6667
"""
68+
if 'Query' in kwargs:
69+
kwargs.update({'Query': urllib.parse.quote_plus(kwargs.pop('Query'))})
6770
return self._request(kwargs.pop('path'), params=kwargs)
68-

sp_api/api/fulfillment_inbound/fulfillment_inbound.py

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,71 @@
33

44

55
class FulfillmentInbound(Client):
6-
@sp_endpoint('/fba/inbound/v0/shipments')
7-
def get_shipments(self, **kwargs) -> ApiResponse:
8-
return self._request(kwargs.get('path'), params=kwargs)
6+
@sp_endpoint("/fba/inbound/v0/itemsGuidance")
7+
def item_guidance(self, **kwargs):
8+
return self._request(kwargs.pop('path'), params=kwargs)
9+
10+
@sp_endpoint("/fba/inbound/v0/plans", method='POST')
11+
def plans(self, **kwargs):
12+
return self._request(kwargs.pop('path'), data=kwargs)
13+
14+
@sp_endpoint("/fba/inbound/v0/shipments/{}", method='POST')
15+
def create_shipment(self, shipment_id, **kwargs):
16+
return self._request(fill_query_params(kwargs.pop('path'), shipment_id), data=kwargs)
17+
18+
@sp_endpoint("/fba/inbound/v0/shipments/{}", method='PUT')
19+
def update_shipment(self, shipment_id, **kwargs):
20+
return self._request(fill_query_params(kwargs.pop('path'), shipment_id), data=kwargs)
21+
22+
@sp_endpoint("/fba/inbound/v0/shipments/{}/preorder")
23+
def preorder(self, shipment_id, **kwargs):
24+
return self._request(fill_query_params(kwargs.pop('path'), shipment_id), params=kwargs)
25+
26+
@sp_endpoint("/fba/inbound/v0/shipments/{}/preorder/confirm", method='PUT')
27+
def confirm_preorder(self, shipment_id, **kwargs):
28+
return self._request(fill_query_params(kwargs.pop('path'), shipment_id), params=kwargs)
29+
30+
@sp_endpoint("/fba/inbound/v0/prepInstructions")
31+
def prep_instruction(self, **kwargs):
32+
return self._request(kwargs.pop('path'), params=kwargs)
33+
34+
@sp_endpoint("/fba/inbound/v0/shipments/{}/transport")
35+
def get_transport_information(self, shipment_id, **kwargs):
36+
return self._request(fill_query_params(kwargs.pop('path'), shipment_id), params=kwargs)
37+
38+
@sp_endpoint("/fba/inbound/v0/shipments/{}/transport", method='PUT')
39+
def update_transport_information(self, shipment_id, **kwargs):
40+
return self._request(fill_query_params(kwargs.pop('path'), shipment_id), data=kwargs)
41+
42+
@sp_endpoint("/fba/inbound/v0/shipments/{}/transport/void", method='POST')
43+
def void_transport(self, shipment_id, **kwargs):
44+
return self._request(fill_query_params(kwargs.pop('path'), shipment_id), data=kwargs, add_marketplace=False)
45+
46+
@sp_endpoint("/fba/inbound/v0/shipments/{}/transport/estimate", method='POST')
47+
def estimate_transport(self, shipment_id, **kwargs):
48+
return self._request(fill_query_params(kwargs.pop('path'), shipment_id), data=kwargs, add_marketplace=False)
49+
50+
@sp_endpoint("/fba/inbound/v0/shipments/{}/transport/confirm", method='POST')
51+
def confirm_transport(self, shipment_id, **kwargs):
52+
return self._request(fill_query_params(kwargs.pop('path'), shipment_id), data=kwargs, add_marketplace=False)
53+
54+
@sp_endpoint("/fba/inbound/v0/shipments/{}/labels")
55+
def get_labels(self, shipment_id, **kwargs):
56+
return self._request(fill_query_params(kwargs.pop('path'), shipment_id), params=kwargs, add_marketplace=False)
57+
58+
@sp_endpoint("/fba/inbound/v0/shipments/{}/billOfLading")
59+
def bill_of_lading(self, shipment_id, **kwargs):
60+
return self._request(fill_query_params(kwargs.pop('path'), shipment_id), params=kwargs)
61+
62+
@sp_endpoint("/fba/inbound/v0/shipments")
63+
def get_shipments(self, **kwargs):
64+
return self._request(kwargs.pop('path'), params=kwargs)
65+
66+
@sp_endpoint("/fba/inbound/v0/shipments/{}/items")
67+
def shipment_items_by_shipment(self, shipment_id, **kwargs):
68+
return self._request(fill_query_params(kwargs.pop('path'), shipment_id), params=kwargs)
69+
70+
@sp_endpoint("/fba/inbound/v0/shipmentItems")
71+
def shipment_items(self, **kwargs):
72+
return self._request(kwargs.pop('path'), params=kwargs)
973

sp_api/base/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def _request(self, path: str, *, data: dict = None, params: dict = None, headers
9696
self._add_marketplaces(data if self.method == 'POST' else params)
9797

9898
res = request(self.method, self.endpoint + path, params=params,
99-
data=json.dumps(data) if self.method == 'POST' else None, headers=headers or self.headers,
99+
data=json.dumps(data) if data and self.method in ('POST', 'PUT') else None, headers=headers or self.headers,
100100
auth=self._sign_request())
101101

102102
return self._check_response(res)
Lines changed: 165 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,165 @@
1-
# from datetime import datetime, timedelta
2-
#
3-
# from sp_api.api import FulfillmentInbound
4-
#
5-
# def test_get_shipments():
6-
# r = FulfillmentInbound().get_shipments(QueryType='DATE_RANGE', LastUpdatedAfter=(datetime.now() - timedelta(days=30)).isoformat(), LastUpdatedBefore=datetime.now().isoformat(), ShipmentStatusList=','.join([
7-
# 'WORKING','SHIPPED','RECEIVING','CANCELLED','DELETED','CLOSED','ERROR','IN_TRANSIT','DELIVERED','CHECKED_IN'
8-
# ]))
9-
# print(r)
1+
from datetime import datetime, timedelta
2+
3+
from sp_api.api import FulfillmentInbound
4+
5+
6+
def test_item_guidance():
7+
res = FulfillmentInbound().item_guidance(SellerSKUList=','.join(["sku1", "sku2"]), MarketplaceId='MarketplaceId')
8+
assert res.errors is None
9+
10+
11+
def test_plans():
12+
res = FulfillmentInbound().plans(**{
13+
"ShipFromAddress": {
14+
"Name": "Name",
15+
"AddressLine1": "123 any st",
16+
"AddressLine2": "AddressLine2",
17+
"DistrictOrCounty": "Washtenaw",
18+
"City": "Ann Arbor",
19+
"StateOrProvinceCode": "MI",
20+
"CountryCode": "US",
21+
"PostalCode": "48188"
22+
},
23+
"LabelPrepPreference": "SELLER_LABEL",
24+
"ShipToCountryCode": "ShipToCountryCode",
25+
"ShipToCountrySubdivisionCode": "ShipToCountrySubdivisionCode",
26+
"InboundShipmentPlanRequestItems": [
27+
{
28+
"SellerSKU": "SellerSKU",
29+
"ASIN": "ASIN",
30+
"Condition": "NewItem",
31+
"Quantity": 1,
32+
"QuantityInCase": 1,
33+
"PrepDetailsList": [
34+
{
35+
"PrepInstruction": "Polybagging",
36+
"PrepOwner": "AMAZON"
37+
}
38+
]
39+
}
40+
]
41+
})
42+
assert res.errors is None
43+
44+
45+
def test_create_inbound_shipment():
46+
res = FulfillmentInbound().create_shipment('123', **{
47+
"InboundShipmentHeader": {
48+
"ShipmentName": "43545345",
49+
"ShipFromAddress": {
50+
"Name": "35435345",
51+
"AddressLine1": "123 any st",
52+
"DistrictOrCounty": "Washtenaw",
53+
"City": "Ann Arbor",
54+
"StateOrProvinceCode": "Test",
55+
"CountryCode": "US",
56+
"PostalCode": "48103"
57+
},
58+
"DestinationFulfillmentCenterId": "AEB2",
59+
"AreCasesRequired": True,
60+
"ShipmentStatus": "WORKING",
61+
"LabelPrepPreference": "SELLER_LABEL",
62+
"IntendedBoxContentsSource": "NONE"
63+
},
64+
"InboundShipmentItems": [
65+
{
66+
"ShipmentId": "345453",
67+
"SellerSKU": "34534545",
68+
"FulfillmentNetworkSKU": "435435435",
69+
"QuantityShipped": 0,
70+
"QuantityReceived": 0,
71+
"QuantityInCase": 0,
72+
"ReleaseDate": "2020-04-23",
73+
"PrepDetailsList": [
74+
{
75+
"PrepInstruction": "Polybagging",
76+
"PrepOwner": "AMAZON"
77+
}
78+
]
79+
}
80+
],
81+
"MarketplaceId": "MarketplaceId"
82+
})
83+
assert res.errors is None
84+
85+
86+
def test_update_shipment():
87+
res = FulfillmentInbound().update_shipment('123', **{
88+
"MarketplaceId": "ATVPDKIKX0DER",
89+
"InboundShipmentHeader": {
90+
"ShipmentName": "Shipment for FBA15DJCQ1ZF",
91+
"ShipFromAddress": {
92+
"Name": "Uma Test",
93+
"AddressLine1": "123 any st",
94+
"AddressLine2": "",
95+
"DistrictOrCounty": "Washtenaw",
96+
"City": "Ann Arbor",
97+
"StateOrProvinceCode": "CO",
98+
"CountryCode": "US",
99+
"PostalCode": "48104"
100+
},
101+
"DestinationFulfillmentCenterId": "ABE2",
102+
"ShipmentStatus": "WORKING",
103+
"LabelPrepPreference": "SELLER_LABEL"
104+
},
105+
"InboundShipmentItems": [
106+
{
107+
"SellerSKU": "PSMM-TEST-SKU-Apr-03_21_17_20-0379",
108+
"QuantityShipped": 1
109+
}
110+
]
111+
})
112+
assert res.errors is None
113+
114+
115+
def test_preorder():
116+
res = FulfillmentInbound().preorder('shipmentId1', MarketplaceId='MarketplaceId1')
117+
assert res.errors is None
118+
119+
120+
def test_confirm_preorder():
121+
res = FulfillmentInbound().confirm_preorder('shipmentId1', **{
122+
"NeedByDate": "2020-10-10",
123+
"MarketplaceId": "MarketplaceId1"
124+
})
125+
assert res.errors is None
126+
127+
128+
def test_get_prep_orders():
129+
res = FulfillmentInbound().prep_instruction(**{"ShipToCountryCode": "US", "ASINList": ["ASIN1"]})
130+
assert res.errors is None
131+
132+
133+
def test_get_transport():
134+
res = FulfillmentInbound().get_transport_information('shipmentId1')
135+
assert res.errors is None
136+
137+
138+
def test_void_transport():
139+
res = FulfillmentInbound().void_transport('shipmentId1')
140+
assert res.errors is None
141+
142+
143+
def test_estimate_transport():
144+
res = FulfillmentInbound().estimate_transport('shipmentId1')
145+
assert res.errors is None
146+
147+
148+
def test_get_bill_of_lading():
149+
res = FulfillmentInbound().bill_of_lading('shipmentId')
150+
assert res.errors is None
151+
152+
153+
def test_get_shipments():
154+
res = FulfillmentInbound().get_shipments(QueryType='SHIPMENT')
155+
assert res.errors is None
156+
157+
158+
def test_get_shipment_items():
159+
res = FulfillmentInbound().shipment_items_by_shipment('FBA15DJ9SVVD')
160+
assert res.errors is None
161+
162+
163+
def test_get_items():
164+
res = FulfillmentInbound().shipment_items(QueryType='SHIPMENT', NextToken='NextToken')
165+
assert res.errors is None

0 commit comments

Comments
 (0)