Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / quotaholder_app / callpoint.py @ fe4000a3

History | View | Annotate | Download (10.4 kB)

1 1d734153 Giorgos Korfiatis
# Copyright 2012, 2013 GRNET S.A. All rights reserved.
2 3e5941c1 Giorgos Korfiatis
#
3 3e5941c1 Giorgos Korfiatis
# Redistribution and use in source and binary forms, with or
4 3e5941c1 Giorgos Korfiatis
# without modification, are permitted provided that the following
5 3e5941c1 Giorgos Korfiatis
# conditions are met:
6 3e5941c1 Giorgos Korfiatis
#
7 3e5941c1 Giorgos Korfiatis
#   1. Redistributions of source code must retain the above
8 3e5941c1 Giorgos Korfiatis
#      copyright notice, this list of conditions and the following
9 3e5941c1 Giorgos Korfiatis
#      disclaimer.
10 3e5941c1 Giorgos Korfiatis
#
11 3e5941c1 Giorgos Korfiatis
#   2. Redistributions in binary form must reproduce the above
12 3e5941c1 Giorgos Korfiatis
#      copyright notice, this list of conditions and the following
13 3e5941c1 Giorgos Korfiatis
#      disclaimer in the documentation and/or other materials
14 3e5941c1 Giorgos Korfiatis
#      provided with the distribution.
15 3e5941c1 Giorgos Korfiatis
#
16 3e5941c1 Giorgos Korfiatis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 3e5941c1 Giorgos Korfiatis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 3e5941c1 Giorgos Korfiatis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 3e5941c1 Giorgos Korfiatis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 3e5941c1 Giorgos Korfiatis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 3e5941c1 Giorgos Korfiatis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 3e5941c1 Giorgos Korfiatis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 3e5941c1 Giorgos Korfiatis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 3e5941c1 Giorgos Korfiatis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 3e5941c1 Giorgos Korfiatis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 3e5941c1 Giorgos Korfiatis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 3e5941c1 Giorgos Korfiatis
# POSSIBILITY OF SUCH DAMAGE.
28 3e5941c1 Giorgos Korfiatis
#
29 3e5941c1 Giorgos Korfiatis
# The views and conclusions contained in the software and
30 3e5941c1 Giorgos Korfiatis
# documentation are those of the authors and should not be
31 3e5941c1 Giorgos Korfiatis
# interpreted as representing official policies, either expressed
32 3e5941c1 Giorgos Korfiatis
# or implied, of GRNET S.A.
33 3e5941c1 Giorgos Korfiatis
34 164e64d5 Giorgos Korfiatis
from datetime import datetime
35 5a0f9d6c Giorgos Korfiatis
from django.db.models import Q
36 ec5e00aa Giorgos Korfiatis
from astakos.quotaholder_app.exception import (
37 b0727daf Giorgos Korfiatis
    QuotaholderError,
38 79e3da8a Giorgos Korfiatis
    NoCommissionError,
39 fe4000a3 Giorgos Korfiatis
    CorruptedError,
40 79e3da8a Giorgos Korfiatis
    NoHoldingError,
41 1d734153 Giorgos Korfiatis
    DuplicateError)
42 fac1de87 Georgios D. Tsoukalas
43 ec5e00aa Giorgos Korfiatis
from astakos.quotaholder_app.commission import (
44 6c0f4562 Giorgos Korfiatis
    Import, Release, Operations, finalize, undo)
45 d03796c2 Giorgos Korfiatis
46 ea1369dc Giorgos Korfiatis
from astakos.quotaholder_app.models import (
47 164e64d5 Giorgos Korfiatis
    Holding, Commission, Provision, ProvisionLog)
48 fac1de87 Georgios D. Tsoukalas
49 e5a2e942 Georgios D. Tsoukalas
50 c3b42b86 Giorgos Korfiatis
def format_datetime(d):
51 c3b42b86 Giorgos Korfiatis
    return d.strftime('%Y-%m-%dT%H:%M:%S.%f')[:24]
52 c3b42b86 Giorgos Korfiatis
53 c3b42b86 Giorgos Korfiatis
54 5a0f9d6c Giorgos Korfiatis
def get_quota(holders=None, sources=None, resources=None, flt=None):
55 5a0f9d6c Giorgos Korfiatis
    if flt is None:
56 5a0f9d6c Giorgos Korfiatis
        flt = Q()
57 5a0f9d6c Giorgos Korfiatis
58 5a0f9d6c Giorgos Korfiatis
    holdings = Holding.objects.filter(flt)
59 fac1de87 Georgios D. Tsoukalas
60 948e15bc Giorgos Korfiatis
    if holders is not None:
61 948e15bc Giorgos Korfiatis
        holdings = holdings.filter(holder__in=holders)
62 5afce44d Giorgos Korfiatis
63 948e15bc Giorgos Korfiatis
    if sources is not None:
64 948e15bc Giorgos Korfiatis
        holdings = holdings.filter(source__in=sources)
65 dc9da5b9 Giorgos Korfiatis
66 948e15bc Giorgos Korfiatis
    if resources is not None:
67 948e15bc Giorgos Korfiatis
        holdings = holdings.filter(resource__in=resources)
68 dc9da5b9 Giorgos Korfiatis
69 948e15bc Giorgos Korfiatis
    quotas = {}
70 948e15bc Giorgos Korfiatis
    for holding in holdings:
71 948e15bc Giorgos Korfiatis
        key = (holding.holder, holding.source, holding.resource)
72 68b991bc Giorgos Korfiatis
        value = (holding.limit, holding.usage_min, holding.usage_max)
73 948e15bc Giorgos Korfiatis
        quotas[key] = value
74 dc9da5b9 Giorgos Korfiatis
75 948e15bc Giorgos Korfiatis
    return quotas
76 dc9da5b9 Giorgos Korfiatis
77 dc9da5b9 Giorgos Korfiatis
78 44d950c6 Giorgos Korfiatis
def delete_quota(keys):
79 44d950c6 Giorgos Korfiatis
    for holder, source, resource in keys:
80 44d950c6 Giorgos Korfiatis
        Holding.objects.filter(holder=holder,
81 44d950c6 Giorgos Korfiatis
                               source=source,
82 44d950c6 Giorgos Korfiatis
                               resource=resource).delete()
83 44d950c6 Giorgos Korfiatis
84 44d950c6 Giorgos Korfiatis
85 548938f6 Giorgos Korfiatis
def _get_holdings_for_update(holding_keys, resource=None, delete=False):
86 548938f6 Giorgos Korfiatis
    flt = Q(resource=resource) if resource is not None else Q()
87 f7b7da5d Giorgos Korfiatis
    holders = set(holder for (holder, source, resource) in holding_keys)
88 548938f6 Giorgos Korfiatis
    objs = Holding.objects.filter(flt, holder__in=holders).order_by('pk')
89 20c6de35 Giorgos Korfiatis
    hs = objs.select_for_update()
90 f7b7da5d Giorgos Korfiatis
91 20c6de35 Giorgos Korfiatis
    keys = set(holding_keys)
92 948e15bc Giorgos Korfiatis
    holdings = {}
93 20c6de35 Giorgos Korfiatis
    put_back = []
94 f7b7da5d Giorgos Korfiatis
    for h in hs:
95 f7b7da5d Giorgos Korfiatis
        key = h.holder, h.source, h.resource
96 20c6de35 Giorgos Korfiatis
        if key in keys:
97 20c6de35 Giorgos Korfiatis
            holdings[key] = h
98 20c6de35 Giorgos Korfiatis
        else:
99 20c6de35 Giorgos Korfiatis
            put_back.append(h)
100 20c6de35 Giorgos Korfiatis
101 20c6de35 Giorgos Korfiatis
    if delete:
102 20c6de35 Giorgos Korfiatis
        objs.delete()
103 20c6de35 Giorgos Korfiatis
        Holding.objects.bulk_create(put_back)
104 948e15bc Giorgos Korfiatis
    return holdings
105 ae16bcad Giorgos Korfiatis
106 ae16bcad Giorgos Korfiatis
107 948e15bc Giorgos Korfiatis
def _mkProvision(key, quantity):
108 948e15bc Giorgos Korfiatis
    holder, source, resource = key
109 948e15bc Giorgos Korfiatis
    return {'holder': holder,
110 948e15bc Giorgos Korfiatis
            'source': source,
111 948e15bc Giorgos Korfiatis
            'resource': resource,
112 948e15bc Giorgos Korfiatis
            'quantity': quantity,
113 948e15bc Giorgos Korfiatis
            }
114 948e15bc Giorgos Korfiatis
115 948e15bc Giorgos Korfiatis
116 548938f6 Giorgos Korfiatis
def set_quota(quotas, resource=None):
117 948e15bc Giorgos Korfiatis
    holding_keys = [key for (key, limit) in quotas]
118 548938f6 Giorgos Korfiatis
    holdings = _get_holdings_for_update(
119 548938f6 Giorgos Korfiatis
        holding_keys, resource=resource, delete=True)
120 948e15bc Giorgos Korfiatis
121 20c6de35 Giorgos Korfiatis
    new_holdings = {}
122 948e15bc Giorgos Korfiatis
    for key, limit in quotas:
123 548938f6 Giorgos Korfiatis
        holder, source, res = key
124 548938f6 Giorgos Korfiatis
        if resource is not None and resource != res:
125 548938f6 Giorgos Korfiatis
            continue
126 20c6de35 Giorgos Korfiatis
        h = Holding(holder=holder,
127 20c6de35 Giorgos Korfiatis
                    source=source,
128 548938f6 Giorgos Korfiatis
                    resource=res,
129 20c6de35 Giorgos Korfiatis
                    limit=limit)
130 948e15bc Giorgos Korfiatis
        try:
131 20c6de35 Giorgos Korfiatis
            h_old = holdings[key]
132 20c6de35 Giorgos Korfiatis
            h.usage_min = h_old.usage_min
133 20c6de35 Giorgos Korfiatis
            h.usage_max = h_old.usage_max
134 28330325 Giorgos Korfiatis
            h.id = h_old.id
135 948e15bc Giorgos Korfiatis
        except KeyError:
136 20c6de35 Giorgos Korfiatis
            pass
137 20c6de35 Giorgos Korfiatis
        new_holdings[key] = h
138 20c6de35 Giorgos Korfiatis
139 20c6de35 Giorgos Korfiatis
    Holding.objects.bulk_create(new_holdings.values())
140 ae16bcad Giorgos Korfiatis
141 9747707e Giorgos Korfiatis
142 643b3d82 Giorgos Korfiatis
def issue_commission(clientkey, provisions, name="", force=False):
143 948e15bc Giorgos Korfiatis
    operations = Operations()
144 948e15bc Giorgos Korfiatis
    provisions_to_create = []
145 79e3da8a Giorgos Korfiatis
146 948e15bc Giorgos Korfiatis
    keys = [key for (key, value) in provisions]
147 948e15bc Giorgos Korfiatis
    holdings = _get_holdings_for_update(keys)
148 948e15bc Giorgos Korfiatis
    try:
149 948e15bc Giorgos Korfiatis
        checked = []
150 948e15bc Giorgos Korfiatis
        for key, quantity in provisions:
151 948e15bc Giorgos Korfiatis
            if key in checked:
152 948e15bc Giorgos Korfiatis
                m = "Duplicate provision for %s" % str(key)
153 948e15bc Giorgos Korfiatis
                provision = _mkProvision(key, quantity)
154 948e15bc Giorgos Korfiatis
                raise DuplicateError(m,
155 948e15bc Giorgos Korfiatis
                                     provision=provision)
156 948e15bc Giorgos Korfiatis
            checked.append(key)
157 e5a2e942 Georgios D. Tsoukalas
158 948e15bc Giorgos Korfiatis
            # Target
159 948e15bc Giorgos Korfiatis
            try:
160 948e15bc Giorgos Korfiatis
                th = holdings[key]
161 948e15bc Giorgos Korfiatis
            except KeyError:
162 948e15bc Giorgos Korfiatis
                m = ("There is no such holding %s" % str(key))
163 948e15bc Giorgos Korfiatis
                provision = _mkProvision(key, quantity)
164 948e15bc Giorgos Korfiatis
                raise NoHoldingError(m,
165 948e15bc Giorgos Korfiatis
                                     provision=provision)
166 948e15bc Giorgos Korfiatis
167 948e15bc Giorgos Korfiatis
            if quantity >= 0:
168 948e15bc Giorgos Korfiatis
                operations.prepare(Import, th, quantity, force)
169 948e15bc Giorgos Korfiatis
170 948e15bc Giorgos Korfiatis
            else:  # release
171 948e15bc Giorgos Korfiatis
                abs_quantity = -quantity
172 01b8fb9a Giorgos Korfiatis
                operations.prepare(Release, th, abs_quantity, False)
173 948e15bc Giorgos Korfiatis
174 948e15bc Giorgos Korfiatis
            holdings[key] = th
175 948e15bc Giorgos Korfiatis
            provisions_to_create.append((key, quantity))
176 948e15bc Giorgos Korfiatis
177 948e15bc Giorgos Korfiatis
    except QuotaholderError:
178 948e15bc Giorgos Korfiatis
        operations.revert()
179 948e15bc Giorgos Korfiatis
        raise
180 948e15bc Giorgos Korfiatis
181 3679f852 Giorgos Korfiatis
    commission = Commission.objects.create(clientkey=clientkey,
182 3679f852 Giorgos Korfiatis
                                           name=name,
183 164e64d5 Giorgos Korfiatis
                                           issue_datetime=datetime.now())
184 948e15bc Giorgos Korfiatis
    for (holder, source, resource), quantity in provisions_to_create:
185 948e15bc Giorgos Korfiatis
        Provision.objects.create(serial=commission,
186 948e15bc Giorgos Korfiatis
                                 holder=holder,
187 948e15bc Giorgos Korfiatis
                                 source=source,
188 948e15bc Giorgos Korfiatis
                                 resource=resource,
189 948e15bc Giorgos Korfiatis
                                 quantity=quantity)
190 948e15bc Giorgos Korfiatis
191 948e15bc Giorgos Korfiatis
    return commission.serial
192 948e15bc Giorgos Korfiatis
193 948e15bc Giorgos Korfiatis
194 164e64d5 Giorgos Korfiatis
def _log_provision(commission, provision, holding, log_datetime, reason):
195 948e15bc Giorgos Korfiatis
196 948e15bc Giorgos Korfiatis
    kwargs = {
197 948e15bc Giorgos Korfiatis
        'serial':              commission.serial,
198 948e15bc Giorgos Korfiatis
        'name':                commission.name,
199 948e15bc Giorgos Korfiatis
        'holder':              holding.holder,
200 948e15bc Giorgos Korfiatis
        'source':              holding.source,
201 948e15bc Giorgos Korfiatis
        'resource':            holding.resource,
202 948e15bc Giorgos Korfiatis
        'limit':               holding.limit,
203 68b991bc Giorgos Korfiatis
        'usage_min':           holding.usage_min,
204 68b991bc Giorgos Korfiatis
        'usage_max':           holding.usage_max,
205 948e15bc Giorgos Korfiatis
        'delta_quantity':      provision.quantity,
206 c3b42b86 Giorgos Korfiatis
        'issue_time':          format_datetime(commission.issue_datetime),
207 c3b42b86 Giorgos Korfiatis
        'log_time':            format_datetime(log_datetime),
208 948e15bc Giorgos Korfiatis
        'reason':              reason,
209 948e15bc Giorgos Korfiatis
    }
210 948e15bc Giorgos Korfiatis
211 948e15bc Giorgos Korfiatis
    ProvisionLog.objects.create(**kwargs)
212 948e15bc Giorgos Korfiatis
213 948e15bc Giorgos Korfiatis
214 948e15bc Giorgos Korfiatis
def _get_commissions_for_update(clientkey, serials):
215 948e15bc Giorgos Korfiatis
    cs = Commission.objects.filter(
216 948e15bc Giorgos Korfiatis
        clientkey=clientkey, serial__in=serials).select_for_update()
217 948e15bc Giorgos Korfiatis
218 948e15bc Giorgos Korfiatis
    commissions = {}
219 948e15bc Giorgos Korfiatis
    for c in cs:
220 948e15bc Giorgos Korfiatis
        commissions[c.serial] = c
221 948e15bc Giorgos Korfiatis
    return commissions
222 948e15bc Giorgos Korfiatis
223 948e15bc Giorgos Korfiatis
224 948e15bc Giorgos Korfiatis
def _partition_by(f, l):
225 948e15bc Giorgos Korfiatis
    d = {}
226 948e15bc Giorgos Korfiatis
    for x in l:
227 948e15bc Giorgos Korfiatis
        group = f(x)
228 948e15bc Giorgos Korfiatis
        group_l = d.get(group, [])
229 948e15bc Giorgos Korfiatis
        group_l.append(x)
230 948e15bc Giorgos Korfiatis
        d[group] = group_l
231 948e15bc Giorgos Korfiatis
    return d
232 948e15bc Giorgos Korfiatis
233 948e15bc Giorgos Korfiatis
234 643b3d82 Giorgos Korfiatis
def resolve_pending_commissions(clientkey, accept_set=None, reject_set=None,
235 948e15bc Giorgos Korfiatis
                                reason=''):
236 643b3d82 Giorgos Korfiatis
    if accept_set is None:
237 643b3d82 Giorgos Korfiatis
        accept_set = []
238 643b3d82 Giorgos Korfiatis
    if reject_set is None:
239 643b3d82 Giorgos Korfiatis
        reject_set = []
240 643b3d82 Giorgos Korfiatis
241 948e15bc Giorgos Korfiatis
    actions = dict.fromkeys(accept_set, True)
242 948e15bc Giorgos Korfiatis
    conflicting = set()
243 948e15bc Giorgos Korfiatis
    for serial in reject_set:
244 948e15bc Giorgos Korfiatis
        if actions.get(serial) is True:
245 948e15bc Giorgos Korfiatis
            actions.pop(serial)
246 948e15bc Giorgos Korfiatis
            conflicting.add(serial)
247 948e15bc Giorgos Korfiatis
        else:
248 948e15bc Giorgos Korfiatis
            actions[serial] = False
249 948e15bc Giorgos Korfiatis
250 948e15bc Giorgos Korfiatis
    conflicting = list(conflicting)
251 948e15bc Giorgos Korfiatis
    serials = actions.keys()
252 948e15bc Giorgos Korfiatis
    commissions = _get_commissions_for_update(clientkey, serials)
253 948e15bc Giorgos Korfiatis
    ps = Provision.objects.filter(serial__in=serials).select_for_update()
254 948e15bc Giorgos Korfiatis
    holding_keys = sorted(p.holding_key() for p in ps)
255 948e15bc Giorgos Korfiatis
    holdings = _get_holdings_for_update(holding_keys)
256 948e15bc Giorgos Korfiatis
    provisions = _partition_by(lambda p: p.serial_id, ps)
257 948e15bc Giorgos Korfiatis
258 164e64d5 Giorgos Korfiatis
    log_datetime = datetime.now()
259 948e15bc Giorgos Korfiatis
260 948e15bc Giorgos Korfiatis
    accepted, rejected, notFound = [], [], []
261 948e15bc Giorgos Korfiatis
    for serial, accept in actions.iteritems():
262 948e15bc Giorgos Korfiatis
        commission = commissions.get(serial)
263 948e15bc Giorgos Korfiatis
        if commission is None:
264 948e15bc Giorgos Korfiatis
            notFound.append(serial)
265 948e15bc Giorgos Korfiatis
            continue
266 948e15bc Giorgos Korfiatis
267 948e15bc Giorgos Korfiatis
        accepted.append(serial) if accept else rejected.append(serial)
268 948e15bc Giorgos Korfiatis
269 7585a768 Giorgos Korfiatis
        ps = provisions.get(serial, [])
270 948e15bc Giorgos Korfiatis
        for pv in ps:
271 948e15bc Giorgos Korfiatis
            key = pv.holding_key()
272 948e15bc Giorgos Korfiatis
            h = holdings.get(key)
273 948e15bc Giorgos Korfiatis
            if h is None:
274 948e15bc Giorgos Korfiatis
                raise CorruptedError("Corrupted provision")
275 948e15bc Giorgos Korfiatis
276 948e15bc Giorgos Korfiatis
            quantity = pv.quantity
277 948e15bc Giorgos Korfiatis
            action = finalize if accept else undo
278 948e15bc Giorgos Korfiatis
            if quantity >= 0:
279 948e15bc Giorgos Korfiatis
                action(Import, h, quantity)
280 948e15bc Giorgos Korfiatis
            else:  # release
281 948e15bc Giorgos Korfiatis
                action(Release, h, -quantity)
282 948e15bc Giorgos Korfiatis
283 948e15bc Giorgos Korfiatis
            prefix = 'ACCEPT:' if accept else 'REJECT:'
284 948e15bc Giorgos Korfiatis
            comm_reason = prefix + reason[-121:]
285 164e64d5 Giorgos Korfiatis
            _log_provision(commission, pv, h, log_datetime, comm_reason)
286 948e15bc Giorgos Korfiatis
            pv.delete()
287 948e15bc Giorgos Korfiatis
        commission.delete()
288 948e15bc Giorgos Korfiatis
    return accepted, rejected, notFound, conflicting
289 948e15bc Giorgos Korfiatis
290 948e15bc Giorgos Korfiatis
291 948e15bc Giorgos Korfiatis
def resolve_pending_commission(clientkey, serial, accept=True):
292 948e15bc Giorgos Korfiatis
    if accept:
293 948e15bc Giorgos Korfiatis
        ok, notOk, notF, confl = resolve_pending_commissions(
294 948e15bc Giorgos Korfiatis
            clientkey=clientkey, accept_set=[serial])
295 948e15bc Giorgos Korfiatis
    else:
296 948e15bc Giorgos Korfiatis
        notOk, ok, notF, confl = resolve_pending_commissions(
297 948e15bc Giorgos Korfiatis
            clientkey=clientkey, reject_set=[serial])
298 948e15bc Giorgos Korfiatis
299 948e15bc Giorgos Korfiatis
    assert notOk == confl == []
300 948e15bc Giorgos Korfiatis
    assert ok + notF == [serial]
301 948e15bc Giorgos Korfiatis
    return bool(ok)
302 948e15bc Giorgos Korfiatis
303 948e15bc Giorgos Korfiatis
304 643b3d82 Giorgos Korfiatis
def get_pending_commissions(clientkey):
305 948e15bc Giorgos Korfiatis
    pending = Commission.objects.filter(clientkey=clientkey)
306 948e15bc Giorgos Korfiatis
    pending_list = pending.values_list('serial', flat=True)
307 948e15bc Giorgos Korfiatis
    return list(pending_list)
308 948e15bc Giorgos Korfiatis
309 948e15bc Giorgos Korfiatis
310 643b3d82 Giorgos Korfiatis
def get_commission(clientkey, serial):
311 948e15bc Giorgos Korfiatis
    try:
312 948e15bc Giorgos Korfiatis
        commission = Commission.objects.get(clientkey=clientkey,
313 948e15bc Giorgos Korfiatis
                                            serial=serial)
314 948e15bc Giorgos Korfiatis
    except Commission.DoesNotExist:
315 948e15bc Giorgos Korfiatis
        raise NoCommissionError(serial)
316 948e15bc Giorgos Korfiatis
317 a4451f59 Giorgos Korfiatis
    objs = Provision.objects
318 948e15bc Giorgos Korfiatis
    provisions = objs.filter(serial=commission)
319 948e15bc Giorgos Korfiatis
320 948e15bc Giorgos Korfiatis
    ps = [p.todict() for p in provisions]
321 948e15bc Giorgos Korfiatis
322 948e15bc Giorgos Korfiatis
    response = {'serial':     serial,
323 948e15bc Giorgos Korfiatis
                'provisions': ps,
324 164e64d5 Giorgos Korfiatis
                'issue_time': commission.issue_datetime,
325 3a1bed03 Giorgos Korfiatis
                'name':       commission.name,
326 948e15bc Giorgos Korfiatis
                }
327 948e15bc Giorgos Korfiatis
    return response