Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

make an admin view for updating prices (bug 800520)

  • Loading branch information...
commit e7e059fdcd36fda45a087b26576c2c82c6e297a6 1 parent 6d7cb3b
Andy McKay authored January 15, 2013
37  apps/market/tests/test_utils_.py
... ...
@@ -0,0 +1,37 @@
  1
+from StringIO import StringIO
  2
+
  3
+from nose.tools import eq_
  4
+
  5
+import amo.tests
  6
+
  7
+from market.models import Price, PriceCurrency
  8
+from market.utils import update, update_from_csv
  9
+
  10
+tiers = [
  11
+    {'USD': '0.99', 'BRL': '1.99'},
  12
+    # This row should be ignored, no tier of value 3.
  13
+    {'USD': '3.00'},
  14
+    # This row should be ignored, not US tier.
  15
+    {'CAD': '10'}
  16
+]
  17
+
  18
+csv = StringIO("""USD\tCAD\tBRL\n0.99\t1.99\t1.00""")
  19
+
  20
+class TestUpdate(amo.tests.TestCase):
  21
+
  22
+    def setUp(self):
  23
+        self.tier = Price.objects.create(name='tier 1', price='0.99')
  24
+
  25
+    def test_create(self):
  26
+        update(tiers)
  27
+        eq_(str(PriceCurrency.objects.get(currency='BRL').price), '1.99')
  28
+        assert not PriceCurrency.objects.filter(currency='CAD').exists()
  29
+
  30
+    def test_update(self):
  31
+        PriceCurrency.objects.create(currency='BRL', tier=self.tier, price='2')
  32
+        update(tiers)
  33
+        eq_(str(PriceCurrency.objects.get(currency='BRL').price), '1.99')
  34
+
  35
+    def test_csv(self):
  36
+        update_from_csv(csv)
  37
+        assert PriceCurrency.objects.filter(currency='CAD').exists()
62  apps/market/utils.py
... ...
@@ -0,0 +1,62 @@
  1
+import csv
  2
+
  3
+import commonware.log
  4
+
  5
+from decimal import Decimal
  6
+from market.models import Price, PriceCurrency
  7
+
  8
+log = commonware.log.getLogger('z.market')
  9
+
  10
+
  11
+def update(tiers):
  12
+    """
  13
+    Updates the prices and price currency objects based on the tiers.
  14
+
  15
+    Tiers should be a list containing a dictionary of currency / value pairs.
  16
+    The value of US is required so that we can look up the price tier. If the
  17
+    price tier for US isn't found, we skip whole tier. If the currency isn't
  18
+    found but the tier is, we create the currency.
  19
+
  20
+    This is intended to be called via a migration or other command.
  21
+    """
  22
+    output = []
  23
+    for row in tiers:
  24
+        us = row.get('USD')
  25
+        if not us:
  26
+            output.append('No USD in row, skipped')
  27
+            continue
  28
+
  29
+        try:
  30
+            tier = Price.objects.get(price=Decimal(us))
  31
+        except Price.DoesNotExist:
  32
+            output.append('Tier not found, skipping: %s' % us)
  33
+            continue
  34
+
  35
+        for currency, value in row.iteritems():
  36
+            if currency == 'USD':
  37
+                continue
  38
+
  39
+            try:
  40
+                curr = PriceCurrency.objects.get(tier=tier, currency=currency)
  41
+            except PriceCurrency.DoesNotExist:
  42
+                curr = PriceCurrency(tier=tier, currency=currency)
  43
+
  44
+            curr.price = Decimal(value)
  45
+            curr.save()
  46
+            output.append('Currency updated: %s, %s, tier %s' %
  47
+                          (currency, value, us))
  48
+
  49
+    return output
  50
+
  51
+
  52
+def update_from_csv(handle):
  53
+    reader = csv.reader(handle, delimiter='\t')
  54
+    headers = []
  55
+    output = []
  56
+    for row in reader:
  57
+        if not headers:
  58
+            headers = row
  59
+            continue
  60
+        output.append(dict(zip(headers, row)))
  61
+
  62
+    return update(output)
4  apps/zadmin/forms.py
@@ -329,3 +329,7 @@ class IOError(Exception):
329 329
                 1 / 0
330 330
             except:
331 331
                 settings.METLOG.raven('metlog_sentry error triggered')
  332
+
  333
+
  334
+class PriceTiersForm(happyforms.Form):
  335
+    prices = forms.FileField()
28  apps/zadmin/templates/zadmin/update-prices.html
... ...
@@ -0,0 +1,28 @@
  1
+{% extends "admin/base.html" %}
  2
+
  3
+{% block title %}Update Prices {{ super() }}{% endblock %}
  4
+
  5
+{% block extrahead %}
  6
+<style>form { margin-bottom: 1em }</style>
  7
+{% endblock %}
  8
+
  9
+{% block content %}
  10
+  {% if result %}
  11
+    <p>{% for row in result %}{{ row }}{% if not loop.last %}<br>{% endif %}{% endfor %}</p>
  12
+  {% endif %}
  13
+  <p>
  14
+    This form accepts a tab delimited CSV file containing prices and currencies.
  15
+    Columns can be in any order. Do not include any currency symbols.
  16
+    Format:
  17
+    <pre>
  18
+      USD   CAD   BRL
  19
+      0.99  1.99  2.99
  20
+      1.99  2.99  3.99
  21
+    </pre>
  22
+  </p>
  23
+  <form enctype="multipart/form-data" method="post">
  24
+    {{ csrf() }}
  25
+    {{ form }}
  26
+    <input type="submit" value="Update">
  27
+  </form>
  28
+{% endblock %}
2  apps/zadmin/urls.py
@@ -69,6 +69,8 @@
69 69
     url('^email_addresses_file$', views.email_addresses_file,
70 70
         name='zadmin.email_addresses_file'),
71 71
 
  72
+    url('^price-tiers$', views.price_tiers, name='zadmin.price_tiers'),
  73
+
72 74
     # Site Event admin.
73 75
     url('^events/(?P<event_id>\d+)?$', views.site_events,
74 76
         name='zadmin.site_events'),
14  apps/zadmin/views.py
@@ -43,13 +43,14 @@
43 43
 from files.models import Approval, File
44 44
 from files.tasks import start_upgrade as start_upgrade_task
45 45
 from files.utils import find_jetpacks, JetpackUpgrader
  46
+from market.utils import update_from_csv
46 47
 from stats.cron import index_latest_stats
47 48
 from stats.search import setup_indexes
48 49
 from users.cron import reindex_users
49 50
 from users.models import UserProfile
50 51
 from versions.compare import version_int as vint
51 52
 from versions.models import Version
52  
-from zadmin.forms import GenerateErrorForm, SiteEventForm
  53
+from zadmin.forms import GenerateErrorForm, PriceTiersForm, SiteEventForm
53 54
 from zadmin.models import SiteEvent
54 55
 
55 56
 from . import tasks
@@ -902,3 +903,14 @@ def email_addresses_file(request):
902 903
         if e is not None:
903 904
             resp.write(e + '\n')
904 905
     return resp
  906
+
  907
+
  908
+@admin_required
  909
+def price_tiers(request):
  910
+    output = []
  911
+    form = PriceTiersForm(request.POST or None, request.FILES)
  912
+    if request.method == 'POST' and form.is_valid():
  913
+        output = update_from_csv(form.cleaned_data['prices'])
  914
+
  915
+    return jingo.render(request, 'zadmin/update-prices.html',
  916
+                        {'result': output, 'form': form})
1  default/site/helpers.py
@@ -31,6 +31,7 @@ def admin_site_links():
31 31
             ('View site settings', url('zadmin.settings')),
32 32
             ('Django admin pages', url('zadmin.home')),
33 33
             ('Site Events', url('zadmin.site_events')),
  34
+            ('Update prices', url('zadmin.price_tiers')),
34 35
         ],
35 36
         'tools': [
36 37
             ('View request environment', url('amo.env')),
1  mkt/purchase/webpay.py
@@ -117,6 +117,7 @@ def prepare_pay(request, addon):
117 117
             'aud': 'tu.com',
118 118
             'memo': contrib_for}
119 119
 
  120
+    data['app_description'] = 'foo'
120 121
     return {'webpayJWT': prepare_webpay_pay(data),
121 122
             'contribStatusURL': reverse('webpay.pay_status',
122 123
                                         args=[addon.app_slug, uuid_])}

0 notes on commit e7e059f

Please sign in to comment.
Something went wrong with that request. Please try again.