Added money conversion feature

This commit is contained in:
Felipe Martín 2015-06-25 20:46:45 +02:00
parent 0babc78d63
commit 0431feba3b
14 changed files with 235 additions and 17 deletions

View File

@ -1,10 +1,17 @@
# coding: utf-8
# amiibo
from .models import Collection
from .models import Collection, AmiiboPrice
def collections(request):
return {
'collections': Collection.objects.all().order_by('name_eu')
'COLLECTIONS': Collection.objects.all().order_by('name_eu')
}
def currencies(request):
return {
'CURRENCIES': AmiiboPrice.objects.all().distinct('currency')\
.values_list('currency', flat=True)
}

View File

@ -11,3 +11,10 @@ def debug(request):
return {
'DEBUG': settings.DEBUG,
}
def files(request):
return {
'MEDIA_URL': settings.MEDIA_URL,
'STATIC_URL': settings.STATIC_URL,
}

View File

@ -0,0 +1,45 @@
# coding: utf-8
# python
from __future__ import unicode_literals
import json
import os
# third party
import requests
# django
from django.conf import settings
from django.core.management.base import BaseCommand
# amiibo
from amiibofindr.apps.amiibo.models import AmiiboPrice
class Command(BaseCommand):
@property
def rates_url(self):
return 'https://openexchangerates.org/api/latest.json?app_id={}'.format(
settings.OPENEXCHANGERATES_KEY
)
def handle(self, *args, **kwargs):
currencies = AmiiboPrice.objects.all().distinct('currency')\
.values_list('currency', flat=True)
rates = requests.get(self.rates_url).json()
result = {
'base': rates['base'],
'rates': {}
}
for currency, rate in rates['rates'].iteritems():
if currency in currencies:
result['rates'][currency] = rate
handler = open(os.path.join(settings.MEDIA_ROOT, 'rates.json'), 'w')
handler.write(json.dumps(result))
handler.close()
print(result)

View File

@ -78,7 +78,9 @@ TEMPLATES = [
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'amiibofindr.apps.amiibo.context_processors.collections',
'amiibofindr.apps.amiibo.context_processors.currencies',
'amiibofindr.apps.core.context_processors.debug',
'amiibofindr.apps.core.context_processors.files',
],
},
},

View File

@ -21,6 +21,8 @@ DATABASES = {
MEDIA_URL = '/media/'
MEDIA_ROOT = '/vagrant/media'
OPENEXCHANGERATES_KEY = 'aa703ed87a7749afab77b2966559c9df'
try:
from local_settings import *
except ImportError:

View File

@ -0,0 +1,94 @@
(function() {
var MoneyComponent = function() {
this.DEBUG = DEBUG;
this.currency = 'EUR';
this.currencies = CURRENCIES;
this.ratesSet = false;
this.initialize();
};
MoneyComponent.prototype.initialize = function() {
// Load user currency
this.refreshRates();
this.handlers();
var userCurrency = window.localStorage.getItem('currency');
if (userCurrency && this.currencies.indexOf(userCurrency) !== -1) {
this.currency = userCurrency;
}
this.setCurrency(this.currency);
};
/*
* Rates
*/
MoneyComponent.prototype.setRates = function(data) {
if (!this.ratesSet) {
if (typeof fx !== "undefined" && fx.rates) {
fx.rates = data.rates;
fx.base = data.base;
}
this.ratesSet = true;
}
};
MoneyComponent.prototype.refreshRates = function() {
var self = this;
$.getJSON(
MEDIA_URL + '/rates.json',
function(data) {
data['time'] = new Date();
window.localStorage.setItem('rates', JSON.stringify(data));
self.setRates(data);
}
);
};
MoneyComponent.prototype.setCurrency = function(currency) {
var self = this;
if (this.currencies.indexOf(currency) !== -1) {
if (this.DEBUG) console.log('[money] set user currency: ' + currency)
$('[data-currency-change]').removeClass('active');
$('[data-currency-change="' + currency + '"]').addClass('active');
window.localStorage.setItem('currency', currency);
this.currency = currency;
this.convertPrices();
}
};
MoneyComponent.prototype.convertPrices = function() {
var self = this;
if (!this.ratesSet) {
if (this.DEBUG) console.log('[money] wait 300ms to convert prices...');
setTimeout(function() {
self.convertPrices()
}, 300);
return false;
}
[].forEach.call(document.querySelectorAll('[data-money]'), function(item) {
var price = item.getAttribute('data-price');
var currency = item.getAttribute('data-currency');
if ((price && currency)) {
if (currency != self.currency) {
var conversion = fx(parseFloat(price)).from(currency).to(self.currency);
if (self.DEBUG) console.log('[money] converting ' + price + ' from ' + currency + ' to ' + self.currency + ': ' + conversion);
if (conversion) item.innerHTML = '<span class="price-converted">' + conversion.toFixed(2) + ' ' + self.currency + '</span>';
} else {
item.innerHTML = price + ' ' + currency;
}
}
});
};
MoneyComponent.prototype.handlers = function() {
var self = this;
[].forEach.call(document.querySelectorAll('[data-currency-change]'), function(item) {
var currency = item.getAttribute('data-currency-change');
item.addEventListener('click', function(event) {
event.preventDefault();
self.setCurrency(currency);
})
});
};
SimpleViews.register('money', MoneyComponent);
})();

View File

@ -0,0 +1,37 @@
(function() {
var SimpleViews = function() {
this.views = {};
var self = this;
window.addEventListener("load", function() {
self.onLoad();
});
};
SimpleViews.prototype.register = function(identifier, object) {
if (identifier in this.views) {
throw "Identifier '" + identifier + "' is already registered.";
};
this.views[identifier] = object;
};
SimpleViews.prototype.loadView = function(identifier) {
if (typeof(this.views[identifier]) === 'function') {
console.log('[SimpleViews] loaded view: ' + identifier);
this.views[identifier] = new this.views[identifier](window);
} else {
console.error('Identifier ' + identifier + ' not registered or already loaded.');
}
};
SimpleViews.prototype.onLoad = function() {
var body = document.querySelector('body');
var views = body.getAttribute('data-views').split(',');
var self = this;
[].forEach.call(views, function(view) {
self.loadView(view);
})
};
window.SimpleViews = new SimpleViews();
})(window);

View File

@ -1,2 +1,11 @@
// Semantic-UI
@import "../semantic/semantic.css";
.price-converted {
font-style: italic;
&:before {
content: '~';
}
}

View File

@ -9,7 +9,7 @@
<title>{% block page_title %}AmiiboFindr{% endblock %}</title>
</head>
<body>
<body data-views="{% block js_views %}{% endblock %}">
<div class="ui page grid">
<br />
<div class="sixteen wide column">
@ -21,25 +21,30 @@
{% trans "Collections" %}
<i class="dropdown icon"></i>
<div class="menu">
<a class="item" href="#">{% trans "All" %}</a> {% for col in collections %}
<a class="item" href="{{ col.get_absolute_url }}">{{ col.name }}</a> {% endfor %}
<a class="item" href="#">{% trans "All" %}</a>
{% for col in COLLECTIONS %}
<a class="item" href="{{ col.get_absolute_url }}">{{ col.name }}</a>
{% endfor %}
</div>
</div>
<div class="right menu"></div>
</div>
<div class="ui breadcrumb">
{% block breadcrumb %}
<a class="section" href="{% url 'amiibo:collection' 'all' %}">Home</a>
{% endblock %}
</div>
<div class="ui breadcrumb">
{% block breadcrumb %}
<a class="section" href="{% url 'amiibo:collection' 'all' %}">Home</a>
{% endblock %}
</div>
</div>
</div>
{% block main_content %}{% endblock %}
<div class="ui page grid right aligned">
<div class="sixteen wide column">
<div class="ui page grid">
<hr >
<div class="eight wide column">
<small>{% trans "CHANGE CURRENCY" %} {% for currency in CURRENCIES %}<a href="#" data-currency-change="{{ currency }}">{{ currency }}</a> {% endfor %}</small>
</div>
<div class="eight wide column right aligned">
<div class="">
AmiiboFindr &copy; 2015 | <a href="https://twitter.com/amiibofindr" target="_blank"><i class="ui icon twitter"></i>Twitter</a>
AmiiboFindr &copy; 2015 | <a href="https://twitter.com/amiibofindr" target="_blank"><i class="ui icon twitter"></i>Twitter</a>
</div>
</div>
</div>
@ -53,6 +58,11 @@
ga('send', 'pageview');
</script>
{% endif %}
<script type="text/javascript">
var DEBUG = {{ DEBUG|yesno:"true,false" }};
var MEDIA_URL = '{{ MEDIA_URL }}';
var CURRENCIES = ['{{ CURRENCIES|join:"', '" }}'];
</script>
<script type="text/javascript" src={% static "dist/app.js" %}></script>
</body>

View File

@ -3,6 +3,7 @@
{% block page_title %}{% blocktrans with collection=selected_collection.name amiibo=amiibo.name %}{{ amiibo }} amiibo from {{ collection }} in {% endblocktrans %}{{ block.super }}{% endblock %}
{% block js_views %}money{% endblock %}
{% block breadcrumb %}
{{ block.super }}
@ -55,14 +56,14 @@
<tbody>
{% for relation in amiibo.shops_set.all %}
<tr>
{% with price=relation.last_price.price stock=relation.last_price.stock %}
{% with price=relation.last_price.price stock=relation.last_price.stock currency=relation.last_price.currency %}
<td><a href="{{ relation.get_url }}" target="_blank"><i class="{% if relation.shop.flag_code == 'uk' %}gb{% else %}{{ relation.shop.flag_code }}{% endif %} flag"></i> {{ relation.shop.name }}</a></td>
<td class="center aligned {{ stock|yesno:'positive,negative' }}" {% if not price %}colspan="2"{% endif %}>
<i class="icon {{ stock|yesno:'checkmark,close' }}"></i>
{{ stock|yesno|capfirst }}
</td>
{% if price %}
<td class="center aligned">
<td class="center aligned" data-price="{{ price }}" data-currency="{{ currency }}" data-money>
{{ price }} {{ relation.last_price.currency }}
</td>
{% endif %}

View File

@ -12,6 +12,7 @@
],
"dependencies": {
"semantic-ui": "~1.12.3",
"jquery": "~2.1.4"
"jquery": "~2.1.4",
"money": "~0.1.3"
}
}

View File

@ -7,8 +7,11 @@ var gulp = require('gulp'),
gulp.task('scripts', function() {
return gulp.src([
'bower_components/jquery/dist/jquery.js',
'bower_components/money/money.js',
'amiibofindr/static/semantic/semantic.js',
'amiibofindr/static/app/global.js'
'amiibofindr/static/app/simpleViews.js',
'amiibofindr/static/app/global.js',
'amiibofindr/static/app/money.js'
])
.pipe(concat('app.js'))
.pipe(gulp.dest('amiibofindr/static/dist'));