Skip to content

Commit

Permalink
added getReports() #31
Browse files Browse the repository at this point in the history
  • Loading branch information
saleweaver committed Feb 8, 2021
1 parent 2ec100e commit 1ddbee0
Show file tree
Hide file tree
Showing 9 changed files with 170 additions and 5 deletions.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setup(
name='python-amazon-sp-api',
version='0.2.0',
version='0.2.1',
install_requires=[
"requests",
"six~=1.15.0",
Expand Down
50 changes: 49 additions & 1 deletion sp_api/api/reports/reports.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from collections import abc
from datetime import datetime
import zlib

import requests

from sp_api.base import sp_endpoint, fill_query_params, SellingApiException, ApiResponse
from sp_api.base import sp_endpoint, fill_query_params, SellingApiException, ApiResponse, ProcessingStatus, Marketplaces
from sp_api.base import Client
from sp_api.base.helpers import decrypt_aes

Expand Down Expand Up @@ -182,6 +184,52 @@ def get_report_schedule(self, schedule_id, **kwargs) -> ApiResponse:
"""
return self._request(fill_query_params(kwargs.pop('path'), schedule_id), params=kwargs)

@sp_endpoint('/reports/2020-09-04/reports')
def get_reports(self, **kwargs) -> ApiResponse:
"""
get_reports(self, **kwargs) -> ApiResponse
Returns report details for the reports that match the filters that you specify.
**Usage Plan:**
====================================== ==============
Rate (requests per second) Burst
====================================== ==============
0.0222 10
====================================== ==============
For more information, see "Usage Plans and Rate Limits" in the Selling Partner API documentation.
Args:
key reportTypes: str[] or ReportType[] | optional A list of report types used to filter reports. When reportTypes is provided, the other filter parameters (processingStatuses, marketplaceIds, createdSince, createdUntil) and pageSize may also be provided. Either reportTypes or nextToken is required.
key processingStatuses: str[] or ProcessingStatus[] optional A list of processing statuses used to filter reports.
key marketplaceIds: str[] or Marketplaces[] optional A list of marketplace identifiers used to filter reports. The reports returned will match at least one of the marketplaces that you specify.
key pageSize: int optional The maximum number of reports to return in a single call.
key createdSince: str or datetime optional The earliest report creation date and time for reports to include in the response, in ISO 8601 date time format. The default is 90 days ago. Reports are retained for a maximum of 90 days. string (date-time) -
key createdUntil: str or datetime optional The latest report creation date and time for reports to include in the response, in ISO 8601 date time format. The default is now. string (date-time) -
key nextToken: str optional A string token returned in the response to your previous request. nextToken is returned when the number of results exceeds the specified pageSize value. To get the next page of results, call the getReports operation and include this token as the only parameter. Specifying nextToken with any other parameters will cause the request to fail. string -
Returns:
ApiResponse
"""
if kwargs.get('reportTypes', None) and isinstance(kwargs.get('reportTypes'), abc.Iterable):
kwargs.update({'reportTypes': ','.join(kwargs.get('reportTypes'))})
if kwargs.get('processingStatuses', None) and isinstance(kwargs.get('processingStatuses'), abc.Iterable):
kwargs.update({'processingStatuses': ','.join(kwargs.get('processingStatuses'))})
if kwargs.get('marketplaceIds', None) and isinstance(kwargs.get('marketplaceIds'), abc.Iterable):
marketplaces = kwargs.get('marketplaceIds')
if not isinstance(marketplaces, abc.Iterable):
marketplaces = [marketplaces]
kwargs.update({'marketplaceIds': ','.join([m.marketplace_id if isinstance(m, Marketplaces) else m for m in marketplaces])})
for k in ['createdSince', 'createdUntil']:
if kwargs.get(k, None) and isinstance(kwargs.get(k), datetime):
kwargs.update({k: kwargs.get(k).isoformat()})

return self._request(kwargs.pop('path'), params=kwargs, add_marketplace=False)

@staticmethod
def decrypt_report_document(url, initialization_vector, key, encryption_standard, payload):
"""
Expand Down
4 changes: 3 additions & 1 deletion sp_api/base/ApiResponse.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@


class ApiResponse:
def __init__(self, payload=None, errors=None, pagination=None, headers=None):
def __init__(self, payload=None, errors=None, pagination=None, headers=None, nextToken=None, **kwargs):
self.payload = payload
self.errors = errors
self.pagination = pagination
self.headers = headers
self.next_token = nextToken
self.kwargs = kwargs

def __str__(self):
return pprint.pformat(self.__dict__)
Expand Down
4 changes: 4 additions & 0 deletions sp_api/base/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@
from .notifications import NotificationType
from .config import CredentialProvider, MissingCredentials
from .ApiResponse import ApiResponse
from .processing_status import ProcessingStatus
from .reportTypes import ReportType

__all__ = [
'ReportType',
'ProcessingStatus',
'ApiResponse',
'Client',
'BaseClient',
Expand Down
1 change: 1 addition & 0 deletions sp_api/base/fulfillment_channel.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from enum import Enum


class FulfillmentChannel(Enum):
AFN = 'AFN'
MFN = 'MFN'
2 changes: 1 addition & 1 deletion sp_api/base/notifications.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from enum import Enum


class NotificationType(Enum):
class NotificationType(str, Enum):
ANY_OFFER_CHANGED = 'ANY_OFFER_CHANGED'
FEED_PROCESSING_FINISHED = 'FEED_PROCESSING_FINISHED'
FBA_OUTBOUND_SHIPMENT_STATUS = 'FBA_OUTBOUND_SHIPMENT_STATUS'
Expand Down
9 changes: 9 additions & 0 deletions sp_api/base/processing_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from enum import Enum


class ProcessingStatus(str, Enum):
CANCELLED = 'CANCELLED'
DONE = 'DONE'
FATAL = 'FATAL'
IN_PROGRESS = 'IN_PROGRESS'
IN_QUEUE = 'IN_QUEUE'
59 changes: 59 additions & 0 deletions sp_api/base/reportTypes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from enum import Enum


class ReportType(str, Enum):
GET_FLAT_FILE_OPEN_LISTINGS_DATA = 'GET_FLAT_FILE_OPEN_LISTINGS_DATA'
GET_MERCHANT_LISTINGS_DATA = 'GET_MERCHANT_LISTINGS_DATA'
GET_MERCHANT_LISTINGS_DATA_BACK_COMPAT = 'GET_MERCHANT_LISTINGS_DATA_BACK_COMPAT'
GET_MERCHANT_LISTINGS_DATA_LITE = 'GET_MERCHANT_LISTINGS_DATA_LITE'
GET_MERCHANT_LISTINGS_DATA_LITER = 'GET_MERCHANT_LISTINGS_DATA_LITER'
GET_MERCHANT_CANCELLED_LISTINGS_DATA = 'GET_MERCHANT_CANCELLED_LISTINGS_DATA'
GET_CONVERGED_FLAT_FILE_SOLD_LISTINGS_DATA = 'GET_CONVERGED_FLAT_FILE_SOLD_LISTINGS_DATA'
GET_MERCHANT_LISTINGS_DEFECT_DATA = 'GET_MERCHANT_LISTINGS_DEFECT_DATA'
GET_FLAT_FILE_ACTIONABLE_ORDER_DATA = 'GET_FLAT_FILE_ACTIONABLE_ORDER_DATA'
GET_ORDERS_DATA = 'GET_ORDERS_DATA'
GET_FLAT_FILE_ORDERS_DATA = 'GET_FLAT_FILE_ORDERS_DATA'
GET_CONVERGED_FLAT_FILE_ORDER_REPORT_DATA = 'GET_CONVERGED_FLAT_FILE_ORDER_REPORT_DATA'
GET_FLAT_FILE_PENDING_ORDERS_DATA = 'GET_FLAT_FILE_PENDING_ORDERS_DATA'
GET_PENDING_ORDERS_DATA = 'GET_PENDING_ORDERS_DATA'
GET_CONVERGED_FLAT_FILE_PENDING_ORDERS_DATA = 'GET_CONVERGED_FLAT_FILE_PENDING_ORDERS_DATA'
GET_SELLER_FEEDBACK_DATA = 'GET_SELLER_FEEDBACK_DATA'
GET_V1_SELLER_PERFORMANCE_REPORT = 'GET_V1_SELLER_PERFORMANCE_REPORT'
GET_V2_SETTLEMENT_REPORT_DATA_FLAT_FILE = 'GET_V2_SETTLEMENT_REPORT_DATA_FLAT_FILE'
GET_V2_SETTLEMENT_REPORT_DATA_FLAT_FILE_V2 = 'GET_V2_SETTLEMENT_REPORT_DATA_FLAT_FILE_V2'
GET_FLAT_FILE_SALES_TAX_DATA = 'GET_FLAT_FILE_SALES_TAX_DATA'
SC_VAT_TAX_REPORT = 'SC_VAT_TAX_REPORT'
GET_VAT_TRANSACTION_DATA = 'GET_VAT_TRANSACTION_DATA'
GET_XML_BROWSE_TREE_DATA = 'GET_XML_BROWSE_TREE_DATA'
GET_AMAZON_FULFILLED_SHIPMENTS_DATA = 'GET_AMAZON_FULFILLED_SHIPMENTS_DATA'
FEE_DISCOUNTS_REPORT = 'FEE_DISCOUNTS_REPORT'
GET_FLAT_FILE_ALL_ORDERS_DATA_BY_LAST_UPDATE = 'GET_FLAT_FILE_ALL_ORDERS_DATA_BY_LAST_UPDATE'
GET_FLAT_FILE_ALL_ORDERS_DATA_BY_ORDER_DATE = 'GET_FLAT_FILE_ALL_ORDERS_DATA_BY_ORDER_DATE'
GET_XML_ALL_ORDERS_DATA_BY_LAST_UPDATE = 'GET_XML_ALL_ORDERS_DATA_BY_LAST_UPDATE'
GET_XML_ALL_ORDERS_DATA_BY_ORDER_DATE = 'GET_XML_ALL_ORDERS_DATA_BY_ORDER_DATE'
GET_FBA_FULFILLMENT_CUSTOMER_SHIPMENT_SALES_DATA = 'GET_FBA_FULFILLMENT_CUSTOMER_SHIPMENT_SALES_DATA'
GET_FBA_FULFILLMENT_CUSTOMER_SHIPMENT_PROMOTION_DATA = 'GET_FBA_FULFILLMENT_CUSTOMER_SHIPMENT_PROMOTION_DATA'
GET_FBA_FULFILLMENT_CUSTOMER_TAXES_DATA = 'GET_FBA_FULFILLMENT_CUSTOMER_TAXES_DATA'
GET_AFN_INVENTORY_DATA = 'GET_AFN_INVENTORY_DATA'
GET_FBA_FULFILLMENT_CURRENT_INVENTORY_DATA = 'GET_FBA_FULFILLMENT_CURRENT_INVENTORY_DATA'
GET_FBA_FULFILLMENT_MONTHLY_INVENTORY_DATA = 'GET_FBA_FULFILLMENT_MONTHLY_INVENTORY_DATA'
GET_FBA_FULFILLMENT_INVENTORY_RECEIPTS_DATA = 'GET_FBA_FULFILLMENT_INVENTORY_RECEIPTS_DATA'
GET_RESERVED_INVENTORY_DATA = 'GET_RESERVED_INVENTORY_DATA'
GET_FBA_FULFILLMENT_INVENTORY_SUMMARY_DATA = 'GET_FBA_FULFILLMENT_INVENTORY_SUMMARY_DATA'
GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA = 'GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA'
GET_FBA_FULFILLMENT_INVENTORY_HEALTH_DATA = 'GET_FBA_FULFILLMENT_INVENTORY_HEALTH_DATA'
GET_FBA_MYI_UNSUPPRESSED_INVENTORY_DATA = 'GET_FBA_MYI_UNSUPPRESSED_INVENTORY_DATA'
GET_FBA_MYI_ALL_INVENTORY_DATA = 'GET_FBA_MYI_ALL_INVENTORY_DATA'
GET_FBA_FULFILLMENT_CROSS_BORDER_INVENTORY_MOVEMENT_DATA = 'GET_FBA_FULFILLMENT_CROSS_BORDER_INVENTORY_MOVEMENT_DATA'
GET_FBA_FULFILLMENT_INBOUND_NONCOMPLIANCE_DATA = 'GET_FBA_FULFILLMENT_INBOUND_NONCOMPLIANCE_DATA'
GET_STRANDED_INVENTORY_UI_DATA = 'GET_STRANDED_INVENTORY_UI_DATA'
GET_STRANDED_INVENTORY_LOADER_DATA = 'GET_STRANDED_INVENTORY_LOADER_DATA'
GET_FBA_INVENTORY_AGED_DATA = 'GET_FBA_INVENTORY_AGED_DATA'
GET_EXCESS_INVENTORY_DATA = 'GET_EXCESS_INVENTORY_DATA'
GET_FBA_ESTIMATED_FBA_FEES_TXT_DATA = 'GET_FBA_ESTIMATED_FBA_FEES_TXT_DATA'
GET_FBA_REIMBURSEMENTS_DATA = 'GET_FBA_REIMBURSEMENTS_DATA'
GET_FBA_FULFILLMENT_CUSTOMER_RETURNS_DATA = 'GET_FBA_FULFILLMENT_CUSTOMER_RETURNS_DATA'
GET_FBA_RECOMMENDED_REMOVAL_DATA = 'GET_FBA_RECOMMENDED_REMOVAL_DATA'
GET_FBA_FULFILLMENT_REMOVAL_ORDER_DETAIL_DATA = 'GET_FBA_FULFILLMENT_REMOVAL_ORDER_DETAIL_DATA'
GET_FBA_FULFILLMENT_REMOVAL_SHIPMENT_DETAIL_DATA = 'GET_FBA_FULFILLMENT_REMOVAL_SHIPMENT_DETAIL_DATA'

44 changes: 43 additions & 1 deletion tests/api/reports/test_reports.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from sp_api.api import Reports
from sp_api.base import Marketplaces, Schedules, SellingApiBadRequestException, SellingApiServerException
from sp_api.base import Marketplaces, Schedules, SellingApiBadRequestException, SellingApiServerException, \
ProcessingStatus
from sp_api.base.reportTypes import ReportType


def test_create_report():
Expand Down Expand Up @@ -70,3 +72,43 @@ def test_get_schedule_by_id():
assert res.errors is None
assert 'period' in res.payload
assert res.payload.get('reportType') == 'FEE_DISCOUNTS_REPORT'


def test_get_reports_1():
report_types = [
"FEE_DISCOUNTS_REPORT",
"GET_AFN_INVENTORY_DATA"
]
processing_status = [
"IN_QUEUE",
"IN_PROGRESS"
]
res = Reports().get_reports(reportTypes=report_types, processingStatuses=processing_status)
assert res.errors is None


def test_get_reports_2():
report_types = [
"FEE_DISCOUNTS_REPORT",
"GET_AFN_INVENTORY_DATA"
]
processing_status = [
ProcessingStatus.IN_QUEUE,
ProcessingStatus.IN_PROGRESS
]
res = Reports().get_reports(reportTypes=report_types, processingStatuses=processing_status)
assert res.errors is None


def test_get_reports_3():
report_types = [
ReportType.FEE_DISCOUNTS_REPORT,
ReportType.GET_AFN_INVENTORY_DATA
]
processing_status = [
ProcessingStatus.IN_QUEUE,
ProcessingStatus.IN_PROGRESS
]
res = Reports().get_reports(reportTypes=report_types, processingStatuses=processing_status)
assert res.errors is None

0 comments on commit 1ddbee0

Please sign in to comment.