# Path: oscar_mws/api.py
# class MWSObject(OrderedDict):
# 
#     def get_list(self, name):
#         value = self.get(name)
#         if not value:
#             return []
#         if isinstance(value, (list, tuple)):
#             return value
#         return [value]
# 
#     def __getattribute__(self, name):
#         try:
#             value = self[name]
#         except KeyError:
#             value = super(MWSObject, self).__getattribute__(name)
#         return value
# 
# class MWSError(Exception):
#     """
#     Main MWS Exception class
#     """
#     # Allows quick access to the response object.
#     # Do not rely on this attribute, always check if its not None.
#     response = None
#     url = None
# 
# Path: oscar_mws/signals.py

# 
# Path: oscar_mws/connection.py
# def get_merchant_connection(merchant_id, api_name):
#     global _mws_connections
# 
#     if merchant_id in _mws_connections:
#         return _mws_connections[merchant_id].get_api_class(api_name)
# 
#     try:
#         connection = Connection(merchant_id)
#     except ImproperlyConfigured as exc:
#         logger.error(exc.message)
#         return None
# 
#     _mws_connections[merchant_id] = connection
#     return _mws_connections[merchant_id].get_api_class(api_name)


import logging
from collections import defaultdict
from dateutil import parser as du_parser
from django.db.models import get_model
from django.core.exceptions import ObjectDoesNotExist
from oscar.core.loading import get_class
from ..api import MWSObject, MWSError
from ..signals import mws_fulfillment_created
from ..connection import get_merchant_connection
            extra={'seller_id': seller_id,
                   'fulfillment_id': fulfillment_order.fulfillment_id,
                   'order_id': fulfillment_order.order.number})
        fulfillment_order.status = fulfillment_order.SUBMISSION_FAILED
    else:
        fulfillment_order.status = fulfillment_order.SUBMITTED
        mws_fulfillment_created.send(
            sender=outbound_api, fulfillment_order=fulfillment_order)
    fulfillment_order.save()


def update_fulfillment_order(fulfillment_order):
    """
    Update the provided *fulfillment_order* with the latest details from MWS.
    Details for the given *fulfillment_order* are requested from MWS, parsed
    and stored in the database.
    It creates/updates ``FulfillmentOrder``, ``FulfillmentShipment`` and
    ``FulfillmentShipmentPackage`` as well as affected ``FulfillmentOrderLine``
    items. As a side-effect, a ``ShippingEvent`` is created for every shipment
    item received from MWS that changes the status of the corresponding model.

    :param FulfillmentOrder fulfillment_order: A fulfillment order has been
        submitted to Amazon.
    """
    outbound_api = get_merchant_connection(
        fulfillment_order.merchant.seller_id, 'outbound')
    try:
        response = outbound_api.get_fulfillment_order(
            order_id=fulfillment_order.fulfillment_id,
        ).parsed

# Path: oscar_mws/api.py
# class MWSObject(OrderedDict):
# 
#     def get_list(self, name):
#         value = self.get(name)
#         if not value:
#             return []
#         if isinstance(value, (list, tuple)):
#             return value
#         return [value]
# 
#     def __getattribute__(self, name):
#         try:
#             value = self[name]
#         except KeyError:
#             value = super(MWSObject, self).__getattribute__(name)
#         return value
# 
# class MWSError(Exception):
#     """
#     Main MWS Exception class
#     """
#     # Allows quick access to the response object.
#     # Do not rely on this attribute, always check if its not None.
#     response = None
#     url = None
# 
# Path: oscar_mws/signals.py

# 
# Path: oscar_mws/connection.py
# def get_merchant_connection(merchant_id, api_name):
#     global _mws_connections
# 
#     if merchant_id in _mws_connections:
#         return _mws_connections[merchant_id].get_api_class(api_name)
# 
#     try:
#         connection = Connection(merchant_id)
#     except ImproperlyConfigured as exc:
#         logger.error(exc.message)
#         return None
# 
#     _mws_connections[merchant_id] = connection
#     return _mws_connections[merchant_id].get_api_class(api_name)


# Path: oscar_mws/fulfillment/gateway.py
import logging
from collections import defaultdict
from dateutil import parser as du_parser
from django.db.models import get_model
from django.core.exceptions import ObjectDoesNotExist
from oscar.core.loading import get_class
from ..api import MWSObject, MWSError
from ..signals import mws_fulfillment_created
from ..connection import get_merchant_connection

            extra={'seller_id': seller_id,
                   'fulfillment_id': fulfillment_order.fulfillment_id,
                   'order_id': fulfillment_order.order.number})
        fulfillment_order.status = fulfillment_order.SUBMISSION_FAILED
    else:
        fulfillment_order.status = fulfillment_order.SUBMITTED
        mws_fulfillment_created.send(
            sender=outbound_api, fulfillment_order=fulfillment_order)
    fulfillment_order.save()


def update_fulfillment_order(fulfillment_order):
    """
    Update the provided *fulfillment_order* with the latest details from MWS.
    Details for the given *fulfillment_order* are requested from MWS, parsed
    and stored in the database.
    It creates/updates ``FulfillmentOrder``, ``FulfillmentShipment`` and
    ``FulfillmentShipmentPackage`` as well as affected ``FulfillmentOrderLine``
    items. As a side-effect, a ``ShippingEvent`` is created for every shipment
    item received from MWS that changes the status of the corresponding model.

    :param FulfillmentOrder fulfillment_order: A fulfillment order has been
        submitted to Amazon.
    """
    outbound_api = get_merchant_connection(
        fulfillment_order.merchant.seller_id, 'outbound')
    try:
        response = outbound_api.get_fulfillment_order(
            order_id=fulfillment_order.fulfillment_id,
        ).parsed

    except MWSError: