lingo: accept french amount format (#35052)
This commit is contained in:
parent
73a7643788
commit
ff6878c39d
|
@ -26,7 +26,7 @@ from django.core.urlresolvers import reverse
|
|||
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseBadRequest
|
||||
from django.http import HttpResponseForbidden, Http404, JsonResponse
|
||||
from django.template.response import TemplateResponse
|
||||
from django.utils import timezone, dateparse
|
||||
from django.utils import timezone, dateparse, six
|
||||
from django.utils.encoding import force_text
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.views.generic import View, DetailView, ListView, TemplateView
|
||||
|
@ -72,6 +72,14 @@ def lingo_check_request_signature(request):
|
|||
return check_request_signature(request, keys=keys)
|
||||
|
||||
|
||||
class LocaleDecimal(Decimal):
|
||||
# accept , instead of . for French users comfort
|
||||
def __new__(cls, value="0", *args, **kwargs):
|
||||
if isinstance(value, six.string_types) and settings.LANGUAGE_CODE.startswith('fr-'):
|
||||
value = value.replace(',', '.')
|
||||
return super(LocaleDecimal, cls).__new__(cls, value, *args, **kwargs)
|
||||
|
||||
|
||||
class RegiesApiView(ListView):
|
||||
model = Regie
|
||||
|
||||
|
@ -94,9 +102,9 @@ class AddBasketItemApiView(View):
|
|||
|
||||
def get_amount(self, amount):
|
||||
if isinstance(amount, list):
|
||||
d = Decimal(sum([Decimal(a) for a in amount]))
|
||||
d = Decimal(sum([LocaleDecimal(a) for a in amount]))
|
||||
else:
|
||||
d = Decimal(amount)
|
||||
d = LocaleDecimal(amount)
|
||||
return d.quantize(Decimal('0.01'), ROUND_HALF_UP)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
|
@ -111,13 +119,22 @@ class AddBasketItemApiView(View):
|
|||
raise Exception('missing amount parameter')
|
||||
|
||||
item = BasketItem(amount=0)
|
||||
item.amount = self.get_amount(request.GET.getlist('amount'))
|
||||
try:
|
||||
item.amount = self.get_amount(request.GET.getlist('amount'))
|
||||
except ArithmeticError:
|
||||
return HttpResponseBadRequest('invalid value for "amount" in query string')
|
||||
|
||||
if request_body.get('amount'):
|
||||
item.amount += self.get_amount(request_body['amount'])
|
||||
try:
|
||||
item.amount += self.get_amount(request_body['amount'])
|
||||
except ArithmeticError:
|
||||
return HttpResponseBadRequest('invalid value for "amount" in payload')
|
||||
|
||||
if extra.get('amount'):
|
||||
item.amount += self.get_amount(extra['amount'])
|
||||
try:
|
||||
item.amount += self.get_amount(extra['amount'])
|
||||
except ArithmeticError:
|
||||
return HttpResponseBadRequest('invalid value for "amount" in extra payload')
|
||||
|
||||
if 'extra' in request_body:
|
||||
item.request_data = request_body.get('extra')
|
||||
|
@ -234,11 +251,11 @@ class ValidateTransactionApiView(View):
|
|||
raise Http404
|
||||
|
||||
payment = get_eopayment_object(request, transaction.regie)
|
||||
amount = request.GET['amount']
|
||||
amount = LocaleDecimal(request.GET['amount'])
|
||||
|
||||
logger.info(u'validating amount %s for transaction %s', amount, smart_text(transaction.id))
|
||||
try:
|
||||
result = payment.backend.validate(Decimal(amount), transaction.bank_data)
|
||||
result = payment.backend.validate(amount, transaction.bank_data)
|
||||
except eopayment.ResponseError as e:
|
||||
logger.error(u'failed in validation operation: %s', e)
|
||||
response = HttpResponse(content_type='application/json')
|
||||
|
@ -247,7 +264,7 @@ class ValidateTransactionApiView(View):
|
|||
|
||||
logger.info(u'bank validation result: %r', result)
|
||||
operation = TransactionOperation(transaction=transaction,
|
||||
kind='validation', amount=Decimal(amount), bank_result=result)
|
||||
kind='validation', amount=amount, bank_result=result)
|
||||
operation.save()
|
||||
|
||||
response = HttpResponse(content_type='application/json')
|
||||
|
@ -275,11 +292,11 @@ class CancelTransactionApiView(View):
|
|||
raise Http404
|
||||
|
||||
payment = get_eopayment_object(request, transaction.regie)
|
||||
amount = request.GET['amount']
|
||||
amount = LocaleDecimal(request.GET['amount'])
|
||||
|
||||
logger.info(u'cancelling amount %s for transaction %s', amount, smart_text(transaction.id))
|
||||
try:
|
||||
result = payment.backend.cancel(Decimal(amount), transaction.bank_data)
|
||||
result = payment.backend.cancel(amount, transaction.bank_data)
|
||||
except eopayment.ResponseError as e:
|
||||
logger.error(u'failed in cancel operation: %s', e)
|
||||
response = HttpResponse(content_type='application/json')
|
||||
|
@ -288,7 +305,7 @@ class CancelTransactionApiView(View):
|
|||
|
||||
logger.info(u'bank cancellation result: %r', result)
|
||||
operation = TransactionOperation(transaction=transaction,
|
||||
kind='cancellation', amount=Decimal(amount), bank_result=result)
|
||||
kind='cancellation', amount=amount, bank_result=result)
|
||||
operation.save()
|
||||
|
||||
response = HttpResponse(content_type='application/json')
|
||||
|
@ -710,11 +727,11 @@ class SelfInvoiceView(View):
|
|||
except SelfDeclaredInvoicePayment.DoesNotExist:
|
||||
raise Http404()
|
||||
invoice_id = request.GET.get('invoice-number', '')
|
||||
invoice_amount = request.GET.get('invoice-amount', '').replace(',', '.')
|
||||
invoice_amount = request.GET.get('invoice-amount', '')
|
||||
msg = None
|
||||
url = None
|
||||
try:
|
||||
invoice_amount = Decimal(invoice_amount)
|
||||
invoice_amount = LocaleDecimal(invoice_amount)
|
||||
except ArithmeticError:
|
||||
invoice_amount = '-'
|
||||
msg = _('Sorry, the provided amount is invalid.')
|
||||
|
|
|
@ -12,6 +12,7 @@ from django.contrib.auth.models import User
|
|||
from django.core.urlresolvers import reverse
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
from django.conf import settings
|
||||
from django.test import override_settings
|
||||
from django.utils import timezone
|
||||
from django.utils.six.moves.urllib import parse as urlparse
|
||||
from django.contrib.messages.storage.session import SessionStorage
|
||||
|
@ -238,6 +239,31 @@ def test_add_amount_to_basket(app, key, regie, user):
|
|||
assert json.loads(resp.content)['result'] == 'success'
|
||||
assert BasketItem.objects.filter(amount=Decimal('81.22')).exists()
|
||||
|
||||
# accept french notation if settings.LANGUAGE_CODE is 'fr-*'
|
||||
url = '%s?amount=10,00&email=%s&orig=wcs' % (reverse('api-add-basket-item'), user_email)
|
||||
url = sign_url(url, key)
|
||||
resp = app.post_json(url, params=data, status=400)
|
||||
assert 'invalid value for "amount" in query string' in resp.content
|
||||
data['amount'] = '1,10'
|
||||
url = '%s?amount=10.00&email=%s&orig=wcs' % (reverse('api-add-basket-item'), user_email)
|
||||
url = sign_url(url, key)
|
||||
resp = app.post_json(url, params=data, status=400)
|
||||
assert 'invalid value for "amount" in payload' in resp.content
|
||||
data['amount'] = '1.10'
|
||||
data['extra'] = {'amount': '0,01'}
|
||||
resp = app.post_json(url, params=data, status=400)
|
||||
assert 'invalid value for "amount" in extra payload' in resp.content
|
||||
|
||||
data['amount'] = '1,10'
|
||||
data['extra'] = {'amount': '0,01'}
|
||||
url = '%s?amount=10,00&email=%s&orig=wcs' % (reverse('api-add-basket-item'), user_email)
|
||||
url = sign_url(url, key)
|
||||
with override_settings(LANGUAGE_CODE='fr-be'):
|
||||
resp = app.post_json(url, params=data, status=200)
|
||||
assert resp.status_code == 200
|
||||
assert json.loads(resp.content)['result'] == 'success'
|
||||
assert BasketItem.objects.filter(amount=Decimal('11.11')).exists()
|
||||
|
||||
other_regie.is_default = True
|
||||
other_regie.save()
|
||||
data['amount'] = []
|
||||
|
@ -408,7 +434,7 @@ def test_pay_multiple_regies(app, key, regie, user):
|
|||
resp = resp.forms[0].submit()
|
||||
assert resp.location.startswith('http://dummy-payment.demo.entrouvert.com/')
|
||||
qs = urlparse.parse_qs(urlparse.urlparse(resp.location).query)
|
||||
assert qs['amount'] == ['223.35']
|
||||
assert qs['amount'] == ['234.46']
|
||||
|
||||
resp = login(app).get(page.get_online_url())
|
||||
resp = resp.forms[1].submit()
|
||||
|
|
Loading…
Reference in New Issue