Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / quotaholder / callpoint.py @ 8b54001e

History | View | Annotate | Download (31.3 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 b0727daf Giorgos Korfiatis
from astakos.quotaholder.exception import (
35 b0727daf Giorgos Korfiatis
    QuotaholderError,
36 b0727daf Giorgos Korfiatis
    CorruptedError, InvalidDataError,
37 1d734153 Giorgos Korfiatis
    NoQuantityError, NoCapacityError,
38 1d734153 Giorgos Korfiatis
    ExportLimitError, ImportLimitError,
39 1d734153 Giorgos Korfiatis
    DuplicateError)
40 fac1de87 Georgios D. Tsoukalas
41 b0727daf Giorgos Korfiatis
from astakos.quotaholder.utils.newname import newname
42 b0727daf Giorgos Korfiatis
from astakos.quotaholder.api import QH_PRACTICALLY_INFINITE
43 f54beeea Giorgos Korfiatis
44 2a3f6a3e Giorgos Korfiatis
from django.db.models import Q, Count
45 1d2b20aa Giorgos Korfiatis
from django.db.models import Q
46 1d2b20aa Giorgos Korfiatis
from .models import (Policy, Holding,
47 789d202d Giorgos Korfiatis
                     Commission, Provision, ProvisionLog, CallSerial,
48 789d202d Giorgos Korfiatis
                     now,
49 1d2b20aa Giorgos Korfiatis
                     db_get_holding, db_get_policy,
50 789d202d Giorgos Korfiatis
                     db_get_commission, db_filter_provision, db_get_callserial)
51 fac1de87 Georgios D. Tsoukalas
52 e5a2e942 Georgios D. Tsoukalas
53 b0727daf Giorgos Korfiatis
class QuotaholderDjangoDBCallpoint(object):
54 fac1de87 Georgios D. Tsoukalas
55 e3685916 Giorgos Korfiatis
    def get_limits(self, context=None, get_limits=()):
56 fac1de87 Georgios D. Tsoukalas
        limits = []
57 fac1de87 Georgios D. Tsoukalas
        append = limits.append
58 fac1de87 Georgios D. Tsoukalas
59 3f84d70e Christos KK Loverdos
        for policy in get_limits:
60 fac1de87 Georgios D. Tsoukalas
            try:
61 a116d82a Giorgos Korfiatis
                p = Policy.objects.get(policy=policy)
62 fac1de87 Georgios D. Tsoukalas
            except Policy.DoesNotExist:
63 fac1de87 Georgios D. Tsoukalas
                continue
64 fac1de87 Georgios D. Tsoukalas
65 a116d82a Giorgos Korfiatis
            append((policy, p.quantity, p.capacity,
66 a116d82a Giorgos Korfiatis
                    p.import_limit, p.export_limit))
67 fac1de87 Georgios D. Tsoukalas
68 fac1de87 Georgios D. Tsoukalas
        return limits
69 fac1de87 Georgios D. Tsoukalas
70 e3685916 Giorgos Korfiatis
    def set_limits(self, context=None, set_limits=()):
71 fac1de87 Georgios D. Tsoukalas
72 e5a2e942 Georgios D. Tsoukalas
        for (policy, quantity, capacity,
73 e5a2e942 Georgios D. Tsoukalas
             import_limit, export_limit) in set_limits:
74 fac1de87 Georgios D. Tsoukalas
75 e5a2e942 Georgios D. Tsoukalas
            try:
76 e5a2e942 Georgios D. Tsoukalas
                policy = db_get_policy(policy=policy, for_update=True)
77 e5a2e942 Georgios D. Tsoukalas
            except Policy.DoesNotExist:
78 e5a2e942 Georgios D. Tsoukalas
                Policy.objects.create(policy=policy,
79 e5a2e942 Georgios D. Tsoukalas
                                      quantity=quantity,
80 e5a2e942 Georgios D. Tsoukalas
                                      capacity=capacity,
81 e5a2e942 Georgios D. Tsoukalas
                                      import_limit=import_limit,
82 e5a2e942 Georgios D. Tsoukalas
                                      export_limit=export_limit)
83 e5a2e942 Georgios D. Tsoukalas
            else:
84 e5a2e942 Georgios D. Tsoukalas
                policy.quantity = quantity
85 e5a2e942 Georgios D. Tsoukalas
                policy.capacity = capacity
86 e5a2e942 Georgios D. Tsoukalas
                policy.export_limit = export_limit
87 e5a2e942 Georgios D. Tsoukalas
                policy.import_limit = import_limit
88 e5a2e942 Georgios D. Tsoukalas
                policy.save()
89 fac1de87 Georgios D. Tsoukalas
90 fac1de87 Georgios D. Tsoukalas
        return ()
91 fac1de87 Georgios D. Tsoukalas
92 e3685916 Giorgos Korfiatis
    def get_holding(self, context=None, get_holding=()):
93 fac1de87 Georgios D. Tsoukalas
        holdings = []
94 fac1de87 Georgios D. Tsoukalas
        append = holdings.append
95 fac1de87 Georgios D. Tsoukalas
96 8b54001e Giorgos Korfiatis
        for holder, resource in get_holding:
97 fac1de87 Georgios D. Tsoukalas
            try:
98 8b54001e Giorgos Korfiatis
                h = Holding.objects.get(holder=holder, resource=resource)
99 fac1de87 Georgios D. Tsoukalas
            except Holding.DoesNotExist:
100 fac1de87 Georgios D. Tsoukalas
                continue
101 fac1de87 Georgios D. Tsoukalas
102 8b54001e Giorgos Korfiatis
            append((h.holder, h.resource, h.policy.policy,
103 b435047b root
                    h.imported, h.exported,
104 d6662f65 root
                    h.returned, h.released, h.flags))
105 fac1de87 Georgios D. Tsoukalas
106 fac1de87 Georgios D. Tsoukalas
        return holdings
107 fac1de87 Georgios D. Tsoukalas
108 e3685916 Giorgos Korfiatis
    def set_holding(self, context=None, set_holding=()):
109 fac1de87 Georgios D. Tsoukalas
        rejected = []
110 fac1de87 Georgios D. Tsoukalas
        append = rejected.append
111 fac1de87 Georgios D. Tsoukalas
112 8b54001e Giorgos Korfiatis
        for holder, resource, policy, flags in set_holding:
113 fac1de87 Georgios D. Tsoukalas
            try:
114 fac1de87 Georgios D. Tsoukalas
                p = Policy.objects.get(policy=policy)
115 fac1de87 Georgios D. Tsoukalas
            except Policy.DoesNotExist:
116 8b54001e Giorgos Korfiatis
                append((holder, resource, policy))
117 fac1de87 Georgios D. Tsoukalas
                continue
118 fac1de87 Georgios D. Tsoukalas
119 fac1de87 Georgios D. Tsoukalas
            try:
120 8b54001e Giorgos Korfiatis
                h = db_get_holding(holder=holder, resource=resource,
121 5d996aea Giorgos Korfiatis
                                   for_update=True)
122 fac1de87 Georgios D. Tsoukalas
                h.policy = p
123 fac1de87 Georgios D. Tsoukalas
                h.flags = flags
124 fac1de87 Georgios D. Tsoukalas
                h.save()
125 fac1de87 Georgios D. Tsoukalas
            except Holding.DoesNotExist:
126 8b54001e Giorgos Korfiatis
                h = Holding.objects.create(holder=holder, resource=resource,
127 e5a2e942 Georgios D. Tsoukalas
                                           policy=p, flags=flags)
128 fac1de87 Georgios D. Tsoukalas
129 eeba67ab Giorgos Korfiatis
        if rejected:
130 b0727daf Giorgos Korfiatis
            raise QuotaholderError(rejected)
131 fac1de87 Georgios D. Tsoukalas
        return rejected
132 fac1de87 Georgios D. Tsoukalas
133 1d734153 Giorgos Korfiatis
    def _init_holding(self,
134 8b54001e Giorgos Korfiatis
                      holder, resource, policy,
135 1d734153 Giorgos Korfiatis
                      imported, exported, returned, released,
136 1d734153 Giorgos Korfiatis
                      flags):
137 5b522bc3 Giorgos Korfiatis
        try:
138 8b54001e Giorgos Korfiatis
            h = db_get_holding(holder=holder, resource=resource,
139 5d996aea Giorgos Korfiatis
                               for_update=True)
140 5b522bc3 Giorgos Korfiatis
        except Holding.DoesNotExist:
141 8b54001e Giorgos Korfiatis
            h = Holding(holder=holder, resource=resource)
142 5b522bc3 Giorgos Korfiatis
143 5b522bc3 Giorgos Korfiatis
        h.policy = policy
144 5b522bc3 Giorgos Korfiatis
        h.flags = flags
145 1d734153 Giorgos Korfiatis
        h.imported = imported
146 e5a2e942 Georgios D. Tsoukalas
        h.importing = imported
147 1d734153 Giorgos Korfiatis
        h.exported = exported
148 e5a2e942 Georgios D. Tsoukalas
        h.exporting = exported
149 1d734153 Giorgos Korfiatis
        h.returned = returned
150 e5a2e942 Georgios D. Tsoukalas
        h.returning = returned
151 1d734153 Giorgos Korfiatis
        h.released = released
152 e5a2e942 Georgios D. Tsoukalas
        h.releasing = released
153 5b522bc3 Giorgos Korfiatis
        h.save()
154 5b522bc3 Giorgos Korfiatis
155 e3685916 Giorgos Korfiatis
    def init_holding(self, context=None, init_holding=()):
156 5b522bc3 Giorgos Korfiatis
        rejected = []
157 5b522bc3 Giorgos Korfiatis
        append = rejected.append
158 5b522bc3 Giorgos Korfiatis
159 a7cdc223 Giorgos Korfiatis
        for idx, sfh in enumerate(init_holding):
160 8b54001e Giorgos Korfiatis
            (holder, resource, policy,
161 5b522bc3 Giorgos Korfiatis
             imported, exported, returned, released,
162 5b522bc3 Giorgos Korfiatis
             flags) = sfh
163 5b522bc3 Giorgos Korfiatis
164 5b522bc3 Giorgos Korfiatis
            try:
165 5b522bc3 Giorgos Korfiatis
                p = Policy.objects.get(policy=policy)
166 5b522bc3 Giorgos Korfiatis
            except Policy.DoesNotExist:
167 5b522bc3 Giorgos Korfiatis
                append(idx)
168 5b522bc3 Giorgos Korfiatis
                continue
169 5b522bc3 Giorgos Korfiatis
170 8b54001e Giorgos Korfiatis
            self._init_holding(holder, resource, p,
171 e5a2e942 Georgios D. Tsoukalas
                               imported, exported,
172 e5a2e942 Georgios D. Tsoukalas
                               returned, released,
173 e5a2e942 Georgios D. Tsoukalas
                               flags)
174 eeba67ab Giorgos Korfiatis
        if rejected:
175 b0727daf Giorgos Korfiatis
            raise QuotaholderError(rejected)
176 5b522bc3 Giorgos Korfiatis
        return rejected
177 5b522bc3 Giorgos Korfiatis
178 e3685916 Giorgos Korfiatis
    def reset_holding(self, context=None, reset_holding=()):
179 4c00b904 Giorgos Korfiatis
        rejected = []
180 4c00b904 Giorgos Korfiatis
        append = rejected.append
181 4c00b904 Giorgos Korfiatis
182 4c00b904 Giorgos Korfiatis
        for idx, tpl in enumerate(reset_holding):
183 8b54001e Giorgos Korfiatis
            (holder, resource,
184 4c00b904 Giorgos Korfiatis
             imported, exported, returned, released) = tpl
185 4c00b904 Giorgos Korfiatis
186 4c00b904 Giorgos Korfiatis
            try:
187 8b54001e Giorgos Korfiatis
                h = db_get_holding(holder=holder, resource=resource,
188 5d996aea Giorgos Korfiatis
                                   for_update=True)
189 1d734153 Giorgos Korfiatis
                h.imported = imported
190 e5a2e942 Georgios D. Tsoukalas
                h.importing = imported
191 1d734153 Giorgos Korfiatis
                h.exported = exported
192 e5a2e942 Georgios D. Tsoukalas
                h.exporting = exported
193 1d734153 Giorgos Korfiatis
                h.returned = returned
194 e5a2e942 Georgios D. Tsoukalas
                h.returning = returned
195 1d734153 Giorgos Korfiatis
                h.released = released
196 e5a2e942 Georgios D. Tsoukalas
                h.releasing = released
197 4c00b904 Giorgos Korfiatis
                h.save()
198 4c00b904 Giorgos Korfiatis
            except Holding.DoesNotExist:
199 4c00b904 Giorgos Korfiatis
                append(idx)
200 4c00b904 Giorgos Korfiatis
                continue
201 4c00b904 Giorgos Korfiatis
202 eeba67ab Giorgos Korfiatis
        if rejected:
203 b0727daf Giorgos Korfiatis
            raise QuotaholderError(rejected)
204 4c00b904 Giorgos Korfiatis
        return rejected
205 4c00b904 Giorgos Korfiatis
206 8b54001e Giorgos Korfiatis
    def _check_pending(self, holder, resource):
207 8b54001e Giorgos Korfiatis
        cs = Commission.objects.filter(holder=holder)
208 cceadca8 Giorgos Korfiatis
        cs = [c for c in cs if c.provisions.filter(resource=resource)]
209 cceadca8 Giorgos Korfiatis
        as_target = [c.serial for c in cs]
210 8dc7c13b Giorgos Korfiatis
211 8b54001e Giorgos Korfiatis
        ps = Provision.objects.filter(holder=holder, resource=resource)
212 cceadca8 Giorgos Korfiatis
        as_source = [p.serial.serial for p in ps]
213 cceadca8 Giorgos Korfiatis
214 cceadca8 Giorgos Korfiatis
        return as_target + as_source
215 8dc7c13b Giorgos Korfiatis
216 8dc7c13b Giorgos Korfiatis
    def _actual_quantity(self, holding):
217 8dc7c13b Giorgos Korfiatis
        hp = holding.policy
218 8dc7c13b Giorgos Korfiatis
        return hp.quantity + (holding.imported + holding.returned -
219 8dc7c13b Giorgos Korfiatis
                              holding.exported - holding.released)
220 8dc7c13b Giorgos Korfiatis
221 e3685916 Giorgos Korfiatis
    def release_holding(self, context=None, release_holding=()):
222 8dc7c13b Giorgos Korfiatis
        rejected = []
223 8dc7c13b Giorgos Korfiatis
        append = rejected.append
224 8dc7c13b Giorgos Korfiatis
225 8b54001e Giorgos Korfiatis
        for idx, (holder, resource) in enumerate(release_holding):
226 8dc7c13b Giorgos Korfiatis
            try:
227 8b54001e Giorgos Korfiatis
                h = db_get_holding(holder=holder, resource=resource,
228 5d996aea Giorgos Korfiatis
                                   for_update=True)
229 8dc7c13b Giorgos Korfiatis
            except Holding.DoesNotExist:
230 8dc7c13b Giorgos Korfiatis
                append(idx)
231 8dc7c13b Giorgos Korfiatis
                continue
232 8dc7c13b Giorgos Korfiatis
233 8b54001e Giorgos Korfiatis
            if self._check_pending(holder, resource):
234 8dc7c13b Giorgos Korfiatis
                append(idx)
235 8dc7c13b Giorgos Korfiatis
                continue
236 8dc7c13b Giorgos Korfiatis
237 8dc7c13b Giorgos Korfiatis
            q = self._actual_quantity(h)
238 32464501 Giorgos Korfiatis
            if q > 0:
239 1d2b20aa Giorgos Korfiatis
                append(idx)
240 1d2b20aa Giorgos Korfiatis
                continue
241 32464501 Giorgos Korfiatis
242 8dc7c13b Giorgos Korfiatis
            h.delete()
243 8dc7c13b Giorgos Korfiatis
244 eeba67ab Giorgos Korfiatis
        if rejected:
245 b0727daf Giorgos Korfiatis
            raise QuotaholderError(rejected)
246 8dc7c13b Giorgos Korfiatis
        return rejected
247 8dc7c13b Giorgos Korfiatis
248 8b54001e Giorgos Korfiatis
    def list_resources(self, context=None, holder=None):
249 8b54001e Giorgos Korfiatis
        holdings = Holding.objects.filter(holder=holder)
250 fac1de87 Georgios D. Tsoukalas
        resources = [h.resource for h in holdings]
251 fac1de87 Georgios D. Tsoukalas
        return resources
252 fac1de87 Georgios D. Tsoukalas
253 e3685916 Giorgos Korfiatis
    def list_holdings(self, context=None, list_holdings=()):
254 65f214a2 Georgios D. Tsoukalas
        rejected = []
255 65f214a2 Georgios D. Tsoukalas
        reject = rejected.append
256 65f214a2 Georgios D. Tsoukalas
        holdings_list = []
257 65f214a2 Georgios D. Tsoukalas
        append = holdings_list.append
258 65f214a2 Georgios D. Tsoukalas
259 8b54001e Giorgos Korfiatis
        for holder in list_holdings:
260 8b54001e Giorgos Korfiatis
            holdings = list(Holding.objects.filter(holder=holder))
261 1d2b20aa Giorgos Korfiatis
            if not holdings:
262 8b54001e Giorgos Korfiatis
                reject(holder)
263 65f214a2 Georgios D. Tsoukalas
                continue
264 65f214a2 Georgios D. Tsoukalas
265 8b54001e Giorgos Korfiatis
            append([[holder, h.resource,
266 65f214a2 Georgios D. Tsoukalas
                     h.imported, h.exported, h.returned, h.released]
267 1d734153 Giorgos Korfiatis
                    for h in holdings])
268 65f214a2 Georgios D. Tsoukalas
269 65f214a2 Georgios D. Tsoukalas
        return holdings_list, rejected
270 65f214a2 Georgios D. Tsoukalas
271 e3685916 Giorgos Korfiatis
    def get_quota(self, context=None, get_quota=()):
272 fac1de87 Georgios D. Tsoukalas
        quotas = []
273 fac1de87 Georgios D. Tsoukalas
        append = quotas.append
274 fac1de87 Georgios D. Tsoukalas
275 8b54001e Giorgos Korfiatis
        holders = set(holder for holder, r in get_quota)
276 8b54001e Giorgos Korfiatis
        hs = Holding.objects.select_related().filter(holder__in=holders)
277 8acd9708 Giorgos Korfiatis
        holdings = {}
278 8acd9708 Giorgos Korfiatis
        for h in hs:
279 8b54001e Giorgos Korfiatis
            holdings[(h.holder, h.resource)] = h
280 8acd9708 Giorgos Korfiatis
281 8b54001e Giorgos Korfiatis
        for holder, resource in get_quota:
282 fac1de87 Georgios D. Tsoukalas
            try:
283 8b54001e Giorgos Korfiatis
                h = holdings[(holder, resource)]
284 8acd9708 Giorgos Korfiatis
            except:
285 fac1de87 Georgios D. Tsoukalas
                continue
286 fac1de87 Georgios D. Tsoukalas
287 fac1de87 Georgios D. Tsoukalas
            p = h.policy
288 fac1de87 Georgios D. Tsoukalas
289 8b54001e Giorgos Korfiatis
            append((h.holder, h.resource, p.quantity, p.capacity,
290 fac1de87 Georgios D. Tsoukalas
                    p.import_limit, p.export_limit,
291 b435047b root
                    h.imported, h.exported,
292 d6662f65 root
                    h.returned, h.released,
293 b435047b root
                    h.flags))
294 fac1de87 Georgios D. Tsoukalas
295 fac1de87 Georgios D. Tsoukalas
        return quotas
296 fac1de87 Georgios D. Tsoukalas
297 e3685916 Giorgos Korfiatis
    def set_quota(self, context=None, set_quota=()):
298 fac1de87 Georgios D. Tsoukalas
        rejected = []
299 fac1de87 Georgios D. Tsoukalas
        append = rejected.append
300 fac1de87 Georgios D. Tsoukalas
301 2a3f6a3e Giorgos Korfiatis
        q_holdings = Q()
302 8b54001e Giorgos Korfiatis
        holders = []
303 8b54001e Giorgos Korfiatis
        for (holder, resource, _, _, _, _, _) in set_quota:
304 8b54001e Giorgos Korfiatis
            holders.append(holder)
305 2a3f6a3e Giorgos Korfiatis
306 8b54001e Giorgos Korfiatis
        hs = Holding.objects.filter(holder__in=holders).select_for_update()
307 2a3f6a3e Giorgos Korfiatis
        holdings = {}
308 2a3f6a3e Giorgos Korfiatis
        for h in hs:
309 8b54001e Giorgos Korfiatis
            holdings[(h.holder, h.resource)] = h
310 2a3f6a3e Giorgos Korfiatis
311 2a3f6a3e Giorgos Korfiatis
        old_policies = []
312 2a3f6a3e Giorgos Korfiatis
313 8b54001e Giorgos Korfiatis
        for (holder, resource,
314 e5a2e942 Georgios D. Tsoukalas
             quantity, capacity,
315 e5a2e942 Georgios D. Tsoukalas
             import_limit, export_limit, flags) in set_quota:
316 fac1de87 Georgios D. Tsoukalas
317 e5a2e942 Georgios D. Tsoukalas
            policy = newname('policy_')
318 1d734153 Giorgos Korfiatis
            newp = Policy(policy=policy,
319 1d734153 Giorgos Korfiatis
                          quantity=quantity,
320 1d734153 Giorgos Korfiatis
                          capacity=capacity,
321 1d734153 Giorgos Korfiatis
                          import_limit=import_limit,
322 1d734153 Giorgos Korfiatis
                          export_limit=export_limit)
323 fac1de87 Georgios D. Tsoukalas
324 e5a2e942 Georgios D. Tsoukalas
            try:
325 8b54001e Giorgos Korfiatis
                h = holdings[(holder, resource)]
326 2a3f6a3e Giorgos Korfiatis
                old_policies.append(h.policy_id)
327 e5a2e942 Georgios D. Tsoukalas
                h.policy = newp
328 e5a2e942 Georgios D. Tsoukalas
                h.flags = flags
329 2a3f6a3e Giorgos Korfiatis
            except KeyError:
330 8b54001e Giorgos Korfiatis
                h = Holding(holder=holder, resource=resource,
331 e5a2e942 Georgios D. Tsoukalas
                            policy=newp, flags=flags)
332 eec92c03 Georgios D. Tsoukalas
333 e5a2e942 Georgios D. Tsoukalas
            # the order is intentionally reversed so that it
334 e5a2e942 Georgios D. Tsoukalas
            # would break if we are not within a transaction.
335 e5a2e942 Georgios D. Tsoukalas
            # Has helped before.
336 e5a2e942 Georgios D. Tsoukalas
            h.save()
337 e5a2e942 Georgios D. Tsoukalas
            newp.save()
338 8b54001e Giorgos Korfiatis
            holdings[(holder, resource)] = h
339 fac1de87 Georgios D. Tsoukalas
340 2a3f6a3e Giorgos Korfiatis
        objs = Policy.objects.annotate(refs=Count('holding'))
341 2a3f6a3e Giorgos Korfiatis
        objs.filter(policy__in=old_policies, refs=0).delete()
342 fac1de87 Georgios D. Tsoukalas
343 eeba67ab Giorgos Korfiatis
        if rejected:
344 b0727daf Giorgos Korfiatis
            raise QuotaholderError(rejected)
345 fac1de87 Georgios D. Tsoukalas
        return rejected
346 fac1de87 Georgios D. Tsoukalas
347 1d734153 Giorgos Korfiatis
    def add_quota(self,
348 e3685916 Giorgos Korfiatis
                  context=None, clientkey=None, serial=None,
349 1d734153 Giorgos Korfiatis
                  sub_quota=(), add_quota=()):
350 4ec8c043 Giorgos Korfiatis
        rejected = []
351 4ec8c043 Giorgos Korfiatis
        append = rejected.append
352 4ec8c043 Giorgos Korfiatis
353 789d202d Giorgos Korfiatis
        if serial is not None:
354 789d202d Giorgos Korfiatis
            if clientkey is None:
355 d2b32360 Giorgos Korfiatis
                all_pairs = [(q[0], q[1]) for q in sub_quota + add_quota]
356 b0727daf Giorgos Korfiatis
                raise QuotaholderError(all_pairs)
357 789d202d Giorgos Korfiatis
            try:
358 789d202d Giorgos Korfiatis
                cs = CallSerial.objects.get(serial=serial, clientkey=clientkey)
359 d2b32360 Giorgos Korfiatis
                all_pairs = [(q[0], q[1]) for q in sub_quota + add_quota]
360 b0727daf Giorgos Korfiatis
                raise QuotaholderError(all_pairs)
361 789d202d Giorgos Korfiatis
            except CallSerial.DoesNotExist:
362 789d202d Giorgos Korfiatis
                pass
363 789d202d Giorgos Korfiatis
364 2a3f6a3e Giorgos Korfiatis
        sources = sub_quota + add_quota
365 2a3f6a3e Giorgos Korfiatis
        q_holdings = Q()
366 8b54001e Giorgos Korfiatis
        holders = []
367 8b54001e Giorgos Korfiatis
        for (holder, resource, _, _, _, _) in sources:
368 8b54001e Giorgos Korfiatis
            holders.append(holder)
369 2a3f6a3e Giorgos Korfiatis
370 8b54001e Giorgos Korfiatis
        hs = Holding.objects.filter(holder__in=holders).select_for_update()
371 2a3f6a3e Giorgos Korfiatis
        holdings = {}
372 2a3f6a3e Giorgos Korfiatis
        for h in hs:
373 8b54001e Giorgos Korfiatis
            holdings[(h.holder, h.resource)] = h
374 2a3f6a3e Giorgos Korfiatis
375 2a3f6a3e Giorgos Korfiatis
        pids = [h.policy_id for h in hs]
376 2a3f6a3e Giorgos Korfiatis
        policies = Policy.objects.in_bulk(pids)
377 2a3f6a3e Giorgos Korfiatis
378 2a3f6a3e Giorgos Korfiatis
        old_policies = []
379 2a3f6a3e Giorgos Korfiatis
380 d2b32360 Giorgos Korfiatis
        for removing, source in [(True, sub_quota), (False, add_quota)]:
381 8b54001e Giorgos Korfiatis
            for (holder, resource,
382 e5a2e942 Georgios D. Tsoukalas
                 quantity, capacity,
383 e5a2e942 Georgios D. Tsoukalas
                 import_limit, export_limit) in source:
384 4ec8c043 Giorgos Korfiatis
385 e5a2e942 Georgios D. Tsoukalas
                try:
386 8b54001e Giorgos Korfiatis
                    h = holdings[(holder, resource)]
387 2a3f6a3e Giorgos Korfiatis
                    old_policies.append(h.policy_id)
388 2a3f6a3e Giorgos Korfiatis
                    try:
389 2a3f6a3e Giorgos Korfiatis
                        p = policies[h.policy_id]
390 2a3f6a3e Giorgos Korfiatis
                    except KeyError:
391 2a3f6a3e Giorgos Korfiatis
                        raise AssertionError("no policy %s" % h.policy_id)
392 2a3f6a3e Giorgos Korfiatis
                except KeyError:
393 e5a2e942 Georgios D. Tsoukalas
                    if removing:
394 8b54001e Giorgos Korfiatis
                        append((holder, resource))
395 d2b32360 Giorgos Korfiatis
                        continue
396 1d2b20aa Giorgos Korfiatis
397 8b54001e Giorgos Korfiatis
                    h = Holding(holder=holder, resource=resource, flags=0)
398 e5a2e942 Georgios D. Tsoukalas
                    p = None
399 e5a2e942 Georgios D. Tsoukalas
400 e5a2e942 Georgios D. Tsoukalas
                policy = newname('policy_')
401 e5a2e942 Georgios D. Tsoukalas
                newp = Policy(policy=policy)
402 e5a2e942 Georgios D. Tsoukalas
403 e5a2e942 Georgios D. Tsoukalas
                newp.quantity = _add(p.quantity if p else 0, quantity,
404 e5a2e942 Georgios D. Tsoukalas
                                     invert=removing)
405 e5a2e942 Georgios D. Tsoukalas
                newp.capacity = _add(p.capacity if p else 0, capacity,
406 e5a2e942 Georgios D. Tsoukalas
                                     invert=removing)
407 e5a2e942 Georgios D. Tsoukalas
                newp.import_limit = _add(p.import_limit if p else 0,
408 e5a2e942 Georgios D. Tsoukalas
                                         import_limit, invert=removing)
409 e5a2e942 Georgios D. Tsoukalas
                newp.export_limit = _add(p.export_limit if p else 0,
410 e5a2e942 Georgios D. Tsoukalas
                                         export_limit, invert=removing)
411 e5a2e942 Georgios D. Tsoukalas
412 e5a2e942 Georgios D. Tsoukalas
                new_values = [newp.capacity,
413 e5a2e942 Georgios D. Tsoukalas
                              newp.import_limit, newp.export_limit]
414 e5a2e942 Georgios D. Tsoukalas
                if any(map(_isneg, new_values)):
415 8b54001e Giorgos Korfiatis
                    append((holder, resource))
416 e5a2e942 Georgios D. Tsoukalas
                    continue
417 4ec8c043 Giorgos Korfiatis
418 e5a2e942 Georgios D. Tsoukalas
                h.policy = newp
419 4ec8c043 Giorgos Korfiatis
420 e5a2e942 Georgios D. Tsoukalas
                # the order is intentionally reversed so that it
421 e5a2e942 Georgios D. Tsoukalas
                # would break if we are not within a transaction.
422 e5a2e942 Georgios D. Tsoukalas
                # Has helped before.
423 e5a2e942 Georgios D. Tsoukalas
                h.save()
424 e5a2e942 Georgios D. Tsoukalas
                newp.save()
425 2a3f6a3e Giorgos Korfiatis
                policies[policy] = newp
426 8b54001e Giorgos Korfiatis
                holdings[(holder, resource)] = h
427 4ec8c043 Giorgos Korfiatis
428 2a3f6a3e Giorgos Korfiatis
        objs = Policy.objects.annotate(refs=Count('holding'))
429 2a3f6a3e Giorgos Korfiatis
        objs.filter(policy__in=old_policies, refs=0).delete()
430 4ec8c043 Giorgos Korfiatis
431 4ec8c043 Giorgos Korfiatis
        if rejected:
432 b0727daf Giorgos Korfiatis
            raise QuotaholderError(rejected)
433 789d202d Giorgos Korfiatis
434 789d202d Giorgos Korfiatis
        if serial is not None and clientkey is not None:
435 2fd11a01 Giorgos Korfiatis
            CallSerial.objects.create(serial=serial, clientkey=clientkey)
436 4ec8c043 Giorgos Korfiatis
        return rejected
437 4ec8c043 Giorgos Korfiatis
438 e3685916 Giorgos Korfiatis
    def ack_serials(self, context=None, clientkey=None, serials=()):
439 2fd11a01 Giorgos Korfiatis
        if clientkey is None:
440 2fd11a01 Giorgos Korfiatis
            return
441 2fd11a01 Giorgos Korfiatis
442 2fd11a01 Giorgos Korfiatis
        for serial in serials:
443 2fd11a01 Giorgos Korfiatis
            try:
444 2fd11a01 Giorgos Korfiatis
                c = db_get_callserial(clientkey=clientkey,
445 2fd11a01 Giorgos Korfiatis
                                      serial=serial,
446 2fd11a01 Giorgos Korfiatis
                                      for_update=True)
447 2fd11a01 Giorgos Korfiatis
                c.delete()
448 2fd11a01 Giorgos Korfiatis
            except CallSerial.DoesNotExist:
449 2fd11a01 Giorgos Korfiatis
                pass
450 2fd11a01 Giorgos Korfiatis
        return
451 2fd11a01 Giorgos Korfiatis
452 e3685916 Giorgos Korfiatis
    def query_serials(self, context=None, clientkey=None, serials=()):
453 ef0fa70b Giorgos Korfiatis
        result = []
454 2fd11a01 Giorgos Korfiatis
        append = result.append
455 2fd11a01 Giorgos Korfiatis
456 2fd11a01 Giorgos Korfiatis
        if clientkey is None:
457 ef0fa70b Giorgos Korfiatis
            return result
458 ef0fa70b Giorgos Korfiatis
459 2fd11a01 Giorgos Korfiatis
        if not serials:
460 2fd11a01 Giorgos Korfiatis
            cs = CallSerial.objects.filter(clientkey=clientkey)
461 2fd11a01 Giorgos Korfiatis
            return [c.serial for c in cs]
462 2fd11a01 Giorgos Korfiatis
463 2fd11a01 Giorgos Korfiatis
        for serial in serials:
464 2fd11a01 Giorgos Korfiatis
            try:
465 2fd11a01 Giorgos Korfiatis
                db_get_callserial(clientkey=clientkey, serial=serial)
466 2fd11a01 Giorgos Korfiatis
                append(serial)
467 2fd11a01 Giorgos Korfiatis
            except CallSerial.DoesNotExist:
468 2fd11a01 Giorgos Korfiatis
                pass
469 ef0fa70b Giorgos Korfiatis
470 ef0fa70b Giorgos Korfiatis
        return result
471 789d202d Giorgos Korfiatis
472 1d734153 Giorgos Korfiatis
    def issue_commission(self,
473 e3685916 Giorgos Korfiatis
                         context=None,
474 1d734153 Giorgos Korfiatis
                         clientkey=None,
475 1d734153 Giorgos Korfiatis
                         target=None,
476 1d734153 Giorgos Korfiatis
                         name=None,
477 1d734153 Giorgos Korfiatis
                         provisions=()):
478 fac1de87 Georgios D. Tsoukalas
479 c3a709ad root
        create = Commission.objects.create
480 8b54001e Giorgos Korfiatis
        commission = create(holder=target, clientkey=clientkey, name=name)
481 fac1de87 Georgios D. Tsoukalas
        serial = commission.serial
482 fac1de87 Georgios D. Tsoukalas
483 6afede3f Giorgos Korfiatis
        checked = []
484 8b54001e Giorgos Korfiatis
        for holder, resource, quantity in provisions:
485 6afede3f Giorgos Korfiatis
486 8b54001e Giorgos Korfiatis
            if holder == target:
487 8b54001e Giorgos Korfiatis
                m = "Cannot issue commission from an holder to itself (%s)" % (
488 8b54001e Giorgos Korfiatis
                    holder,)
489 4eb170f3 Giorgos Korfiatis
                raise InvalidDataError(m)
490 4eb170f3 Giorgos Korfiatis
491 8b54001e Giorgos Korfiatis
            ent_res = holder, resource
492 6afede3f Giorgos Korfiatis
            if ent_res in checked:
493 6afede3f Giorgos Korfiatis
                m = "Duplicate provision for %s.%s" % ent_res
494 6afede3f Giorgos Korfiatis
                raise DuplicateError(m)
495 6afede3f Giorgos Korfiatis
            checked.append(ent_res)
496 6afede3f Giorgos Korfiatis
497 c3a709ad root
            release = 0
498 c3a709ad root
            if quantity < 0:
499 c3a709ad root
                release = 1
500 c3a709ad root
501 f631150c Giorgos Korfiatis
            # Source limits checks
502 fac1de87 Georgios D. Tsoukalas
            try:
503 8b54001e Giorgos Korfiatis
                h = db_get_holding(holder=holder, resource=resource,
504 5d996aea Giorgos Korfiatis
                                   for_update=True)
505 fac1de87 Georgios D. Tsoukalas
            except Holding.DoesNotExist:
506 d551c841 Georgios D. Tsoukalas
                m = ("There is no quantity "
507 8b54001e Giorgos Korfiatis
                     "to allocate from in %s.%s" % (holder, resource))
508 f631150c Giorgos Korfiatis
                raise NoQuantityError(m,
509 8b54001e Giorgos Korfiatis
                                      source=holder, target=target,
510 f631150c Giorgos Korfiatis
                                      resource=resource, requested=quantity,
511 f631150c Giorgos Korfiatis
                                      current=0, limit=0)
512 fac1de87 Georgios D. Tsoukalas
513 fac1de87 Georgios D. Tsoukalas
            hp = h.policy
514 fac1de87 Georgios D. Tsoukalas
515 d551c841 Georgios D. Tsoukalas
            if not release:
516 d551c841 Georgios D. Tsoukalas
                current = h.exporting
517 d551c841 Georgios D. Tsoukalas
                limit = hp.export_limit
518 d551c841 Georgios D. Tsoukalas
                if current + quantity > limit:
519 8b54001e Giorgos Korfiatis
                    m = ("Export limit reached for %s.%s" % (holder, resource))
520 d551c841 Georgios D. Tsoukalas
                    raise ExportLimitError(m,
521 8b54001e Giorgos Korfiatis
                                           source=holder,
522 e5a2e942 Georgios D. Tsoukalas
                                           target=target,
523 e5a2e942 Georgios D. Tsoukalas
                                           resource=resource,
524 e5a2e942 Georgios D. Tsoukalas
                                           requested=quantity,
525 e5a2e942 Georgios D. Tsoukalas
                                           current=current,
526 e5a2e942 Georgios D. Tsoukalas
                                           limit=limit)
527 d551c841 Georgios D. Tsoukalas
528 d551c841 Georgios D. Tsoukalas
                limit = hp.quantity + h.imported - h.releasing
529 d551c841 Georgios D. Tsoukalas
                unavailable = h.exporting - h.returned
530 d551c841 Georgios D. Tsoukalas
                available = limit - unavailable
531 d551c841 Georgios D. Tsoukalas
532 d551c841 Georgios D. Tsoukalas
                if quantity > available:
533 d551c841 Georgios D. Tsoukalas
                    m = ("There is not enough quantity "
534 8b54001e Giorgos Korfiatis
                         "to allocate from in %s.%s" % (holder, resource))
535 d551c841 Georgios D. Tsoukalas
                    raise NoQuantityError(m,
536 8b54001e Giorgos Korfiatis
                                          source=holder,
537 e5a2e942 Georgios D. Tsoukalas
                                          target=target,
538 e5a2e942 Georgios D. Tsoukalas
                                          resource=resource,
539 e5a2e942 Georgios D. Tsoukalas
                                          requested=quantity,
540 e5a2e942 Georgios D. Tsoukalas
                                          current=unavailable,
541 e5a2e942 Georgios D. Tsoukalas
                                          limit=limit)
542 d551c841 Georgios D. Tsoukalas
            else:
543 d551c841 Georgios D. Tsoukalas
                current = (+ h.importing + h.returning
544 1d734153 Giorgos Korfiatis
                           - h.exported - h.returned)
545 d551c841 Georgios D. Tsoukalas
                limit = hp.capacity
546 d551c841 Georgios D. Tsoukalas
                if current - quantity > limit:
547 d551c841 Georgios D. Tsoukalas
                    m = ("There is not enough capacity "
548 8b54001e Giorgos Korfiatis
                         "to release to in %s.%s" % (holder, resource))
549 d551c841 Georgios D. Tsoukalas
                    raise NoQuantityError(m,
550 8b54001e Giorgos Korfiatis
                                          source=holder,
551 e5a2e942 Georgios D. Tsoukalas
                                          target=target,
552 e5a2e942 Georgios D. Tsoukalas
                                          resource=resource,
553 e5a2e942 Georgios D. Tsoukalas
                                          requested=quantity,
554 e5a2e942 Georgios D. Tsoukalas
                                          current=current,
555 e5a2e942 Georgios D. Tsoukalas
                                          limit=limit)
556 fac1de87 Georgios D. Tsoukalas
557 f631150c Giorgos Korfiatis
            # Target limits checks
558 fac1de87 Georgios D. Tsoukalas
            try:
559 8b54001e Giorgos Korfiatis
                th = db_get_holding(holder=target, resource=resource,
560 5d996aea Giorgos Korfiatis
                                    for_update=True)
561 fac1de87 Georgios D. Tsoukalas
            except Holding.DoesNotExist:
562 ea818d33 Georgios D. Tsoukalas
                m = ("There is no capacity "
563 fac1de87 Georgios D. Tsoukalas
                     "to allocate into in %s.%s" % (target, resource))
564 f631150c Giorgos Korfiatis
                raise NoCapacityError(m,
565 8b54001e Giorgos Korfiatis
                                      source=holder,
566 e5a2e942 Georgios D. Tsoukalas
                                      target=target,
567 e5a2e942 Georgios D. Tsoukalas
                                      resource=resource,
568 e5a2e942 Georgios D. Tsoukalas
                                      requested=quantity,
569 e5a2e942 Georgios D. Tsoukalas
                                      current=0,
570 e5a2e942 Georgios D. Tsoukalas
                                      limit=0)
571 fac1de87 Georgios D. Tsoukalas
572 fac1de87 Georgios D. Tsoukalas
            tp = th.policy
573 fac1de87 Georgios D. Tsoukalas
574 d551c841 Georgios D. Tsoukalas
            if not release:
575 d551c841 Georgios D. Tsoukalas
                limit = tp.import_limit
576 d551c841 Georgios D. Tsoukalas
                current = th.importing
577 d551c841 Georgios D. Tsoukalas
                if current + quantity > limit:
578 d551c841 Georgios D. Tsoukalas
                    m = ("Import limit reached for %s.%s" % (target, resource))
579 d551c841 Georgios D. Tsoukalas
                    raise ImportLimitError(m,
580 8b54001e Giorgos Korfiatis
                                           source=holder,
581 e5a2e942 Georgios D. Tsoukalas
                                           target=target,
582 e5a2e942 Georgios D. Tsoukalas
                                           resource=resource,
583 e5a2e942 Georgios D. Tsoukalas
                                           requested=quantity,
584 e5a2e942 Georgios D. Tsoukalas
                                           current=current,
585 e5a2e942 Georgios D. Tsoukalas
                                           limit=limit)
586 08ce0e6f Giorgos Korfiatis
587 6e4e100b Giorgos Korfiatis
                limit = tp.quantity + tp.capacity
588 6e4e100b Giorgos Korfiatis
                current = (+ th.importing + th.returning + tp.quantity
589 d551c841 Georgios D. Tsoukalas
                           - th.exported - th.released)
590 08ce0e6f Giorgos Korfiatis
591 6e4e100b Giorgos Korfiatis
                if current + quantity > limit:
592 08ce0e6f Giorgos Korfiatis
                    m = ("There is not enough capacity "
593 08ce0e6f Giorgos Korfiatis
                         "to allocate into in %s.%s" % (target, resource))
594 08ce0e6f Giorgos Korfiatis
                    raise NoCapacityError(m,
595 8b54001e Giorgos Korfiatis
                                          source=holder,
596 e5a2e942 Georgios D. Tsoukalas
                                          target=target,
597 e5a2e942 Georgios D. Tsoukalas
                                          resource=resource,
598 e5a2e942 Georgios D. Tsoukalas
                                          requested=quantity,
599 e5a2e942 Georgios D. Tsoukalas
                                          current=current,
600 e5a2e942 Georgios D. Tsoukalas
                                          limit=limit)
601 d551c841 Georgios D. Tsoukalas
            else:
602 d551c841 Georgios D. Tsoukalas
                limit = tp.quantity + th.imported - th.releasing
603 d551c841 Georgios D. Tsoukalas
                unavailable = th.exporting - th.returned
604 d551c841 Georgios D. Tsoukalas
                available = limit - unavailable
605 d551c841 Georgios D. Tsoukalas
606 d551c841 Georgios D. Tsoukalas
                if available + quantity < 0:
607 d551c841 Georgios D. Tsoukalas
                    m = ("There is not enough quantity "
608 d551c841 Georgios D. Tsoukalas
                         "to release from in %s.%s" % (target, resource))
609 d551c841 Georgios D. Tsoukalas
                    raise NoCapacityError(m,
610 8b54001e Giorgos Korfiatis
                                          source=holder,
611 e5a2e942 Georgios D. Tsoukalas
                                          target=target,
612 e5a2e942 Georgios D. Tsoukalas
                                          resource=resource,
613 e5a2e942 Georgios D. Tsoukalas
                                          requested=quantity,
614 e5a2e942 Georgios D. Tsoukalas
                                          current=unavailable,
615 e5a2e942 Georgios D. Tsoukalas
                                          limit=limit)
616 e5a2e942 Georgios D. Tsoukalas
617 1d734153 Giorgos Korfiatis
            Provision.objects.create(serial=commission,
618 8b54001e Giorgos Korfiatis
                                     holder=holder,
619 1d734153 Giorgos Korfiatis
                                     resource=resource,
620 1d734153 Giorgos Korfiatis
                                     quantity=quantity)
621 f590f930 Georgios D. Tsoukalas
            if release:
622 d6662f65 root
                h.returning -= quantity
623 f590f930 Georgios D. Tsoukalas
                th.releasing -= quantity
624 f590f930 Georgios D. Tsoukalas
            else:
625 f590f930 Georgios D. Tsoukalas
                h.exporting += quantity
626 f590f930 Georgios D. Tsoukalas
                th.importing += quantity
627 fac1de87 Georgios D. Tsoukalas
628 fac1de87 Georgios D. Tsoukalas
            h.save()
629 fac1de87 Georgios D. Tsoukalas
            th.save()
630 fac1de87 Georgios D. Tsoukalas
631 fac1de87 Georgios D. Tsoukalas
        return serial
632 fac1de87 Georgios D. Tsoukalas
633 1d734153 Giorgos Korfiatis
    def _log_provision(self,
634 1d734153 Giorgos Korfiatis
                       commission, s_holding, t_holding,
635 1d734153 Giorgos Korfiatis
                       provision, log_time, reason):
636 1dedc367 Georgios D. Tsoukalas
637 8b54001e Giorgos Korfiatis
        s_holder = s_holding.holder
638 d6662f65 root
        s_policy = s_holding.policy
639 8b54001e Giorgos Korfiatis
        t_holder = t_holding.holder
640 d6662f65 root
        t_policy = t_holding.policy
641 1dedc367 Georgios D. Tsoukalas
642 1d734153 Giorgos Korfiatis
        kwargs = {
643 1d734153 Giorgos Korfiatis
            'serial':              commission.serial,
644 1d734153 Giorgos Korfiatis
            'name':                commission.name,
645 8b54001e Giorgos Korfiatis
            'source':              s_holder,
646 8b54001e Giorgos Korfiatis
            'target':              t_holder,
647 1d734153 Giorgos Korfiatis
            'resource':            provision.resource,
648 1d734153 Giorgos Korfiatis
            'source_quantity':     s_policy.quantity,
649 1d734153 Giorgos Korfiatis
            'source_capacity':     s_policy.capacity,
650 1d734153 Giorgos Korfiatis
            'source_import_limit': s_policy.import_limit,
651 1d734153 Giorgos Korfiatis
            'source_export_limit': s_policy.export_limit,
652 1d734153 Giorgos Korfiatis
            'source_imported':     s_holding.imported,
653 1d734153 Giorgos Korfiatis
            'source_exported':     s_holding.exported,
654 1d734153 Giorgos Korfiatis
            'source_returned':     s_holding.returned,
655 1d734153 Giorgos Korfiatis
            'source_released':     s_holding.released,
656 1d734153 Giorgos Korfiatis
            'target_quantity':     t_policy.quantity,
657 1d734153 Giorgos Korfiatis
            'target_capacity':     t_policy.capacity,
658 1d734153 Giorgos Korfiatis
            'target_import_limit': t_policy.import_limit,
659 1d734153 Giorgos Korfiatis
            'target_export_limit': t_policy.export_limit,
660 1d734153 Giorgos Korfiatis
            'target_imported':     t_holding.imported,
661 1d734153 Giorgos Korfiatis
            'target_exported':     t_holding.exported,
662 1d734153 Giorgos Korfiatis
            'target_returned':     t_holding.returned,
663 1d734153 Giorgos Korfiatis
            'target_released':     t_holding.released,
664 1d734153 Giorgos Korfiatis
            'delta_quantity':      provision.quantity,
665 1d734153 Giorgos Korfiatis
            'issue_time':          commission.issue_time,
666 1d734153 Giorgos Korfiatis
            'log_time':            log_time,
667 1d734153 Giorgos Korfiatis
            'reason':              reason,
668 1d734153 Giorgos Korfiatis
        }
669 1d734153 Giorgos Korfiatis
670 1d734153 Giorgos Korfiatis
        ProvisionLog.objects.create(**kwargs)
671 1d734153 Giorgos Korfiatis
672 1d734153 Giorgos Korfiatis
    def accept_commission(self,
673 e3685916 Giorgos Korfiatis
                          context=None, clientkey=None,
674 1d734153 Giorgos Korfiatis
                          serials=(), reason=''):
675 b435047b root
        log_time = now()
676 b435047b root
677 fe6c61fb root
        for serial in serials:
678 fe6c61fb root
            try:
679 5d996aea Giorgos Korfiatis
                c = db_get_commission(clientkey=clientkey, serial=serial,
680 5d996aea Giorgos Korfiatis
                                      for_update=True)
681 fe6c61fb root
            except Commission.DoesNotExist:
682 fe6c61fb root
                return
683 fac1de87 Georgios D. Tsoukalas
684 8b54001e Giorgos Korfiatis
            t = c.holder
685 fac1de87 Georgios D. Tsoukalas
686 5d996aea Giorgos Korfiatis
            provisions = db_filter_provision(serial=serial, for_update=True)
687 fe6c61fb root
            for pv in provisions:
688 fe6c61fb root
                try:
689 8b54001e Giorgos Korfiatis
                    h = db_get_holding(holder=pv.holder,
690 5d996aea Giorgos Korfiatis
                                       resource=pv.resource, for_update=True)
691 8b54001e Giorgos Korfiatis
                    th = db_get_holding(holder=t, resource=pv.resource,
692 5d996aea Giorgos Korfiatis
                                        for_update=True)
693 fe6c61fb root
                except Holding.DoesNotExist:
694 fe6c61fb root
                    m = "Corrupted provision"
695 fe6c61fb root
                    raise CorruptedError(m)
696 fac1de87 Georgios D. Tsoukalas
697 fe6c61fb root
                quantity = pv.quantity
698 fe6c61fb root
                release = 0
699 fe6c61fb root
                if quantity < 0:
700 fe6c61fb root
                    release = 1
701 f590f930 Georgios D. Tsoukalas
702 fe6c61fb root
                if release:
703 d6662f65 root
                    h.returned -= quantity
704 fe6c61fb root
                    th.released -= quantity
705 fe6c61fb root
                else:
706 fe6c61fb root
                    h.exported += quantity
707 fe6c61fb root
                    th.imported += quantity
708 f590f930 Georgios D. Tsoukalas
709 fe6c61fb root
                reason = 'ACCEPT:' + reason[-121:]
710 b435047b root
                self._log_provision(c, h, th, pv, log_time, reason)
711 fe6c61fb root
                h.save()
712 fe6c61fb root
                th.save()
713 fe6c61fb root
                pv.delete()
714 7661c43c Christos Stavrakakis
            c.delete()
715 fac1de87 Georgios D. Tsoukalas
716 fac1de87 Georgios D. Tsoukalas
        return
717 fac1de87 Georgios D. Tsoukalas
718 1d734153 Giorgos Korfiatis
    def reject_commission(self,
719 e3685916 Giorgos Korfiatis
                          context=None, clientkey=None,
720 1d734153 Giorgos Korfiatis
                          serials=(), reason=''):
721 b435047b root
        log_time = now()
722 b435047b root
723 fe6c61fb root
        for serial in serials:
724 fe6c61fb root
            try:
725 5d996aea Giorgos Korfiatis
                c = db_get_commission(clientkey=clientkey, serial=serial,
726 5d996aea Giorgos Korfiatis
                                      for_update=True)
727 fe6c61fb root
            except Commission.DoesNotExist:
728 fe6c61fb root
                return
729 fac1de87 Georgios D. Tsoukalas
730 8b54001e Giorgos Korfiatis
            t = c.holder
731 fac1de87 Georgios D. Tsoukalas
732 5d996aea Giorgos Korfiatis
            provisions = db_filter_provision(serial=serial, for_update=True)
733 fe6c61fb root
            for pv in provisions:
734 fe6c61fb root
                try:
735 8b54001e Giorgos Korfiatis
                    h = db_get_holding(holder=pv.holder,
736 5d996aea Giorgos Korfiatis
                                       resource=pv.resource, for_update=True)
737 8b54001e Giorgos Korfiatis
                    th = db_get_holding(holder=t, resource=pv.resource,
738 5d996aea Giorgos Korfiatis
                                        for_update=True)
739 fe6c61fb root
                except Holding.DoesNotExist:
740 fe6c61fb root
                    m = "Corrupted provision"
741 fe6c61fb root
                    raise CorruptedError(m)
742 fac1de87 Georgios D. Tsoukalas
743 fe6c61fb root
                quantity = pv.quantity
744 fe6c61fb root
                release = 0
745 fe6c61fb root
                if quantity < 0:
746 fe6c61fb root
                    release = 1
747 f590f930 Georgios D. Tsoukalas
748 fe6c61fb root
                if release:
749 d6662f65 root
                    h.returning += quantity
750 fe6c61fb root
                    th.releasing += quantity
751 fe6c61fb root
                else:
752 fe6c61fb root
                    h.exporting -= quantity
753 fe6c61fb root
                    th.importing -= quantity
754 fe6c61fb root
755 fe6c61fb root
                reason = 'REJECT:' + reason[-121:]
756 b435047b root
                self._log_provision(c, h, th, pv, log_time, reason)
757 fe6c61fb root
                h.save()
758 fe6c61fb root
                th.save()
759 fe6c61fb root
                pv.delete()
760 7661c43c Christos Stavrakakis
            c.delete()
761 fac1de87 Georgios D. Tsoukalas
762 fac1de87 Georgios D. Tsoukalas
        return
763 fac1de87 Georgios D. Tsoukalas
764 e3685916 Giorgos Korfiatis
    def get_pending_commissions(self, context=None, clientkey=None):
765 e5a2e942 Georgios D. Tsoukalas
        pending = Commission.objects.filter(clientkey=clientkey)
766 e5a2e942 Georgios D. Tsoukalas
        pending_list = pending.values_list('serial', flat=True)
767 e5a2e942 Georgios D. Tsoukalas
        return pending_list
768 fac1de87 Georgios D. Tsoukalas
769 1d734153 Giorgos Korfiatis
    def resolve_pending_commissions(self,
770 e3685916 Giorgos Korfiatis
                                    context=None, clientkey=None,
771 1d734153 Giorgos Korfiatis
                                    max_serial=None, accept_set=()):
772 fac1de87 Georgios D. Tsoukalas
        accept_set = set(accept_set)
773 e5a2e942 Georgios D. Tsoukalas
        pending = self.get_pending_commissions(context=context,
774 e5a2e942 Georgios D. Tsoukalas
                                               clientkey=clientkey)
775 fac1de87 Georgios D. Tsoukalas
        pending = sorted(pending)
776 fac1de87 Georgios D. Tsoukalas
777 fac1de87 Georgios D. Tsoukalas
        accept = self.accept_commission
778 fac1de87 Georgios D. Tsoukalas
        reject = self.reject_commission
779 fac1de87 Georgios D. Tsoukalas
780 fac1de87 Georgios D. Tsoukalas
        for serial in pending:
781 fac1de87 Georgios D. Tsoukalas
            if serial > max_serial:
782 fac1de87 Georgios D. Tsoukalas
                break
783 fac1de87 Georgios D. Tsoukalas
784 fac1de87 Georgios D. Tsoukalas
            if serial in accept_set:
785 ddf2e911 Giorgos Korfiatis
                accept(context=context, clientkey=clientkey, serials=[serial])
786 fac1de87 Georgios D. Tsoukalas
            else:
787 ddf2e911 Giorgos Korfiatis
                reject(context=context, clientkey=clientkey, serials=[serial])
788 fac1de87 Georgios D. Tsoukalas
789 fac1de87 Georgios D. Tsoukalas
        return
790 fac1de87 Georgios D. Tsoukalas
791 e3685916 Giorgos Korfiatis
    def get_timeline(self, context=None, after="", before="Z", get_timeline=()):
792 8b54001e Giorgos Korfiatis
        holder_set = set()
793 8b54001e Giorgos Korfiatis
        e_add = holder_set.add
794 0360f54b root
        resource_set = set()
795 0360f54b root
        r_add = resource_set.add
796 f590f930 Georgios D. Tsoukalas
797 8b54001e Giorgos Korfiatis
        for holder, resource in get_timeline:
798 8b54001e Giorgos Korfiatis
            if holder not in holder_set:
799 8b54001e Giorgos Korfiatis
                e_add(holder)
800 0360f54b root
801 8b54001e Giorgos Korfiatis
            r_add((holder, resource))
802 f590f930 Georgios D. Tsoukalas
803 f590f930 Georgios D. Tsoukalas
        chunk_size = 65536
804 f590f930 Georgios D. Tsoukalas
        nr = 0
805 f590f930 Georgios D. Tsoukalas
        timeline = []
806 0360f54b root
        append = timeline.append
807 1dedc367 Georgios D. Tsoukalas
        filterlogs = ProvisionLog.objects.filter
808 8b54001e Giorgos Korfiatis
        if holder_set:
809 8b54001e Giorgos Korfiatis
            q_holder = Q(source__in=holder_set) | Q(target__in=holder_set)
810 1dedc367 Georgios D. Tsoukalas
        else:
811 8b54001e Giorgos Korfiatis
            q_holder = Q()
812 1dedc367 Georgios D. Tsoukalas
813 1dedc367 Georgios D. Tsoukalas
        while 1:
814 8b54001e Giorgos Korfiatis
            logs = filterlogs(q_holder,
815 1d734153 Giorgos Korfiatis
                              issue_time__gt=after,
816 1d734153 Giorgos Korfiatis
                              issue_time__lte=before,
817 1d734153 Giorgos Korfiatis
                              reason__startswith='ACCEPT:')
818 f590f930 Georgios D. Tsoukalas
819 f590f930 Georgios D. Tsoukalas
            logs = logs.order_by('issue_time')
820 d6662f65 root
            #logs = logs.values()
821 f590f930 Georgios D. Tsoukalas
            logs = logs[:chunk_size]
822 f590f930 Georgios D. Tsoukalas
            nr += len(logs)
823 f590f930 Georgios D. Tsoukalas
            if not logs:
824 f590f930 Georgios D. Tsoukalas
                break
825 0360f54b root
            for g in logs:
826 0360f54b root
                if ((g.source, g.resource) not in resource_set
827 0360f54b root
                    or (g.target, g.resource) not in resource_set):
828 e5a2e942 Georgios D. Tsoukalas
                    continue
829 0360f54b root
830 d6662f65 root
                o = {
831 1d734153 Giorgos Korfiatis
                    'serial':                   g.serial,
832 1d734153 Giorgos Korfiatis
                    'source':                   g.source,
833 1d734153 Giorgos Korfiatis
                    'target':                   g.target,
834 1d734153 Giorgos Korfiatis
                    'resource':                 g.resource,
835 1d734153 Giorgos Korfiatis
                    'name':                     g.name,
836 1d734153 Giorgos Korfiatis
                    'quantity':                 g.delta_quantity,
837 1d734153 Giorgos Korfiatis
                    'source_allocated':         g.source_allocated(),
838 1d734153 Giorgos Korfiatis
                    'source_allocated_through': g.source_allocated_through(),
839 1d734153 Giorgos Korfiatis
                    'source_inbound':           g.source_inbound(),
840 1d734153 Giorgos Korfiatis
                    'source_inbound_through':   g.source_inbound_through(),
841 1d734153 Giorgos Korfiatis
                    'source_outbound':          g.source_outbound(),
842 1d734153 Giorgos Korfiatis
                    'source_outbound_through':  g.source_outbound_through(),
843 1d734153 Giorgos Korfiatis
                    'target_allocated':         g.target_allocated(),
844 1d734153 Giorgos Korfiatis
                    'target_allocated_through': g.target_allocated_through(),
845 1d734153 Giorgos Korfiatis
                    'target_inbound':           g.target_inbound(),
846 1d734153 Giorgos Korfiatis
                    'target_inbound_through':   g.target_inbound_through(),
847 1d734153 Giorgos Korfiatis
                    'target_outbound':          g.target_outbound(),
848 1d734153 Giorgos Korfiatis
                    'target_outbound_through':  g.target_outbound_through(),
849 1d734153 Giorgos Korfiatis
                    'issue_time':               g.issue_time,
850 1d734153 Giorgos Korfiatis
                    'log_time':                 g.log_time,
851 1d734153 Giorgos Korfiatis
                    'reason':                   g.reason,
852 d6662f65 root
                }
853 d36dcd3d Christos KK Loverdos
854 0360f54b root
                append(o)
855 d6662f65 root
856 d6662f65 root
            after = g.issue_time
857 f590f930 Georgios D. Tsoukalas
            if after >= before:
858 f590f930 Georgios D. Tsoukalas
                break
859 f590f930 Georgios D. Tsoukalas
860 f590f930 Georgios D. Tsoukalas
        return timeline
861 f590f930 Georgios D. Tsoukalas
862 e5a2e942 Georgios D. Tsoukalas
863 d2b32360 Giorgos Korfiatis
def _add(x, y, invert=False):
864 d2b32360 Giorgos Korfiatis
    return x + y if not invert else x - y
865 4ec8c043 Giorgos Korfiatis
866 e5a2e942 Georgios D. Tsoukalas
867 4ec8c043 Giorgos Korfiatis
def _isneg(x):
868 4ec8c043 Giorgos Korfiatis
    return x < 0
869 f590f930 Georgios D. Tsoukalas
870 e5a2e942 Georgios D. Tsoukalas
871 fac1de87 Georgios D. Tsoukalas
API_Callpoint = QuotaholderDjangoDBCallpoint