Projet

Général

Profil

auquo-payment-cancel.diff

Thomas Noël, 28 février 2012 00:40

Télécharger (9,43 ko)

Voir les différences:


  

payments.py (copie de travail)
6 6

  
7 7
from decimal import Decimal
8 8

  
9
from quixote import redirect, get_request, get_session
9
from quixote import redirect, get_publisher, get_request, get_session
10 10
from quixote.directory import Directory
11 11

  
12 12
if not set:
......
47 47

  
48 48
class Invoice(StorableObject):
49 49
    _names = 'invoices'
50
    _hashed_indexes = ['user_id', 'regie_id']
50
    _hashed_indexes = ['user_id', 'user_hash', 'regie_id']
51 51

  
52 52
    user_id = None
53
    user_hash = None
53 54
    regie_id = None
54 55
    formdef_id = None
55 56
    formdata_id = None
......
59 60
    date = None
60 61
    paid = False
61 62
    paid_date = None
63
    canceled = False
64
    canceled_date = None
65
    canceled_reason = None
62 66
    next_status = None
63 67

  
64 68
    def __init__(self, id=None, regie_id=None, formdef_id=None):
......
90 94
            return False
91 95
    check_crc = classmethod(check_crc)
92 96

  
97
    def cancel(self, reason=None):
98
        self.canceled = True
99
        self.canceled_date = dt.now()
100
        if reason:
101
            self.canceled_reason = reason
102
        self.store()
93 103

  
104

  
105
INVOICE_EVO_VIEW = {
106
    'create': N_('Create Invoice <a href="%(url)s">%(id)s</a>: %(subject)s - %(amount)s &euro;'),
107
    'pay': N_('Invoice <a href="%(url)s">%(id)s</a> is paid'),
108
    'cancel': N_('Cancel Invoice <a href="%(url)s">%(id)s</a>'),
109
}
110

  
111
class InvoiceEvolutionPart:
112
    action = None
113
    id = None
114
    subject = None
115
    amount = None
116

  
117
    def __init__(self, action, invoice):
118
        self.action = action
119
        self.id = invoice.id
120
        self.subject = invoice.subject
121
        self.amount = invoice.amount
122

  
123
    def view(self):
124
        vars = {
125
            'url': '%s/invoices/%s' % (get_publisher().get_frontoffice_url(), self.id),
126
            'id': self.id,
127
            'subject': self.subject,
128
            'amount': self.amount,
129
        }
130
        return htmltext('<p>' + _(INVOICE_EVO_VIEW[self.action]) % vars + '</p>')
131

  
132

  
94 133
class Transaction(StorableObject):
95 134
    _names = 'transactions'
96 135
    _hashed_indexes = ['invoice_ids']
......
168 207

  
169 208
    def perform(self, formdata):
170 209
        invoice = Invoice(regie_id=self.regie_id, formdef_id=formdata.formdef.id)
171
        invoice.user_id = get_request().user.id  # FIXME: handle user_hash
210
        invoice.user_id = formdata.user_id
211
        invoice.user_hash = formdata.user_hash
172 212
        invoice.formdata_id = formdata.id
173 213
        invoice.next_status = self.next_status
174 214
        if self.subject:
......
181 221
        invoice.amount = self.calculate_amount(formdata)
182 222
        invoice.date = dt.now()
183 223
        invoice.store()
184
        # FIXME: add a message in formdata.evolution
185

  
224
        # add a message in formdata.evolution
225
        evo = Evolution()
226
        evo.time = time.localtime()
227
        evo.status = formdata.status
228
        evo.add_part(InvoiceEvolutionPart('create', invoice))
229
        if not formdata.evolution:
230
            formdata.evolution = []
231
        formdata.evolution.append(evo)
232
        formdata.store()
233
        # redirect the user to "my invoices"
186 234
        return get_publisher().get_frontoffice_url() + '/myspace/invoices/'
187 235

  
188 236
register_item_class(PaymentWorkflowStatusItem)
189 237

  
238
class PaymentCancelWorkflowStatusItem(WorkflowStatusItem):
239
    description = N_('Payment Cancel')
240
    key = 'payment-cancel'
241
    endpoint = False
242

  
243
    reason = None
244
    regie_id = None
245

  
246
    def render_as_line(self):
247
        if self.regie_id:
248
            if self.regie_id == '_all':
249
                return _('Cancel all Payments')
250
            else:
251
                return _('Cancel Payments for %s' % Regie.get(self.regie_id).label)
252
        else:
253
            return _('Cancel Payments (non completed)')
254

  
255
    def get_parameters(self):
256
        return ('reason', 'regie_id')
257

  
258
    def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
259
        if 'reason' in parameters:
260
            form.add(StringWidget, '%sreason' % prefix, title=_('Reason'),
261
                     value=self.reason, size=40)
262
        if 'regie_id' in parameters:
263
            form.add(SingleSelectWidget, '%sregie_id' % prefix,
264
                title=_('Regie'), value=self.regie_id,
265
                options = [(None, '---'), ('_all', _('All Regies'))] + \
266
                            [(x.id, x.label) for x in Regie.select()])
267

  
268
    def perform(self, formdata):
269
        invoices_id = []
270
        # get all invoices for the formdata and the selected regie
271
        for evo in [evo for evo in formdata.evolution if evo.parts]:
272
            for part in [part for part in evo.parts if isinstance(part, InvoiceEvolutionPart)]:
273
                if part.action == 'create':
274
                    invoices_id.append(part.id)
275
                elif part.id in invoices_id:
276
                    invoices_id.remove(part.id)
277
        invoices = [Invoice.get(id) for id in invoices_id]
278
        # select invoices for the selected regie (if not "all regies")
279
        if self.regie_id != '_all':
280
            invoices = [i for i in invoices if i.regie_id == self.regie_id]
281
        # security filter: check user 
282
        invoices = [i for i in invoices if (i.user_id == formdata.user_id) \
283
                or (i.user_hash == formdata.user_hash)]
284
        # security filter: check formdata & formdef
285
        invoices = [i for i in invoices if (i.formdata_id == formdata.id) \
286
                and (i.formdef_id == formdata.formdef.id)]
287
        evo = Evolution()
288
        evo.time = time.localtime()
289
        for invoice in invoices:
290
            if not (invoice.paid or invoice.canceled):
291
                invoice.cancel(self.reason)
292
                evo.add_part(InvoiceEvolutionPart('cancel', invoice))
293
        if not formdata.evolution:
294
            formdata.evolution = []
295
        formdata.evolution.append(evo)
296
        formdata.store()
297
        return get_publisher().get_frontoffice_url() + '/myspace/invoices/'
298

  
299
register_item_class(PaymentCancelWorkflowStatusItem)
300

  
301

  
190 302
def request_payment(invoice_ids, url, add_regie=True):
191 303
    for invoice_id in invoice_ids:
192 304
        if not Invoice.check_crc(invoice_id):
193 305
            raise KeyError()
194 306
    invoices = [ Invoice.get(invoice_id) for invoice_id in invoice_ids ]
195
    invoices = filter(lambda x: not x.paid, invoices)
307
    invoices = [ i for i in invoices if not (i.paid or i.canceled) ]
196 308
    regie_ids = set([invoice.regie_id for invoice in invoices])
197
    # Do not apply if more than one regie is used or no invoice is not paid
309
    # Do not apply if more than one regie is used or no invoice is not paid or canceled
198 310
    if len(invoices) == 0 or len(regie_ids) != 1:
199 311
        url = get_publisher().get_frontoffice_url()
200 312
        if get_session().user:
payments_ui.ptl (copie de travail)
39 39
        '<div class="details">'
40 40
        htmltext(invoice.details)
41 41
        '</div>'
42
    if invoice.canceled:
43
        '<p class="canceled">'
44
        '%s' % _('canceled on %s') % misc.localstrftime(invoice.canceled_date)
45
        if invoice.canceled_reason:
46
            ' (%s)' % invoice.canceled_reason
47
        '</p>'
42 48
    if invoice.paid:
43 49
        '<p class="paid">%s</p>' % _('paid on %s') % misc.localstrftime(invoice.paid_date)
44 50
    '</div>'
......
81 87
            except KeyError:
82 88
                raise errors.TraversalError()
83 89
            invoice_as_html(invoice)
84
            if not invoice.paid:
90
            if not (invoice.paid or invoice.canceled):
85 91
                regies_id.add(invoice.regie_id)
86 92

  
87 93
        if len(regies_id) == 1:
myspace.ptl (copie de travail)
35 35
        return Directory._q_traverse(self, path)
36 36

  
37 37
    def _q_index [html] (self):
38
        user = get_request().user
39
        if not user or user.anonymous:
40
            raise errors.AccessUnauthorizedError()
41

  
38 42
        template.html_top(_('Invoices'))
39 43
        TextsDirectory.get_html_text('aq-myspace-invoice')
40 44

  
41 45
        get_session().display_message()
42 46

  
43
        invoices = Invoice.get_with_indexed_value(
44
                        str('user_id'), str(get_request().user.id))
47
        invoices = []
48
        invoices.extend(Invoice.get_with_indexed_value(
49
            str('user_id'), str(user.id)))
50
        try:
51
            invoices.extend(Invoice.get_with_indexed_value(
52
                str('user_hash'), str(user.hash)))
53
        except AttributeError:
54
            pass
45 55

  
46 56
        def cmp_invoice(a, b):
47 57
            t = cmp(a.regie_id, b.regie_id)
......
67 77
                '<ul>'
68 78

  
69 79
            '<li>'
70
            if not invoice.paid:
80
            if not (invoice.paid or invoice.canceled):
71 81
                '<input type="checkbox" name="invoice" value="%s"/>' % invoice.id
72 82
                unpaid = True
73 83
            misc.localstrftime(invoice.date)
......
77 87
            '%s' % invoice.amount
78 88
            ' &euro;'
79 89
            ' - '
80
            button = '<strong>%s</strong>' % _('Pay')
90
            button = '<span class="paybutton">%s</span>' % _('Pay')
91
            if invoice.canceled:
92
                _('canceled on %s') % misc.localstrftime(invoice.canceled_date)
93
                ' - '
94
                button = _('Details')
81 95
            if invoice.paid:
82 96
                _('paid on %s') % misc.localstrftime(invoice.paid_date)
83 97
                ' - '