views.py 9.43 KB
Newer Older
Skia's avatar
Skia committed
1
2
from collections import OrderedDict
from datetime import datetime
Skia's avatar
Skia committed
3
import pytz
Skia's avatar
Skia committed
4
5
6
import hmac
import base64
from OpenSSL import crypto
7

Skia's avatar
Skia committed
8
from django.shortcuts import render
9
10
11
from django.core.urlresolvers import reverse_lazy
from django.views.generic import TemplateView, View
from django.http import HttpResponse, HttpResponseRedirect
12
from django.core.exceptions import SuspiciousOperation
13
14
15
from django.shortcuts import render
from django.db import transaction, DataError
from django.utils.translation import ugettext as _
Skia's avatar
Skia committed
16
from django.conf import settings
17

18
from counter.models import Product, Customer, Counter, ProductType, Selling
Skia's avatar
Skia committed
19
from eboutic.models import Basket, Invoice, BasketItem, InvoiceItem
20
21
22
23

class EbouticMain(TemplateView):
    template_name = 'eboutic/eboutic_main.jinja'

Skia's avatar
Skia committed
24
25
26
27
28
29
30
31
32
33
34
    def make_basket(self, request):
        if 'basket_id' not in request.session.keys(): # Init the basket session entry
            self.basket = Basket(user=request.user)
            self.basket.save()
        else:
            self.basket = Basket.objects.filter(id=request.session['basket_id']).first()
            if self.basket is None:
                self.basket = Basket(user=request.user)
                self.basket.save()
        request.session['basket_id'] = self.basket.id
        request.session.modified = True
35
36

    def get(self, request, *args, **kwargs):
Skia's avatar
Skia committed
37
        if not request.user.is_authenticated():
Skia's avatar
Skia committed
38
39
            return HttpResponseRedirect(reverse_lazy('core:login', args=self.args, kwargs=kwargs) + "?next=" +
                    request.path)
Skia's avatar
Skia committed
40
        self.make_basket(request)
41
42
43
        return super(EbouticMain, self).get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
Skia's avatar
Skia committed
44
        if not request.user.is_authenticated():
Skia's avatar
Skia committed
45
46
            return HttpResponseRedirect(reverse_lazy('core:login', args=self.args, kwargs=kwargs) + "?next=" +
                    request.path)
Skia's avatar
Skia committed
47
        self.make_basket(request)
48
49
50
51
52
53
54
        if 'add_product' in request.POST['action']:
            self.add_product(request)
        elif 'del_product' in request.POST['action']:
            self.del_product(request)
        return self.render_to_response(self.get_context_data(**kwargs))


Skia's avatar
Skia committed
55
    def add_product(self, request):
56
        """ Add a product to the basket """
Skia's avatar
Skia committed
57
58
        try:
            p = Product.objects.filter(id=int(request.POST['product_id'])).first()
59
60
            if not p.buying_groups.exists():
                self.basket.add_product(p)
61
62
63
64
            for g in p.buying_groups.all():
                if request.user.is_in_group(g.name):
                    self.basket.add_product(p)
                    break
Skia's avatar
Skia committed
65
66
        except:
            pass
67
68
69

    def del_product(self, request):
        """ Delete a product from the basket """
Skia's avatar
Skia committed
70
71
72
73
74
        try:
            p = Product.objects.filter(id=int(request.POST['product_id'])).first()
            self.basket.del_product(p)
        except:
            pass
75
76
77

    def get_context_data(self, **kwargs):
        kwargs = super(EbouticMain, self).get_context_data(**kwargs)
Skia's avatar
Skia committed
78
        kwargs['basket'] = self.basket
Skia's avatar
Skia committed
79
        kwargs['eboutic'] = Counter.objects.filter(type="EBOUTIC").first()
80
        kwargs['categories'] = ProductType.objects.all()
81
82
83
84
85
        return kwargs

class EbouticCommand(TemplateView):
    template_name = 'eboutic/eboutic_makecommand.jinja'

Skia's avatar
Skia committed
86
    def get(self, request, *args, **kwargs):
Skia's avatar
Skia committed
87
        if not request.user.is_authenticated():
Skia's avatar
Skia committed
88
89
            return HttpResponseRedirect(reverse_lazy('core:login', args=self.args, kwargs=kwargs) + "?next=" +
                    request.path)
Skia's avatar
Skia committed
90
91
        return HttpResponseRedirect(reverse_lazy('eboutic:main', args=self.args, kwargs=kwargs))

92
    def post(self, request, *args, **kwargs):
Skia's avatar
Skia committed
93
        if not request.user.is_authenticated():
Skia's avatar
Skia committed
94
95
            return HttpResponseRedirect(reverse_lazy('core:login', args=self.args, kwargs=kwargs) + "?next=" +
                    request.path)
Skia's avatar
Skia committed
96
97
98
99
        if 'basket_id' not in request.session.keys():
            return HttpResponseRedirect(reverse_lazy('eboutic:main', args=self.args, kwargs=kwargs))
        self.basket = Basket.objects.filter(id=request.session['basket_id']).first()
        if self.basket is None:
100
            return HttpResponseRedirect(reverse_lazy('eboutic:main', args=self.args, kwargs=kwargs))
Skia's avatar
Skia committed
101
        else:
Skia's avatar
Skia committed
102
            kwargs['basket'] = self.basket
103
104
        return self.render_to_response(self.get_context_data(**kwargs))

Skia's avatar
Skia committed
105
106
107
108
109
110
111
112
    def get_context_data(self, **kwargs):
        kwargs = super(EbouticCommand, self).get_context_data(**kwargs)
        kwargs['et_request'] = OrderedDict()
        kwargs['et_request']['PBX_SITE'] = settings.SITH_EBOUTIC_PBX_SITE
        kwargs['et_request']['PBX_RANG'] = settings.SITH_EBOUTIC_PBX_RANG
        kwargs['et_request']['PBX_IDENTIFIANT'] = settings.SITH_EBOUTIC_PBX_IDENTIFIANT
        kwargs['et_request']['PBX_TOTAL'] = int(self.basket.get_total()*100)
        kwargs['et_request']['PBX_DEVISE'] = 978 # This is Euro. ET support only this value anyway
Skia's avatar
Skia committed
113
        kwargs['et_request']['PBX_CMD'] = self.basket.id
Skia's avatar
Skia committed
114
115
116
        kwargs['et_request']['PBX_PORTEUR'] = self.basket.user.email
        kwargs['et_request']['PBX_RETOUR'] = "Amount:M;BasketID:R;Auto:A;Error:E;Sig:K"
        kwargs['et_request']['PBX_HASH'] = "SHA512"
Skia's avatar
Skia committed
117
118
        kwargs['et_request']['PBX_TYPEPAIEMENT'] = "CARTE"
        kwargs['et_request']['PBX_TYPECARTE'] = "CB"
Skia's avatar
Skia committed
119
120
121
122
123
124
        kwargs['et_request']['PBX_TIME'] = str(datetime.now().replace(microsecond=0).isoformat('T'))
        kwargs['et_request']['PBX_HMAC'] = hmac.new(settings.SITH_EBOUTIC_HMAC_KEY,
                bytes("&".join(["%s=%s"%(k,v) for k,v in kwargs['et_request'].items()]), 'utf-8'),
                "sha512").hexdigest().upper()
        return kwargs

125
126
127
128
129
130
131
132
133
class EbouticPayWithSith(TemplateView):
    template_name = 'eboutic/eboutic_payment_result.jinja'

    def post(self, request, *args, **kwargs):
        try:
            with transaction.atomic():
                if 'basket_id' not in request.session.keys() or not request.user.is_authenticated():
                    return HttpResponseRedirect(reverse_lazy('eboutic:main', args=self.args, kwargs=kwargs))
                b = Basket.objects.filter(id=request.session['basket_id']).first()
134
                if b is None or b.items.filter(type_id=settings.SITH_COUNTER_PRODUCTTYPE_REFILLING).exists():
Skia's avatar
Skia committed
135
136
137
                    return HttpResponseRedirect(reverse_lazy('eboutic:main', args=self.args, kwargs=kwargs))
                c = Customer.objects.filter(user__id=b.user.id).first()
                if c is None:
138
139
140
                    return HttpResponseRedirect(reverse_lazy('eboutic:main', args=self.args, kwargs=kwargs))
                kwargs['not_enough'] = True
                if c.amount < b.get_total():
Skia's avatar
Skia committed
141
                    raise DataError(_("You do not have enough money to buy the basket"))
142
                else:
143
                    eboutic = Counter.objects.filter(type="EBOUTIC").first()
144
                    for it in b.items.all():
145
146
147
148
149
150
151
152
153
154
155
156
                        product = Product.objects.filter(id=it.product_id).first()
                        Selling(
                                label=it.product_name,
                                counter=eboutic,
                                club=product.club,
                                product=product,
                                seller=c.user,
                                customer=c,
                                unit_price=it.product_unit_price,
                                quantity=it.quantity,
                                payment_method="SITH_ACCOUNT",
                                ).save()
Skia's avatar
Skia committed
157
                    b.delete()
158
159
160
161
162
163
164
                    kwargs['not_enough'] = False
                    request.session.pop('basket_id', None)
        except DataError as e:
                kwargs['not_enough'] = True
        return self.render_to_response(self.get_context_data(**kwargs))

class EtransactionAutoAnswer(View):
Skia's avatar
Skia committed
165
166
167
168
169
170
    def get(self, request, *args, **kwargs):
        if (not 'Amount' in request.GET.keys() or
            not 'BasketID' in request.GET.keys() or
            not 'Auto' in request.GET.keys() or
            not 'Error' in request.GET.keys() or
            not 'Sig' in request.GET.keys()):
Skia's avatar
Skia committed
171
            return HttpResponse("Bad arguments", status=400)
Skia's avatar
Skia committed
172
173
174
175
176
177
178
        key = crypto.load_publickey(crypto.FILETYPE_PEM, settings.SITH_EBOUTIC_PUB_KEY)
        cert = crypto.X509()
        cert.set_pubkey(key)
        sig = base64.b64decode(request.GET['Sig'])
        try:
            crypto.verify(cert, sig, '&'.join(request.META['QUERY_STRING'].split('&')[:-1]), "sha1")
        except:
Skia's avatar
Skia committed
179
            return HttpResponse("Bad signature", status=400)
Skia's avatar
Skia committed
180
        if request.GET['Error'] == "00000":
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
            try:
                with transaction.atomic():
                    b = Basket.objects.filter(id=request.GET['BasketID']).first()
                    if b is None:
                        raise SuspiciousOperation("Basket does not exists")
                    i = Invoice()
                    i.user = b.user
                    i.payment_method = "CARD"
                    i.save()
                    for it in b.items.all():
                        InvoiceItem(invoice=i, product_id=it.product_id, product_name=it.product_name, type_id=it.type_id,
                            product_unit_price=it.product_unit_price, quantity=it.quantity).save()
                    i.validate()
                    b.delete()
            except Exception as e:
                return HttpResponse("Payment failed with error: "+repr(e), status=400)
Skia's avatar
Skia committed
197
            return HttpResponse()
Skia's avatar
Skia committed
198
        else:
199
            return HttpResponse("Payment failed with error: "+request.GET['Error'], status=400)
Skia's avatar
Skia committed
200