Statistics
| Branch: | Tag: | Revision:

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

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 daa780fa Giorgos Korfiatis
)
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 daa780fa Giorgos Korfiatis
def _merge_same_keys(provisions):
143 daa780fa Giorgos Korfiatis
    prov_dict = _partition_by(lambda t: t[0], provisions, lambda t: t[1])
144 daa780fa Giorgos Korfiatis
    tuples = []
145 daa780fa Giorgos Korfiatis
    for key, values in prov_dict.iteritems():
146 daa780fa Giorgos Korfiatis
        tuples.append((key, sum(values)))
147 daa780fa Giorgos Korfiatis
    return tuples
148 daa780fa Giorgos Korfiatis
149 daa780fa Giorgos Korfiatis
150 643b3d82 Giorgos Korfiatis
def issue_commission(clientkey, provisions, name="", force=False):
151 948e15bc Giorgos Korfiatis
    operations = Operations()
152 948e15bc Giorgos Korfiatis
    provisions_to_create = []
153 79e3da8a Giorgos Korfiatis
154 daa780fa Giorgos Korfiatis
    provisions = _merge_same_keys(provisions)
155 948e15bc Giorgos Korfiatis
    keys = [key for (key, value) in provisions]
156 948e15bc Giorgos Korfiatis
    holdings = _get_holdings_for_update(keys)
157 948e15bc Giorgos Korfiatis
    try:
158 948e15bc Giorgos Korfiatis
        for key, quantity in provisions:
159 948e15bc Giorgos Korfiatis
            # Target
160 948e15bc Giorgos Korfiatis
            try:
161 948e15bc Giorgos Korfiatis
                th = holdings[key]
162 948e15bc Giorgos Korfiatis
            except KeyError:
163 948e15bc Giorgos Korfiatis
                m = ("There is no such holding %s" % str(key))
164 948e15bc Giorgos Korfiatis
                provision = _mkProvision(key, quantity)
165 948e15bc Giorgos Korfiatis
                raise NoHoldingError(m,
166 948e15bc Giorgos Korfiatis
                                     provision=provision)
167 948e15bc Giorgos Korfiatis
168 948e15bc Giorgos Korfiatis
            if quantity >= 0:
169 948e15bc Giorgos Korfiatis
                operations.prepare(Import, th, quantity, force)
170 948e15bc Giorgos Korfiatis
171 948e15bc Giorgos Korfiatis
            else:  # release
172 948e15bc Giorgos Korfiatis
                abs_quantity = -quantity
173 01b8fb9a Giorgos Korfiatis
                operations.prepare(Release, th, abs_quantity, False)
174 948e15bc Giorgos Korfiatis
175 948e15bc Giorgos Korfiatis
            holdings[key] = th
176 948e15bc Giorgos Korfiatis
            provisions_to_create.append((key, quantity))
177 948e15bc Giorgos Korfiatis
178 948e15bc Giorgos Korfiatis
    except QuotaholderError:
179 948e15bc Giorgos Korfiatis
        operations.revert()
180 948e15bc Giorgos Korfiatis
        raise
181 948e15bc Giorgos Korfiatis
182 3679f852 Giorgos Korfiatis
    commission = Commission.objects.create(clientkey=clientkey,
183 3679f852 Giorgos Korfiatis
                                           name=name,
184 164e64d5 Giorgos Korfiatis
                                           issue_datetime=datetime.now())
185 948e15bc Giorgos Korfiatis
    for (holder, source, resource), quantity in provisions_to_create:
186 948e15bc Giorgos Korfiatis
        Provision.objects.create(serial=commission,
187 948e15bc Giorgos Korfiatis
                                 holder=holder,
188 948e15bc Giorgos Korfiatis
                                 source=source,
189 948e15bc Giorgos Korfiatis
                                 resource=resource,
190 948e15bc Giorgos Korfiatis
                                 quantity=quantity)
191 948e15bc Giorgos Korfiatis
192 948e15bc Giorgos Korfiatis
    return commission.serial
193 948e15bc Giorgos Korfiatis
194 948e15bc Giorgos Korfiatis
195 164e64d5 Giorgos Korfiatis
def _log_provision(commission, provision, holding, log_datetime, reason):
196 948e15bc Giorgos Korfiatis
197 948e15bc Giorgos Korfiatis
    kwargs = {
198 948e15bc Giorgos Korfiatis
        'serial':              commission.serial,
199 948e15bc Giorgos Korfiatis
        'name':                commission.name,
200 948e15bc Giorgos Korfiatis
        'holder':              holding.holder,
201 948e15bc Giorgos Korfiatis
        'source':              holding.source,
202 948e15bc Giorgos Korfiatis
        'resource':            holding.resource,
203 948e15bc Giorgos Korfiatis
        'limit':               holding.limit,
204 68b991bc Giorgos Korfiatis
        'usage_min':           holding.usage_min,
205 68b991bc Giorgos Korfiatis
        'usage_max':           holding.usage_max,
206 948e15bc Giorgos Korfiatis
        'delta_quantity':      provision.quantity,
207 c3b42b86 Giorgos Korfiatis
        'issue_time':          format_datetime(commission.issue_datetime),
208 c3b42b86 Giorgos Korfiatis
        'log_time':            format_datetime(log_datetime),
209 948e15bc Giorgos Korfiatis
        'reason':              reason,
210 948e15bc Giorgos Korfiatis
    }
211 948e15bc Giorgos Korfiatis
212 948e15bc Giorgos Korfiatis
    ProvisionLog.objects.create(**kwargs)
213 948e15bc Giorgos Korfiatis
214 948e15bc Giorgos Korfiatis
215 948e15bc Giorgos Korfiatis
def _get_commissions_for_update(clientkey, serials):
216 948e15bc Giorgos Korfiatis
    cs = Commission.objects.filter(
217 948e15bc Giorgos Korfiatis
        clientkey=clientkey, serial__in=serials).select_for_update()
218 948e15bc Giorgos Korfiatis
219 948e15bc Giorgos Korfiatis
    commissions = {}
220 948e15bc Giorgos Korfiatis
    for c in cs:
221 948e15bc Giorgos Korfiatis
        commissions[c.serial] = c
222 948e15bc Giorgos Korfiatis
    return commissions
223 948e15bc Giorgos Korfiatis
224 948e15bc Giorgos Korfiatis
225 daa780fa Giorgos Korfiatis
def _partition_by(f, l, convert=None):
226 daa780fa Giorgos Korfiatis
    if convert is None:
227 daa780fa Giorgos Korfiatis
        convert = lambda x: x
228 948e15bc Giorgos Korfiatis
    d = {}
229 948e15bc Giorgos Korfiatis
    for x in l:
230 948e15bc Giorgos Korfiatis
        group = f(x)
231 948e15bc Giorgos Korfiatis
        group_l = d.get(group, [])
232 daa780fa Giorgos Korfiatis
        group_l.append(convert(x))
233 948e15bc Giorgos Korfiatis
        d[group] = group_l
234 948e15bc Giorgos Korfiatis
    return d
235 948e15bc Giorgos Korfiatis
236 948e15bc Giorgos Korfiatis
237 643b3d82 Giorgos Korfiatis
def resolve_pending_commissions(clientkey, accept_set=None, reject_set=None,
238 948e15bc Giorgos Korfiatis
                                reason=''):
239 643b3d82 Giorgos Korfiatis
    if accept_set is None:
240 643b3d82 Giorgos Korfiatis
        accept_set = []
241 643b3d82 Giorgos Korfiatis
    if reject_set is None:
242 643b3d82 Giorgos Korfiatis
        reject_set = []
243 643b3d82 Giorgos Korfiatis
244 948e15bc Giorgos Korfiatis
    actions = dict.fromkeys(accept_set, True)
245 948e15bc Giorgos Korfiatis
    conflicting = set()
246 948e15bc Giorgos Korfiatis
    for serial in reject_set:
247 948e15bc Giorgos Korfiatis
        if actions.get(serial) is True:
248 948e15bc Giorgos Korfiatis
            actions.pop(serial)
249 948e15bc Giorgos Korfiatis
            conflicting.add(serial)
250 948e15bc Giorgos Korfiatis
        else:
251 948e15bc Giorgos Korfiatis
            actions[serial] = False
252 948e15bc Giorgos Korfiatis
253 948e15bc Giorgos Korfiatis
    conflicting = list(conflicting)
254 948e15bc Giorgos Korfiatis
    serials = actions.keys()
255 948e15bc Giorgos Korfiatis
    commissions = _get_commissions_for_update(clientkey, serials)
256 948e15bc Giorgos Korfiatis
    ps = Provision.objects.filter(serial__in=serials).select_for_update()
257 948e15bc Giorgos Korfiatis
    holding_keys = sorted(p.holding_key() for p in ps)
258 948e15bc Giorgos Korfiatis
    holdings = _get_holdings_for_update(holding_keys)
259 948e15bc Giorgos Korfiatis
    provisions = _partition_by(lambda p: p.serial_id, ps)
260 948e15bc Giorgos Korfiatis
261 164e64d5 Giorgos Korfiatis
    log_datetime = datetime.now()
262 948e15bc Giorgos Korfiatis
263 948e15bc Giorgos Korfiatis
    accepted, rejected, notFound = [], [], []
264 948e15bc Giorgos Korfiatis
    for serial, accept in actions.iteritems():
265 948e15bc Giorgos Korfiatis
        commission = commissions.get(serial)
266 948e15bc Giorgos Korfiatis
        if commission is None:
267 948e15bc Giorgos Korfiatis
            notFound.append(serial)
268 948e15bc Giorgos Korfiatis
            continue
269 948e15bc Giorgos Korfiatis
270 948e15bc Giorgos Korfiatis
        accepted.append(serial) if accept else rejected.append(serial)
271 948e15bc Giorgos Korfiatis
272 7585a768 Giorgos Korfiatis
        ps = provisions.get(serial, [])
273 948e15bc Giorgos Korfiatis
        for pv in ps:
274 948e15bc Giorgos Korfiatis
            key = pv.holding_key()
275 948e15bc Giorgos Korfiatis
            h = holdings.get(key)
276 948e15bc Giorgos Korfiatis
            if h is None:
277 948e15bc Giorgos Korfiatis
                raise CorruptedError("Corrupted provision")
278 948e15bc Giorgos Korfiatis
279 948e15bc Giorgos Korfiatis
            quantity = pv.quantity
280 948e15bc Giorgos Korfiatis
            action = finalize if accept else undo
281 948e15bc Giorgos Korfiatis
            if quantity >= 0:
282 948e15bc Giorgos Korfiatis
                action(Import, h, quantity)
283 948e15bc Giorgos Korfiatis
            else:  # release
284 948e15bc Giorgos Korfiatis
                action(Release, h, -quantity)
285 948e15bc Giorgos Korfiatis
286 948e15bc Giorgos Korfiatis
            prefix = 'ACCEPT:' if accept else 'REJECT:'
287 948e15bc Giorgos Korfiatis
            comm_reason = prefix + reason[-121:]
288 164e64d5 Giorgos Korfiatis
            _log_provision(commission, pv, h, log_datetime, comm_reason)
289 948e15bc Giorgos Korfiatis
            pv.delete()
290 948e15bc Giorgos Korfiatis
        commission.delete()
291 948e15bc Giorgos Korfiatis
    return accepted, rejected, notFound, conflicting
292 948e15bc Giorgos Korfiatis
293 948e15bc Giorgos Korfiatis
294 948e15bc Giorgos Korfiatis
def resolve_pending_commission(clientkey, serial, accept=True):
295 948e15bc Giorgos Korfiatis
    if accept:
296 948e15bc Giorgos Korfiatis
        ok, notOk, notF, confl = resolve_pending_commissions(
297 948e15bc Giorgos Korfiatis
            clientkey=clientkey, accept_set=[serial])
298 948e15bc Giorgos Korfiatis
    else:
299 948e15bc Giorgos Korfiatis
        notOk, ok, notF, confl = resolve_pending_commissions(
300 948e15bc Giorgos Korfiatis
            clientkey=clientkey, reject_set=[serial])
301 948e15bc Giorgos Korfiatis
302 948e15bc Giorgos Korfiatis
    assert notOk == confl == []
303 948e15bc Giorgos Korfiatis
    assert ok + notF == [serial]
304 948e15bc Giorgos Korfiatis
    return bool(ok)
305 948e15bc Giorgos Korfiatis
306 948e15bc Giorgos Korfiatis
307 643b3d82 Giorgos Korfiatis
def get_pending_commissions(clientkey):
308 948e15bc Giorgos Korfiatis
    pending = Commission.objects.filter(clientkey=clientkey)
309 948e15bc Giorgos Korfiatis
    pending_list = pending.values_list('serial', flat=True)
310 948e15bc Giorgos Korfiatis
    return list(pending_list)
311 948e15bc Giorgos Korfiatis
312 948e15bc Giorgos Korfiatis
313 643b3d82 Giorgos Korfiatis
def get_commission(clientkey, serial):
314 948e15bc Giorgos Korfiatis
    try:
315 948e15bc Giorgos Korfiatis
        commission = Commission.objects.get(clientkey=clientkey,
316 948e15bc Giorgos Korfiatis
                                            serial=serial)
317 948e15bc Giorgos Korfiatis
    except Commission.DoesNotExist:
318 948e15bc Giorgos Korfiatis
        raise NoCommissionError(serial)
319 948e15bc Giorgos Korfiatis
320 a4451f59 Giorgos Korfiatis
    objs = Provision.objects
321 948e15bc Giorgos Korfiatis
    provisions = objs.filter(serial=commission)
322 948e15bc Giorgos Korfiatis
323 948e15bc Giorgos Korfiatis
    ps = [p.todict() for p in provisions]
324 948e15bc Giorgos Korfiatis
325 948e15bc Giorgos Korfiatis
    response = {'serial':     serial,
326 948e15bc Giorgos Korfiatis
                'provisions': ps,
327 164e64d5 Giorgos Korfiatis
                'issue_time': commission.issue_datetime,
328 3a1bed03 Giorgos Korfiatis
                'name':       commission.name,
329 948e15bc Giorgos Korfiatis
                }
330 948e15bc Giorgos Korfiatis
    return response