Skip to content
This repository has been archived by the owner on Oct 6, 2020. It is now read-only.

Commit

Permalink
Fix issues with new stockrecords
Browse files Browse the repository at this point in the history
  • Loading branch information
Sebastian Vetter committed Nov 1, 2013
1 parent 1be9dc0 commit 40c3f1a
Show file tree
Hide file tree
Showing 16 changed files with 301 additions and 51 deletions.
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.1.0
files = setup.py oscar_mws/__init__.py
files = setup.py oscar_mws/__init__.py docs/source/conf.py
commit = True
tag = True
1 change: 1 addition & 0 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ def pytest_configure():
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'oscar.apps.basket.middleware.BasketMiddleware',
),
ROOT_URLCONF='sandbox.sandbox.urls',
TEMPLATE_DIRS=[
Expand Down
33 changes: 23 additions & 10 deletions oscar_mws/abstract_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

from lxml.builder import E

Partner = models.get_model('partner', 'Partner')
StockRecord = models.get_model('partner', 'StockRecord')


STATUS_DONE = "_DONE_"
STATUS_SUBMITTED = "_SUBMITTED_"
Expand Down Expand Up @@ -189,9 +192,6 @@ class Meta:


class AbstractAmazonProfile(models.Model):
SELLER_SKU_FIELD = "product__{0}".format(
getattr(settings, "MWS_SELLER_SKU_FIELD")
)
FULFILLMENT_BY_AMAZON = "AFN"
FULFILLMENT_BY_MERCHANT = "MFN"
FULFILLMENT_TYPES = (
Expand All @@ -202,6 +202,7 @@ class AbstractAmazonProfile(models.Model):
# We don't necessarily get the ASIN back right away so we need
# to be able to create a profile without a ASIN
asin = models.CharField(_("ASIN"), max_length=10, blank=True)
sku = models.CharField(_("SKU"), max_length=64)
product = models.OneToOneField(
'catalogue.Product',
verbose_name=_("Product"),
Expand Down Expand Up @@ -261,13 +262,11 @@ def get_standard_product_id(self):
)
return None

@property
def sku(self):
if not hasattr(self, '_cached_sku'):
if not self.product.has_stockrecord:
self._cached_sku = None
self._cached_sku = self.product.stockrecord.partner_sku.strip()
return self._cached_sku
def save(self, *args, **kwargs):
super(AbstractAmazonProfile, self).save(*args, **kwargs)
if getattr(settings, 'MWS_ENFORCE_PARTNER_SKU', True):
StockRecord.objects.filter(product__amazon_profile=self).update(
partner_sku=self.sku)

def __unicode__(self):
return "Amazon profile for {0}".format(self.product.title)
Expand Down Expand Up @@ -455,6 +454,20 @@ class AbstractMerchantAccount(models.Model):
aws_api_secret = models.CharField(_("AWS API Secret"), max_length=200)
seller_id = models.CharField(_("Seller/Merchant ID"), max_length=200)

partner = models.OneToOneField(
"partner.Partner",
verbose_name=_("Partner"),
related_name="amazon_merchant",
null=True, blank=True
)

def save(self, *args, **kwargs):
if not self.partner:
self.partner, __ = Partner.objects.get_or_create(
name="Amazon {} ({})".format(self.name, self.region)
)
super(AbstractMerchantAccount, self).save(*args, **kwargs)

@property
def marketplace_ids(self):
return [m.marketplace_id for m in self.marketplaces.all()]
Expand Down
32 changes: 31 additions & 1 deletion oscar_mws/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#
# Basic interface to Amazon MWS
# Based on http://code.google.com/p/amazon-mws-python
import re
import hmac
import urllib
import base64
Expand All @@ -14,12 +13,15 @@
from time import strftime, gmtime
from collections import OrderedDict

from django.conf import settings

try:
from xml.etree.ElementTree import ParseError as XMLError
except ImportError:
from xml.parsers.expat import ExpatError as XMLError

from requests import request
from requests.sessions import Session
from requests.exceptions import HTTPError


Expand Down Expand Up @@ -143,6 +145,34 @@ def __init__(self, access_key, secret_key, account_id,
self.domain = domain
self.uri = uri or self.URI
self.version = version or self.VERSION
self.session = Session()

bucket_key = getattr(settings, 'RUNSCOPE_BUCKET_KEY', None)
if settings.DEBUG and bucket_key:
self.configure_runscope(bucket_key)

def configure_runscope(self, bucket_key):
"""
Configure all connections to be proxied through runscope for easier
debugging and logging of all requests and responses. *bucket_key* is
API for the bucket you want to use for all the request. Check Runscope
for more details on that.
"""
try:
from requests_runscope import RunscopeAdapter
except ImportError:
logger.error(
"Could not import runscope adapter. Is requests-runscope "
"installed? Try running pip install requests-runscope."
)
else:
logger.debug(
'Mounting runscope proxy adapter for bucket {}'.format(
bucket_key
)
)
self.session.mount('http://', RunscopeAdapter(bucket_key))
self.session.mount('https://', RunscopeAdapter(bucket_key))

def _get_quote_params(self, params):
quoted_params = []
Expand Down
3 changes: 0 additions & 3 deletions oscar_mws/defaults.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
from django.utils.translation import ugettext_lazy as _

# Django ORM field description for seller SKU relative to Product model
MWS_SELLER_SKU_FIELD = 'stockrecord__partner_sku'

# Callable that returns an appropriate region for a given order and address
MWS_FULFILLMENT_MERCHANT_FINDER = 'oscar_mws.fulfillment.finders.default_merchant_finder'

Expand Down
8 changes: 4 additions & 4 deletions oscar_mws/feeds/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ def process_submission_results(submission):
if product_sku:
try:
product = Product.objects.get(
product__stockrecord__partner_sku=product_sku
amazon_profile__sku=product_sku
)
except Product.DoesNotExist:
pass
Expand Down Expand Up @@ -329,9 +329,9 @@ def update_product_identifiers(merchant, products):
logger.debug('ASIN in response: {}'.format(asin))

if asin:
profiles = AmazonProfile.objects.filter(**{
AmazonProfile.SELLER_SKU_FIELD: response.get("@Id")
})
profiles = AmazonProfile.objects.filter(
sku=response.get("@Id")
)
profiles.update(asin=asin)


Expand Down
1 change: 0 additions & 1 deletion oscar_mws/fulfillment/creator.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,4 @@ def create_fulfillment_order(self, order, lines=None, **kwargs):
fulfillment_order=fulfillment_order,
order_item_id=la.get_seller_fulfillment_order_item_id(),
)

return fulfillment_orders
56 changes: 56 additions & 0 deletions oscar_mws/test/factories.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,53 @@
import factory

from time import time
from decimal import Decimal as D

from django.utils.timezone import now
from django.db.models import get_model

from oscar.core.loading import get_class

from oscar_mws import MWS_MARKETPLACE_US

Selector = get_class('partner.strategy', 'Selector')


class ProductClassFactory(factory.DjangoModelFactory):
FACTORY_FOR = get_model('catalogue', 'ProductClass')

name = factory.Sequence(lambda n: 'Dummy product class {}'.format(n))


class ProductFactory(factory.DjangoModelFactory):
FACTORY_FOR = get_model('catalogue', 'Product')

title = 'Dummy Product'
product_class = factory.SubFactory(ProductClassFactory)

@factory.post_generation
def stockrecord(self, created, extracted, **kwargs):
if not created:
return
if not extracted:
kwargs.setdefault('product', self)
extracted = StockRecordFactory(**kwargs)
self.stockrecords.add(extracted)


class BasketFactory(factory.DjangoModelFactory):
FACTORY_FOR = get_model('basket', 'Basket')

strategy = Selector().strategy()


class AmazonProfileFactory(factory.DjangoModelFactory):
FACTORY_FOR = get_model('oscar_mws', 'AmazonProfile')

sku = factory.Sequence(lambda n: "sku_{}".format(str(time())[:10]))
release_date = now()
product = factory.SubFactory(ProductFactory)


class MerchantAccountFactory(factory.DjangoModelFactory):
FACTORY_FOR = get_model('oscar_mws', 'MerchantAccount')
Expand Down Expand Up @@ -37,3 +80,16 @@ class FeedSubmissionFactory(factory.DjangoModelFactory):

merchant = factory.SubFactory(MerchantAccountFactory)
date_submitted = now()


class PartnerFactory(factory.DjangoModelFactory):
FACTORY_FOR = get_model('partner', 'Partner')

name = factory.Sequence(lambda n:'Dummy partner {}'.format(n))


class StockRecordFactory(factory.DjangoModelFactory):
FACTORY_FOR = get_model('partner', 'StockRecord')

price_excl_tax = D('12.99')
partner = factory.SubFactory(PartnerFactory)
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pyflakes>=0.5.0
coveralls>=0.1.1,<0.2

# we need this to make sure that we test against Oscar 0.6
-e git+https://github.com/tangentlabs/django-oscar.git@6252164705fb4d08d94329666d3a20e52ddd2c61#egg=django-oscar
-e git+https://github.com/tangentlabs/django-oscar.git@89d12c8701d293f23afa19c6efac17b249ae1b6d#egg=django-oscar

# Others
Whoosh>=2.4.1
Expand Down
4 changes: 4 additions & 0 deletions sandbox/sandbox/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@

'compressor',
'south',
'django_extensions',
]

THIRD_PARTY_APPS = [
Expand Down Expand Up @@ -222,3 +223,6 @@

INTERNAL_IPS = ('127.0.0.1',)

########## RUNSCOPE SETTINGS
RUNSCOPE_BUCKET_KEY = os.getenv('RUNSCOPE_BUCKET_KEY')
########## END RUNSCOPE SETTINGS
7 changes: 4 additions & 3 deletions tests/functional/test_fulfillment.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
from django.test import TestCase
from django.db.models import get_model

from oscar_testsupport.factories import create_order
from oscar.test.factories import create_order

from oscar_mws.test import mixins, factories

from oscar_mws.fulfillment.gateway import update_fulfillment_order

ShippingEvent = get_model('order', 'ShippingEvent')
Expand All @@ -30,7 +29,9 @@ def test_parses_the_response_correctly(self):
body=xml_data,
)

order = create_order()
basket = factories.BasketFactory()
basket.add_product(factories.ProductFactory())
order = create_order(basket=basket)

update_fulfillment_order(
factories.FulfillmentOrderFactory(order=order)
Expand Down
9 changes: 4 additions & 5 deletions tests/functional/test_profile_dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,13 @@ def test_can_create_amazon_profile(self):
)

profile_form = create_page.form
profile_form['sku'] = 'fake12345'
profile_form['marketplaces'] = [self.marketplace.id]
page = profile_form.submit()

self.assertRedirects(page, reverse('mws-dashboard:profile-list'))

profile = AmazonProfile.objects.get(product=self.product)
self.assertEquals(profile.sku, self.product.stockrecord.partner_sku)
self.assertSequenceEqual(
profile.marketplaces.all(),
[self.marketplace]
)
self.assertEquals(profile.sku, 'fake12345')
self.assertSequenceEqual(profile.marketplaces.all(),
[self.marketplace])
Loading

0 comments on commit 40c3f1a

Please sign in to comment.